Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/libexec/bootpd/getif.c
34822 views
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 <sys/time.h> /* for struct timeval in net/if.h */
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(u_char *ca, u_char *cb);
38
39
/* Return a pointer to the interface struct for the passed address. */
40
struct ifreq *
41
getif(int s, struct in_addr *addrp)
42
{
43
int maxmatch;
44
int len, m, incr;
45
struct ifreq *ifrq, *ifrmax;
46
struct sockaddr_in *sip;
47
char *p;
48
49
/* If no address was supplied, just return NULL. */
50
if (!addrp)
51
return (struct ifreq *) 0;
52
53
/* Get the interface config if not done already. */
54
if (ifconf.ifc_len == 0) {
55
#ifdef SVR4
56
/*
57
* SysVr4 returns garbage if you do this the obvious way!
58
* This one took a while to figure out... -gwr
59
*/
60
struct strioctl ioc;
61
ioc.ic_cmd = SIOCGIFCONF;
62
ioc.ic_timout = 0;
63
ioc.ic_len = sizeof(ifreq);
64
ioc.ic_dp = (char *) ifreq;
65
m = ioctl(s, I_STR, (char *) &ioc);
66
ifconf.ifc_len = ioc.ic_len;
67
ifconf.ifc_req = ifreq;
68
#else /* SVR4 */
69
ifconf.ifc_len = sizeof(ifreq);
70
ifconf.ifc_req = ifreq;
71
m = ioctl(s, SIOCGIFCONF, (caddr_t) & ifconf);
72
#endif /* SVR4 */
73
if ((m < 0) || (ifconf.ifc_len <= 0)) {
74
report(LOG_ERR, "ioctl SIOCGIFCONF");
75
return (struct ifreq *) 0;
76
}
77
}
78
maxmatch = 7; /* this many bits or less... */
79
ifrmax = (struct ifreq *) 0;/* ... is not a valid match */
80
p = (char *) ifreq;
81
len = ifconf.ifc_len;
82
while (len > 0) {
83
ifrq = (struct ifreq *) p;
84
sip = (struct sockaddr_in *) &ifrq->ifr_addr;
85
m = nmatch((u_char *)addrp, (u_char *)&(sip->sin_addr));
86
if (m > maxmatch) {
87
maxmatch = m;
88
ifrmax = ifrq;
89
}
90
#ifndef IFNAMSIZ
91
/* BSD not defined or earlier than 4.3 */
92
incr = sizeof(*ifrq);
93
#else
94
incr = ifrq->ifr_addr.sa_len + IFNAMSIZ;
95
#endif
96
97
p += incr;
98
len -= incr;
99
}
100
101
return ifrmax;
102
}
103
104
/*
105
* Return the number of leading bits matching in the
106
* internet addresses supplied.
107
*/
108
static int
109
nmatch(u_char *ca, u_char *cb)
110
{
111
u_int m = 0; /* count of matching bits */
112
u_int n = 4; /* bytes left, then bitmask */
113
114
/* Count matching bytes. */
115
while (n && (*ca == *cb)) {
116
ca++;
117
cb++;
118
m += 8;
119
n--;
120
}
121
/* Now count matching bits. */
122
if (n) {
123
n = 0x80;
124
while (n && ((*ca & n) == (*cb & n))) {
125
m++;
126
n >>= 1;
127
}
128
}
129
return (m);
130
}
131
132
/*
133
* Local Variables:
134
* tab-width: 4
135
* c-indent-level: 4
136
* c-argdecl-indent: 4
137
* c-continued-statement-offset: 4
138
* c-continued-brace-offset: -4
139
* c-label-offset: -4
140
* c-brace-offset: 0
141
* End:
142
*/
143
144