• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * dhcpcd - DHCP client daemon
3  * Copyright (c) 2006-2011 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/netlink.h>
36 #include <linux/rtnetlink.h>
37 
38 /* Support older kernels */
39 #ifndef IFLA_WIRELESS
40 # define IFLA_WIRELESS (IFLA_MASTER + 1)
41 #endif
42 
43 /* For some reason, glibc doesn't include newer flags from linux/if.h
44  * However, we cannot include linux/if.h directly as it conflicts
45  * with the glibc version. D'oh! */
46 #ifndef IFF_LOWER_UP
47 #define IFF_LOWER_UP	0x10000		/* driver signals L1 up		*/
48 #endif
49 
50 #include <errno.h>
51 #include <ctype.h>
52 #include <stddef.h>
53 #include <stdio.h>
54 #include <stdlib.h>
55 #include <string.h>
56 #include <unistd.h>
57 
58 #include "config.h"
59 #include "common.h"
60 #include "configure.h"
61 #include "dhcp.h"
62 #include "net.h"
63 
64 static int sock_fd;
65 static struct sockaddr_nl sock_nl;
66 
67 int
if_init(struct interface * iface)68 if_init(struct interface *iface)
69 {
70 	char path[PATH_MAX];
71 	FILE *fp;
72 	int n;
73 
74 	/* We enable promote_secondaries so that we can do this
75 	 * add 192.168.1.2/24
76 	 * add 192.168.1.3/24
77 	 * del 192.168.1.2/24
78 	 * and the subnet mask moves onto 192.168.1.3/24
79 	 * This matches the behaviour of BSD which makes coding dhcpcd
80 	 * a little easier as there's just one behaviour. */
81 	snprintf(path, sizeof(path),
82 	    "/proc/sys/net/ipv4/conf/%s/promote_secondaries",
83 	    iface->name);
84 
85 	fp = fopen(path, "w");
86 	if (fp == NULL)
87 		return errno == ENOENT ? 0 : -1;
88 	n = fprintf(fp, "1");
89 	fclose(fp);
90 	return n == -1 ? -1 : 0;
91 }
92 
93 int
if_conf(struct interface * iface)94 if_conf(struct interface *iface)
95 {
96 	char path[PATH_MAX], buf[1];
97 	FILE *fp;
98 
99 	/* Some qeth setups require the use of the broadcast flag. */
100 	snprintf(path, sizeof(path),
101 	    "/sys/class/net/%s/device/layer2",
102 	    iface->name);
103 
104 	fp = fopen(path, "r");
105 	if (fp == NULL)
106 		return errno == ENOENT ? 0 : -1;
107 	if (fgets(buf, sizeof(buf), fp) != NULL && buf[0] == '0')
108 		iface->state->options->options |= DHCPCD_BROADCAST;
109 	fclose(fp);
110 	return 0;
111 }
112 
113 static int
_open_link_socket(struct sockaddr_nl * nl)114 _open_link_socket(struct sockaddr_nl *nl)
115 {
116 	int fd;
117 
118 	if ((fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1)
119 		return -1;
120 	nl->nl_family = AF_NETLINK;
121 	if (bind(fd, (struct sockaddr *)nl, sizeof(*nl)) == -1)
122 		return -1;
123 	set_cloexec(fd);
124 	return fd;
125 }
126 
127 int
init_sockets(void)128 init_sockets(void)
129 {
130 	if ((socket_afnet = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
131 		return -1;
132 	set_cloexec(socket_afnet);
133 	sock_fd = _open_link_socket(&sock_nl);
134 	set_cloexec(sock_fd);
135 	return sock_fd;
136 }
137 
138 int
open_link_socket(void)139 open_link_socket(void)
140 {
141 	struct sockaddr_nl snl;
142 
143 	memset(&snl, 0, sizeof(snl));
144 	snl.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_ROUTE | RTMGRP_IPV4_IFADDR;
145 	return _open_link_socket(&snl);
146 }
147 
148 static int
get_netlink(int fd,int flags,int (* callback)(struct nlmsghdr *))149 get_netlink(int fd, int flags,
150     int (*callback)(struct nlmsghdr *))
151 {
152 	char *buf = NULL, *nbuf;
153 	ssize_t buflen = 0, bytes;
154 	struct nlmsghdr *nlm;
155 	int r = -1;
156 
157 	for (;;) {
158 		bytes = recv(fd, NULL, 0,
159 		    flags | MSG_PEEK | MSG_DONTWAIT | MSG_TRUNC);
160 		if (bytes == -1) {
161 			if (errno == EAGAIN) {
162 				r = 0;
163 				goto eexit;
164 			}
165 			if (errno == EINTR)
166 				continue;
167 			goto eexit;
168 		} else if (bytes == buflen) {
169 			/* Support kernels older than 2.6.22 */
170 			if (bytes == 0)
171 				bytes = 512;
172 			else
173 				bytes *= 2;
174 		}
175 		if (buflen < bytes) {
176 			/* Alloc 1 more so we work with older kernels */
177 			buflen = bytes + 1;
178 			nbuf = realloc(buf, buflen);
179 			if (nbuf == NULL)
180 				goto eexit;
181 			buf = nbuf;
182 		}
183 		bytes = recv(fd, buf, buflen, flags);
184 		if (bytes == -1) {
185 			if (errno == EAGAIN) {
186 				r = 0;
187 				goto eexit;
188 			}
189 			if (errno == EINTR)
190 				continue;
191 			goto eexit;
192 		}
193 		for (nlm = (struct nlmsghdr *)buf;
194 		     NLMSG_OK(nlm, (size_t)bytes);
195 		     nlm = NLMSG_NEXT(nlm, bytes))
196 		{
197 			r = callback(nlm);
198 			if (r != 0)
199 				goto eexit;
200 		}
201 	}
202 
203 eexit:
204 	free(buf);
205 	return r;
206 }
207 
208 static int
err_netlink(struct nlmsghdr * nlm)209 err_netlink(struct nlmsghdr *nlm)
210 {
211 	struct nlmsgerr *err;
212 	int l;
213 
214 	if (nlm->nlmsg_type != NLMSG_ERROR)
215 		return 0;
216 	l = nlm->nlmsg_len - sizeof(*nlm);
217 	if ((size_t)l < sizeof(*err)) {
218 		errno = EBADMSG;
219 		return -1;
220 	}
221 	err = (struct nlmsgerr *)NLMSG_DATA(nlm);
222 	if (err->error == 0)
223 		return l;
224 	errno = -err->error;
225 	return -1;
226 }
227 
228 static int
link_route(struct nlmsghdr * nlm)229 link_route(struct nlmsghdr *nlm)
230 {
231 	int len, idx, metric;
232 	struct rtattr *rta;
233 	struct rtmsg *rtm;
234 	struct rt rt;
235 	char ifn[IF_NAMESIZE + 1];
236 
237 	if (nlm->nlmsg_type != RTM_DELROUTE)
238 		return 0;
239 
240 	len = nlm->nlmsg_len - sizeof(*nlm);
241 	if ((size_t)len < sizeof(*rtm)) {
242 		errno = EBADMSG;
243 		return -1;
244 	}
245 	rtm = NLMSG_DATA(nlm);
246 	if (rtm->rtm_type != RTN_UNICAST ||
247 	    rtm->rtm_table != RT_TABLE_MAIN ||
248 	    rtm->rtm_family != AF_INET ||
249 	    nlm->nlmsg_pid == (uint32_t)getpid())
250 		return 1;
251 	rta = (struct rtattr *) ((char *)rtm + NLMSG_ALIGN(sizeof(*rtm)));
252 	len = NLMSG_PAYLOAD(nlm, sizeof(*rtm));
253 	rt.iface = NULL;
254 	rt.dest.s_addr = INADDR_ANY;
255 	rt.net.s_addr = INADDR_ANY;
256 	rt.gate.s_addr = INADDR_ANY;
257 	rt.next = NULL;
258 	metric = 0;
259 	while (RTA_OK(rta, len)) {
260 		switch (rta->rta_type) {
261 		case RTA_DST:
262 			memcpy(&rt.dest.s_addr, RTA_DATA(rta),
263 			    sizeof(rt.dest.s_addr));
264 			break;
265 		case RTA_GATEWAY:
266 			memcpy(&rt.gate.s_addr, RTA_DATA(rta),
267 			    sizeof(rt.gate.s_addr));
268 			break;
269 		case RTA_OIF:
270 			idx = *(int *)RTA_DATA(rta);
271 			if (if_indextoname(idx, ifn))
272 				rt.iface = find_interface(ifn);
273 			break;
274 		case RTA_PRIORITY:
275 			metric = *(int *)RTA_DATA(rta);
276 			break;
277 		}
278 		rta = RTA_NEXT(rta, len);
279 	}
280 	if (rt.iface != NULL) {
281 		if (metric == rt.iface->metric) {
282 			inet_cidrtoaddr(rtm->rtm_dst_len, &rt.net);
283 			route_deleted(&rt);
284 		}
285 	}
286 	return 1;
287 }
288 
289 static int
link_addr(struct nlmsghdr * nlm)290 link_addr(struct nlmsghdr *nlm)
291 {
292 	int len;
293 	struct rtattr *rta;
294 	struct ifaddrmsg *ifa;
295 	struct in_addr addr, net, dest;
296 	char ifn[IF_NAMESIZE + 1];
297 	struct interface *iface;
298 
299 	if (nlm->nlmsg_type != RTM_DELADDR && nlm->nlmsg_type != RTM_NEWADDR)
300 		return 0;
301 
302 	len = nlm->nlmsg_len - sizeof(*nlm);
303 	if ((size_t)len < sizeof(*ifa)) {
304 		errno = EBADMSG;
305 		return -1;
306 	}
307 	if (nlm->nlmsg_pid == (uint32_t)getpid())
308 		return 1;
309 	ifa = NLMSG_DATA(nlm);
310 	if (if_indextoname(ifa->ifa_index, ifn) == NULL)
311 		return -1;
312 	iface = find_interface(ifn);
313 	if (iface == NULL)
314 		return 1;
315 	rta = (struct rtattr *) IFA_RTA(ifa);
316 	len = NLMSG_PAYLOAD(nlm, sizeof(*ifa));
317 	addr.s_addr = dest.s_addr = INADDR_ANY;
318 	dest.s_addr = INADDR_ANY;
319 	inet_cidrtoaddr(ifa->ifa_prefixlen, &net);
320 	while (RTA_OK(rta, len)) {
321 		switch (rta->rta_type) {
322 		case IFA_ADDRESS:
323 			if (iface->flags & IFF_POINTOPOINT) {
324 				memcpy(&dest.s_addr, RTA_DATA(rta),
325 				    sizeof(addr.s_addr));
326 			}
327 			break;
328 		case IFA_LOCAL:
329 			memcpy(&addr.s_addr, RTA_DATA(rta),
330 			    sizeof(addr.s_addr));
331 			break;
332 		}
333 		rta = RTA_NEXT(rta, len);
334 	}
335 	handle_ifa(nlm->nlmsg_type, ifn, &addr, &net, &dest);
336 	return 1;
337 }
338 
339 static int
link_netlink(struct nlmsghdr * nlm)340 link_netlink(struct nlmsghdr *nlm)
341 {
342 	int len;
343 	struct rtattr *rta;
344 	struct ifinfomsg *ifi;
345 	char ifn[IF_NAMESIZE + 1];
346 
347 	len = link_route(nlm);
348 	if (len != 0)
349 		return len;
350 	len = link_addr(nlm);
351 	if (len != 0)
352 		return len;
353 
354 	if (nlm->nlmsg_type != RTM_NEWLINK && nlm->nlmsg_type != RTM_DELLINK)
355 		return 0;
356 	len = nlm->nlmsg_len - sizeof(*nlm);
357 	if ((size_t)len < sizeof(*ifi)) {
358 		errno = EBADMSG;
359 		return -1;
360 	}
361 	ifi = NLMSG_DATA(nlm);
362 	if (ifi->ifi_flags & IFF_LOOPBACK)
363 		return 1;
364 	rta = (struct rtattr *) ((char *)ifi + NLMSG_ALIGN(sizeof(*ifi)));
365 	len = NLMSG_PAYLOAD(nlm, sizeof(*ifi));
366 	*ifn = '\0';
367 	while (RTA_OK(rta, len)) {
368 		switch (rta->rta_type) {
369 		case IFLA_WIRELESS:
370 			/* Ignore wireless messages */
371 			if (nlm->nlmsg_type == RTM_NEWLINK &&
372 			    ifi->ifi_change == 0)
373 				return 1;
374 			break;
375 		case IFLA_IFNAME:
376 			strlcpy(ifn, RTA_DATA(rta), sizeof(ifn));
377 			break;
378 		}
379 		rta = RTA_NEXT(rta, len);
380 	}
381 
382 	if (nlm->nlmsg_type == RTM_DELLINK) {
383 		handle_interface(-1, ifn);
384 		return 1;
385 	}
386 
387 	/* Bridge interfaces set IFF_LOWER_UP when they have a valid
388 	 * hardware address. To trigger a valid hardware address pickup
389 	 * we need to pretend that that don't exist until they have
390 	 * IFF_LOWER_UP set. */
391 	if (ifi->ifi_flags & IFF_MASTER && !(ifi->ifi_flags & IFF_LOWER_UP)) {
392 		handle_interface(-1, ifn);
393 		return 1;
394 	}
395 
396 	handle_carrier(ifi->ifi_flags & IFF_RUNNING ? 1 : -1,
397 	    ifi->ifi_flags, ifn);
398 	return 1;
399 }
400 
401 int
manage_link(int fd)402 manage_link(int fd)
403 {
404 	return get_netlink(fd, MSG_DONTWAIT, &link_netlink);
405 }
406 
407 static int
send_netlink(struct nlmsghdr * hdr)408 send_netlink(struct nlmsghdr *hdr)
409 {
410 	int r;
411 	struct iovec iov;
412 	struct msghdr msg;
413 	static unsigned int seq;
414 
415 	memset(&iov, 0, sizeof(iov));
416 	iov.iov_base = hdr;
417 	iov.iov_len = hdr->nlmsg_len;
418 	memset(&msg, 0, sizeof(msg));
419 	msg.msg_name = &sock_nl;
420 	msg.msg_namelen = sizeof(sock_nl);
421 	msg.msg_iov = &iov;
422 	msg.msg_iovlen = 1;
423 	/* Request a reply */
424 	hdr->nlmsg_flags |= NLM_F_ACK;
425 	hdr->nlmsg_seq = ++seq;
426 
427 	if (sendmsg(sock_fd, &msg, 0) != -1)
428 		r = get_netlink(sock_fd, 0, &err_netlink);
429 	else
430 		r = -1;
431 	return r;
432 }
433 
434 #define NLMSG_TAIL(nmsg)						\
435 	((struct rtattr *)(((ptrdiff_t)(nmsg))+NLMSG_ALIGN((nmsg)->nlmsg_len)))
436 
437 static int
add_attr_l(struct nlmsghdr * n,unsigned int maxlen,int type,const void * data,int alen)438 add_attr_l(struct nlmsghdr *n, unsigned int maxlen, int type,
439     const void *data, int alen)
440 {
441 	int len = RTA_LENGTH(alen);
442 	struct rtattr *rta;
443 
444 	if (NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len) > maxlen) {
445 		errno = ENOBUFS;
446 		return -1;
447 	}
448 
449 	rta = NLMSG_TAIL(n);
450 	rta->rta_type = type;
451 	rta->rta_len = len;
452 	memcpy(RTA_DATA(rta), data, alen);
453 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + RTA_ALIGN(len);
454 
455 	return 0;
456 }
457 
458 static int
add_attr_32(struct nlmsghdr * n,unsigned int maxlen,int type,uint32_t data)459 add_attr_32(struct nlmsghdr *n, unsigned int maxlen, int type, uint32_t data)
460 {
461 	int len = RTA_LENGTH(sizeof(data));
462 	struct rtattr *rta;
463 
464 	if (NLMSG_ALIGN(n->nlmsg_len) + len > maxlen) {
465 		errno = ENOBUFS;
466 		return -1;
467 	}
468 
469 	rta = NLMSG_TAIL(n);
470 	rta->rta_type = type;
471 	rta->rta_len = len;
472 	memcpy(RTA_DATA(rta), &data, sizeof(data));
473 	n->nlmsg_len = NLMSG_ALIGN(n->nlmsg_len) + len;
474 
475 	return 0;
476 }
477 
478 struct nlma
479 {
480 	struct nlmsghdr hdr;
481 	struct ifaddrmsg ifa;
482 	char buffer[64];
483 };
484 
485 struct nlmr
486 {
487 	struct nlmsghdr hdr;
488 	struct rtmsg rt;
489 	char buffer[256];
490 };
491 
492 int
if_address(const struct interface * iface,const struct in_addr * address,const struct in_addr * netmask,const struct in_addr * broadcast,int action)493 if_address(const struct interface *iface,
494     const struct in_addr *address, const struct in_addr *netmask,
495     const struct in_addr *broadcast, int action)
496 {
497 	struct nlma *nlm;
498 	int retval = 0;
499 
500 	nlm = xzalloc(sizeof(*nlm));
501 	nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifaddrmsg));
502 	nlm->hdr.nlmsg_flags = NLM_F_REQUEST;
503 	if (action >= 0) {
504 		nlm->hdr.nlmsg_flags |= NLM_F_CREATE | NLM_F_REPLACE;
505 		nlm->hdr.nlmsg_type = RTM_NEWADDR;
506 	} else
507 		nlm->hdr.nlmsg_type = RTM_DELADDR;
508 	if (!(nlm->ifa.ifa_index = if_nametoindex(iface->name))) {
509 		free(nlm);
510 		errno = ENODEV;
511 		return -1;
512 	}
513 	nlm->ifa.ifa_family = AF_INET;
514 	nlm->ifa.ifa_prefixlen = inet_ntocidr(*netmask);
515 	/* This creates the aliased interface */
516 	add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LABEL,
517 	    iface->name, strlen(iface->name) + 1);
518 	add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_LOCAL,
519 	    &address->s_addr, sizeof(address->s_addr));
520 	if (action >= 0 && broadcast)
521 		add_attr_l(&nlm->hdr, sizeof(*nlm), IFA_BROADCAST,
522 		    &broadcast->s_addr, sizeof(broadcast->s_addr));
523 
524 	if (send_netlink(&nlm->hdr) == -1)
525 		retval = -1;
526 	free(nlm);
527 	return retval;
528 }
529 
530 int
if_route(const struct rt * rt,int action)531 if_route(const struct rt *rt, int action)
532 {
533 	struct nlmr *nlm;
534 	unsigned int ifindex;
535 	int retval = 0;
536 
537 	if (!(ifindex = if_nametoindex(rt->iface->name))) {
538 		errno = ENODEV;
539 		return -1;
540 	}
541 
542 	nlm = xzalloc(sizeof(*nlm));
543 	nlm->hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtmsg));
544 	nlm->hdr.nlmsg_type = RTM_NEWROUTE;
545 	if (action == 0)
546 		nlm->hdr.nlmsg_flags = NLM_F_REPLACE;
547 	else if (action == 1)
548 		nlm->hdr.nlmsg_flags = NLM_F_CREATE /*| NLM_F_EXCL*/;
549 	else
550 		nlm->hdr.nlmsg_type = RTM_DELROUTE;
551 	nlm->hdr.nlmsg_flags |= NLM_F_REQUEST;
552 	nlm->rt.rtm_family = AF_INET;
553 	nlm->rt.rtm_table = RT_TABLE_MAIN;
554 
555 	if (action == -1 || action == -2)
556 		nlm->rt.rtm_scope = RT_SCOPE_NOWHERE;
557 	else {
558 		nlm->hdr.nlmsg_flags |= NLM_F_CREATE /*| NLM_F_EXCL*/;
559 		/* We only change route metrics for kernel routes */
560 		if (rt->dest.s_addr ==
561 		    (rt->iface->addr.s_addr & rt->iface->net.s_addr) &&
562 		    rt->net.s_addr == rt->iface->net.s_addr)
563 			nlm->rt.rtm_protocol = RTPROT_KERNEL;
564 		else
565 			nlm->rt.rtm_protocol = RTPROT_BOOT;
566 		if (rt->gate.s_addr == INADDR_ANY ||
567 		    (rt->gate.s_addr == rt->dest.s_addr &&
568 			rt->net.s_addr == INADDR_BROADCAST))
569 			nlm->rt.rtm_scope = RT_SCOPE_LINK;
570 		else
571 			nlm->rt.rtm_scope = RT_SCOPE_UNIVERSE;
572 		nlm->rt.rtm_type = RTN_UNICAST;
573 	}
574 
575 	nlm->rt.rtm_dst_len = inet_ntocidr(rt->net);
576 	add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_DST,
577 	    &rt->dest.s_addr, sizeof(rt->dest.s_addr));
578 	if (nlm->rt.rtm_protocol == RTPROT_KERNEL) {
579 		add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_PREFSRC,
580 		    &rt->iface->addr.s_addr, sizeof(rt->iface->addr.s_addr));
581 	}
582 	/* If destination == gateway then don't add the gateway */
583 	if (rt->dest.s_addr != rt->gate.s_addr ||
584 	    rt->net.s_addr != INADDR_BROADCAST)
585 		add_attr_l(&nlm->hdr, sizeof(*nlm), RTA_GATEWAY,
586 		    &rt->gate.s_addr, sizeof(rt->gate.s_addr));
587 
588 	add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_OIF, ifindex);
589 	add_attr_32(&nlm->hdr, sizeof(*nlm), RTA_PRIORITY, rt->metric);
590 
591 	if (send_netlink(&nlm->hdr) == -1)
592 		retval = -1;
593 	free(nlm);
594 	return retval;
595 }
596