home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / bootp-2.4.0 / part01 / getif.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-22  |  3.0 KB  |  146 lines

  1. /*
  2.  * getif.c : get an interface structure
  3.  */
  4.  
  5. #include <sys/types.h>
  6. #include <sys/socket.h>
  7. #include <sys/ioctl.h>
  8.  
  9. #if defined(SUNOS) || defined(SVR4)
  10. #include <sys/sockio.h>
  11. #endif
  12. #ifdef    SVR4
  13. #include <sys/stropts.h>
  14. #endif
  15.  
  16. #include <net/if.h>                /* for struct ifreq */
  17. #include <netinet/in.h>
  18.  
  19. #ifndef    NO_UNISTD
  20. #include <unistd.h>
  21. #endif
  22. #include <syslog.h>
  23. #include <errno.h>
  24. #include <assert.h>
  25.  
  26. #include "getif.h"
  27. #include "report.h"
  28.  
  29. #ifdef    __bsdi__
  30. #define BSD 43
  31. #endif
  32.  
  33. static struct ifreq ifreq[10];    /* Holds interface configuration */
  34. static struct ifconf ifconf;    /* points to ifreq */
  35.  
  36. static int nmatch();
  37.  
  38. /* Return a pointer to the interface struct for the passed address. */
  39. struct ifreq *
  40. getif(s, addrp)
  41.     int s;                        /* socket file descriptor */
  42.     struct in_addr *addrp;        /* destination address on interface */
  43. {
  44.     int maxmatch;
  45.     int len, m, incr;
  46.     struct ifreq *ifrq, *ifrmax;
  47.     struct sockaddr_in *sip;
  48.     char *p;
  49.  
  50.     /* If no address was supplied, just return NULL. */
  51.     if (!addrp)
  52.         return (struct ifreq *) 0;
  53.  
  54.     /* Get the interface config if not done already. */
  55.     if (ifconf.ifc_len == 0) {
  56. #ifdef    SVR4
  57.         /*
  58.          * SysVr4 returns garbage if you do this the obvious way!
  59.          * This one took a while to figure out... -gwr
  60.          */
  61.         struct strioctl ioc;
  62.         ioc.ic_cmd = SIOCGIFCONF;
  63.         ioc.ic_timout = 0;
  64.         ioc.ic_len = sizeof(ifreq);
  65.         ioc.ic_dp = (char *) ifreq;
  66.         m = ioctl(s, I_STR, (char *) &ioc);
  67.         ifconf.ifc_len = ioc.ic_len;
  68.         ifconf.ifc_req = ifreq;
  69. #else    /* SVR4 */
  70.         ifconf.ifc_len = sizeof(ifreq);
  71.         ifconf.ifc_req = ifreq;
  72.         m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf);
  73. #endif    /* SVR4 */
  74.         if ((m < 0) || (ifconf.ifc_len <= 0)) {
  75.             report(LOG_ERR, "ioctl SIOCGIFCONF");
  76.             return (struct ifreq *) 0;
  77.         }
  78.     }
  79.     maxmatch = 7;                /* this many bits or less... */
  80.     ifrmax = (struct ifreq *) 0;/* ... is not a valid match  */
  81.     p = (char *) ifreq;
  82.     len = ifconf.ifc_len;
  83.     while (len > 0) {
  84.         ifrq = (struct ifreq *) p;
  85.         sip = (struct sockaddr_in *) &ifrq->ifr_addr;
  86.         m = nmatch(addrp, &(sip->sin_addr));
  87.         if (m > maxmatch) {
  88.             maxmatch = m;
  89.             ifrmax = ifrq;
  90.         }
  91.         /* XXX - Could this be just #ifndef IFNAMSIZ instead? -gwr */
  92. #if (BSD - 0) < 43
  93.         /* BSD not defined or earlier than 4.3 */
  94.         incr = sizeof(*ifrq);
  95. #else /* NetBSD */
  96.         incr = ifrq->ifr_addr.sa_len + IFNAMSIZ;
  97. #endif /* NetBSD */
  98.  
  99.         p += incr;
  100.         len -= incr;
  101.     }
  102.  
  103.     return ifrmax;
  104. }
  105.  
  106. /*
  107.  * Return the number of leading bits matching in the
  108.  * internet addresses supplied.
  109.  */
  110. static int
  111. nmatch(ca, cb)
  112.     u_char *ca, *cb;            /* ptrs to IP address, network order */
  113. {
  114.     u_int m = 0;                /* count of matching bits */
  115.     u_int n = 4;                /* bytes left, then bitmask */
  116.  
  117.     /* Count matching bytes. */
  118.     while (n && (*ca == *cb)) {
  119.         ca++;
  120.         cb++;
  121.         m += 8;
  122.         n--;
  123.     }
  124.     /* Now count matching bits. */
  125.     if (n) {
  126.         n = 0x80;
  127.         while (n && ((*ca & n) == (*cb & n))) {
  128.             m++;
  129.             n >>= 1;
  130.         }
  131.     }
  132.     return (m);
  133. }
  134.  
  135. /*
  136.  * Local Variables:
  137.  * tab-width: 4
  138.  * c-indent-level: 4
  139.  * c-argdecl-indent: 4
  140.  * c-continued-statement-offset: 4
  141.  * c-continued-brace-offset: -4
  142.  * c-label-offset: -4
  143.  * c-brace-offset: 0
  144.  * End:
  145.  */
  146.