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