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