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