net.c revision 4c5a5fb53bccceff331bae70f748bf9b4609fe0a
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright 2006-2008 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 <sys/types.h>
29#include <sys/ioctl.h>
30#include <sys/socket.h>
31#include <sys/time.h>
32
33#include <net/if.h>
34#include <net/if_arp.h>
35#include <arpa/inet.h>
36#include <netinet/in_systm.h>
37#ifdef __linux__
38#include <netinet/ether.h>
39#include <netpacket/packet.h>
40#endif
41#include <netinet/in.h>
42#include <netinet/ip.h>
43#define __FAVOR_BSD /* Nasty glibc hack so we can use BSD semantics for UDP */
44#include <netinet/udp.h>
45#undef __FAVOR_BSD
46#ifdef SIOCGIFMEDIA
47#include <net/if_media.h>
48#endif
49#include <arpa/inet.h>
50#ifdef AF_LINK
51# include <net/if_dl.h>
52#endif
53
54#include <ctype.h>
55#include <errno.h>
56#include <stddef.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <unistd.h>
61
62#include "config.h"
63#include "common.h"
64#include "dhcp.h"
65#include "logger.h"
66#include "net.h"
67#include "signals.h"
68
69int
70inet_ntocidr(struct in_addr address)
71{
72	int cidr = 0;
73	uint32_t mask = htonl(address.s_addr);
74
75	while (mask) {
76		cidr++;
77		mask <<= 1;
78	}
79
80	return cidr;
81}
82
83int
84inet_cidrtoaddr(int cidr, struct in_addr *addr)
85{
86	int ocets;
87
88	if (cidr < 0 || cidr > 32) {
89		errno = EINVAL;
90		return -1;
91	}
92	ocets = (cidr + 7) / 8;
93
94	addr->s_addr = 0;
95	if (ocets > 0) {
96		memset(&addr->s_addr, 255, (size_t)ocets - 1);
97		memset((unsigned char *)&addr->s_addr + (ocets - 1),
98		       (256 - (1 << (32 - cidr) % 8)), 1);
99	}
100
101	return 0;
102}
103
104uint32_t
105get_netmask(uint32_t addr)
106{
107	uint32_t dst;
108
109	if (addr == 0)
110		return 0;
111
112	dst = htonl(addr);
113	if (IN_CLASSA(dst))
114		return ntohl(IN_CLASSA_NET);
115	if (IN_CLASSB (dst))
116		return ntohl(IN_CLASSB_NET);
117	if (IN_CLASSC (dst))
118		return ntohl(IN_CLASSC_NET);
119
120	return 0;
121}
122
123char *
124hwaddr_ntoa(const unsigned char *hwaddr, size_t hwlen)
125{
126	static char buffer[(HWADDR_LEN * 3) + 1];
127	char *p = buffer;
128	size_t i;
129
130	for (i = 0; i < hwlen && i < HWADDR_LEN; i++) {
131		if (i > 0)
132			*p ++= ':';
133		p += snprintf(p, 3, "%.2x", hwaddr[i]);
134	}
135
136	*p ++= '\0';
137
138	return buffer;
139}
140
141size_t
142hwaddr_aton(unsigned char *buffer, const char *addr)
143{
144	char c[3];
145	const char *p = addr;
146	unsigned char *bp = buffer;
147	size_t len = 0;
148
149	c[2] = '\0';
150	while (*p) {
151		c[0] = *p++;
152		c[1] = *p++;
153		/* Ensure that digits are hex */
154		if (isxdigit((unsigned char)c[0]) == 0 ||
155		    isxdigit((unsigned char)c[1]) == 0)
156		{
157			errno = EINVAL;
158			return 0;
159		}
160		/* We should have at least two entries 00:01 */
161		if (len == 0 && *p == '\0') {
162			errno = EINVAL;
163			return 0;
164		}
165		/* Ensure that next data is EOL or a seperator with data */
166		if (!(*p == '\0' || (*p == ':' && *(p + 1) != '\0'))) {
167			errno = EINVAL;
168			return 0;
169		}
170		if (*p)
171			p++;
172		if (bp)
173			*bp++ = (unsigned char)strtol(c, NULL, 16);
174		len++;
175	}
176	return len;
177}
178
179int
180do_interface(const char *ifname,
181	     _unused unsigned char *hwaddr, _unused size_t *hwlen,
182	     struct in_addr *addr, struct in_addr *net, int get)
183{
184	int s;
185	struct ifconf ifc;
186	int retval = 0, found = 0;
187	int len = 10 * sizeof(struct ifreq);
188	int lastlen = 0;
189	char *p;
190	union {
191		char *buffer;
192		struct ifreq *ifr;
193	} ifreqs;
194	struct sockaddr_in address;
195	struct ifreq *ifr;
196	struct sockaddr_in netmask;
197#ifdef AF_LINK
198	struct sockaddr_dl *sdl;
199#endif
200
201	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
202		return -1;
203
204	/* Not all implementations return the needed buffer size for
205	 * SIOGIFCONF so we loop like so for all until it works */
206	memset(&ifc, 0, sizeof(ifc));
207	for (;;) {
208		ifc.ifc_len = len;
209		ifc.ifc_buf = xmalloc((size_t)len);
210		if (ioctl(s, SIOCGIFCONF, &ifc) == -1) {
211			if (errno != EINVAL || lastlen != 0) {
212				close(s);
213				free(ifc.ifc_buf);
214				return -1;
215			}
216		} else {
217			if (ifc.ifc_len == lastlen)
218				break;
219			lastlen = ifc.ifc_len;
220		}
221
222		free(ifc.ifc_buf);
223		ifc.ifc_buf = NULL;
224		len *= 2;
225	}
226
227	for (p = (char *)ifc.ifc_buf; p < (char *)ifc.ifc_buf + ifc.ifc_len;) {
228		/* Cast the ifc buffer to an ifreq cleanly */
229		ifreqs.buffer = p;
230		ifr = ifreqs.ifr;
231
232#ifndef __linux__
233		if (ifr->ifr_addr.sa_len > sizeof(ifr->ifr_ifru))
234			p += offsetof(struct ifreq, ifr_ifru) +
235				ifr->ifr_addr.sa_len;
236		else
237#endif
238			p += sizeof(*ifr);
239
240		if (strcmp(ifname, ifr->ifr_name) != 0)
241			continue;
242
243		found = 1;
244
245#ifdef AF_LINK
246		if (hwaddr && hwlen && ifr->ifr_addr.sa_family == AF_LINK) {
247			sdl = xmalloc(ifr->ifr_addr.sa_len);
248			memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
249			*hwlen = sdl->sdl_alen;
250			memcpy(hwaddr, LLADDR(sdl), *hwlen);
251			free(sdl);
252			retval = 1;
253			break;
254		}
255#endif
256
257		if (ifr->ifr_addr.sa_family == AF_INET)	{
258			memcpy(&address, &ifr->ifr_addr, sizeof(address));
259			if (ioctl(s, SIOCGIFNETMASK, ifr) == -1)
260				continue;
261			memcpy(&netmask, &ifr->ifr_addr, sizeof(netmask));
262			if (get) {
263				addr->s_addr = address.sin_addr.s_addr;
264				net->s_addr = netmask.sin_addr.s_addr;
265				retval = 1;
266				break;
267			} else {
268				if (address.sin_addr.s_addr == addr->s_addr &&
269				    (!net ||
270				     netmask.sin_addr.s_addr == net->s_addr))
271				{
272					retval = 1;
273					break;
274				}
275			}
276		}
277
278	}
279
280	if (!found)
281		errno = ENXIO;
282	close(s);
283	free(ifc.ifc_buf);
284	return retval;
285}
286
287int
288up_interface(const char *ifname)
289{
290	int s;
291	struct ifreq ifr;
292	int retval = -1;
293#ifdef __linux__
294	char *p;
295#endif
296
297	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
298		return -1;
299	memset(&ifr, 0, sizeof(ifr));
300	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
301#ifdef __linux__
302	/* We can only bring the real interface up */
303	if ((p = strchr(ifr.ifr_name, ':')))
304		*p = '\0';
305#endif
306	if (ioctl(s, SIOCGIFFLAGS, &ifr) == 0) {
307		if ((ifr.ifr_flags & IFF_UP))
308			retval = 0;
309		else {
310			ifr.ifr_flags |= IFF_UP;
311			if (ioctl(s, SIOCSIFFLAGS, &ifr) == 0)
312				retval = 0;
313		}
314	}
315	close(s);
316	return retval;
317}
318
319int
320carrier_status(const char *ifname)
321{
322	int s;
323	struct ifreq ifr;
324	int retval = -1;
325#ifdef SIOCGIFMEDIA
326	struct ifmediareq ifmr;
327#endif
328#ifdef __linux__
329	char *p;
330#endif
331
332	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
333		return -1;
334	memset(&ifr, 0, sizeof(ifr));
335	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
336#ifdef __linux__
337	/* We can only test the real interface up */
338	if ((p = strchr(ifr.ifr_name, ':')))
339		*p = '\0';
340#endif
341	if ((retval = ioctl(s, SIOCGIFFLAGS, &ifr)) == 0) {
342		if (ifr.ifr_flags & IFF_UP && ifr.ifr_flags & IFF_RUNNING)
343			retval = 1;
344		else
345			retval = 0;
346	}
347
348#ifdef SIOCGIFMEDIA
349	if (retval == 1) {
350		memset(&ifmr, 0, sizeof(ifmr));
351		strncpy(ifmr.ifm_name, ifr.ifr_name, sizeof(ifmr.ifm_name));
352		if (ioctl(s, SIOCGIFMEDIA, &ifmr) != -1 &&
353		    ifmr.ifm_status & IFM_AVALID)
354		{
355			if (!(ifmr.ifm_status & IFM_ACTIVE))
356				retval = 0;
357		}
358	}
359#endif
360	close(s);
361	return retval;
362}
363
364struct interface *
365read_interface(const char *ifname, _unused int metric)
366{
367	int s;
368	struct ifreq ifr;
369	struct interface *iface = NULL;
370	unsigned char *hwaddr = NULL;
371	size_t hwlen = 0;
372	sa_family_t family = 0;
373
374	memset(&ifr, 0, sizeof(ifr));
375	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
376
377	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
378		return NULL;
379
380#ifdef __linux__
381	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
382	if (ioctl(s, SIOCGIFHWADDR, &ifr) == -1)
383		goto eexit;
384
385	switch (ifr.ifr_hwaddr.sa_family) {
386	case ARPHRD_ETHER:
387	case ARPHRD_IEEE802:
388		hwlen = ETHER_ADDR_LEN;
389		break;
390	case ARPHRD_IEEE1394:
391		hwlen = EUI64_ADDR_LEN;
392	case ARPHRD_INFINIBAND:
393		hwlen = INFINIBAND_ADDR_LEN;
394		break;
395	}
396
397	hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN);
398	memcpy(hwaddr, ifr.ifr_hwaddr.sa_data, hwlen);
399	family = ifr.ifr_hwaddr.sa_family;
400#else
401	ifr.ifr_metric = metric;
402	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
403	if (ioctl(s, SIOCSIFMETRIC, &ifr) == -1)
404		goto eexit;
405
406	hwaddr = xmalloc(sizeof(unsigned char) * HWADDR_LEN);
407	if (do_interface(ifname, hwaddr, &hwlen, NULL, NULL, 0) != 1)
408		goto eexit;
409
410	family = ARPHRD_ETHER;
411#endif
412
413	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
414	if (ioctl(s, SIOCGIFMTU, &ifr) == -1)
415		goto eexit;
416
417	/* Ensure that the MTU is big enough for DHCP */
418	if (ifr.ifr_mtu < MTU_MIN) {
419		ifr.ifr_mtu = MTU_MIN;
420		strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
421		if (ioctl(s, SIOCSIFMTU, &ifr) == -1)
422			goto eexit;
423	}
424
425	if (up_interface(ifname) != 0)
426		goto eexit;
427
428	iface = xzalloc(sizeof(*iface));
429	strlcpy(iface->name, ifname, IF_NAMESIZE);
430	snprintf(iface->leasefile, PATH_MAX, LEASEFILE, ifname);
431	memcpy(&iface->hwaddr, hwaddr, hwlen);
432	iface->hwlen = hwlen;
433
434	iface->family = family;
435	iface->arpable = !(ifr.ifr_flags & (IFF_NOARP | IFF_LOOPBACK));
436
437	/* 0 is a valid fd, so init to -1 */
438	iface->raw_fd = -1;
439	iface->udp_fd = -1;
440	iface->arp_fd = -1;
441	iface->link_fd = -1;
442
443eexit:
444	close(s);
445	free(hwaddr);
446	return iface;
447}
448
449int
450do_mtu(const char *ifname, short int mtu)
451{
452	struct ifreq ifr;
453	int r;
454	int s;
455
456	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
457		return -1;
458
459	memset(&ifr, 0, sizeof(ifr));
460	strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
461	ifr.ifr_mtu = mtu;
462	r = ioctl(s, mtu ? SIOCSIFMTU : SIOCGIFMTU, &ifr);
463	close(s);
464	if (r == -1)
465		return -1;
466	return ifr.ifr_mtu;
467}
468
469void
470free_routes(struct rt *routes)
471{
472	struct rt *r;
473
474	while (routes) {
475		r = routes->next;
476		free(routes);
477		routes = r;
478	}
479}
480
481int
482open_udp_socket(struct interface *iface)
483{
484	int s;
485	union sockunion {
486		struct sockaddr sa;
487		struct sockaddr_in sin;
488	} su;
489	int n;
490#ifdef SO_BINDTODEVICE
491	struct ifreq ifr;
492#endif
493
494	if ((s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
495		return -1;
496
497	n = 1;
498	if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)) == -1)
499		goto eexit;
500#ifdef SO_BINDTODEVICE
501	memset(&ifr, 0, sizeof(ifr));
502	strlcpy(ifr.ifr_name, iface->name, sizeof(ifr.ifr_name));
503	if (setsockopt(s, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr)) == -1)
504		goto eexit;
505#endif
506	/* As we don't use this socket for receiving, set the
507	 * receive buffer to 1 */
508	n = 1;
509	if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) == -1)
510		goto eexit;
511	memset(&su, 0, sizeof(su));
512	su.sin.sin_family = AF_INET;
513	su.sin.sin_port = htons(DHCP_CLIENT_PORT);
514	su.sin.sin_addr.s_addr = iface->addr.s_addr;
515	if (bind(s, &su.sa, sizeof(su)) == -1)
516		goto eexit;
517
518	iface->udp_fd = s;
519	set_cloexec(s);
520	return 0;
521
522eexit:
523	close(s);
524	return -1;
525}
526
527ssize_t
528send_packet(const struct interface *iface, struct in_addr to,
529	    const uint8_t *data, ssize_t len)
530{
531	union sockunion {
532		struct sockaddr sa;
533		struct sockaddr_in sin;
534	} su;
535
536	memset(&su, 0, sizeof(su));
537	su.sin.sin_family = AF_INET;
538	su.sin.sin_addr.s_addr = to.s_addr;
539	su.sin.sin_port = htons(DHCP_SERVER_PORT);
540
541	return sendto(iface->udp_fd, data, len, 0, &su.sa, sizeof(su));
542}
543
544struct udp_dhcp_packet
545{
546	struct ip ip;
547	struct udphdr udp;
548	struct dhcp_message dhcp;
549};
550const size_t udp_dhcp_len = sizeof(struct udp_dhcp_packet);
551
552static uint16_t
553checksum(const void *data, uint16_t len)
554{
555	const uint8_t *addr = data;
556	uint32_t sum = 0;
557
558	while (len > 1) {
559		sum += addr[0] * 256 + addr[1];
560		addr += 2;
561		len -= 2;
562	}
563
564	if (len == 1)
565		sum += *addr * 256;
566
567	sum = (sum >> 16) + (sum & 0xffff);
568	sum += (sum >> 16);
569
570	sum = htons(sum);
571
572	return ~sum;
573}
574
575ssize_t
576make_udp_packet(uint8_t **packet, const uint8_t *data, size_t length,
577		struct in_addr source, struct in_addr dest)
578{
579	struct udp_dhcp_packet *udpp;
580	struct ip *ip;
581	struct udphdr *udp;
582
583	udpp = xzalloc(sizeof(*udpp));
584	ip = &udpp->ip;
585	udp = &udpp->udp;
586
587	/* OK, this is important :)
588	 * We copy the data to our packet and then create a small part of the
589	 * ip structure and an invalid ip_len (basically udp length).
590	 * We then fill the udp structure and put the checksum
591	 * of the whole packet into the udp checksum.
592	 * Finally we complete the ip structure and ip checksum.
593	 * If we don't do the ordering like so then the udp checksum will be
594	 * broken, so find another way of doing it! */
595
596	memcpy(&udpp->dhcp, data, length);
597
598	ip->ip_p = IPPROTO_UDP;
599	ip->ip_src.s_addr = source.s_addr;
600	if (dest.s_addr == 0)
601		ip->ip_dst.s_addr = INADDR_BROADCAST;
602	else
603		ip->ip_dst.s_addr = dest.s_addr;
604
605	udp->uh_sport = htons(DHCP_CLIENT_PORT);
606	udp->uh_dport = htons(DHCP_SERVER_PORT);
607	udp->uh_ulen = htons(sizeof(*udp) + length);
608	ip->ip_len = udp->uh_ulen;
609	udp->uh_sum = checksum(udpp, sizeof(*udpp));
610
611	ip->ip_v = IPVERSION;
612	ip->ip_hl = 5;
613	ip->ip_id = 0;
614	ip->ip_tos = IPTOS_LOWDELAY;
615	ip->ip_len = htons (sizeof(*ip) + sizeof(*udp) + length);
616	ip->ip_id = 0;
617	ip->ip_off = htons(IP_DF); /* Don't fragment */
618	ip->ip_ttl = IPDEFTTL;
619
620	ip->ip_sum = checksum(ip, sizeof(*ip));
621
622	*packet = (uint8_t *)udpp;
623	return sizeof(*ip) + sizeof(*udp) + length;
624}
625
626ssize_t
627get_udp_data(const uint8_t **data, const uint8_t *udp)
628{
629	struct udp_dhcp_packet packet;
630
631	memcpy(&packet, udp, sizeof(packet));
632	*data = udp + offsetof(struct udp_dhcp_packet, dhcp);
633	return ntohs(packet.ip.ip_len) - sizeof(packet.ip) - sizeof(packet.udp);
634}
635
636int
637valid_udp_packet(const uint8_t *data)
638{
639	struct udp_dhcp_packet packet;
640	uint16_t bytes;
641	uint16_t ipsum;
642	uint16_t iplen;
643	uint16_t udpsum;
644	struct in_addr source;
645	struct in_addr dest;
646	int retval = 0;
647
648	memcpy(&packet, data, sizeof(packet));
649	bytes = ntohs(packet.ip.ip_len);
650	ipsum = packet.ip.ip_sum;
651	iplen = packet.ip.ip_len;
652	udpsum = packet.udp.uh_sum;
653
654	if (0 != checksum(&packet.ip, sizeof(packet.ip))) {
655		errno = EINVAL;
656		return -1;
657	}
658
659	packet.ip.ip_sum = 0;
660	memcpy(&source, &packet.ip.ip_src, sizeof(packet.ip.ip_src));
661	memcpy(&dest, &packet.ip.ip_dst, sizeof(packet.ip.ip_dst));
662	memset(&packet.ip, 0, sizeof(packet.ip));
663	packet.udp.uh_sum = 0;
664
665	packet.ip.ip_p = IPPROTO_UDP;
666	memcpy(&packet.ip.ip_src, &source, sizeof(packet.ip.ip_src));
667	memcpy(&packet.ip.ip_dst, &dest, sizeof(packet.ip.ip_dst));
668	packet.ip.ip_len = packet.udp.uh_ulen;
669	if (udpsum && udpsum != checksum(&packet, bytes)) {
670		errno = EINVAL;
671		retval = -1;
672	}
673
674	return retval;
675}
676
677int
678send_arp(const struct interface *iface, int op, in_addr_t sip, in_addr_t tip)
679{
680	struct arphdr *arp;
681	size_t arpsize;
682	uint8_t *p;
683	int retval;
684
685	arpsize = sizeof(*arp) + 2 * iface->hwlen + 2 * sizeof(sip);
686	arp = xmalloc(arpsize);
687	arp->ar_hrd = htons(iface->family);
688	arp->ar_pro = htons(ETHERTYPE_IP);
689	arp->ar_hln = iface->hwlen;
690	arp->ar_pln = sizeof(sip);
691	arp->ar_op = htons(op);
692	p = (uint8_t *)arp;
693	p += sizeof(*arp);
694	memcpy(p, iface->hwaddr, iface->hwlen);
695	p += iface->hwlen;
696	memcpy(p, &sip, sizeof(sip));
697	p += sizeof(sip);
698	/* ARP requests should ignore this */
699	retval = iface->hwlen;
700	while (retval--)
701		*p++ = '\0';
702	memcpy(p, &tip, sizeof(tip));
703	p += sizeof(tip);
704	retval = send_raw_packet(iface, ETHERTYPE_ARP, arp, arpsize);
705	free(arp);
706	return retval;
707}
708