home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume26 / sysinfo-1.0 / part01 / netif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-10  |  9.6 KB  |  434 lines

  1. /*
  2.  * Copyright (c) 1992 Michael A. Cooper.
  3.  * This software may be freely distributed provided it is not sold for 
  4.  * profit and the author is credited appropriately.
  5.  */
  6.  
  7. #ifndef lint
  8. static char *RCSid = "$Header: /src/common/usc/bin/sysinfo/RCS/netif.c,v 1.18 1992/04/26 23:32:06 mcooper Exp $";
  9. #endif
  10.  
  11. /*
  12.  * $Log: netif.c,v $
  13.  * Revision 1.18  1992/04/26  23:32:06  mcooper
  14.  * Add Copyright notice
  15.  *
  16.  * Revision 1.17  1992/04/17  01:07:59  mcooper
  17.  * More de-linting
  18.  *
  19.  * Revision 1.16  1992/04/16  02:25:39  mcooper
  20.  * Bug fixes, de-linting, and other changes found with CodeCenter.
  21.  *
  22.  * Revision 1.15  1992/03/31  01:55:17  mcooper
  23.  * Use new CheckNlist to check nlist success.
  24.  *
  25.  * Revision 1.14  1992/03/31  00:15:09  mcooper
  26.  * Add error check for nlist.n_type.
  27.  *
  28.  * Revision 1.13  1992/03/28  21:29:38  mcooper
  29.  * Initial port to NeXT.  Only works partially.
  30.  *
  31.  * Revision 1.12  1992/03/22  00:20:10  mcooper
  32.  * Major cleanup and re-org.
  33.  *
  34.  * Revision 1.11  1992/03/09  01:24:05  mcooper
  35.  * Remove HAVE_NIT stuff.
  36.  *
  37.  * Revision 1.10  1992/03/08  23:09:18  mcooper
  38.  * - Cleanup set_macinfo() code to support Ultrix packetfilter.
  39.  * - Pass device down to set_macinfo().
  40.  *
  41.  * Revision 1.9  1992/03/08  04:53:39  mcooper
  42.  * Major re-write to clean things up and add better
  43.  * support for multiple addresses per interface.
  44.  *
  45.  * Revision 1.8  1992/03/05  22:36:35  mcooper
  46.  * Cleanup format.
  47.  *
  48.  * Revision 1.7  1992/03/05  22:11:02  mcooper
  49.  * Cleanup variable declarations.
  50.  *
  51.  * Revision 1.6  1992/02/25  23:36:58  mcooper
  52.  * Remove NULL garbage at end of source file.
  53.  *
  54.  * Revision 1.5  1992/02/25  03:08:43  mcooper
  55.  * Fix gethostbyaddr() stuff for sun3/sun386.
  56.  *
  57.  * Revision 1.4  1992/02/25  00:16:57  mcooper
  58.  * Use new mkmaster_from_devdata().
  59.  *
  60.  * Revision 1.3  1992/02/22  02:20:19  mcooper
  61.  * Major changes to support scanning kernel mainbus and
  62.  * openprom data for device's.
  63.  *
  64.  * Revision 1.2  1992/02/20  04:15:16  mcooper
  65.  * Update known interfaces.
  66.  *
  67.  * Revision 1.1  1992/02/16  22:48:39  mcooper
  68.  * Initial revision
  69.  *
  70.  */
  71.  
  72.  
  73. /*
  74.  * Portions of code found in this file are based on the 4.3BSD 
  75.  * netstat(8) program.
  76.  */
  77.  
  78. /*
  79.  * Network Interface routines
  80.  */
  81.  
  82. #include <stdio.h>
  83. #include "system.h"
  84.  
  85. #include <fcntl.h>
  86. #include <nlist.h>
  87. #include <sys/types.h>
  88. #include <sys/socket.h>
  89. #if    defined(NEED_SOCKIO)
  90. #include <sys/sockio.h>
  91. #endif    /* NEED_SOCKIO */
  92. #include <sys/param.h>
  93. #include <sys/errno.h>
  94. #include <net/if.h>
  95. #include <netinet/in.h>
  96. #include <netinet/in_var.h>
  97. #include <netinet/if_ether.h>
  98. #include <netdb.h>
  99.  
  100. #include "defs.h"
  101.  
  102. /*
  103.  * Network Interface name list
  104.  */
  105. struct nlist NetifNL[] = {
  106. #if    defined(COFF)
  107.     { "ifnet" },
  108. #else
  109.     { "_ifnet" },
  110. #endif    /* COFF */
  111.     { 0 },
  112. };
  113.  
  114. static struct netent            *GetNet();
  115. static void             SetMacInfo();
  116.  
  117. /*
  118.  * Interface Address union
  119.  */
  120. union {
  121.     struct ifaddr     ifa;
  122.     struct in_ifaddr     in;
  123. }                 ifaddr;
  124.  
  125. /*
  126.  * Create a DEVICE for a network interface.
  127.  */
  128. static DEVICE *CreateNetif(FullName, IfNet, DevData, DevDataTab)
  129.     char               *FullName;
  130.     struct ifnet               *IfNet;
  131.     DEVDATA               *DevData;
  132.     DEVDATATAB               *DevDataTab;
  133. {
  134.     DEVICE               *dev;
  135.  
  136.     dev = NewDevice(NULL);
  137.  
  138.     dev->dv_name     = strdup(FullName);
  139.     dev->dv_type     = DT_NETIF;
  140.     dev->dv_unit     = IfNet->if_unit;
  141.     dev->dv_master     = MkMasterFromDevData(DevData);
  142.  
  143. #if    defined(HAVE_IF_VERSION)
  144.     if (IfNet->if_version && IfNet->if_version[0])
  145.     dev->dv_model     = strdup(IfNet->if_version);
  146.     else
  147. #endif    /* HAVE_IF_VERSION */
  148.     dev->dv_model     = DevDataTab->ddt_model;
  149.  
  150.     dev->dv_desc     = DevDataTab->ddt_desc;
  151.  
  152.     return(dev);
  153. }
  154.  
  155. /*
  156.  * Get NETIF for an Internet address
  157.  */
  158. extern NETIF *GetNetifINET(aftab)
  159.     AFTAB               *aftab;
  160. {
  161.     struct in_addr        in_addr;
  162.     struct netent            *np;
  163.     struct hostent            *hp;
  164.     struct sockaddr_in            *sin;
  165.     char               *inet_ntoa();
  166.     NETIF               *ni;
  167.  
  168.     ni = NewNetif(NULL);
  169.  
  170.     np = GetNet(htonl(ifaddr.in.ia_subnet), ifaddr.in.ia_subnetmask);
  171.     in_addr.s_addr = ntohl(ifaddr.in.ia_subnet);
  172.     ni->ni_netaddr = strdup(inet_ntoa(in_addr));
  173.     if (np)
  174.     ni->ni_netname = strdup(np->n_name);
  175.         
  176.     sin = (struct sockaddr_in *)&ifaddr.in.ia_addr;
  177.     ni->ni_hostaddr = strdup(inet_ntoa(sin->sin_addr));
  178.     hp = gethostbyaddr((char *) &(sin->sin_addr),
  179.                sizeof(struct in_addr),
  180.                AF_INET);
  181.     if (hp)
  182.     ni->ni_hostname = strdup(hp->h_name);
  183.  
  184.     if (aftab)
  185.     ni->ni_typename = aftab->af_name;
  186.  
  187.     return(ni);
  188. }
  189.  
  190. /*
  191.  * Get NETIF for an unknown address type
  192.  */
  193. extern NETIF *GetNetifUnknown(aftab)
  194.     AFTAB               *aftab;
  195. {
  196.     NETIF               *ni = NULL;
  197.  
  198.     ni = NewNetif(NULL);
  199.     ni->ni_hostaddr = "<unknown>";
  200.     if (aftab) {
  201.     ni->ni_typename = aftab->af_name;
  202.     }
  203.  
  204.     return(ni);
  205. }
  206.  
  207. /*
  208.  * Get an Address Family table entry
  209.  */
  210. static AFTAB *GetAFTab(type)
  211.     int                type;
  212. {
  213.     extern AFTAB        AFTab[];
  214.     register int        i;
  215.  
  216.     for (i = 0; AFTab[i].af_name; ++i)
  217.     if (AFTab[i].af_type == type)
  218.         return(&AFTab[i]);
  219.  
  220.     return((AFTAB *) NULL);
  221. }
  222.  
  223. /*
  224.  * Get a linked list of NETIF's for each address starting at 'startaddr'.
  225.  */
  226. static NETIF *GetNetifAddrs(kd, startaddr, FullName, Device)
  227.     kvm_t               *kd;
  228.     off_t            startaddr;
  229.     char               *FullName;
  230.     DEVICE               *Device;
  231. {
  232.     u_long            addr;
  233.     NETIF               *base = NULL;
  234.     register NETIF           *ni, *pni;
  235.     AFTAB               *paftab;
  236.  
  237.     for (addr = startaddr; addr; addr = (off_t) ifaddr.ifa.ifa_next) {
  238.     /*
  239.      * Read the ifaddr structure from kernel space
  240.      */
  241.     if (KVM_read(kd, addr, (char *) &ifaddr, sizeof(ifaddr))) {
  242.         Error("cannot read if address");
  243.         continue;
  244.     }
  245.  
  246.     /*
  247.      * Now get and call the Address Family specific routine
  248.      * to extract a NETIF.
  249.      */
  250.     if (paftab = GetAFTab(ifaddr.ifa.ifa_addr.sa_family)) {
  251.         if (ni = (*paftab->af_getnetif)(paftab))
  252.         SetMacInfo(FullName, ni, Device);
  253.     } else {
  254.         if (Debug) Error("Address family %d is not defined.", 
  255.                  ifaddr.ifa.ifa_addr.sa_family);
  256.         continue;
  257.     }
  258.  
  259.     /*
  260.      * Add the new NETIF to the base of the linked list.
  261.      */
  262.     if (base) {
  263.         for (pni = base; pni && pni->ni_nxt; pni = pni->ni_nxt);
  264.         pni->ni_nxt = ni;
  265.     } else {
  266.         base = ni;
  267.     }
  268.     }
  269.  
  270.     return(base);
  271. }
  272.  
  273. /*
  274.  * Find and set the MAC info
  275.  */
  276. static void SetMacInfo(DevName, NetIf, Device)
  277.     char                *DevName;
  278.     NETIF                *NetIf;
  279.     DEVICE               *Device;    /* ARGSUSED */
  280. {
  281. #if    defined(HAVE_NIT)
  282.     extern void         SetMacInfoNIT();
  283.  
  284.     SetMacInfoNIT(DevName, NetIf);
  285.     return;
  286. #endif    /* HAVE_NIT */
  287.  
  288. #if    defined(HAVE_PACKETFILTER)
  289.     extern void            SetMacInfoPacketFilter();
  290.  
  291.     SetMacInfoPacketFilter(DevName, NetIf, Device);
  292.     return;
  293. #endif    /* HAVE_PACKETFILTER */
  294. }
  295.  
  296. /*
  297.  * Return the netent of the network whose address is given.
  298.  * The address is assumed to be that of a net or subnet, not a host.
  299.  */
  300. static struct netent *GetNet(inaddr, mask)
  301.     u_long             inaddr;
  302.     u_long             mask;
  303. {
  304.     u_long             net;
  305.     register u_long         i, netaddr;
  306.     int             subnetshift;
  307.     static struct in_addr     in;
  308.  
  309.     if (in.s_addr = ntohl(inaddr)) {
  310.     i = in.s_addr;
  311.     if (mask == 0) {
  312.         if (IN_CLASSA(i)) {
  313.         mask = IN_CLASSA_NET;
  314.         subnetshift = 8;
  315.         } else if (IN_CLASSB(i)) {
  316.         mask = IN_CLASSB_NET;
  317.         subnetshift = 8;
  318.         } else {
  319.         mask = IN_CLASSC_NET;
  320.         subnetshift = 4;
  321.         }
  322.         /*
  323.          * If there are more bits than the standard mask
  324.          * would suggest, subnets must be in use.
  325.          * Guess at the subnet mask, assuming reasonable
  326.          * width subnet fields.
  327.          */
  328.         while (in.s_addr &~ mask)
  329.         mask = (long)mask >> subnetshift;
  330.     }
  331.     net = in.s_addr & mask;
  332.     while ((mask & 1) == 0)
  333.         mask >>= 1, net >>= 1;
  334.     netaddr = net;
  335.     } else {
  336.     netaddr = inaddr;
  337.     }
  338.  
  339.     return(getnetbyaddr(netaddr, AF_INET));
  340. }
  341.  
  342. /*
  343.  * Query/find network interface devices and add them to devicelist
  344.  */
  345. extern DEVICE *ProbeNetif(name, DevData, DevDataTab)
  346.     char                *name;
  347.     DEVDATA                *DevData;
  348.     DEVDATATAB                *DevDataTab;
  349. {
  350.     DEVICE                *dev = NULL;
  351.     static struct ifnet         ifnet;
  352.     static char         ifname[16], FullName[17];
  353.     register char           *p;
  354.     u_long                 ifnetaddr;
  355.     kvm_t                *kd;
  356.  
  357.     if (!(kd = KVM_open(NetifNL))) {
  358.     if (Debug) Error("Cannot read ifnet from kernel");
  359.     return((DEVICE *) NULL);
  360.     }
  361.  
  362.     /*
  363.      * See if we got a valid entry
  364.      */
  365.     if (CheckNlist(&NetifNL[0]))
  366.     return((DEVICE *) NULL);
  367.  
  368.     /*
  369.      * Read address of ifnet structure from kernel space
  370.      */
  371.     if (KVM_read(kd, NetifNL[0].n_value, (char *) &ifnetaddr, 
  372.          sizeof(ifnetaddr))) {
  373.     if (Debug) Error("kvm_read ifnetaddr failed");
  374.     KVM_close(kd);
  375.     return((DEVICE *) NULL);
  376.     }
  377.  
  378.     /*
  379.      * Read and then check each ifnet entry we found.
  380.      */
  381.     for (; ifnetaddr; ifnetaddr = (off_t) ifnet.if_next) {
  382.     /*
  383.      * Read the ifnet structure
  384.      */
  385.     if (KVM_read(kd, ifnetaddr, (char *)&ifnet, sizeof(ifnet))) {
  386.         if (Debug) Error("kvm_read ifnetaddr ifnet failed");
  387.         continue;
  388.     }
  389.  
  390.     /*
  391.      * Read if_name from kernel space
  392.      */
  393.     if (KVM_read(kd, (u_long)ifnet.if_name, ifname, sizeof(ifname))) {
  394.         if (Debug) Error("kvm_read ifname failed");
  395.         continue;
  396.     }
  397.  
  398.     /*
  399.      * Copy if_name to 'FullName' and add unit number
  400.      */
  401.     strncpy(FullName, ifname, sizeof(ifname));
  402.     p = (char *) index(FullName, C_NULL);
  403.     *p++ = ifnet.if_unit + '0';
  404.     *p = C_NULL;
  405.     ifname[sizeof(ifname)-1] = C_NULL;
  406.  
  407.     /*
  408.      * Check to see if this is the interface we want.
  409.      */
  410.     if (!EQ(FullName, name))
  411.         continue;
  412.  
  413.     /*
  414.      * Create and set device
  415.      */
  416.     dev = CreateNetif(FullName, &ifnet, DevData, DevDataTab);
  417.  
  418.     /*
  419.      * Get and set address info
  420.      */
  421.     if (ifnet.if_addrlist) {
  422.         NETIF            *ni;
  423.  
  424.         if (ni = GetNetifAddrs(kd, (off_t) ifnet.if_addrlist, 
  425.                    FullName, dev))
  426.         dev->dv_devspec = (caddr_t *) ni;
  427.     }
  428.     }
  429.  
  430.     KVM_close(kd);
  431.  
  432.     return(dev);
  433. }
  434.