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