1 /*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2015 Roy Marples <roy@marples.name>
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <asm/types.h> /* Needed for 2.4 kernels */
29
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <sys/ioctl.h>
33 #include <sys/param.h>
34
35 #include <linux/if_addr.h>
36 #include <linux/if_link.h>
37 #include <linux/if_packet.h>
38 #include <linux/filter.h>
39 #include <linux/netlink.h>
40 #include <linux/rtnetlink.h>
41
42 #include <arpa/inet.h>
43 #include <net/if.h>
44 #include <netinet/if_ether.h>
45 #include <netinet/in_systm.h>
46 #include <netinet/in.h>
47 #include <net/route.h>
48
49 /* Support older kernels */
50 #ifndef IFLA_WIRELESS
51 # define IFLA_WIRELESS (IFLA_MASTER + 1)
52 #endif
53
54 /* Linux has these in an enum and there is just no way to work
55 * out of they exist at compile time. Silly silly silly. */
56 #define IFLA_AF_SPEC 26
57 #define IFLA_INET6_ADDR_GEN_MODE 8
58 #define IN6_ADDR_GEN_MODE_NONE 1
59
60 /* For some reason, glibc doesn't include newer flags from linux/if.h
61 * However, we cannot include linux/if.h directly as it conflicts
62 * with the glibc version. D'oh! */
63 #ifndef IFF_LOWER_UP
64 #define IFF_LOWER_UP 0x10000 /* driver signals L1 up */
65 #endif
66
67 #include <errno.h>
68 #include <fcntl.h>
69 #include <ctype.h>
70 #include <stddef.h>
71 #include <stdio.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <time.h>
75 #include <unistd.h>
76
77 #include "config.h"
78 #include "common.h"
79 #include "dev.h"
80 #include "dhcp.h"
81 #include "if.h"
82 #include "ipv4.h"
83 #include "ipv6.h"
84 #include "ipv6nd.h"
85
86 #ifdef HAVE_NL80211_H
87 #include <linux/genetlink.h>
88 #include <linux/nl80211.h>
89 #endif
90 int if_getssid_wext(const char *ifname, uint8_t *ssid);
91
92 #define bpf_insn sock_filter
93 #define BPF_SKIPTYPE
94 #define BPF_ETHCOOK -ETH_HLEN
95 #define BPF_WHOLEPACKET 0x0fffffff /* work around buggy LPF filters */
96
97 #include "bpf-filter.h"
98
99 /* Broadcast address for IPoIB */
100 static const uint8_t ipv4_bcast_addr[] = {
101 0x00, 0xff, 0xff, 0xff,
102 0xff, 0x12, 0x40, 0x1b, 0x00, 0x00, 0x00, 0x00,
103 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff
104 };
105
106 #define PROC_INET6 "/proc/net/if_inet6"
107 #define PROC_PROMOTE "/proc/sys/net/ipv4/conf/%s/promote_secondaries"
108 #define SYS_LAYER2 "/sys/class/net/%s/device/layer2"
109
110 static const char *mproc =
111 #if defined(__alpha__)
112 "system type"
113 #elif defined(__arm__)
114 "Hardware"
115 #elif defined(__avr32__)
116 "cpu family"
117 #elif defined(__bfin__)
118 "BOARD Name"
119 #elif defined(__cris__)
120 "cpu model"
121 #elif defined(__frv__)
122 "System"
123 #elif defined(__i386__) || defined(__x86_64__)
124 "vendor_id"
125 #elif defined(__ia64__)
126 "vendor"
127 #elif defined(__hppa__)
128 "model"
129 #elif defined(__m68k__)
130 "MMU"
131 #elif defined(__mips__)
132 "system type"
133 #elif defined(__powerpc__) || defined(__powerpc64__)
134 "machine"
135 #elif defined(__s390__) || defined(__s390x__)
136 "Manufacturer"
137 #elif defined(__sh__)
138 "machine"
139 #elif defined(sparc) || defined(__sparc__)
140 "cpu"
141 #elif defined(__vax__)
142 "cpu"
143 #else
144 NULL
145 #endif
146 ;
147
148 int
if_machinearch(char * str,size_t len)149 if_machinearch(char *str, size_t len)
150 {
151 FILE *fp;
152 char buf[256];
153
154 if (mproc == NULL) {
155 errno = EINVAL;
156 return -1;
157 }
158
159 fp = fopen("/proc/cpuinfo", "r");
160 if (fp == NULL)
161 return -1;
162
163 while (fscanf(fp, "%255s : ", buf) != EOF) {
164 if (strncmp(buf, mproc, strlen(mproc)) == 0 &&
165 fscanf(fp, "%255s", buf) == 1)
166 {
167 fclose(fp);
168 return snprintf(str, len, ":%s", buf);
169 }
170 }
171 fclose(fp);
172 errno = ESRCH;
173 return -1;
174 }
175
176 static int
check_proc_int(const char * path)177 check_proc_int(const char *path)
178 {
179 FILE *fp;
180 int i;
181
182 fp = fopen(path, "r");
183 if (fp == NULL)
184 return -1;
185 if (fscanf(fp, "%d", &i) != 1)
186 i = -1;
187 fclose(fp);
188 return i;
189 }
190
191 static ssize_t
write_path(const char * path,const char * val)192 write_path(const char *path, const char *val)
193 {
194 FILE *fp;
195 ssize_t r;
196
197 fp = fopen(path, "w");
198 if (fp == NULL)
199 return -1;
200 r = fprintf(fp, "%s\n", val);
201 fclose(fp);
202 return r;
203 }
204
205 int
if_init(struct interface * ifp)206 if_init(struct interface *ifp)
207 {
208 char path[sizeof(PROC_PROMOTE) + IF_NAMESIZE];
209 int n;
210
211 /* We enable promote_secondaries so that we can do this
212 * add 192.168.1.2/24
213 * add 192.168.1.3/24
214 * del 192.168.1.2/24
215 * and the subnet mask moves onto 192.168.1.3/24
216 * This matches the behaviour of BSD which makes coding dhcpcd
217 * a little easier as there's just one behaviour. */
218 snprintf(path, sizeof(path), PROC_PROMOTE, ifp->name);
219 n = check_proc_int(path);
220 if (n == -1)
221 return errno == ENOENT ? 0 : -1;
222 if (n == 1)
223 return 0;
224 return write_path(path, "1") == -1 ? -1 : 0;
225 }
226
227 int
if_conf(struct interface * ifp)228 if_conf(struct interface *ifp)
229 {
230 char path[sizeof(SYS_LAYER2) + IF_NAMESIZE];
231 int n;
232
233 /* Some qeth setups require the use of the broadcast flag. */
234 snprintf(path, sizeof(path), SYS_LAYER2, ifp->name);
235 n = check_proc_int(path);
236 if (n == -1)
237 return errno == ENOENT ? 0 : -1;
238 if (n == 0)
239 ifp->options->options |= DHCPCD_BROADCAST;
240 return 0;
241 }
242
243 /* XXX work out Virtal Interface Masters */
244 int
if_vimaster(__unused const char * ifname)245 if_vimaster(__unused const char *ifname)
246 {
247
248 return 0;
249 }
250
251 static int
_open_link_socket(struct sockaddr_nl * nl,int flags,int protocol)252 _open_link_socket(struct sockaddr_nl *nl, int flags, int protocol)
253 {
254 int fd;
255
256 #ifdef SOCK_CLOEXEC
257 if (flags)
258 flags = SOCK_CLOEXEC;
259 fd = socket(AF_NETLINK, SOCK_RAW | flags, protocol);
260 if (fd == -1)
261 return -1;
262 #else
263 fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
264 if (fd == -1)
265 return -1;
266 if (flags &&
267 (flags = fcntl(fd, F_GETFD, 0)) == -1 ||
268 fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
269 {
270 close(fd);
271 return -1;
272 }
273 #endif
274 nl->nl_family = AF_NETLINK;
275 if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1) {
276 close(fd);
277 return -1;
278 }
279 return fd;
280 }
281
282 int
if_openlinksocket(void)283 if_openlinksocket(void)
284 {
285 struct sockaddr_nl snl;
286
287 memset(&snl, 0, sizeof(snl));
288 snl.nl_groups = RTMGRP_LINK;
289
290 #ifdef INET
291 snl.nl_groups |= RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
292 #endif
293 #ifdef INET6
294 snl.nl_groups |= RTMGRP_IPV6_ROUTE | RTMGRP_IPV6_IFADDR | RTMGRP_NEIGH;
295 #endif
296
297 return _open_link_socket(&snl, 1, NETLINK_ROUTE);
298 }
299
300 static int
err_netlink(struct nlmsghdr * nlm)301 err_netlink(struct nlmsghdr *nlm)
302 {
303 struct nlmsgerr *err;
304 size_t len;
305
306 if (nlm->nlmsg_type != NLMSG_ERROR)
307 return 0;
308 len = nlm->nlmsg_len - sizeof(*nlm);
309 if (len < sizeof(*err)) {
310 errno = EBADMSG;
311 return -1;
312 }
313 err = (struct nlmsgerr *)NLMSG_DATA(nlm);
314 if (err->error == 0)
315 return (int)len;
316 errno = -err->error;
317 return -1;
318 }
319
320 static int
get_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,int fd,int flags,int (* callback)(struct dhcpcd_ctx *,struct interface *,struct nlmsghdr *))321 get_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp, int fd, int flags,
322 int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
323 {
324 char *buf = NULL, *nbuf;
325 ssize_t bytes;
326 size_t buflen;
327 struct nlmsghdr *nlm;
328 struct sockaddr_nl nladdr;
329 socklen_t nladdr_len;
330 int r;
331
332 buflen = 0;
333 r = -1;
334 for (;;) {
335 bytes = recv(fd, NULL, 0,
336 flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC);
337 if (bytes == -1)
338 goto eexit;
339 if ((size_t)bytes == buflen) {
340 /* Support kernels older than 2.6.22 */
341 if (bytes == 0)
342 bytes = 512;
343 else
344 bytes *= 2;
345 }
346 if (buflen < (size_t)bytes) {
347 /* Alloc 1 more so we work with older kernels */
348 buflen = (size_t)bytes + 1;
349 nbuf = realloc(buf, buflen);
350 if (nbuf == NULL)
351 goto eexit;
352 buf = nbuf;
353 }
354 nladdr_len = sizeof(nladdr);
355 bytes = recvfrom(fd, buf, buflen, flags,
356 (struct sockaddr *)&nladdr, &nladdr_len);
357 if (bytes == -1 || bytes == 0)
358 goto eexit;
359
360 /* Check sender */
361 if (nladdr_len != sizeof(nladdr)) {
362 errno = EINVAL;
363 goto eexit;
364 }
365 /* Ignore message if it is not from kernel */
366 if (nladdr.nl_pid != 0) {
367 r = 0;
368 continue;
369 }
370
371 for (nlm = (struct nlmsghdr *)(void *)buf;
372 nlm && NLMSG_OK(nlm, (size_t)bytes);
373 nlm = NLMSG_NEXT(nlm, bytes))
374 {
375 r = err_netlink(nlm);
376 if (r == -1)
377 goto eexit;
378 if (r)
379 continue;
380 if (callback) {
381 r = callback(ctx, ifp, nlm);
382 if (r != 0)
383 goto eexit;
384 }
385 }
386 }
387
388 eexit:
389 free(buf);
390 return r;
391 }
392
393 #ifdef INET
394 static int
if_copyrt(struct dhcpcd_ctx * ctx,struct rt * rt,struct nlmsghdr * nlm)395 if_copyrt(struct dhcpcd_ctx *ctx, struct rt *rt, struct nlmsghdr *nlm)
396 {
397 size_t len;
398 struct rtmsg *rtm;
399 struct rtattr *rta;
400 struct in_addr prefsrc;
401
402 len = nlm->nlmsg_len - sizeof(*nlm);
403 if (len < sizeof(*rtm)) {
404 errno = EBADMSG;
405 return -1;
406 }
407 rtm = (struct rtmsg *)NLMSG_DATA(nlm);
408 if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET)
409 return -1;
410
411 memset(rt, 0, sizeof(*rt));
412 if (rtm->rtm_type == RTN_UNREACHABLE)
413 rt->flags = RTF_REJECT;
414 if (rtm->rtm_scope == RT_SCOPE_HOST)
415 rt->flags |= RTF_HOST;
416
417 prefsrc.s_addr = INADDR_ANY;
418 rta = (struct rtattr *)RTM_RTA(rtm);
419 len = RTM_PAYLOAD(nlm);
420 while (RTA_OK(rta, len)) {
421 switch (rta->rta_type) {
422 case RTA_DST:
423 memcpy(&rt->dest.s_addr, RTA_DATA(rta),
424 sizeof(rt->dest.s_addr));
425 break;
426 case RTA_GATEWAY:
427 memcpy(&rt->gate.s_addr, RTA_DATA(rta),
428 sizeof(rt->gate.s_addr));
429 break;
430 case RTA_PREFSRC:
431 memcpy(&prefsrc.s_addr, RTA_DATA(rta),
432 sizeof(prefsrc.s_addr));
433 break;
434 case RTA_OIF:
435 rt->iface = if_findindex(ctx->ifaces,
436 *(unsigned int *)RTA_DATA(rta));
437 break;
438 case RTA_PRIORITY:
439 rt->metric = *(unsigned int *)RTA_DATA(rta);
440 break;
441 }
442 rta = RTA_NEXT(rta, len);
443 }
444
445 inet_cidrtoaddr(rtm->rtm_dst_len, &rt->net);
446 if (rt->iface == NULL && prefsrc.s_addr != INADDR_ANY) {
447 struct ipv4_addr *ap;
448
449 /* For some reason the default route comes back with the
450 * loopback interface in RTA_OIF? Lets find it by
451 * preferred source address */
452 if ((ap = ipv4_findaddr(ctx, &prefsrc)))
453 rt->iface = ap->iface;
454 }
455 return 0;
456 }
457 #endif
458
459 #ifdef INET6
460 static int
if_copyrt6(struct dhcpcd_ctx * ctx,struct rt6 * rt,struct nlmsghdr * nlm)461 if_copyrt6(struct dhcpcd_ctx *ctx, struct rt6 *rt, struct nlmsghdr *nlm)
462 {
463 size_t len;
464 struct rtmsg *rtm;
465 struct rtattr *rta;
466
467 len = nlm->nlmsg_len - sizeof(*nlm);
468 if (len < sizeof(*rtm)) {
469 errno = EBADMSG;
470 return -1;
471 }
472 rtm = (struct rtmsg *)NLMSG_DATA(nlm);
473 if (rtm->rtm_table != RT_TABLE_MAIN || rtm->rtm_family != AF_INET6)
474 return -1;
475
476 memset(rt, 0, sizeof(*rt));
477 if (rtm->rtm_type == RTN_UNREACHABLE)
478 rt->flags = RTF_REJECT;
479 if (rtm->rtm_scope == RT_SCOPE_HOST)
480 rt->flags |= RTF_HOST;
481 ipv6_mask(&rt->net, rtm->rtm_dst_len);
482
483 rta = (struct rtattr *)RTM_RTA(rtm);
484 len = RTM_PAYLOAD(nlm);
485 while (RTA_OK(rta, len)) {
486 switch (rta->rta_type) {
487 case RTA_DST:
488 memcpy(&rt->dest.s6_addr, RTA_DATA(rta),
489 sizeof(rt->dest.s6_addr));
490 break;
491 case RTA_GATEWAY:
492 memcpy(&rt->gate.s6_addr, RTA_DATA(rta),
493 sizeof(rt->gate.s6_addr));
494 break;
495 case RTA_OIF:
496 rt->iface = if_findindex(ctx->ifaces,
497 *(unsigned int *)RTA_DATA(rta));
498 break;
499 case RTA_PRIORITY:
500 rt->metric = *(unsigned int *)RTA_DATA(rta);
501 break;
502 }
503 rta = RTA_NEXT(rta, len);
504 }
505
506 return 0;
507 }
508 #endif
509
510 /* Work out the maximum pid size */
511 static inline long long
get_max_pid_t()512 get_max_pid_t()
513 {
514
515 if (sizeof(pid_t) == sizeof(short)) return SHRT_MAX;
516 if (sizeof(pid_t) == sizeof(int)) return INT_MAX;
517 if (sizeof(pid_t) == sizeof(long)) return LONG_MAX;
518 if (sizeof(pid_t) == sizeof(long long)) return LLONG_MAX;
519 abort();
520 }
521
522 static int
link_route(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)523 link_route(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
524 struct nlmsghdr *nlm)
525 {
526 size_t len;
527 struct rtmsg *rtm;
528 int cmd;
529 #ifdef INET
530 struct rt rt;
531 #endif
532 #ifdef INET6
533 struct rt6 rt6;
534 #endif
535 switch (nlm->nlmsg_type) {
536 case RTM_NEWROUTE:
537 cmd = RTM_ADD;
538 break;
539 case RTM_DELROUTE:
540 cmd = RTM_DELETE;
541 break;
542 default:
543 return 0;
544 }
545
546 len = nlm->nlmsg_len - sizeof(*nlm);
547 if (len < sizeof(*rtm)) {
548 errno = EBADMSG;
549 return -1;
550 }
551
552 /* Ignore messages generated by us.
553 * For some reason we get messages generated by us
554 * with a very large value in nlmsg_pid that seems to be
555 * sequentially changing. Is there a better test for this? */
556 if (nlm->nlmsg_pid > get_max_pid_t())
557 return 1;
558
559 rtm = NLMSG_DATA(nlm);
560 switch (rtm->rtm_family) {
561 #ifdef INET
562 case AF_INET:
563 if (if_copyrt(ctx, &rt, nlm) == 0)
564 ipv4_handlert(ctx, cmd, &rt);
565 break;
566 #endif
567 #ifdef INET6
568 case AF_INET6:
569 if (if_copyrt6(ctx, &rt6, nlm) == 0)
570 ipv6_handlert(ctx, cmd, &rt6);
571 break;
572 #endif
573 }
574
575 return 0;
576 }
577
578 static int
link_addr(struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)579 link_addr(struct dhcpcd_ctx *ctx, struct interface *ifp, struct nlmsghdr *nlm)
580 {
581 size_t len;
582 struct rtattr *rta;
583 struct ifaddrmsg *ifa;
584 #ifdef INET
585 struct in_addr addr, net, dest;
586 #endif
587 #ifdef INET6
588 struct in6_addr addr6;
589 #endif
590
591 if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR)
592 return 0;
593
594 len = nlm->nlmsg_len - sizeof(*nlm);
595 if (len < sizeof(*ifa)) {
596 errno = EBADMSG;
597 return -1;
598 }
599 ifa = NLMSG_DATA(nlm);
600 if ((ifp = if_findindex(ctx->ifaces, ifa->ifa_index)) == NULL) {
601 /* We don't know about the interface the address is for
602 * so it's not really an error */
603 return 1;
604 }
605 rta = (struct rtattr *)IFA_RTA(ifa);
606 len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
607 switch (ifa->ifa_family) {
608 #ifdef INET
609 case AF_INET:
610 addr.s_addr = dest.s_addr = INADDR_ANY;
611 dest.s_addr = INADDR_ANY;
612 inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
613 while (RTA_OK(rta, len)) {
614 switch (rta->rta_type) {
615 case IFA_ADDRESS:
616 if (ifp->flags & IFF_POINTOPOINT) {
617 memcpy(&dest.s_addr, RTA_DATA(rta),
618 sizeof(addr.s_addr));
619 }
620 break;
621 case IFA_LOCAL:
622 memcpy(&addr.s_addr, RTA_DATA(rta),
623 sizeof(addr.s_addr));
624 break;
625 }
626 rta = RTA_NEXT(rta, len);
627 }
628 ipv4_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
629 &addr, &net, &dest, ifa->ifa_flags);
630 break;
631 #endif
632 #ifdef INET6
633 case AF_INET6:
634 memset(&addr6, 0, sizeof(addr6));
635 while (RTA_OK(rta, len)) {
636 switch (rta->rta_type) {
637 case IFA_ADDRESS:
638 memcpy(&addr6.s6_addr, RTA_DATA(rta),
639 sizeof(addr6.s6_addr));
640 break;
641 }
642 rta = RTA_NEXT(rta, len);
643 }
644 ipv6_handleifa(ctx, nlm->nlmsg_type, NULL, ifp->name,
645 &addr6, ifa->ifa_prefixlen, ifa->ifa_flags);
646 break;
647 #endif
648 }
649 return 0;
650 }
651
652 static uint8_t
l2addr_len(unsigned short if_type)653 l2addr_len(unsigned short if_type)
654 {
655
656 switch (if_type) {
657 case ARPHRD_ETHER: /* FALLTHROUGH */
658 case ARPHRD_IEEE802: /*FALLTHROUGH */
659 case ARPHRD_IEEE80211:
660 return 6;
661 case ARPHRD_IEEE1394:
662 return 8;
663 case ARPHRD_INFINIBAND:
664 return 20;
665 }
666
667 /* Impossible */
668 return 0;
669 }
670
671 static int
handle_rename(struct dhcpcd_ctx * ctx,unsigned int ifindex,const char * ifname)672 handle_rename(struct dhcpcd_ctx *ctx, unsigned int ifindex, const char *ifname)
673 {
674 struct interface *ifp;
675
676 TAILQ_FOREACH(ifp, ctx->ifaces, next) {
677 if (ifp->index == ifindex && strcmp(ifp->name, ifname)) {
678 dhcpcd_handleinterface(ctx, -1, ifp->name);
679 /* Let dev announce the interface for renaming */
680 if (!dev_listening(ctx))
681 dhcpcd_handleinterface(ctx, 1, ifname);
682 return 1;
683 }
684 }
685 return 0;
686 }
687
688 #ifdef INET6
689 static int
link_neigh(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)690 link_neigh(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
691 struct nlmsghdr *nlm)
692 {
693 struct ndmsg *r;
694 struct rtattr *rta;
695 size_t len;
696 struct in6_addr addr6;
697 int flags;
698
699 if (nlm->nlmsg_type != RTM_NEWNEIGH && nlm->nlmsg_type != RTM_DELNEIGH)
700 return 0;
701 if (nlm->nlmsg_len < sizeof(*r))
702 return -1;
703
704 r = NLMSG_DATA(nlm);
705 rta = (struct rtattr *)RTM_RTA(r);
706 len = RTM_PAYLOAD(nlm);
707 if (r->ndm_family == AF_INET6) {
708 flags = 0;
709 if (r->ndm_flags & NTF_ROUTER)
710 flags |= IPV6ND_ROUTER;
711 if (nlm->nlmsg_type == RTM_NEWNEIGH &&
712 r->ndm_state &
713 (NUD_REACHABLE | NUD_STALE | NUD_DELAY | NUD_PROBE |
714 NUD_PERMANENT))
715 flags |= IPV6ND_REACHABLE;
716 memset(&addr6, 0, sizeof(addr6));
717 while (RTA_OK(rta, len)) {
718 switch (rta->rta_type) {
719 case NDA_DST:
720 memcpy(&addr6.s6_addr, RTA_DATA(rta),
721 sizeof(addr6.s6_addr));
722 break;
723 }
724 rta = RTA_NEXT(rta, len);
725 }
726 ipv6nd_neighbour(ctx, &addr6, flags);
727 }
728
729 return 0;
730 }
731 #endif
732
733 static int
link_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)734 link_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
735 struct nlmsghdr *nlm)
736 {
737 int r;
738 size_t len;
739 struct rtattr *rta, *hwaddr;
740 struct ifinfomsg *ifi;
741 char ifn[IF_NAMESIZE + 1];
742
743 r = link_route(ctx, ifp, nlm);
744 if (r != 0)
745 return r;
746 r = link_addr(ctx, ifp, nlm);
747 if (r != 0)
748 return r;
749 #ifdef INET6
750 r = link_neigh(ctx, ifp, nlm);
751 if (r != 0)
752 return r;
753 #endif
754
755 if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
756 return 0;
757 len = nlm->nlmsg_len - sizeof(*nlm);
758 if ((size_t)len < sizeof(*ifi)) {
759 errno = EBADMSG;
760 return -1;
761 }
762 ifi = NLMSG_DATA(nlm);
763 if (ifi->ifi_flags & IFF_LOOPBACK)
764 return 0;
765 rta = (struct rtattr *)(void *)((char *)ifi +NLMSG_ALIGN(sizeof(*ifi)));
766 len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
767 *ifn = '\0';
768 hwaddr = NULL;
769
770 while (RTA_OK(rta, len)) {
771 switch (rta->rta_type) {
772 case IFLA_WIRELESS:
773 /* Ignore wireless messages */
774 if (nlm->nlmsg_type == RTM_NEWLINK &&
775 ifi->ifi_change == 0)
776 return 0;
777 break;
778 case IFLA_IFNAME:
779 strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
780 break;
781 case IFLA_ADDRESS:
782 hwaddr = rta;
783 break;
784 }
785 rta = RTA_NEXT(rta, len);
786 }
787
788 if (nlm->nlmsg_type == RTM_DELLINK) {
789 dhcpcd_handleinterface(ctx, -1, ifn);
790 return 0;
791 }
792
793 /* Virtual interfaces may not get a valid hardware address
794 * at this point.
795 * To trigger a valid hardware address pickup we need to pretend
796 * that that don't exist until they have one. */
797 if (ifi->ifi_flags & IFF_MASTER && !hwaddr) {
798 dhcpcd_handleinterface(ctx, -1, ifn);
799 return 0;
800 }
801
802 /* Check for interface name change */
803 if (handle_rename(ctx, (unsigned int)ifi->ifi_index, ifn))
804 return 0;
805
806 /* Check for a new interface */
807 if ((ifp = if_find(ctx->ifaces, ifn)) == NULL) {
808 /* If are listening to a dev manager, let that announce
809 * the interface rather than the kernel. */
810 if (dev_listening(ctx) < 1)
811 dhcpcd_handleinterface(ctx, 1, ifn);
812 return 0;
813 }
814
815 /* Re-read hardware address and friends */
816 if (!(ifi->ifi_flags & IFF_UP) && hwaddr) {
817 uint8_t l;
818
819 l = l2addr_len(ifi->ifi_type);
820 if (hwaddr->rta_len == RTA_LENGTH(l))
821 dhcpcd_handlehwaddr(ctx, ifn, RTA_DATA(hwaddr), l);
822 }
823
824 dhcpcd_handlecarrier(ctx,
825 ifi->ifi_flags & IFF_RUNNING ? LINK_UP : LINK_DOWN,
826 ifi->ifi_flags, ifn);
827 return 0;
828 }
829
830 int
if_managelink(struct dhcpcd_ctx * ctx)831 if_managelink(struct dhcpcd_ctx *ctx)
832 {
833
834 return get_netlink(ctx, NULL,
835 ctx->link_fd, MSG_DONTWAIT, &link_netlink);
836 }
837
838 static int
send_netlink(struct dhcpcd_ctx * ctx,struct interface * ifp,int protocol,struct nlmsghdr * hdr,int (* callback)(struct dhcpcd_ctx *,struct interface *,struct nlmsghdr *))839 send_netlink(struct dhcpcd_ctx *ctx, struct interface *ifp,
840 int protocol, struct nlmsghdr *hdr,
841 int (*callback)(struct dhcpcd_ctx *, struct interface *, struct nlmsghdr *))
842 {
843 int s, r;
844 struct sockaddr_nl snl;
845 struct iovec iov;
846 struct msghdr msg;
847 static unsigned int seq;
848
849 memset(&snl, 0, sizeof(snl));
850 if ((s = _open_link_socket(&snl, 0, protocol)) == -1)
851 return -1;
852 memset(&iov, 0, sizeof(iov));
853 iov.iov_base = hdr;
854 iov.iov_len = hdr->nlmsg_len;
855 memset(&msg, 0, sizeof(msg));
856 msg.msg_name = &snl;
857 msg.msg_namelen = sizeof(snl);
858 msg.msg_iov = &iov;
859 msg.msg_iovlen = 1;
860 /* Request a reply */
861 hdr->nlmsg_flags |= NLM_F_ACK;
862 hdr->nlmsg_seq = ++seq;
863
864 if (sendmsg(s, &msg, 0) != -1)
865 r = get_netlink(ctx, ifp, s, 0, callback);
866 else
867 r = -1;
868 close(s);
869 return r;
870 }
871
872 #define NLMSG_TAIL(nmsg) \
873 ((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len)))
874
875 static int
add_attr_l(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,const void * data,unsigned short alen)876 add_attr_l(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
877 const void *data, unsigned short alen)
878 {
879 unsigned short len = (unsigned short)RTA_LENGTH(alen);
880 struct rtattr *rta;
881
882 if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
883 errno = ENOBUFS;
884 return -1;
885 }
886
887 rta = NLMSG_TAIL(n);
888 rta->rta_type = type;
889 rta->rta_len = len;
890 if (alen)
891 memcpy(RTA_DATA(rta), data, alen);
892 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
893
894 return 0;
895 }
896
897 static int
add_attr_32(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint32_t data)898 add_attr_32(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
899 uint32_t data)
900 {
901 unsigned short len = RTA_LENGTH(sizeof(data));
902 struct rtattr *rta;
903
904 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
905 errno = ENOBUFS;
906 return -1;
907 }
908
909 rta = NLMSG_TAIL(n);
910 rta->rta_type = type;
911 rta->rta_len = len;
912 memcpy(RTA_DATA(rta), &data, sizeof(data));
913 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
914
915 return 0;
916 }
917
918 #ifdef HAVE_NL80211_H
919 static struct nlattr *
nla_next(struct nlattr * nla,size_t * rem)920 nla_next(struct nlattr *nla, size_t *rem)
921 {
922
923 *rem -= NLA_ALIGN(nla->nla_len);
924 return (struct nlattr *)(void *)((char *)nla + NLA_ALIGN(nla->nla_len));
925 }
926
927 #define NLA_TYPE(nla) ((nla)->nla_type & NLA_TYPE_MASK)
928 #define NLA_LEN(nla) (unsigned int)((nla)->nla_len - NLA_HDRLEN)
929 #define NLA_OK(nla, rem) \
930 ((rem) >= sizeof(struct nlattr) && \
931 (nla)->nla_len >= sizeof(struct nlattr) && \
932 (nla)->nla_len <= rem)
933 #define NLA_DATA(nla) ((char *)(nla) + NLA_HDRLEN)
934 #define NLA_FOR_EACH_ATTR(pos, head, len, rem) \
935 for (pos = head, rem = len; NLA_OK(pos, rem); pos = nla_next(pos, &(rem)))
936
937 struct nlmg
938 {
939 struct nlmsghdr hdr;
940 struct genlmsghdr ghdr;
941 char buffer[64];
942 };
943
944 static int
nla_put_32(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint32_t data)945 nla_put_32(struct nlmsghdr *n, unsigned short maxlen,
946 unsigned short type, uint32_t data)
947 {
948 unsigned short len;
949 struct nlattr *nla;
950
951 len = NLA_ALIGN(NLA_HDRLEN + sizeof(data));
952 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
953 errno = ENOBUFS;
954 return -1;
955 }
956
957 nla = (struct nlattr *)NLMSG_TAIL(n);
958 nla->nla_type = type;
959 nla->nla_len = len;
960 memcpy(NLA_DATA(nla), &data, sizeof(data));
961 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
962
963 return 0;
964 }
965
966 static int
nla_put_string(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,const char * data)967 nla_put_string(struct nlmsghdr *n, unsigned short maxlen,
968 unsigned short type, const char *data)
969 {
970 struct nlattr *nla;
971 size_t len, sl;
972
973 sl = strlen(data) + 1;
974 len = NLA_ALIGN(NLA_HDRLEN + sl);
975 if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
976 errno = ENOBUFS;
977 return -1;
978 }
979
980 nla = (struct nlattr *)NLMSG_TAIL(n);
981 nla->nla_type = type;
982 nla->nla_len = (unsigned short)len;
983 memcpy(NLA_DATA(nla), data, sl);
984 n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + (unsigned short)len;
985 return 0;
986 }
987
988 static int
gnl_parse(struct nlmsghdr * nlm,struct nlattr * tb[],int maxtype)989 gnl_parse(struct nlmsghdr *nlm, struct nlattr *tb[], int maxtype)
990 {
991 struct genlmsghdr *ghdr;
992 struct nlattr *head, *nla;
993 size_t len, rem;
994 int type;
995
996 memset(tb, 0, sizeof(*tb) * ((unsigned int)maxtype + 1));
997 ghdr = NLMSG_DATA(nlm);
998 head = (struct nlattr *)(void *)((char *) ghdr + GENL_HDRLEN);
999 len = nlm->nlmsg_len - GENL_HDRLEN - NLMSG_HDRLEN;
1000 NLA_FOR_EACH_ATTR(nla, head, len, rem) {
1001 type = NLA_TYPE(nla);
1002 if (type > maxtype)
1003 continue;
1004 tb[type] = nla;
1005 }
1006 return 0;
1007 }
1008
1009 static int
_gnl_getfamily(__unused struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1010 _gnl_getfamily(__unused struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1011 struct nlmsghdr *nlm)
1012 {
1013 struct nlattr *tb[CTRL_ATTR_FAMILY_ID + 1];
1014 uint16_t family;
1015
1016 if (gnl_parse(nlm, tb, CTRL_ATTR_FAMILY_ID) == -1)
1017 return -1;
1018 if (tb[CTRL_ATTR_FAMILY_ID] == NULL) {
1019 errno = ENOENT;
1020 return -1;
1021 }
1022 family = *(uint16_t *)(void *)NLA_DATA(tb[CTRL_ATTR_FAMILY_ID]);
1023 return (int)family;
1024 }
1025
1026 static int
gnl_getfamily(struct dhcpcd_ctx * ctx,const char * name)1027 gnl_getfamily(struct dhcpcd_ctx *ctx, const char *name)
1028 {
1029 struct nlmg nlm;
1030
1031 memset(&nlm, 0, sizeof(nlm));
1032 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr));
1033 nlm.hdr.nlmsg_type = GENL_ID_CTRL;
1034 nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1035 nlm.ghdr.cmd = CTRL_CMD_GETFAMILY;
1036 nlm.ghdr.version = 1;
1037 if (nla_put_string(&nlm.hdr, sizeof(nlm),
1038 CTRL_ATTR_FAMILY_NAME, name) == -1)
1039 return -1;
1040 return send_netlink(ctx, NULL, NETLINK_GENERIC, &nlm.hdr,
1041 &_gnl_getfamily);
1042 }
1043
1044 static int
_if_getssid(__unused struct dhcpcd_ctx * ctx,struct interface * ifp,struct nlmsghdr * nlm)1045 _if_getssid(__unused struct dhcpcd_ctx *ctx, struct interface *ifp,
1046 struct nlmsghdr *nlm)
1047 {
1048 struct nlattr *tb[NL80211_ATTR_SSID + 1];
1049
1050 if (gnl_parse(nlm, tb, NL80211_ATTR_SSID) == -1)
1051 return -1;
1052
1053 if (tb[NL80211_ATTR_SSID] == NULL) {
1054 /* If the SSID is not found then it means that
1055 * we're not associated to an AP. */
1056 ifp->ssid_len = 0;
1057 goto out;
1058 }
1059
1060 ifp->ssid_len = NLA_LEN(tb[NL80211_ATTR_SSID]);
1061 if (ifp->ssid_len > sizeof(ifp->ssid)) {
1062 errno = ENOBUFS;
1063 ifp->ssid_len = 0;
1064 return -1;
1065 }
1066 memcpy(ifp->ssid, NLA_DATA(tb[NL80211_ATTR_SSID]), ifp->ssid_len);
1067
1068 out:
1069 ifp->ssid[ifp->ssid_len] = '\0';
1070 return (int)ifp->ssid_len;
1071 }
1072
1073 static int
if_getssid_nl80211(struct interface * ifp)1074 if_getssid_nl80211(struct interface *ifp)
1075 {
1076 int family;
1077 struct nlmg nlm;
1078
1079 errno = 0;
1080 family = gnl_getfamily(ifp->ctx, "nl80211");
1081 if (family == -1)
1082 return -1;
1083 memset(&nlm, 0, sizeof(nlm));
1084 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct genlmsghdr));
1085 nlm.hdr.nlmsg_type = (unsigned short)family;
1086 nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1087 nlm.ghdr.cmd = NL80211_CMD_GET_INTERFACE;
1088 nla_put_32(&nlm.hdr, sizeof(nlm), NL80211_ATTR_IFINDEX, ifp->index);
1089
1090 return send_netlink(ifp->ctx, ifp,
1091 NETLINK_GENERIC, &nlm.hdr, &_if_getssid);
1092 }
1093 #endif
1094
1095 int
if_getssid(struct interface * ifp)1096 if_getssid(struct interface *ifp)
1097 {
1098 int r;
1099
1100 r = if_getssid_wext(ifp->name, ifp->ssid);
1101 if (r != -1)
1102 ifp->ssid_len = (unsigned int)r;
1103 #ifdef HAVE_NL80211_H
1104 else if (r == -1)
1105 r = if_getssid_nl80211(ifp);
1106 #endif
1107 return r;
1108 }
1109
1110 struct nlma
1111 {
1112 struct nlmsghdr hdr;
1113 struct ifaddrmsg ifa;
1114 char buffer[64];
1115 };
1116
1117 struct nlmr
1118 {
1119 struct nlmsghdr hdr;
1120 struct rtmsg rt;
1121 char buffer[256];
1122 };
1123
1124 #ifdef INET
1125 const char *if_pfname = "Packet Socket";
1126
1127 int
if_openrawsocket(struct interface * ifp,uint16_t protocol)1128 if_openrawsocket(struct interface *ifp, uint16_t protocol)
1129 {
1130 int s;
1131 union sockunion {
1132 struct sockaddr sa;
1133 struct sockaddr_ll sll;
1134 struct sockaddr_storage ss;
1135 } su;
1136 struct sock_fprog pf;
1137 #ifdef PACKET_AUXDATA
1138 int n;
1139 #endif
1140
1141 #ifdef SOCK_CLOEXEC
1142 if ((s = socket(PF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
1143 htons(protocol))) == -1)
1144 return -1;
1145 #else
1146 int flags;
1147
1148 if ((s = socket(PF_PACKET, SOCK_DGRAM, htons(protocol))) == -1)
1149 return -1;
1150 if ((flags = fcntl(s, F_GETFD, 0)) == -1 ||
1151 fcntl(s, F_SETFD, flags | FD_CLOEXEC) == -1)
1152 {
1153 close(s);
1154 return -1;
1155 }
1156 if ((flags = fcntl(s, F_GETFL, 0)) == -1 ||
1157 fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
1158 {
1159 close(s);
1160 return -1;
1161 }
1162 #endif
1163 /* Install the DHCP filter */
1164 memset(&pf, 0, sizeof(pf));
1165 if (protocol == ETHERTYPE_ARP) {
1166 pf.filter = UNCONST(arp_bpf_filter);
1167 pf.len = arp_bpf_filter_len;
1168 } else {
1169 pf.filter = UNCONST(dhcp_bpf_filter);
1170 pf.len = dhcp_bpf_filter_len;
1171 }
1172 if (setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, &pf, sizeof(pf)) != 0)
1173 goto eexit;
1174 #ifdef PACKET_AUXDATA
1175 n = 1;
1176 if (setsockopt(s, SOL_PACKET, PACKET_AUXDATA, &n, sizeof(n)) != 0) {
1177 if (errno != ENOPROTOOPT)
1178 goto eexit;
1179 }
1180 #endif
1181
1182 memset(&su, 0, sizeof(su));
1183 su.sll.sll_family = PF_PACKET;
1184 su.sll.sll_protocol = htons(protocol);
1185 su.sll.sll_ifindex = (int)ifp->index;
1186 if (bind(s, &su.sa, sizeof(su.sll)) == -1)
1187 goto eexit;
1188 return s;
1189
1190 eexit:
1191 close(s);
1192 return -1;
1193 }
1194
1195 ssize_t
if_sendrawpacket(const struct interface * ifp,uint16_t protocol,const void * data,size_t len,const uint8_t * dest_hw_addr)1196 if_sendrawpacket(const struct interface *ifp, uint16_t protocol,
1197 const void *data, size_t len, const uint8_t *dest_hw_addr)
1198 {
1199 const struct dhcp_state *state;
1200 union sockunion {
1201 struct sockaddr sa;
1202 struct sockaddr_ll sll;
1203 struct sockaddr_storage ss;
1204 } su;
1205 int fd;
1206
1207 memset(&su, 0, sizeof(su));
1208 su.sll.sll_family = AF_PACKET;
1209 su.sll.sll_protocol = htons(protocol);
1210 su.sll.sll_ifindex = (int)ifp->index;
1211 su.sll.sll_hatype = htons(ifp->family);
1212 su.sll.sll_halen = (unsigned char)ifp->hwlen;
1213 if (ifp->family == ARPHRD_INFINIBAND)
1214 memcpy(&su.sll.sll_addr,
1215 &ipv4_bcast_addr, sizeof(ipv4_bcast_addr));
1216 else {
1217 if (dest_hw_addr)
1218 memcpy(&su.sll.sll_addr, dest_hw_addr, ifp->hwlen);
1219 else
1220 memset(&su.sll.sll_addr, 0xff, ifp->hwlen);
1221 }
1222 state = D_CSTATE(ifp);
1223 if (protocol == ETHERTYPE_ARP)
1224 fd = state->arp_fd;
1225 else
1226 fd = state->raw_fd;
1227
1228 return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll));
1229 }
1230
1231 ssize_t
if_readrawpacket(struct interface * ifp,uint16_t protocol,void * data,size_t len,int * flags)1232 if_readrawpacket(struct interface *ifp, uint16_t protocol,
1233 void *data, size_t len, int *flags)
1234 {
1235 struct iovec iov = {
1236 .iov_base = data,
1237 .iov_len = len,
1238 };
1239 struct msghdr msg = {
1240 .msg_iov = &iov,
1241 .msg_iovlen = 1,
1242 };
1243 struct dhcp_state *state;
1244 #ifdef PACKET_AUXDATA
1245 unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
1246 struct cmsghdr *cmsg;
1247 struct tpacket_auxdata *aux;
1248 #endif
1249
1250 ssize_t bytes;
1251 int fd = -1;
1252
1253 #ifdef PACKET_AUXDATA
1254 msg.msg_control = cmsgbuf;
1255 msg.msg_controllen = sizeof(cmsgbuf);
1256 #endif
1257
1258 state = D_STATE(ifp);
1259 if (protocol == ETHERTYPE_ARP)
1260 fd = state->arp_fd;
1261 else
1262 fd = state->raw_fd;
1263 bytes = recvmsg(fd, &msg, 0);
1264 if (bytes == -1)
1265 return -1;
1266 *flags = RAW_EOF; /* We only ever read one packet */
1267 if (bytes) {
1268 #ifdef PACKET_AUXDATA
1269 for (cmsg = CMSG_FIRSTHDR(&msg);
1270 cmsg;
1271 cmsg = CMSG_NXTHDR(&msg, cmsg))
1272 {
1273 if (cmsg->cmsg_level == SOL_PACKET &&
1274 cmsg->cmsg_type == PACKET_AUXDATA) {
1275 aux = (void *)CMSG_DATA(cmsg);
1276 if (aux->tp_status & TP_STATUS_CSUMNOTREADY)
1277 *flags |= RAW_PARTIALCSUM;
1278 }
1279 }
1280 #endif
1281 }
1282 return bytes;
1283 }
1284
1285 int
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)1286 if_address(const struct interface *iface,
1287 const struct in_addr *address, const struct in_addr *netmask,
1288 const struct in_addr *broadcast, int action)
1289 {
1290 struct nlma nlm;
1291 int retval = 0;
1292
1293 memset(&nlm, 0, sizeof(nlm));
1294 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1295 nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1296 if (action >= 0) {
1297 nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
1298 nlm.hdr.nlmsg_type = RTM_NEWADDR;
1299 } else
1300 nlm.hdr.nlmsg_type = RTM_DELADDR;
1301 nlm.ifa.ifa_index = iface->index;
1302 nlm.ifa.ifa_family = AF_INET;
1303 nlm.ifa.ifa_prefixlen = inet_ntocidr(*netmask);
1304 /* This creates the aliased interface */
1305 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
1306 iface->alias, (unsigned short)(strlen(iface->alias) + 1));
1307 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
1308 &address->s_addr, sizeof(address->s_addr));
1309 if (action >= 0 && broadcast)
1310 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_BROADCAST,
1311 &broadcast->s_addr, sizeof(broadcast->s_addr));
1312
1313 if (send_netlink(iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1314 retval = -1;
1315 return retval;
1316 }
1317
1318 int
if_route(unsigned char cmd,const struct rt * rt)1319 if_route(unsigned char cmd, const struct rt *rt)
1320 {
1321 struct nlmr nlm;
1322 int retval = 0;
1323 struct dhcp_state *state;
1324
1325 memset(&nlm, 0, sizeof(nlm));
1326 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1327 switch (cmd) {
1328 case RTM_CHANGE:
1329 nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1330 nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE;
1331 break;
1332 case RTM_ADD:
1333 nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1334 nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
1335 break;
1336 case RTM_DELETE:
1337 nlm.hdr.nlmsg_type = RTM_DELROUTE;
1338 break;
1339 }
1340 nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1341 nlm.rt.rtm_family = AF_INET;
1342 nlm.rt.rtm_table = RT_TABLE_MAIN;
1343
1344 state = D_STATE(rt->iface);
1345 if (cmd == RTM_DELETE)
1346 nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
1347 else {
1348 /* We only change route metrics for kernel routes */
1349 if (rt->dest.s_addr ==
1350 (state->addr.s_addr & state->net.s_addr) &&
1351 rt->net.s_addr == state->net.s_addr)
1352 nlm.rt.rtm_protocol = RTPROT_KERNEL;
1353 else
1354 nlm.rt.rtm_protocol = RTPROT_BOOT;
1355 if (rt->iface->flags & IFF_LOOPBACK)
1356 nlm.rt.rtm_scope = RT_SCOPE_HOST;
1357 else if (rt->gate.s_addr == INADDR_ANY ||
1358 (rt->gate.s_addr == rt->dest.s_addr &&
1359 rt->net.s_addr == INADDR_BROADCAST))
1360 nlm.rt.rtm_scope = RT_SCOPE_LINK;
1361 else
1362 nlm.rt.rtm_scope = RT_SCOPE_UNIVERSE;
1363 nlm.rt.rtm_type = RTN_UNICAST;
1364 }
1365
1366 nlm.rt.rtm_dst_len = inet_ntocidr(rt->net);
1367 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST,
1368 &rt->dest.s_addr, sizeof(rt->dest.s_addr));
1369 if (nlm.rt.rtm_protocol == RTPROT_KERNEL) {
1370 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_PREFSRC,
1371 &state->addr.s_addr, sizeof(state->addr.s_addr));
1372 }
1373 /* If a host route then don't add the gateway */
1374 if ((cmd == RTM_ADD || cmd == RTM_CHANGE) &&
1375 rt->net.s_addr != INADDR_BROADCAST)
1376 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
1377 &rt->gate.s_addr, sizeof(rt->gate.s_addr));
1378
1379 if (rt->gate.s_addr != htonl(INADDR_LOOPBACK))
1380 add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
1381 if (rt->metric)
1382 add_attr_32(&nlm.hdr, sizeof(nlm), RTA_PRIORITY, rt->metric);
1383
1384 if (send_netlink(rt->iface->ctx, NULL,
1385 NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1386 retval = -1;
1387 return retval;
1388 }
1389
1390 static int
_if_initrt(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1391 _if_initrt(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1392 struct nlmsghdr *nlm)
1393 {
1394 struct rt rt;
1395
1396 if (if_copyrt(ctx, &rt, nlm) == 0)
1397 ipv4_handlert(ctx, RTM_ADD, &rt);
1398 return 0;
1399 }
1400
1401 int
if_initrt(struct interface * ifp)1402 if_initrt(struct interface *ifp)
1403 {
1404 struct nlmr nlm;
1405
1406 ipv4_freerts(ifp->ctx->ipv4_kroutes);
1407
1408 memset(&nlm, 0, sizeof(nlm));
1409 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1410 nlm.hdr.nlmsg_type = RTM_GETROUTE;
1411 nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
1412 nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1413 nlm.rt.rtm_family = AF_INET;
1414 nlm.rt.rtm_table = RT_TABLE_MAIN;
1415 add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index);
1416
1417 return send_netlink(ifp->ctx, ifp,
1418 NETLINK_ROUTE, &nlm.hdr, &_if_initrt);
1419 }
1420
1421 int
if_addrflags(__unused const struct in_addr * addr,__unused const struct interface * ifp)1422 if_addrflags(__unused const struct in_addr *addr,
1423 __unused const struct interface *ifp)
1424 {
1425
1426 /* Linux has no support for IPv4 address flags */
1427 return 0;
1428 }
1429 #endif
1430
1431 #ifdef INET6
1432 int
if_address6(const struct ipv6_addr * ap,int action)1433 if_address6(const struct ipv6_addr *ap, int action)
1434 {
1435 struct nlma nlm;
1436 struct ifa_cacheinfo cinfo;
1437 int retval = 0;
1438 /* IFA_FLAGS is not a define, but is was added at the same time
1439 * IFA_F_NOPREFIXROUTE was do use that. */
1440 #if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
1441 uint32_t flags = 0;
1442 #endif
1443
1444 memset(&nlm, 0, sizeof(nlm));
1445 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
1446 nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1447 if (action >= 0) {
1448 nlm.hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
1449 nlm.hdr.nlmsg_type = RTM_NEWADDR;
1450 } else
1451 nlm.hdr.nlmsg_type = RTM_DELADDR;
1452 nlm.ifa.ifa_index = ap->iface->index;
1453 nlm.ifa.ifa_family = AF_INET6;
1454 if (ap->addr_flags & IFA_F_TEMPORARY) {
1455 #ifdef IFA_F_NOPREFIXROUTE
1456 flags |= IFA_F_TEMPORARY;
1457 #else
1458 nlm.ifa.ifa_flags |= IFA_F_TEMPORARY;
1459 #endif
1460 }
1461 #ifdef IFA_F_MANAGETEMPADDR
1462 else if (ap->flags & IPV6_AF_AUTOCONF &&
1463 ip6_use_tempaddr(ap->iface->name))
1464 flags |= IFA_F_MANAGETEMPADDR;
1465 #endif
1466
1467 /* Add as /128 if no IFA_F_NOPREFIXROUTE ? */
1468 nlm.ifa.ifa_prefixlen = ap->prefix_len;
1469 /* This creates the aliased interface */
1470 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LABEL,
1471 ap->iface->alias, (unsigned short)(strlen(ap->iface->alias) + 1));
1472 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_LOCAL,
1473 &ap->addr.s6_addr, sizeof(ap->addr.s6_addr));
1474
1475 if (action >= 0) {
1476 memset(&cinfo, 0, sizeof(cinfo));
1477 cinfo.ifa_prefered = ap->prefix_pltime;
1478 cinfo.ifa_valid = ap->prefix_vltime;
1479 add_attr_l(&nlm.hdr, sizeof(nlm), IFA_CACHEINFO,
1480 &cinfo, sizeof(cinfo));
1481 }
1482
1483 #ifdef IFA_F_NOPREFIXROUTE
1484 if (!IN6_IS_ADDR_LINKLOCAL(&ap->addr))
1485 flags |= IFA_F_NOPREFIXROUTE;
1486 #endif
1487 #if defined(IFA_F_NOPREFIXROUTE) || defined(IFA_F_MANAGETEMPADDR)
1488 if (flags)
1489 add_attr_32(&nlm.hdr, sizeof(nlm), IFA_FLAGS, flags);
1490 #endif
1491
1492 if (send_netlink(ap->iface->ctx, NULL, NETLINK_ROUTE, &nlm.hdr,
1493 NULL) == -1)
1494 retval = -1;
1495 return retval;
1496 }
1497
1498 static int
rta_add_attr_32(struct rtattr * rta,unsigned short maxlen,unsigned short type,uint32_t data)1499 rta_add_attr_32(struct rtattr *rta, unsigned short maxlen,
1500 unsigned short type, uint32_t data)
1501 {
1502 unsigned short len = RTA_LENGTH(sizeof(data));
1503 struct rtattr *subrta;
1504
1505 if (RTA_ALIGN(rta->rta_len) + len > maxlen) {
1506 errno = ENOBUFS;
1507 return -1;
1508 }
1509
1510 subrta = (struct rtattr*)(void *)
1511 (((char*)rta) + RTA_ALIGN(rta->rta_len));
1512 subrta->rta_type = type;
1513 subrta->rta_len = len;
1514 memcpy(RTA_DATA(subrta), &data, sizeof(data));
1515 rta->rta_len = (unsigned short)(NLMSG_ALIGN(rta->rta_len) + len);
1516 return 0;
1517 }
1518
1519 int
if_route6(unsigned char cmd,const struct rt6 * rt)1520 if_route6(unsigned char cmd, const struct rt6 *rt)
1521 {
1522 struct nlmr nlm;
1523 int retval = 0;
1524
1525 memset(&nlm, 0, sizeof(nlm));
1526 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1527 switch (cmd) {
1528 case RTM_CHANGE:
1529 nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1530 nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_REPLACE;
1531 break;
1532 case RTM_ADD:
1533 nlm.hdr.nlmsg_type = RTM_NEWROUTE;
1534 nlm.hdr.nlmsg_flags = NLM_F_CREATE | NLM_F_EXCL;
1535 break;
1536 case RTM_DELETE:
1537 nlm.hdr.nlmsg_type = RTM_DELROUTE;
1538 break;
1539 }
1540 nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1541 nlm.rt.rtm_family = AF_INET6;
1542 nlm.rt.rtm_table = RT_TABLE_MAIN;
1543
1544 if (cmd == RTM_DELETE)
1545 nlm.rt.rtm_scope = RT_SCOPE_NOWHERE;
1546 else {
1547 /* None interface subnet routes are static. */
1548 if (rt->iface->flags & IFF_LOOPBACK)
1549 nlm.rt.rtm_scope = RT_SCOPE_HOST;
1550 else if (IN6_IS_ADDR_UNSPECIFIED(&rt->gate)) {
1551 nlm.rt.rtm_protocol = RTPROT_KERNEL;
1552 nlm.rt.rtm_scope = RT_SCOPE_LINK;
1553 } else
1554 nlm.rt.rtm_protocol = RTPROT_BOOT;
1555 if (rt->flags & RTF_REJECT)
1556 nlm.rt.rtm_type = RTN_UNREACHABLE;
1557 else
1558 nlm.rt.rtm_type = RTN_UNICAST;
1559 }
1560
1561 nlm.rt.rtm_dst_len = ipv6_prefixlen(&rt->net);
1562 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_DST,
1563 &rt->dest.s6_addr, sizeof(rt->dest.s6_addr));
1564
1565 if (cmd == RTM_ADD && !IN6_IS_ADDR_UNSPECIFIED(&rt->gate))
1566 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_GATEWAY,
1567 &rt->gate.s6_addr, sizeof(rt->gate.s6_addr));
1568
1569 if (!(rt->flags & RTF_REJECT)) {
1570 add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, rt->iface->index);
1571 if (rt->metric)
1572 add_attr_32(&nlm.hdr, sizeof(nlm),
1573 RTA_PRIORITY, rt->metric);
1574 }
1575 if (cmd == RTM_ADD && rt->mtu) {
1576 char metricsbuf[32];
1577 struct rtattr *metrics = (void *)metricsbuf;
1578
1579 metrics->rta_type = RTA_METRICS;
1580 metrics->rta_len = RTA_LENGTH(0);
1581 rta_add_attr_32(metrics, sizeof(metricsbuf), RTAX_MTU, rt->mtu);
1582 add_attr_l(&nlm.hdr, sizeof(nlm), RTA_METRICS,
1583 RTA_DATA(metrics), (unsigned short)RTA_PAYLOAD(metrics));
1584 }
1585
1586 if (send_netlink(rt->iface->ctx, NULL,
1587 NETLINK_ROUTE, &nlm.hdr, NULL) == -1)
1588 retval = -1;
1589 return retval;
1590 }
1591
1592 static int
_if_initrt6(struct dhcpcd_ctx * ctx,__unused struct interface * ifp,struct nlmsghdr * nlm)1593 _if_initrt6(struct dhcpcd_ctx *ctx, __unused struct interface *ifp,
1594 struct nlmsghdr *nlm)
1595 {
1596 struct rt6 rt;
1597
1598 if (if_copyrt6(ctx, &rt, nlm) == 0)
1599 ipv6_handlert(ctx, RTM_ADD, &rt);
1600 return 0;
1601 }
1602
1603 int
if_initrt6(struct interface * ifp)1604 if_initrt6(struct interface *ifp)
1605 {
1606 struct nlmr nlm;
1607
1608 ipv6_freerts(&ifp->ctx->ipv6->kroutes);
1609
1610 memset(&nlm, 0, sizeof(nlm));
1611 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
1612 nlm.hdr.nlmsg_type = RTM_GETROUTE;
1613 nlm.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_MATCH;
1614 nlm.hdr.nlmsg_flags |= NLM_F_REQUEST;
1615 nlm.rt.rtm_family = AF_INET6;
1616 nlm.rt.rtm_table = RT_TABLE_MAIN;
1617 add_attr_32(&nlm.hdr, sizeof(nlm), RTA_OIF, ifp->index);
1618
1619 return send_netlink(ifp->ctx, ifp,
1620 NETLINK_ROUTE, &nlm.hdr, &_if_initrt6);
1621 }
1622
1623 int
if_addrflags6(const struct in6_addr * addr,const struct interface * ifp)1624 if_addrflags6(const struct in6_addr *addr, const struct interface *ifp)
1625 {
1626 FILE *fp;
1627 char *p, ifaddress[33], address[33], name[IF_NAMESIZE + 1];
1628 unsigned int ifindex;
1629 int prefix, scope, flags, i;
1630
1631 fp = fopen(PROC_INET6, "r");
1632 if (fp == NULL)
1633 return -1;
1634
1635 p = ifaddress;
1636 for (i = 0; i < (int)sizeof(addr->s6_addr); i++) {
1637 p += snprintf(p, 3, "%.2x", addr->s6_addr[i]);
1638 }
1639 *p = '\0';
1640
1641 while (fscanf(fp, "%32[a-f0-9] %x %x %x %x %"TOSTRING(IF_NAMESIZE)"s\n",
1642 address, &ifindex, &prefix, &scope, &flags, name) == 6)
1643 {
1644 if (strlen(address) != 32) {
1645 fclose(fp);
1646 errno = ENOTSUP;
1647 return -1;
1648 }
1649 if (strcmp(name, ifp->name) == 0 &&
1650 strcmp(ifaddress, address) == 0)
1651 {
1652 fclose(fp);
1653 return flags;
1654 }
1655 }
1656
1657 fclose(fp);
1658 errno = ESRCH;
1659 return -1;
1660 }
1661
1662 int
if_getlifetime6(__unused struct ipv6_addr * ia)1663 if_getlifetime6(__unused struct ipv6_addr *ia)
1664 {
1665
1666 /* God knows how to work out address lifetimes on Linux */
1667 errno = ENOTSUP;
1668 return -1;
1669 }
1670
1671 struct nlml
1672 {
1673 struct nlmsghdr hdr;
1674 struct ifinfomsg i;
1675 char buffer[32];
1676 };
1677
1678 static int
add_attr_8(struct nlmsghdr * n,unsigned short maxlen,unsigned short type,uint8_t data)1679 add_attr_8(struct nlmsghdr *n, unsigned short maxlen, unsigned short type,
1680 uint8_t data)
1681 {
1682
1683 return add_attr_l(n, maxlen, type, &data, sizeof(data));
1684 }
1685
1686 static struct rtattr *
add_attr_nest(struct nlmsghdr * n,unsigned short maxlen,unsigned short type)1687 add_attr_nest(struct nlmsghdr *n, unsigned short maxlen, unsigned short type)
1688 {
1689 struct rtattr *nest;
1690
1691 nest = NLMSG_TAIL(n);
1692 add_attr_l(n, maxlen, type, NULL, 0);
1693 return nest;
1694 }
1695
1696 static void
add_attr_nest_end(struct nlmsghdr * n,struct rtattr * nest)1697 add_attr_nest_end(struct nlmsghdr *n, struct rtattr *nest)
1698 {
1699
1700 nest->rta_len = (unsigned short)((char *)NLMSG_TAIL(n) - (char *)nest);
1701 }
1702
1703 static int
if_disable_autolinklocal(struct dhcpcd_ctx * ctx,int ifindex)1704 if_disable_autolinklocal(struct dhcpcd_ctx *ctx, int ifindex)
1705 {
1706 struct nlml nlm;
1707 struct rtattr *afs, *afs6;
1708
1709 memset(&nlm, 0, sizeof(nlm));
1710 nlm.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
1711 nlm.hdr.nlmsg_type = RTM_NEWLINK;
1712 nlm.hdr.nlmsg_flags = NLM_F_REQUEST;
1713 nlm.i.ifi_family = AF_INET6;
1714 nlm.i.ifi_index = ifindex;
1715 afs = add_attr_nest(&nlm.hdr, sizeof(nlm), IFLA_AF_SPEC);
1716 afs6 = add_attr_nest(&nlm.hdr, sizeof(nlm), AF_INET6);
1717 add_attr_8(&nlm.hdr, sizeof(nlm), IFLA_INET6_ADDR_GEN_MODE,
1718 IN6_ADDR_GEN_MODE_NONE);
1719 add_attr_nest_end(&nlm.hdr, afs6);
1720 add_attr_nest_end(&nlm.hdr, afs);
1721
1722 return send_netlink(ctx, NULL, NETLINK_ROUTE, &nlm.hdr, NULL);
1723 }
1724
1725 static const char *prefix = "/proc/sys/net/ipv6/conf";
1726
1727 int
if_checkipv6(struct dhcpcd_ctx * ctx,const struct interface * ifp,int own)1728 if_checkipv6(struct dhcpcd_ctx *ctx, const struct interface *ifp, int own)
1729 {
1730 const char *ifname;
1731 int ra;
1732 char path[256];
1733
1734 if (ifp == NULL)
1735 ifname = "all";
1736 else if (own) {
1737 if (if_disable_autolinklocal(ctx, (int)ifp->index) == -1)
1738 logger(ctx, LOG_DEBUG,
1739 "%s: if_disable_autolinklocal: %m", ifp->name);
1740 }
1741 if (ifp)
1742 ifname = ifp->name;
1743
1744 snprintf(path, sizeof(path), "%s/%s/autoconf", prefix, ifname);
1745 ra = check_proc_int(path);
1746 if (ra != 1) {
1747 if (!own)
1748 logger(ctx, LOG_WARNING,
1749 "%s: IPv6 kernel autoconf disabled", ifname);
1750 } else if (ra != -1 && own) {
1751 if (write_path(path, "0") == -1) {
1752 logger(ctx, LOG_ERR, "write_path: %s: %m", path);
1753 return -1;
1754 }
1755 }
1756
1757 snprintf(path, sizeof(path), "%s/%s/accept_ra", prefix, ifname);
1758 ra = check_proc_int(path);
1759 if (ra == -1)
1760 /* The sysctl probably doesn't exist, but this isn't an
1761 * error as such so just log it and continue */
1762 logger(ctx, errno == ENOENT ? LOG_DEBUG : LOG_WARNING,
1763 "%s: %m", path);
1764 else if (ra != 0 && own) {
1765 logger(ctx, LOG_DEBUG, "%s: disabling kernel IPv6 RA support",
1766 ifname);
1767 if (write_path(path, "0") == -1) {
1768 logger(ctx, LOG_ERR, "write_path: %s: %m", path);
1769 return ra;
1770 }
1771 return 0;
1772 }
1773
1774 return ra;
1775 }
1776
1777 #ifdef IPV6_MANAGETEMPADDR
1778 int
ip6_use_tempaddr(const char * ifname)1779 ip6_use_tempaddr(const char *ifname)
1780 {
1781 char path[256];
1782 int val;
1783
1784 if (ifname == NULL)
1785 ifname = "all";
1786 snprintf(path, sizeof(path), "%s/%s/use_tempaddr", prefix, ifname);
1787 val = check_proc_int(path);
1788 return val == -1 ? 0 : val;
1789 }
1790
1791 int
ip6_temp_preferred_lifetime(const char * ifname)1792 ip6_temp_preferred_lifetime(const char *ifname)
1793 {
1794 char path[256];
1795 int val;
1796
1797 if (ifname == NULL)
1798 ifname = "all";
1799 snprintf(path, sizeof(path), "%s/%s/temp_prefered_lft", prefix,
1800 ifname);
1801 val = check_proc_int(path);
1802 return val < 0 ? TEMP_PREFERRED_LIFETIME : val;
1803 }
1804
1805 int
ip6_temp_valid_lifetime(const char * ifname)1806 ip6_temp_valid_lifetime(const char *ifname)
1807 {
1808 char path[256];
1809 int val;
1810
1811 if (ifname == NULL)
1812 ifname = "all";
1813 snprintf(path, sizeof(path), "%s/%s/temp_valid_lft", prefix, ifname);
1814 val = check_proc_int(path);
1815 return val < 0 ? TEMP_VALID_LIFETIME : val;
1816 }
1817 #endif /* IPV6_MANAGETEMPADDR */
1818 #endif /* INET6 */
1819