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