home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright (c) 1992 Michael A. Cooper.
- * This software may be freely distributed provided it is not sold for
- * profit and the author is credited appropriately.
- */
-
- #ifndef lint
- static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/netif.c,v 1.18 1992/04/26 23:32:06 mcooper Exp $";
- #endif
-
- /*
- * $Log: netif.c,v $
- * Revision 1.18 1992/04/26 23:32:06 mcooper
- * Add Copyright notice
- *
- * Revision 1.17 1992/04/17 01:07:59 mcooper
- * More de-linting
- *
- * Revision 1.16 1992/04/16 02:25:39 mcooper
- * Bug fixes, de-linting, and other changes found with CodeCenter.
- *
- * Revision 1.15 1992/03/31 01:55:17 mcooper
- * Use new CheckNlist to check nlist success.
- *
- * Revision 1.14 1992/03/31 00:15:09 mcooper
- * Add error check for nlist.n_type.
- *
- * Revision 1.13 1992/03/28 21:29:38 mcooper
- * Initial port to NeXT. Only works partially.
- *
- * Revision 1.12 1992/03/22 00:20:10 mcooper
- * Major cleanup and re-org.
- *
- * Revision 1.11 1992/03/09 01:24:05 mcooper
- * Remove HAVE_NIT stuff.
- *
- * Revision 1.10 1992/03/08 23:09:18 mcooper
- * - Cleanup set_macinfo() code to support Ultrix packetfilter.
- * - Pass device down to set_macinfo().
- *
- * Revision 1.9 1992/03/08 04:53:39 mcooper
- * Major re-write to clean things up and add better
- * support for multiple addresses per interface.
- *
- * Revision 1.8 1992/03/05 22:36:35 mcooper
- * Cleanup format.
- *
- * Revision 1.7 1992/03/05 22:11:02 mcooper
- * Cleanup variable declarations.
- *
- * Revision 1.6 1992/02/25 23:36:58 mcooper
- * Remove NULL garbage at end of source file.
- *
- * Revision 1.5 1992/02/25 03:08:43 mcooper
- * Fix gethostbyaddr() stuff for sun3/sun386.
- *
- * Revision 1.4 1992/02/25 00:16:57 mcooper
- * Use new mkmaster_from_devdata().
- *
- * Revision 1.3 1992/02/22 02:20:19 mcooper
- * Major changes to support scanning kernel mainbus and
- * openprom data for device's.
- *
- * Revision 1.2 1992/02/20 04:15:16 mcooper
- * Update known interfaces.
- *
- * Revision 1.1 1992/02/16 22:48:39 mcooper
- * Initial revision
- *
- */
-
-
- /*
- * Portions of code found in this file are based on the 4.3BSD
- * netstat(8) program.
- */
-
- /*
- * Network Interface routines
- */
-
- #include <stdio.h>
- #include "system.h"
-
- #include <fcntl.h>
- #include <nlist.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #if defined(NEED_SOCKIO)
- #include <sys/sockio.h>
- #endif /* NEED_SOCKIO */
- #include <sys/param.h>
- #include <sys/errno.h>
- #include <net/if.h>
- #include <netinet/in.h>
- #include <netinet/in_var.h>
- #include <netinet/if_ether.h>
- #include <netdb.h>
-
- #include "defs.h"
-
- /*
- * Network Interface name list
- */
- struct nlist NetifNL[] = {
- #if defined(COFF)
- { "ifnet" },
- #else
- { "_ifnet" },
- #endif /* COFF */
- { 0 },
- };
-
- static struct netent *GetNet();
- static void SetMacInfo();
-
- /*
- * Interface Address union
- */
- union {
- struct ifaddr ifa;
- struct in_ifaddr in;
- } ifaddr;
-
- /*
- * Create a DEVICE for a network interface.
- */
- static DEVICE *CreateNetif(FullName, IfNet, DevData, DevDataTab)
- char *FullName;
- struct ifnet *IfNet;
- DEVDATA *DevData;
- DEVDATATAB *DevDataTab;
- {
- DEVICE *dev;
-
- dev = NewDevice(NULL);
-
- dev->dv_name = strdup(FullName);
- dev->dv_type = DT_NETIF;
- dev->dv_unit = IfNet->if_unit;
- dev->dv_master = MkMasterFromDevData(DevData);
-
- #if defined(HAVE_IF_VERSION)
- if (IfNet->if_version && IfNet->if_version[0])
- dev->dv_model = strdup(IfNet->if_version);
- else
- #endif /* HAVE_IF_VERSION */
- dev->dv_model = DevDataTab->ddt_model;
-
- dev->dv_desc = DevDataTab->ddt_desc;
-
- return(dev);
- }
-
- /*
- * Get NETIF for an Internet address
- */
- extern NETIF *GetNetifINET(aftab)
- AFTAB *aftab;
- {
- struct in_addr in_addr;
- struct netent *np;
- struct hostent *hp;
- struct sockaddr_in *sin;
- char *inet_ntoa();
- NETIF *ni;
-
- ni = NewNetif(NULL);
-
- np = GetNet(htonl(ifaddr.in.ia_subnet), ifaddr.in.ia_subnetmask);
- in_addr.s_addr = ntohl(ifaddr.in.ia_subnet);
- ni->ni_netaddr = strdup(inet_ntoa(in_addr));
- if (np)
- ni->ni_netname = strdup(np->n_name);
-
- sin = (struct sockaddr_in *)&ifaddr.in.ia_addr;
- ni->ni_hostaddr = strdup(inet_ntoa(sin->sin_addr));
- hp = gethostbyaddr((char *) &(sin->sin_addr),
- sizeof(struct in_addr),
- AF_INET);
- if (hp)
- ni->ni_hostname = strdup(hp->h_name);
-
- if (aftab)
- ni->ni_typename = aftab->af_name;
-
- return(ni);
- }
-
- /*
- * Get NETIF for an unknown address type
- */
- extern NETIF *GetNetifUnknown(aftab)
- AFTAB *aftab;
- {
- NETIF *ni = NULL;
-
- ni = NewNetif(NULL);
- ni->ni_hostaddr = "<unknown>";
- if (aftab) {
- ni->ni_typename = aftab->af_name;
- }
-
- return(ni);
- }
-
- /*
- * Get an Address Family table entry
- */
- static AFTAB *GetAFTab(type)
- int type;
- {
- extern AFTAB AFTab[];
- register int i;
-
- for (i = 0; AFTab[i].af_name; ++i)
- if (AFTab[i].af_type == type)
- return(&AFTab[i]);
-
- return((AFTAB *) NULL);
- }
-
- /*
- * Get a linked list of NETIF's for each address starting at 'startaddr'.
- */
- static NETIF *GetNetifAddrs(kd, startaddr, FullName, Device)
- kvm_t *kd;
- off_t startaddr;
- char *FullName;
- DEVICE *Device;
- {
- u_long addr;
- NETIF *base = NULL;
- register NETIF *ni, *pni;
- AFTAB *paftab;
-
- for (addr = startaddr; addr; addr = (off_t) ifaddr.ifa.ifa_next) {
- /*
- * Read the ifaddr structure from kernel space
- */
- if (KVM_read(kd, addr, (char *) &ifaddr, sizeof(ifaddr))) {
- Error("cannot read if address");
- continue;
- }
-
- /*
- * Now get and call the Address Family specific routine
- * to extract a NETIF.
- */
- if (paftab = GetAFTab(ifaddr.ifa.ifa_addr.sa_family)) {
- if (ni = (*paftab->af_getnetif)(paftab))
- SetMacInfo(FullName, ni, Device);
- } else {
- if (Debug) Error("Address family %d is not defined.",
- ifaddr.ifa.ifa_addr.sa_family);
- continue;
- }
-
- /*
- * Add the new NETIF to the base of the linked list.
- */
- if (base) {
- for (pni = base; pni && pni->ni_nxt; pni = pni->ni_nxt);
- pni->ni_nxt = ni;
- } else {
- base = ni;
- }
- }
-
- return(base);
- }
-
- /*
- * Find and set the MAC info
- */
- static void SetMacInfo(DevName, NetIf, Device)
- char *DevName;
- NETIF *NetIf;
- DEVICE *Device; /* ARGSUSED */
- {
- #if defined(HAVE_NIT)
- extern void SetMacInfoNIT();
-
- SetMacInfoNIT(DevName, NetIf);
- return;
- #endif /* HAVE_NIT */
-
- #if defined(HAVE_PACKETFILTER)
- extern void SetMacInfoPacketFilter();
-
- SetMacInfoPacketFilter(DevName, NetIf, Device);
- return;
- #endif /* HAVE_PACKETFILTER */
- }
-
- /*
- * Return the netent of the network whose address is given.
- * The address is assumed to be that of a net or subnet, not a host.
- */
- static struct netent *GetNet(inaddr, mask)
- u_long inaddr;
- u_long mask;
- {
- u_long net;
- register u_long i, netaddr;
- int subnetshift;
- static struct in_addr in;
-
- if (in.s_addr = ntohl(inaddr)) {
- i = in.s_addr;
- if (mask == 0) {
- if (IN_CLASSA(i)) {
- mask = IN_CLASSA_NET;
- subnetshift = 8;
- } else if (IN_CLASSB(i)) {
- mask = IN_CLASSB_NET;
- subnetshift = 8;
- } else {
- mask = IN_CLASSC_NET;
- subnetshift = 4;
- }
- /*
- * If there are more bits than the standard mask
- * would suggest, subnets must be in use.
- * Guess at the subnet mask, assuming reasonable
- * width subnet fields.
- */
- while (in.s_addr &~ mask)
- mask = (long)mask >> subnetshift;
- }
- net = in.s_addr & mask;
- while ((mask & 1) == 0)
- mask >>= 1, net >>= 1;
- netaddr = net;
- } else {
- netaddr = inaddr;
- }
-
- return(getnetbyaddr(netaddr, AF_INET));
- }
-
- /*
- * Query/find network interface devices and add them to devicelist
- */
- extern DEVICE *ProbeNetif(name, DevData, DevDataTab)
- char *name;
- DEVDATA *DevData;
- DEVDATATAB *DevDataTab;
- {
- DEVICE *dev = NULL;
- static struct ifnet ifnet;
- static char ifname[16], FullName[17];
- register char *p;
- u_long ifnetaddr;
- kvm_t *kd;
-
- if (!(kd = KVM_open(NetifNL))) {
- if (Debug) Error("Cannot read ifnet from kernel");
- return((DEVICE *) NULL);
- }
-
- /*
- * See if we got a valid entry
- */
- if (CheckNlist(&NetifNL[0]))
- return((DEVICE *) NULL);
-
- /*
- * Read address of ifnet structure from kernel space
- */
- if (KVM_read(kd, NetifNL[0].n_value, (char *) &ifnetaddr,
- sizeof(ifnetaddr))) {
- if (Debug) Error("kvm_read ifnetaddr failed");
- KVM_close(kd);
- return((DEVICE *) NULL);
- }
-
- /*
- * Read and then check each ifnet entry we found.
- */
- for (; ifnetaddr; ifnetaddr = (off_t) ifnet.if_next) {
- /*
- * Read the ifnet structure
- */
- if (KVM_read(kd, ifnetaddr, (char *)&ifnet, sizeof(ifnet))) {
- if (Debug) Error("kvm_read ifnetaddr ifnet failed");
- continue;
- }
-
- /*
- * Read if_name from kernel space
- */
- if (KVM_read(kd, (u_long)ifnet.if_name, ifname, sizeof(ifname))) {
- if (Debug) Error("kvm_read ifname failed");
- continue;
- }
-
- /*
- * Copy if_name to 'FullName' and add unit number
- */
- strncpy(FullName, ifname, sizeof(ifname));
- p = (char *) index(FullName, C_NULL);
- *p++ = ifnet.if_unit + '0';
- *p = C_NULL;
- ifname[sizeof(ifname)-1] = C_NULL;
-
- /*
- * Check to see if this is the interface we want.
- */
- if (!EQ(FullName, name))
- continue;
-
- /*
- * Create and set device
- */
- dev = CreateNetif(FullName, &ifnet, DevData, DevDataTab);
-
- /*
- * Get and set address info
- */
- if (ifnet.if_addrlist) {
- NETIF *ni;
-
- if (ni = GetNetifAddrs(kd, (off_t) ifnet.if_addrlist,
- FullName, dev))
- dev->dv_devspec = (caddr_t *) ni;
- }
- }
-
- KVM_close(kd);
-
- return(dev);
- }
-