1 /* 2 * getif.c : get an interface structure 3 * 4 * $FreeBSD$ 5 */ 6 7 #include <sys/types.h> 8 #include <sys/socket.h> 9 #include <sys/ioctl.h> 10 11 #if defined(SUNOS) || defined(SVR4) 12 #include <sys/sockio.h> 13 #endif 14 #ifdef SVR4 15 #include <sys/stropts.h> 16 #endif 17 18 #include <sys/time.h> /* for struct timeval in net/if.h */ 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(u_char *ca, u_char *cb); 40 41 /* Return a pointer to the interface struct for the passed address. */ 42 struct ifreq * 43 getif(int s, struct in_addr *addrp) 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((u_char *)addrp, (u_char *)&(sip->sin_addr)); 88 if (m > maxmatch) { 89 maxmatch = m; 90 ifrmax = ifrq; 91 } 92 #ifndef IFNAMSIZ 93 /* BSD not defined or earlier than 4.3 */ 94 incr = sizeof(*ifrq); 95 #else 96 incr = ifrq->ifr_addr.sa_len + IFNAMSIZ; 97 #endif 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(u_char *ca, u_char *cb) 112 { 113 u_int m = 0; /* count of matching bits */ 114 u_int n = 4; /* bytes left, then bitmask */ 115 116 /* Count matching bytes. */ 117 while (n && (*ca == *cb)) { 118 ca++; 119 cb++; 120 m += 8; 121 n--; 122 } 123 /* Now count matching bits. */ 124 if (n) { 125 n = 0x80; 126 while (n && ((*ca & n) == (*cb & n))) { 127 m++; 128 n >>= 1; 129 } 130 } 131 return (m); 132 } 133 134 /* 135 * Local Variables: 136 * tab-width: 4 137 * c-indent-level: 4 138 * c-argdecl-indent: 4 139 * c-continued-statement-offset: 4 140 * c-continued-brace-offset: -4 141 * c-label-offset: -4 142 * c-brace-offset: 0 143 * End: 144 */ 145