]> git.ipfire.org Git - people/ms/ipfire-3.x.git/blame - dhcp/patches/dhcp-4.2.4-getifaddrs.patch
dhcp: Update to 4.2.4.
[people/ms/ipfire-3.x.git] / dhcp / patches / dhcp-4.2.4-getifaddrs.patch
CommitLineData
444c1184
MT
1diff -up dhcp-4.2.4rc2/common/discover.c.getifaddrs dhcp-4.2.4rc2/common/discover.c
2--- dhcp-4.2.4rc2/common/discover.c.getifaddrs 2012-05-25 18:05:29.592024035 +0200
3+++ dhcp-4.2.4rc2/common/discover.c 2012-05-25 18:12:05.254266023 +0200
4@@ -379,394 +379,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[256];
47- int len;
48- int i;
49-
50- ifaces->fp = fopen("/proc/net/dev", "re");
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) && !access("/proc/net/if_inet6", R_OK)) {
85- ifaces->fp6 = fopen("/proc/net/if_inet6", "re");
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- } else {
96- ifaces->fp6 = NULL;
97- }
98-#endif
99-
100- return 1;
101-}
102-
103-/*
104- * Read our IPv4 interfaces from /proc/net/dev.
105- *
106- * The file looks something like this:
107- *
108- * Inter-| Receive ...
109- * face |bytes packets errs drop fifo frame ...
110- * lo: 1580562 4207 0 0 0 0 ...
111- * eth0: 0 0 0 0 0 0 ...
112- * eth1:1801552440 37895 0 14 0 ...
113- *
114- * We only care about the interface name, which is at the start of
115- * each line.
116- *
117- * We use an ioctl() to get the address and flags for each interface.
118- */
119-static int
120-next_iface4(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
121- char buf[256];
122- int len;
123- char *p;
124- char *name;
125- struct ifreq tmp;
126-
127- /*
128- * Loop exits when we find an interface that has an address, or
129- * when we run out of interfaces.
130- */
131- for (;;) {
132- do {
133- /*
134- * Read the next line in the file.
135- */
136- if (fgets(buf, sizeof(buf), ifaces->fp) == NULL) {
137- if (ferror(ifaces->fp)) {
138- *err = 1;
139- log_error("Error reading interface "
140- "information");
141- } else {
142- *err = 0;
143- }
144- return 0;
145- }
146-
147- /*
148- * Make sure the line is a nice,
149- * newline-terminated line.
150- */
151- len = strlen(buf);
152- if ((len <= 0) || (buf[len-1] != '\n')) {
153- log_error("Bad line reading interface "
154- "information");
155- *err = 1;
156- return 0;
157- }
158-
159- /*
160- * Figure out our name.
161- */
162- p = strrchr(buf, ':');
163- if (p == NULL) {
164- log_error("Bad line reading interface "
165- "information (no colon)");
166- *err = 1;
167- return 0;
168- }
169- *p = '\0';
170- name = buf;
171- while (isspace(*name)) {
172- name++;
173- }
174-
175- /*
176- * Copy our name into our interface structure.
177- */
178- len = p - name;
179- if (len >= sizeof(info->name)) {
180- *err = 1;
181- log_error("Interface name '%s' too long", name);
182- return 0;
183- }
184- strcpy(info->name, name);
185-
186-#ifdef ALIAS_NAMED_PERMUTED
187- /* interface aliases look like "eth0:1" or "wlan1:3" */
188- s = strchr(info->name, ':');
189- if (s != NULL) {
190- *s = '\0';
191- }
192-#endif
193-
194-#ifdef SKIP_DUMMY_INTERFACES
195- } while (strncmp(info->name, "dummy", 5) == 0);
196-#else
197- } while (0);
198-#endif
199-
200- memset(&tmp, 0, sizeof(tmp));
201- strcpy(tmp.ifr_name, name);
202- if (ioctl(ifaces->sock, SIOCGIFADDR, &tmp) < 0) {
203- if (errno == EADDRNOTAVAIL) {
204- continue;
205- }
206- log_error("Error getting interface address "
207- "for '%s'; %m", name);
208- *err = 1;
209- return 0;
210- }
211- memcpy(&info->addr, &tmp.ifr_addr, sizeof(tmp.ifr_addr));
212-
213- memset(&tmp, 0, sizeof(tmp));
214- strcpy(tmp.ifr_name, name);
215- if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
216- log_error("Error getting interface flags for '%s'; %m",
217- name);
218- *err = 1;
219- return 0;
220- }
221- info->flags = tmp.ifr_flags;
222-
223- *err = 0;
224- return 1;
225- }
226-}
227-
228-#ifdef DHCPv6
229-/*
230- * Read our IPv6 interfaces from /proc/net/if_inet6.
231- *
232- * The file looks something like this:
233- *
234- * fe80000000000000025056fffec00008 05 40 20 80 vmnet8
235- * 00000000000000000000000000000001 01 80 10 80 lo
236- * fe80000000000000025056fffec00001 06 40 20 80 vmnet1
237- * 200108881936000202166ffffe497d9b 03 40 00 00 eth1
238- * fe8000000000000002166ffffe497d9b 03 40 20 80 eth1
239- *
240- * We get IPv6 address from the start, the interface name from the end,
241- * and ioctl() to get flags.
242- */
243-static int
244-next_iface6(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
245- char buf[256];
246- int len;
247- char *p;
248- char *name;
249- int i;
250- struct sockaddr_in6 addr;
251- struct ifreq tmp;
252-
253- do {
254- /*
255- * Read the next line in the file.
256- */
257- if (fgets(buf, sizeof(buf), ifaces->fp6) == NULL) {
258- if (ferror(ifaces->fp6)) {
259- *err = 1;
260- log_error("Error reading IPv6 "
261- "interface information");
262- } else {
263- *err = 0;
264- }
265- return 0;
266- }
267-
268- /*
269- * Make sure the line is a nice, newline-terminated line.
270- */
271- len = strlen(buf);
272- if ((len <= 0) || (buf[len-1] != '\n')) {
273- log_error("Bad line reading IPv6 "
274- "interface information");
275- *err = 1;
276- return 0;
277- }
278-
279- /*
280- * Figure out our name.
281- */
282- buf[--len] = '\0';
283- p = strrchr(buf, ' ');
284- if (p == NULL) {
285- log_error("Bad line reading IPv6 interface "
286- "information (no space)");
287- *err = 1;
288- return 0;
289- }
290- name = p+1;
291-
292- /*
293- * Copy our name into our interface structure.
294- */
295- len = strlen(name);
296- if (len >= sizeof(info->name)) {
297- *err = 1;
298- log_error("IPv6 interface name '%s' too long", name);
299- return 0;
300- }
301- strcpy(info->name, name);
302-
303-#ifdef SKIP_DUMMY_INTERFACES
304- } while (strncmp(info->name, "dummy", 5) == 0);
305-#else
306- } while (0);
307-#endif
308-
309- /*
310- * Double-check we start with the IPv6 address.
311- */
312- for (i=0; i<32; i++) {
313- if (!isxdigit(buf[i]) || isupper(buf[i])) {
314- *err = 1;
315- log_error("Bad line reading IPv6 interface address "
316- "for '%s'", name);
317- return 0;
318- }
319- }
320-
321- /*
322- * Load our socket structure.
323- */
324- memset(&addr, 0, sizeof(addr));
325- addr.sin6_family = AF_INET6;
326- for (i=0; i<16; i++) {
327- unsigned char byte;
328- static const char hex[] = "0123456789abcdef";
329- byte = ((index(hex, buf[i * 2]) - hex) << 4) |
330- (index(hex, buf[i * 2 + 1]) - hex);
331- addr.sin6_addr.s6_addr[i] = byte;
332- }
333- memcpy(&info->addr, &addr, sizeof(addr));
334-
335- /*
336- * Get our flags.
337- */
338- memset(&tmp, 0, sizeof(tmp));
339- strcpy(tmp.ifr_name, name);
340- if (ioctl(ifaces->sock, SIOCGIFFLAGS, &tmp) < 0) {
341- log_error("Error getting interface flags for '%s'; %m", name);
342- *err = 1;
343- return 0;
344- }
345- info->flags = tmp.ifr_flags;
346-
347- *err = 0;
348- return 1;
349-}
350-#endif /* DHCPv6 */
351-
352-/*
353- * Retrieve the next interface.
354- *
355- * Returns information in the info structure.
356- * Sets err to 1 if there is an error, otherwise 0.
357- */
358-int
359-next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
360- if (next_iface4(info, err, ifaces)) {
361- return 1;
362- }
363-#ifdef DHCPv6
364- if (!(*err) && ifaces->fp6) {
365- if (local_family == AF_INET6)
366- return next_iface6(info, err, ifaces);
367- }
368-#endif
369- return 0;
370-}
371-
372-/*
373- * End scan of interfaces.
374- */
375-void
376-end_iface_scan(struct iface_conf_list *ifaces) {
377- fclose(ifaces->fp);
378- ifaces->fp = NULL;
379- close(ifaces->sock);
380- ifaces->sock = -1;
381-#ifdef DHCPv6
382- if (local_family == AF_INET6) {
383- if (ifaces->fp6)
384- fclose(ifaces->fp6);
385- ifaces->fp6 = NULL;
386- }
387-#endif
388-}
389 #else
390
391 /*
392 * BSD support
393 * -----------
394 *
395- * FreeBSD, NetBSD, OpenBSD, and OS X all have the getifaddrs()
396+ * FreeBSD, NetBSD, OpenBSD, OS X and Linux all have the getifaddrs()
397 * function.
398 *
399 * The getifaddrs() man page describes the use.
400@@ -814,6 +433,8 @@ begin_iface_scan(struct iface_conf_list
401 */
402 int
403 next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces) {
404+ size_t sa_len = 0;
405+
406 if (ifaces->next == NULL) {
407 *err = 0;
408 return 0;
409@@ -825,8 +446,20 @@ next_iface(struct iface_info *info, int
410 return 0;
411 }
412 strcpy(info->name, ifaces->next->ifa_name);
413- memcpy(&info->addr, ifaces->next->ifa_addr,
414- ifaces->next->ifa_addr->sa_len);
415+
416+ memset(&info->addr, 0 , sizeof(info->addr));
417+
418+ if (ifaces->next->ifa_addr != NULL) {
419+#ifdef HAVE_SA_LEN
420+ sa_len = ifaces->next->ifa_addr->sa_len;
421+#else
422+ if (ifaces->next->ifa_addr->sa_family == AF_INET)
423+ sa_len = sizeof(struct sockaddr_in);
424+ else if (ifaces->next->ifa_addr->sa_family == AF_INET6)
425+ sa_len = sizeof(struct sockaddr_in6);
426+#endif
427+ memcpy(&info->addr, ifaces->next->ifa_addr, sa_len);
428+ }
429 info->flags = ifaces->next->ifa_flags;
430 ifaces->next = ifaces->next->ifa_next;
431 *err = 0;