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