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