Add my little `ifinfo' program. This is sort of a cross between a
diagnostic program for debugging the interface MIB and an example of how to use same. Someday, netstat should be updated to print this information in a prettier form.
This commit is contained in:
parent
f5b7ed3e67
commit
b01aba1d41
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=18870
7
tools/tools/ifinfo/Makefile
Normal file
7
tools/tools/ifinfo/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
# $Id$
|
||||||
|
|
||||||
|
PROG= ifinfo
|
||||||
|
SRCS= ifinfo.c rfc1650.c
|
||||||
|
NOMAN=
|
||||||
|
|
||||||
|
.include <bsd.prog.mk>
|
272
tools/tools/ifinfo/ifinfo.c
Normal file
272
tools/tools/ifinfo/ifinfo.c
Normal file
@ -0,0 +1,272 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1996 Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and
|
||||||
|
* its documentation for any purpose and without fee is hereby
|
||||||
|
* granted, provided that both the above copyright notice and this
|
||||||
|
* permission notice appear in all copies, that both the above
|
||||||
|
* copyright notice and this permission notice appear in all
|
||||||
|
* supporting documentation, and that the name of M.I.T. not be used
|
||||||
|
* in advertising or publicity pertaining to distribution of the
|
||||||
|
* software without specific, written prior permission. M.I.T. makes
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied
|
||||||
|
* warranty.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||||
|
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||||
|
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h> /* for PF_LINK */
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/if_mib.h>
|
||||||
|
|
||||||
|
#include "ifinfo.h"
|
||||||
|
|
||||||
|
static void printit(const struct ifmibdata *);
|
||||||
|
static const char *iftype(int);
|
||||||
|
static const char *ifphys(int, int);
|
||||||
|
static int isit(int, char **, const char *);
|
||||||
|
static printfcn findlink(int);
|
||||||
|
|
||||||
|
static void
|
||||||
|
usage(const char *argv0)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s: usage:\n\t%s [-i] [ifnames...]\n",
|
||||||
|
argv0, argv0);
|
||||||
|
exit(EX_USAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
int i, maxifno, retval;
|
||||||
|
struct ifmibdata ifmd;
|
||||||
|
int name[6];
|
||||||
|
size_t len;
|
||||||
|
int c;
|
||||||
|
int dolink = 0;
|
||||||
|
void *linkmib;
|
||||||
|
size_t linkmiblen;
|
||||||
|
printfcn pf;
|
||||||
|
|
||||||
|
while ((c = getopt(argc, argv, "l")) != -1) {
|
||||||
|
switch(c) {
|
||||||
|
case 'l':
|
||||||
|
dolink = 1;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
usage(argv[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
retval = 1;
|
||||||
|
|
||||||
|
name[0] = CTL_NET;
|
||||||
|
name[1] = PF_LINK;
|
||||||
|
name[2] = NETLINK_GENERIC;
|
||||||
|
name[3] = IFMIB_SYSTEM;
|
||||||
|
name[4] = IFMIB_IFCOUNT;
|
||||||
|
|
||||||
|
len = sizeof maxifno;
|
||||||
|
if (sysctl(name, 5, &maxifno, &len, 0, 0) < 0)
|
||||||
|
err(EX_OSERR, "sysctl(net.link.generic.system.ifcount)");
|
||||||
|
|
||||||
|
for (i = 1; i <= maxifno; i++) {
|
||||||
|
len = sizeof ifmd;
|
||||||
|
name[3] = IFMIB_IFDATA;
|
||||||
|
name[4] = i;
|
||||||
|
name[5] = IFDATA_GENERAL;
|
||||||
|
if (sysctl(name, 6, &ifmd, &len, 0, 0) < 0)
|
||||||
|
err(EX_OSERR, "sysctl(net.link.ifdata.%d.general)",
|
||||||
|
i);
|
||||||
|
|
||||||
|
if (!isit(argc - optind, argv + optind, ifmd.ifmd_name))
|
||||||
|
continue;
|
||||||
|
printit(&ifmd);
|
||||||
|
if (dolink && (pf = findlink(ifmd.ifmd_data.ifi_type))) {
|
||||||
|
name[5] = IFDATA_LINKSPECIFIC;
|
||||||
|
if (sysctl(name, 6, 0, &linkmiblen, 0, 0) < 0)
|
||||||
|
err(EX_OSERR,
|
||||||
|
"sysctl(net.link.ifdata.%d.linkspec) size",
|
||||||
|
i);
|
||||||
|
linkmib = malloc(linkmiblen);
|
||||||
|
if (!linkmib)
|
||||||
|
err(EX_OSERR, "malloc(%lu)",
|
||||||
|
(u_long)linkmiblen);
|
||||||
|
if (sysctl(name, 6, linkmib, &linkmiblen, 0, 0) < 0)
|
||||||
|
err(EX_OSERR,
|
||||||
|
"sysctl(net.link.ifdata.%d.linkspec)",
|
||||||
|
i);
|
||||||
|
pf(linkmib, linkmiblen);
|
||||||
|
free(linkmib);
|
||||||
|
}
|
||||||
|
retval = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
printit(const struct ifmibdata *ifmd)
|
||||||
|
{
|
||||||
|
printf("Interface %.*s:\n", IFNAMSIZ, ifmd->ifmd_name);
|
||||||
|
printf("\tflags: %x\n", ifmd->ifmd_flags);
|
||||||
|
printf("\tpromiscuous listeners: %d\n", ifmd->ifmd_pcount);
|
||||||
|
printf("\tsend queue length: %d\n", ifmd->ifmd_snd_len);
|
||||||
|
printf("\tsend queue max length: %d\n", ifmd->ifmd_snd_maxlen);
|
||||||
|
printf("\tsend queue drops: %d\n", ifmd->ifmd_snd_drops);
|
||||||
|
printf("\ttype: %s\n", iftype(ifmd->ifmd_data.ifi_type));
|
||||||
|
printf("\tphysical: %s\n", ifphys(ifmd->ifmd_data.ifi_type,
|
||||||
|
ifmd->ifmd_data.ifi_physical));
|
||||||
|
printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen);
|
||||||
|
printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen);
|
||||||
|
printf("\treceive quota: %d\n", ifmd->ifmd_data.ifi_recvquota);
|
||||||
|
printf("\ttransmit quota: %d\n", ifmd->ifmd_data.ifi_xmitquota);
|
||||||
|
printf("\tmtu: %lu\n", ifmd->ifmd_data.ifi_mtu);
|
||||||
|
printf("\tmetric: %lu\n", ifmd->ifmd_data.ifi_metric);
|
||||||
|
printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate);
|
||||||
|
printf("\tpackets received: %lu\n", ifmd->ifmd_data.ifi_ipackets);
|
||||||
|
printf("\tinput errors: %lu\n", ifmd->ifmd_data.ifi_ierrors);
|
||||||
|
printf("\tpackets transmitted: %lu\n", ifmd->ifmd_data.ifi_opackets);
|
||||||
|
printf("\toutput errors: %lu\n", ifmd->ifmd_data.ifi_oerrors);
|
||||||
|
printf("\tcollisions: %lu\n", ifmd->ifmd_data.ifi_collisions);
|
||||||
|
printf("\tbytes received: %lu\n", ifmd->ifmd_data.ifi_ibytes);
|
||||||
|
printf("\tbytes transmitted: %lu\n", ifmd->ifmd_data.ifi_obytes);
|
||||||
|
printf("\tmulticasts received: %lu\n", ifmd->ifmd_data.ifi_imcasts);
|
||||||
|
printf("\tmulticasts transmitted: %lu\n", ifmd->ifmd_data.ifi_omcasts);
|
||||||
|
printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops);
|
||||||
|
printf("\tpackets for unknown protocol: %lu\n",
|
||||||
|
ifmd->ifmd_data.ifi_noproto);
|
||||||
|
printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming);
|
||||||
|
printf("\ttransmit timing: %lu usec\n",
|
||||||
|
ifmd->ifmd_data.ifi_xmittiming);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *const if_types[] = {
|
||||||
|
"reserved",
|
||||||
|
"other",
|
||||||
|
"BBN 1822",
|
||||||
|
"HDH 1822",
|
||||||
|
"X.25 DDN",
|
||||||
|
"X.25",
|
||||||
|
"Ethernet",
|
||||||
|
"ISO 8802-3 CSMA/CD",
|
||||||
|
"ISO 8802-4 Token Bus",
|
||||||
|
"ISO 8802-5 Token Ring",
|
||||||
|
"ISO 8802-6 DQDB MAN",
|
||||||
|
"StarLAN",
|
||||||
|
"Proteon proNET-10",
|
||||||
|
"Proteon proNET-80",
|
||||||
|
"HyperChannel",
|
||||||
|
"FDDI",
|
||||||
|
"LAP-B",
|
||||||
|
"SDLC",
|
||||||
|
"T-1",
|
||||||
|
"CEPT",
|
||||||
|
"Basic rate ISDN",
|
||||||
|
"Primary rate ISDN",
|
||||||
|
"Proprietary P2P",
|
||||||
|
"PPP",
|
||||||
|
"Loopback",
|
||||||
|
"ISO CLNP over IP",
|
||||||
|
"Experimental Ethernet",
|
||||||
|
"XNS over IP",
|
||||||
|
"SLIP",
|
||||||
|
"Ultra Technologies",
|
||||||
|
"DS-3",
|
||||||
|
"SMDS",
|
||||||
|
"Frame Relay",
|
||||||
|
"RS-232 serial",
|
||||||
|
"Parallel printer port",
|
||||||
|
"ARCNET",
|
||||||
|
"ARCNET+",
|
||||||
|
"ATM",
|
||||||
|
"MIOX25",
|
||||||
|
"SONET/SDH",
|
||||||
|
"X25PLE",
|
||||||
|
"ISO 8802-2 LLC",
|
||||||
|
"LocalTalk",
|
||||||
|
"SMDSDXI",
|
||||||
|
"Frame Relay DCE",
|
||||||
|
"V.35",
|
||||||
|
"HSSI",
|
||||||
|
"HIPPI",
|
||||||
|
"Generic Modem",
|
||||||
|
"ATM AAL5",
|
||||||
|
"SONETPATH",
|
||||||
|
"SONETVT",
|
||||||
|
"SMDS InterCarrier Interface",
|
||||||
|
"Proprietary virtual interface",
|
||||||
|
"Proprietary multiplexing"
|
||||||
|
};
|
||||||
|
#define NIFTYPES ((sizeof if_types)/(sizeof if_types[0]))
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
iftype(int type)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
|
||||||
|
if (type <= 0 || type > NIFTYPES) {
|
||||||
|
sprintf(buf, "unknown type %d", type);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
return if_types[type];
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
ifphys(int type, int phys)
|
||||||
|
{
|
||||||
|
static char buf[256];
|
||||||
|
|
||||||
|
sprintf(buf, "unknown physical %d", phys);
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
isit(int argc, char **argv, const char *name)
|
||||||
|
{
|
||||||
|
if (argc == 0)
|
||||||
|
return 1;
|
||||||
|
for (argc = 0; argv[argc]; argc++) {
|
||||||
|
if (strncmp(argv[argc], name, IFNAMSIZ) == 0)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static printfcn
|
||||||
|
findlink(int type)
|
||||||
|
{
|
||||||
|
switch(type) {
|
||||||
|
case IFT_ETHER:
|
||||||
|
case IFT_ISO88023:
|
||||||
|
case IFT_STARLAN:
|
||||||
|
return print_1650;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
38
tools/tools/ifinfo/ifinfo.h
Normal file
38
tools/tools/ifinfo/ifinfo.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 1996 Massachusetts Institute of Technology
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software and
|
||||||
|
* its documentation for any purpose and without fee is hereby
|
||||||
|
* granted, provided that both the above copyright notice and this
|
||||||
|
* permission notice appear in all copies, that both the above
|
||||||
|
* copyright notice and this permission notice appear in all
|
||||||
|
* supporting documentation, and that the name of M.I.T. not be used
|
||||||
|
* in advertising or publicity pertaining to distribution of the
|
||||||
|
* software without specific, written prior permission. M.I.T. makes
|
||||||
|
* no representations about the suitability of this software for any
|
||||||
|
* purpose. It is provided "as is" without express or implied
|
||||||
|
* warranty.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
|
||||||
|
* ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||||
|
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
|
||||||
|
* SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
|
||||||
|
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
|
||||||
|
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||||
|
* SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* $Id$
|
||||||
|
*/
|
||||||
|
#ifndef ifinfo_h
|
||||||
|
#define ifinfo_h 1
|
||||||
|
|
||||||
|
typedef void (*printfcn)(const void *, size_t);
|
||||||
|
|
||||||
|
extern void print_1650(const void *, size_t);
|
||||||
|
|
||||||
|
#endif /* ifinfo_h */
|
124
tools/tools/ifinfo/rfc1650.c
Normal file
124
tools/tools/ifinfo/rfc1650.c
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h> /* for PF_LINK */
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
|
||||||
|
#include <err.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sysexits.h>
|
||||||
|
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if_types.h>
|
||||||
|
#include <net/if_mib.h>
|
||||||
|
|
||||||
|
#include "ifinfo.h"
|
||||||
|
|
||||||
|
#define print(msg, var) \
|
||||||
|
if (var) printf("\t" msg ": %lu\n", (u_long)var)
|
||||||
|
|
||||||
|
static void identify_chipset(u_int32_t chipset);
|
||||||
|
|
||||||
|
void
|
||||||
|
print_1650(const void *xmd, size_t len)
|
||||||
|
{
|
||||||
|
const struct ifmib_iso_8802_3 *md = xmd;
|
||||||
|
|
||||||
|
if (len != sizeof *md)
|
||||||
|
warnx("cannot interpret %lu bytes of MIB data", (u_long)len);
|
||||||
|
|
||||||
|
identify_chipset(md->dot3StatsEtherChipSet);
|
||||||
|
print("Alignment errors", md->dot3StatsAlignmentErrors);
|
||||||
|
print("FCS errors", md->dot3StatsFCSErrors);
|
||||||
|
print("Single-collision frames", md->dot3StatsSingleCollisionFrames);
|
||||||
|
print("Multiple-collision frames", md->dot3StatsMultipleCollisionFrames);
|
||||||
|
print("SQE (Heartbeat) test errors", md->dot3StatsSQETestErrors);
|
||||||
|
print("Deferred transmissions", md->dot3StatsDeferredTransmissions);
|
||||||
|
print("Late collisions", md->dot3StatsLateCollisions);
|
||||||
|
print("Excessive collisions", md->dot3StatsExcessiveCollisions);
|
||||||
|
print("Internal transmit errors", md->dot3StatsInternalMacTransmitErrors);
|
||||||
|
print("Carrier sense errors", md->dot3StatsCarrierSenseErrors);
|
||||||
|
print("Frame-too-long errors", md->dot3StatsFrameTooLongs);
|
||||||
|
print("Internal receive errors", md->dot3StatsInternalMacReceiveErrors);
|
||||||
|
print("Missed frames", md->dot3StatsMissedFrames);
|
||||||
|
#define cprint(num) print("Packets with " #num " collisions", \
|
||||||
|
md->dot3StatsCollFrequencies[num - 1])
|
||||||
|
if (md->dot3Compliance >= DOT3COMPLIANCE_COLLS) {
|
||||||
|
cprint(1); cprint(2); cprint(3); cprint(4);
|
||||||
|
cprint(5); cprint(6); cprint(7); cprint(8);
|
||||||
|
cprint(9); cprint(10); cprint(11); cprint(12);
|
||||||
|
cprint(13); cprint(14); cprint(15); cprint(16);
|
||||||
|
}
|
||||||
|
switch(md->dot3Compliance) {
|
||||||
|
case DOT3COMPLIANCE_STATS:
|
||||||
|
printf("\tCompliance: statistics only\n");
|
||||||
|
break;
|
||||||
|
case DOT3COMPLIANCE_COLLS:
|
||||||
|
printf("\tCompliance: statistics and collisions\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *const amd[] = {
|
||||||
|
0, "Am7990", "Am79900", "Am79C940"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const intel[] = {
|
||||||
|
0, "82586", "82596", "82557"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const national[] = {
|
||||||
|
0, "8390", "Sonic"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const fujitsu[] = {
|
||||||
|
0, "86950"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const digital[] = {
|
||||||
|
0, "DC21040", "DC21140", "DC21041", "DC21140A", "DC21142"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *const westerndigital[] = {
|
||||||
|
0, "83C690", "83C790"
|
||||||
|
};
|
||||||
|
|
||||||
|
#define vendor(name, sets) { name, sets, (sizeof sets)/(sizeof sets[0]) }
|
||||||
|
static struct {
|
||||||
|
const char *name;
|
||||||
|
const char *const *chips;
|
||||||
|
size_t len;
|
||||||
|
} chipset_names[] = {
|
||||||
|
{ 0 },
|
||||||
|
vendor("AMD", amd),
|
||||||
|
vendor("Intel", intel),
|
||||||
|
{ 0 },
|
||||||
|
vendor("National Semiconductor", national),
|
||||||
|
vendor("Fujitsu", fujitsu),
|
||||||
|
vendor("Digital", digital),
|
||||||
|
vendor("Western Digital", westerndigital)
|
||||||
|
};
|
||||||
|
|
||||||
|
static void
|
||||||
|
identify_chipset(u_int32_t chipset)
|
||||||
|
{
|
||||||
|
enum dot3Vendors vendor = DOT3CHIPSET_VENDOR(chipset);
|
||||||
|
u_int part = DOT3CHIPSET_PART(chipset);
|
||||||
|
|
||||||
|
printf("\tChipset: ");
|
||||||
|
if (vendor < 1
|
||||||
|
|| vendor >= (sizeof chipset_names)/(sizeof chipset_names[0])
|
||||||
|
|| !chipset_names[vendor].name) {
|
||||||
|
printf("unknown\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s ", chipset_names[vendor].name);
|
||||||
|
if (part < 1 || part >= chipset_names[vendor].len) {
|
||||||
|
printf("unknown\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("%s\n", chipset_names[vendor].chips[part]);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user