]> git.ipfire.org Git - ipfire-3.x.git/blob - dhcp/patches/0025-dhcp-getifaddrs.patch
kernel: Disable support for 6RD
[ipfire-3.x.git] / dhcp / patches / 0025-dhcp-getifaddrs.patch
1 diff -up dhcp-4.3.5b1/common/discover.c.getifaddrs dhcp-4.3.5b1/common/discover.c
2 --- dhcp-4.3.5b1/common/discover.c.getifaddrs 2016-09-12 17:10:39.585374741 +0200
3 +++ dhcp-4.3.5b1/common/discover.c 2016-09-12 17:15:56.160628636 +0200
4 @@ -373,392 +373,13 @@ end_iface_scan(struct iface_conf_list *i
5 ifaces->sock = -1;
6 }
7
8 -#elif __linux /* !HAVE_SIOCGLIFCONF */
9 -/*
10 - * Linux support
11 - * -------------
12 - *
13 - * In Linux, we use the /proc pseudo-filesystem to get information
14 - * about interfaces, along with selected ioctl() calls.
15 - *
16 - * Linux low level access is documented in the netdevice man page.
17 - */
18 -
19 -/*
20 - * Structure holding state about the scan.
21 - */
22 -struct iface_conf_list {
23 - int sock; /* file descriptor used to get information */
24 - FILE *fp; /* input from /proc/net/dev */
25 -#ifdef DHCPv6
26 - FILE *fp6; /* input from /proc/net/if_inet6 */
27 -#endif
28 -};
29 -
30 -/*
31 - * Structure used to return information about a specific interface.
32 - */
33 -struct iface_info {
34 - char name[IFNAMSIZ]; /* name of the interface, e.g. "eth0" */
35 - struct sockaddr_storage addr; /* address information */
36 - isc_uint64_t flags; /* interface flags, e.g. IFF_LOOPBACK */
37 -};
38 -
39 -/*
40 - * Start a scan of interfaces.
41 - *
42 - * The iface_conf_list structure maintains state for this process.
43 - */
44 -int
45 -begin_iface_scan(struct iface_conf_list *ifaces) {
46 - char buf[IF_LINE_LENGTH];
47 - int len;
48 - int i;
49 -
50 - ifaces->fp = fopen("/proc/net/dev", "r");
51 - if (ifaces->fp == NULL) {
52 - log_error("Error opening '/proc/net/dev' to list interfaces");
53 - return 0;
54 - }
55 -
56 - /*
57 - * The first 2 lines are header information, so read and ignore them.
58 - */
59 - for (i=0; i<2; i++) {
60 - if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
61 - log_error("Error reading headers from '/proc/net/dev'");
62 - fclose(ifaces->fp);
63 - ifaces->fp = NULL;
64 - return 0;
65 - }
66 - len = strlen(buf);
67 - if ((len <= 0) || (buf[len-1] != '\n')) {
68 - log_error("Bad header line in '/proc/net/dev'");
69 - fclose(ifaces->fp);
70 - ifaces->fp = NULL;
71 - return 0;
72 - }
73 - }
74 -
75 - ifaces->sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
76 - if (ifaces->sock < 0) {
77 - log_error("Error creating socket to list interfaces; %m");
78 - fclose(ifaces->fp);
79 - ifaces->fp = NULL;
80 - return 0;
81 - }
82 -
83 -#ifdef DHCPv6
84 - if (local_family == AF_INET6) {
85 - ifaces->fp6 = fopen("/proc/net/if_inet6", "r");
86 - if (ifaces->fp6 == NULL) {
87 - log_error("Error opening '/proc/net/if_inet6' to "
88 - "list IPv6 interfaces; %m");
89 - close(ifaces->sock);
90 - ifaces->sock = -1;
91 - fclose(ifaces->fp);
92 - ifaces->fp = NULL;
93 - return 0;
94 - }
95 - }
96 -#endif
97 -
98 - return 1;
99 -}
100 -
101 -/*
102 - * Read our IPv4 interfaces from /proc/net/dev.
103 - *
104 - * The file looks something like this:
105 - *
106 - * Inter-| Receive ...
107 - * face |bytes packets errs drop fifo frame ...
108 - * lo: 1580562 4207 0 0 0 0 ...
109 - * eth0: 0 0 0 0 0 0 ...
110 - * eth1:1801552440 37895 0 14 0 ...
111 - *
112 - * We only care about the interface name, which is at the start of
113 - * each line.
114 - *
115 - * We use an ioctl() to get the address and flags for each interface.
116 - */
117 -static int
118 -next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
119 - char buf[IF_LINE_LENGTH];
120 - int len;
121 - char *p;
122 - char *name;
123 - struct ifreq tmp;
124 -
125 - /*
126 - * Loop exits when we find an interface that has an address, or
127 - * when we run out of interfaces.
128 - */
129 - for (;;) {
130 - do {
131 - /*
132 - * Read the next line in the file.
133 - */
134 - if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
135 - if (ferror(ifaces->fp)) {
136 - *err = 1;
137 - log_error("Error reading interface "
138 - "information");
139 - } else {
140 - *err = 0;
141 - }
142 - return 0;
143 - }
144 -
145 - /*
146 - * Make sure the line is a nice,
147 - * newline-terminated line.
148 - */
149 - len = strlen(buf);
150 - if ((len <= 0) || (buf[len-1] != '\n')) {
151 - log_error("Bad line reading interface "
152 - "information");
153 - *err = 1;
154 - return 0;
155 - }
156 -
157 - /*
158 - * Figure out our name.
159 - */
160 - p = strrchr(buf, ':');
161 - if (p == NULL) {
162 - log_error("Bad line reading interface "
163 - "information (no colon)");
164 - *err = 1;
165 - return 0;
166 - }
167 - *p = '\0';
168 - name = buf;
169 - while (isspace(*name)) {
170 - name++;
171 - }
172 -
173 - /*
174 - * Copy our name into our interface structure.
175 - */
176 - len = p - name;
177 - if (len >= sizeof(info->name)) {
178 - *err = 1;
179 - log_error("Interface name '%s' too long", name);
180 - return 0;
181 - }
182 - strncpy(info->name, name, sizeof(info->name) - 1);
183 -
184 -#ifdef ALIAS_NAMED_PERMUTED
185 - /* interface aliases look like "eth0:1" or "wlan1:3" */
186 - s = strchr(info->name, ':');
187 - if (s != NULL) {
188 - *s = '\0';
189 - }
190 -#endif
191 -
192 -#ifdef SKIP_DUMMY_INTERFACES
193 - } while (strncmp(info->name, "dummy", 5) == 0);
194 -#else
195 - } while (0);
196 -#endif
197 -
198 - memset(&tmp, 0, sizeof(tmp));
199 - strncpy(tmp.ifr_name, name, sizeof(tmp.ifr_name) - 1);
200 - if (ioctl(ifaces->sock, SIOCGIFADDR, &tmp) < 0) {
201 - if (errno == EADDRNOTAVAIL) {
202 - continue;
203 - }
204 - log_error("Error getting interface address "
205 - "for '%s'; %m", name);
206 - *err = 1;
207 - return 0;
208 - }
209 - memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr));
210 -
211 - memset(&tmp, 0, sizeof(tmp));
212 - strncpy(tmp.ifr_name, name, sizeof(tmp.ifr_name) - 1);
213 - if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
214 - log_error("Error getting interface flags for '%s'; %m",
215 - name);
216 - *err = 1;
217 - return 0;
218 - }
219 - info->flags = tmp.ifr_flags;
220 -
221 - *err = 0;
222 - return 1;
223 - }
224 -}
225 -
226 -#ifdef DHCPv6
227 -/*
228 - * Read our IPv6 interfaces from /proc/net/if_inet6.
229 - *
230 - * The file looks something like this:
231 - *
232 - * fe80000000000000025056fffec00008 05 40 20 80 vmnet8
233 - * 00000000000000000000000000000001 01 80 10 80 lo
234 - * fe80000000000000025056fffec00001 06 40 20 80 vmnet1
235 - * 200108881936000202166ffffe497d9b 03 40 00 00 eth1
236 - * fe8000000000000002166ffffe497d9b 03 40 20 80 eth1
237 - *
238 - * We get IPv6 address from the start, the interface name from the end,
239 - * and ioctl() to get flags.
240 - */
241 -static int
242 -next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
243 - char buf[IF_LINE_LENGTH];
244 - int len;
245 - char *p;
246 - char *name;
247 - int i;
248 - struct sockaddr_in6 addr;
249 - struct ifreq tmp;
250 -
251 - do {
252 - /*
253 - * Read the next line in the file.
254 - */
255 - if (fgets(buf, sizeof(buf), ifaces->fp6) == NULL) {
256 - if (ferror(ifaces->fp6)) {
257 - *err = 1;
258 - log_error("Error reading IPv6 "
259 - "interface information");
260 - } else {
261 - *err = 0;
262 - }
263 - return 0;
264 - }
265 -
266 - /*
267 - * Make sure the line is a nice, newline-terminated line.
268 - */
269 - len = strlen(buf);
270 - if ((len <= 0) || (buf[len-1] != '\n')) {
271 - log_error("Bad line reading IPv6 "
272 - "interface information");
273 - *err = 1;
274 - return 0;
275 - }
276 -
277 - /*
278 - * Figure out our name.
279 - */
280 - buf[--len] = '\0';
281 - p = strrchr(buf, ' ');
282 - if (p == NULL) {
283 - log_error("Bad line reading IPv6 interface "
284 - "information (no space)");
285 - *err = 1;
286 - return 0;
287 - }
288 - name = p+1;
289 -
290 - /*
291 - * Copy our name into our interface structure.
292 - */
293 - len = strlen(name);
294 - if (len >= sizeof(info->name)) {
295 - *err = 1;
296 - log_error("IPv6 interface name '%s' too long", name);
297 - return 0;
298 - }
299 - strncpy(info->name, name, sizeof(info->name) - 1);
300 -
301 -#ifdef SKIP_DUMMY_INTERFACES
302 - } while (strncmp(info->name, "dummy", 5) == 0);
303 -#else
304 - } while (0);
305 -#endif
306 -
307 - /*
308 - * Double-check we start with the IPv6 address.
309 - */
310 - for (i=0; i<32; i++) {
311 - if (!isxdigit(buf[i]) || isupper(buf[i])) {
312 - *err = 1;
313 - log_error("Bad line reading IPv6 interface address "
314 - "for '%s'", name);
315 - return 0;
316 - }
317 - }
318 -
319 - /*
320 - * Load our socket structure.
321 - */
322 - memset(&addr, 0, sizeof(addr));
323 - addr.sin6_family = AF_INET6;
324 - for (i=0; i<16; i++) {
325 - unsigned char byte;
326 - static const char hex[] = "0123456789abcdef";
327 - byte = ((index(hex, buf[i * 2]) - hex) << 4) |
328 - (index(hex, buf[i * 2 + 1]) - hex);
329 - addr.sin6_addr.s6_addr[i] = byte;
330 - }
331 - memcpy(&info->addr, &addr, sizeof(addr));
332 -
333 - /*
334 - * Get our flags.
335 - */
336 - memset(&tmp, 0, sizeof(tmp));
337 - strncpy(tmp.ifr_name, name, sizeof(tmp.ifr_name) - 1);
338 - if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
339 - log_error("Error getting interface flags for '%s'; %m", name);
340 - *err = 1;
341 - return 0;
342 - }
343 - info->flags = tmp.ifr_flags;
344 -
345 - *err = 0;
346 - return 1;
347 -}
348 -#endif /* DHCPv6 */
349 -
350 -/*
351 - * Retrieve the next interface.
352 - *
353 - * Returns information in the info structure.
354 - * Sets err to 1 if there is an error, otherwise 0.
355 - */
356 -int
357 -next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
358 - memset(info, 0, sizeof(struct iface_info));
359 - if (next_iface4(info, err, ifaces)) {
360 - return 1;
361 - }
362 -#ifdef DHCPv6
363 - if (!(*err)) {
364 - if (local_family == AF_INET6)
365 - return next_iface6(info, err, ifaces);
366 - }
367 -#endif
368 - return 0;
369 -}
370 -
371 -/*
372 - * End scan of interfaces.
373 - */
374 -void
375 -end_iface_scan(struct iface_conf_list *ifaces) {
376 - fclose(ifaces->fp);
377 - ifaces->fp = NULL;
378 - close(ifaces->sock);
379 - ifaces->sock = -1;
380 -#ifdef DHCPv6
381 - if (local_family == AF_INET6) {
382 - fclose(ifaces->fp6);
383 - ifaces->fp6 = NULL;
384 - }
385 -#endif
386 -}
387 #else
388
389 /*
390 * BSD support
391 * -----------
392 *
393 - * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs()
394 + * FreeBSD, NetBSD, OpenBSD, OS X and Linux all have the getifaddrs()
395 * function.
396 *
397 * The getifaddrs() man page describes the use.
398 @@ -806,6 +427,8 @@ begin_iface_scan(struct iface_conf_list
399 */
400 int
401 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
402 + size_t sa_len = 0;
403 +
404 if (ifaces->next == NULL) {
405 *err = 0;
406 return 0;
407 @@ -818,8 +441,20 @@ next_iface(struct iface_info *info, int
408 }
409 memset(info, 0, sizeof(struct iface_info));
410 strncpy(info->name, ifaces->next->ifa_name, sizeof(info->name) - 1);
411 - memcpy(&info->addr, ifaces->next->ifa_addr,
412 - ifaces->next->ifa_addr->sa_len);
413 +
414 + memset(&info->addr, 0 , sizeof(info->addr));
415 +
416 + if (ifaces->next->ifa_addr != NULL) {
417 +#ifdef HAVE_SA_LEN
418 + sa_len = ifaces->next->ifa_addr->sa_len;
419 +#else
420 + if (ifaces->next->ifa_addr->sa_family == AF_INET)
421 + sa_len = sizeof(struct sockaddr_in);
422 + else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
423 + sa_len = sizeof(struct sockaddr_in6);
424 +#endif
425 + memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
426 + }
427 info->flags = ifaces->next->ifa_flags;
428 ifaces->next = ifaces->next->ifa_next;
429 *err = 0;