1 /* vi: set sw=4 ts=4: */
2 /*
3  * udhcp server
4  * Copyright (C) 1999 Matthew Ramsay <matthewr@moreton.com.au>
5  *			Chris Trew <ctrew@moreton.com.au>
6  *
7  * Rewrite by Russ Dill <Russ.Dill@asu.edu> July 2001
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  */
23 //applet:IF_UDHCPD(APPLET(udhcpd, BB_DIR_USR_SBIN, BB_SUID_DROP))
24 
25 //kbuild:lib-$(CONFIG_UDHCPD) += common.o packet.o signalpipe.o socket.o
26 //kbuild:lib-$(CONFIG_UDHCPD) += dhcpd.o arpping.o
27 //kbuild:lib-$(CONFIG_FEATURE_UDHCP_RFC3397) += domain_codec.o
28 
29 //usage:#define udhcpd_trivial_usage
30 //usage:       "[-fS] [-I ADDR] [-a MSEC]" IF_FEATURE_UDHCP_PORT(" [-P PORT]") " [CONFFILE]"
31 //usage:#define udhcpd_full_usage "\n\n"
32 //usage:       "DHCP server\n"
33 //usage:     "\n	-f	Run in foreground"
34 //usage:     "\n	-S	Log to syslog too"
35 //usage:     "\n	-I ADDR	Local address"
36 //usage:     "\n	-a MSEC	Timeout for ARP ping (default 2000)"
37 //usage:	IF_FEATURE_UDHCP_PORT(
38 //usage:     "\n	-P PORT	Use PORT (default 67)"
39 //usage:	)
40 //usage:     "\nSignals:"
41 //usage:     "\n	USR1	Update lease file"
42 
43 #include <netinet/ether.h>
44 #include <syslog.h>
45 #include "common.h"
46 #include "dhcpc.h"
47 #include "dhcpd.h"
48 
49 #if ENABLE_PID_FILE_PATH
50 #define PID_FILE_PATH CONFIG_PID_FILE_PATH
51 #else
52 #define PID_FILE_PATH "/var/run"
53 #endif
54 
55 /* globals */
56 #define g_leases ((struct dyn_lease*)ptr_to_globals)
57 /* struct server_data_t server_data is in bb_common_bufsiz1 */
58 
59 struct static_lease {
60 	struct static_lease *next;
61 	uint32_t nip;
62 	uint8_t mac[6];
63 	uint8_t opt[1];
64 };
65 
66 /* Takes the address of the pointer to the static_leases linked list,
67  * address to a 6 byte mac address,
68  * 4 byte IP address */
add_static_lease(struct static_lease ** st_lease_pp,uint8_t * mac,uint32_t nip,const char * opts)69 static void add_static_lease(struct static_lease **st_lease_pp,
70 		uint8_t *mac,
71 		uint32_t nip,
72 		const char *opts)
73 {
74 	struct static_lease *st_lease;
75 	unsigned optlen;
76 
77 	optlen = (opts ? 1+1+strnlen(opts, 120) : 0);
78 
79 	/* Find the tail of the list */
80 	while ((st_lease = *st_lease_pp) != NULL) {
81 		st_lease_pp = &st_lease->next;
82 	}
83 
84 	/* Add new node */
85 	*st_lease_pp = st_lease = xzalloc(sizeof(*st_lease) + optlen);
86 	memcpy(st_lease->mac, mac, 6);
87 	st_lease->nip = nip;
88 	/*st_lease->next = NULL;*/
89 	if (optlen) {
90 		st_lease->opt[OPT_CODE] = DHCP_HOST_NAME;
91 		optlen -= 2;
92 		st_lease->opt[OPT_LEN] = optlen;
93 		memcpy(&st_lease->opt[OPT_DATA], opts, optlen);
94 	}
95 
96 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 2
97 	/* Print out static leases just to check what's going on */
98 	if (dhcp_verbose >= 2) {
99 		bb_info_msg("static lease: mac:%02x:%02x:%02x:%02x:%02x:%02x nip:%x",
100 			st_lease->mac[0], st_lease->mac[1], st_lease->mac[2],
101 			st_lease->mac[3], st_lease->mac[4], st_lease->mac[5],
102 			st_lease->nip
103 		);
104 	}
105 #endif
106 }
107 
108 /* Find static lease IP by mac */
get_static_nip_by_mac(void * mac)109 static uint32_t get_static_nip_by_mac(void *mac)
110 {
111 	struct static_lease *st_lease = server_data.static_leases;
112 
113 	while (st_lease) {
114 		if (memcmp(st_lease->mac, mac, 6) == 0)
115 			return st_lease->nip;
116 		st_lease = st_lease->next;
117 	}
118 
119 	return 0;
120 }
121 
is_nip_reserved_as_static(uint32_t nip)122 static int is_nip_reserved_as_static(uint32_t nip)
123 {
124 	struct static_lease *st_lease = server_data.static_leases;
125 
126 	while (st_lease) {
127 		if (st_lease->nip == nip)
128 			return 1;
129 		st_lease = st_lease->next;
130 	}
131 
132 	return 0;
133 }
134 
135 /* Find the oldest expired lease, NULL if there are no expired leases */
oldest_expired_lease(void)136 static struct dyn_lease *oldest_expired_lease(void)
137 {
138 	struct dyn_lease *oldest_lease = NULL;
139 	leasetime_t oldest_time = time(NULL);
140 	unsigned i;
141 
142 	/* Unexpired leases have g_leases[i].expires >= current time
143 	 * and therefore can't ever match */
144 	for (i = 0; i < server_data.max_leases; i++) {
145 		if (g_leases[i].expires == 0 /* empty entry */
146 		 || g_leases[i].expires < oldest_time
147 		) {
148 			oldest_time = g_leases[i].expires;
149 			oldest_lease = &g_leases[i];
150 		}
151 	}
152 	return oldest_lease;
153 }
154 
155 /* Clear out all leases with matching nonzero chaddr OR yiaddr.
156  * If chaddr == NULL, this is a conflict lease.
157  */
clear_leases(const uint8_t * chaddr,uint32_t yiaddr)158 static void clear_leases(const uint8_t *chaddr, uint32_t yiaddr)
159 {
160 	unsigned i;
161 
162 	for (i = 0; i < server_data.max_leases; i++) {
163 		if ((chaddr && memcmp(g_leases[i].lease_mac, chaddr, 6) == 0)
164 		 || (yiaddr && g_leases[i].lease_nip == yiaddr)
165 		) {
166 			memset(&g_leases[i], 0, sizeof(g_leases[i]));
167 		}
168 	}
169 }
170 
171 /* Add a lease into the table, clearing out any old ones.
172  * If chaddr == NULL, this is a conflict lease.
173  */
add_lease(const uint8_t * chaddr,uint32_t yiaddr,leasetime_t leasetime,const char * hostname,int hostname_len)174 static struct dyn_lease *add_lease(
175 		const uint8_t *chaddr, uint32_t yiaddr,
176 		leasetime_t leasetime,
177 		const char *hostname, int hostname_len)
178 {
179 	struct dyn_lease *oldest;
180 
181 	/* clean out any old ones */
182 	clear_leases(chaddr, yiaddr);
183 
184 	oldest = oldest_expired_lease();
185 
186 	if (oldest) {
187 		memset(oldest, 0, sizeof(*oldest));
188 		if (hostname) {
189 			char *p;
190 
191 			hostname_len++; /* include NUL */
192 			if (hostname_len > sizeof(oldest->hostname))
193 				hostname_len = sizeof(oldest->hostname);
194 			p = safe_strncpy(oldest->hostname, hostname, hostname_len);
195 			/*
196 			 * Sanitization (s/bad_char/./g).
197 			 * The intent is not to allow only "DNS-valid" hostnames,
198 			 * but merely make dumpleases output safe for shells to use.
199 			 * We accept "0-9A-Za-z._-", all other chars turn to dots.
200 			 */
201 			if (*p == '-')
202 				*p = '.'; /* defeat "-option" attacks too */
203 			while (*p) {
204 				if (!isalnum(*p) && *p != '-' && *p != '_')
205 					*p = '.';
206 				p++;
207 			}
208 		}
209 		if (chaddr)
210 			memcpy(oldest->lease_mac, chaddr, 6);
211 		oldest->lease_nip = yiaddr;
212 		oldest->expires = time(NULL) + leasetime;
213 	}
214 
215 	return oldest;
216 }
217 
218 /* True if a lease has expired */
is_expired_lease(struct dyn_lease * lease)219 static int is_expired_lease(struct dyn_lease *lease)
220 {
221 	return (lease->expires < (leasetime_t) time(NULL));
222 }
223 
224 /* Find the first lease that matches MAC, NULL if no match */
find_lease_by_mac(const uint8_t * mac)225 static struct dyn_lease *find_lease_by_mac(const uint8_t *mac)
226 {
227 	unsigned i;
228 
229 	for (i = 0; i < server_data.max_leases; i++)
230 		if (memcmp(g_leases[i].lease_mac, mac, 6) == 0)
231 			return &g_leases[i];
232 
233 	return NULL;
234 }
235 
236 /* Find the first lease that matches IP, NULL is no match */
find_lease_by_nip(uint32_t nip)237 static struct dyn_lease *find_lease_by_nip(uint32_t nip)
238 {
239 	unsigned i;
240 
241 	for (i = 0; i < server_data.max_leases; i++)
242 		if (g_leases[i].lease_nip == nip)
243 			return &g_leases[i];
244 
245 	return NULL;
246 }
247 
248 /* Check if the IP is taken; if it is, add it to the lease table */
nobody_responds_to_arp(uint32_t nip,const uint8_t * safe_mac,unsigned arpping_ms)249 static int nobody_responds_to_arp(uint32_t nip, const uint8_t *safe_mac, unsigned arpping_ms)
250 {
251 	struct in_addr temp;
252 	int r;
253 
254 	r = arpping(nip, safe_mac,
255 			server_data.server_nip,
256 			server_data.server_mac,
257 			server_data.interface,
258 			arpping_ms);
259 	if (r)
260 		return r;
261 
262 	temp.s_addr = nip;
263 	bb_info_msg("%s belongs to someone, reserving it for %u seconds",
264 		inet_ntoa(temp), (unsigned)server_data.conflict_time);
265 	add_lease(NULL, nip, server_data.conflict_time, NULL, 0);
266 	return 0;
267 }
268 
269 /* Find a new usable (we think) address */
find_free_or_expired_nip(const uint8_t * safe_mac,unsigned arpping_ms)270 static uint32_t find_free_or_expired_nip(const uint8_t *safe_mac, unsigned arpping_ms)
271 {
272 	uint32_t addr;
273 	struct dyn_lease *oldest_lease = NULL;
274 
275 #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
276 	uint32_t stop;
277 	unsigned i, hash;
278 
279 	/* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
280 	 * dispersal even with similarly-valued "strings".
281 	 */
282 	hash = 0;
283 	for (i = 0; i < 6; i++)
284 		hash += safe_mac[i] + (hash << 6) + (hash << 16) - hash;
285 
286 	/* pick a seed based on hwaddr then iterate until we find a free address. */
287 	addr = server_data.start_ip
288 		+ (hash % (1 + server_data.end_ip - server_data.start_ip));
289 	stop = addr;
290 #else
291 	addr = server_data.start_ip;
292 #define stop (server_data.end_ip + 1)
293 #endif
294 	do {
295 		uint32_t nip;
296 		struct dyn_lease *lease;
297 
298 		/* (Addresses ending in .0 or .255 can legitimately be allocated
299 		 * in various situations, so _don't_ skip these.  The user needs
300 		 * to choose start_ip and end_ip correctly for a particular
301 		 * network environment.) */
302 
303 		nip = htonl(addr);
304 		/* skip our own address */
305 		if (nip == server_data.server_nip)
306 			goto next_addr;
307 		/* is this a static lease addr? */
308 		if (is_nip_reserved_as_static(nip))
309 			goto next_addr;
310 
311 		lease = find_lease_by_nip(nip);
312 		if (!lease) {
313 //TODO: DHCP servers do not always sit on the same subnet as clients: should *ping*, not arp-ping!
314 			if (nobody_responds_to_arp(nip, safe_mac, arpping_ms))
315 				return nip;
316 		} else {
317 			if (!oldest_lease || lease->expires < oldest_lease->expires)
318 				oldest_lease = lease;
319 		}
320 
321  next_addr:
322 		addr++;
323 #if ENABLE_FEATURE_UDHCPD_BASE_IP_ON_MAC
324 		if (addr > server_data.end_ip)
325 			addr = server_data.start_ip;
326 #endif
327 	} while (addr != stop);
328 
329 	if (oldest_lease
330 	 && is_expired_lease(oldest_lease)
331 	 && nobody_responds_to_arp(oldest_lease->lease_nip, safe_mac, arpping_ms)
332 	) {
333 		return oldest_lease->lease_nip;
334 	}
335 
336 	return 0;
337 }
338 
339 /* On these functions, make sure your datatype matches */
read_str(const char * line,void * arg)340 static int FAST_FUNC read_str(const char *line, void *arg)
341 {
342 	char **dest = arg;
343 
344 	free(*dest);
345 	*dest = xstrdup(line);
346 	return 1;
347 }
348 
read_u32(const char * line,void * arg)349 static int FAST_FUNC read_u32(const char *line, void *arg)
350 {
351 	*(uint32_t*)arg = bb_strtou32(line, NULL, 10);
352 	return errno == 0;
353 }
354 
read_staticlease(const char * const_line,void * arg)355 static int FAST_FUNC read_staticlease(const char *const_line, void *arg)
356 {
357 	char *line;
358 	char *mac_string;
359 	char *ip_string;
360 	char *opts;
361 	struct ether_addr mac_bytes; /* it's "struct { uint8_t mac[6]; }" */
362 	uint32_t nip;
363 
364 	/* Read mac */
365 	line = (char *) const_line;
366 	mac_string = strtok_r(line, " \t", &line);
367 	if (!mac_string || !ether_aton_r(mac_string, &mac_bytes))
368 		return 0;
369 
370 	/* Read ip */
371 	ip_string = strtok_r(NULL, " \t", &line);
372 	if (!ip_string || !udhcp_str2nip(ip_string, &nip))
373 		return 0;
374 
375 	opts = strtok_r(NULL, " \t", &line);
376 	/* opts might be NULL, that's not an error */
377 
378 	add_static_lease(arg, (uint8_t*) &mac_bytes, nip, opts);
379 
380 	return 1;
381 }
382 
read_optset(const char * line,void * arg)383 static int FAST_FUNC read_optset(const char *line, void *arg)
384 {
385 	return udhcp_str2optset(line, arg,
386 			dhcp_optflags, dhcp_option_strings,
387 			/*dhcpv6:*/ 0
388 	);
389 }
390 
391 struct config_keyword {
392 	const char *keyword;
393 	int (*handler)(const char *line, void *var) FAST_FUNC;
394 	unsigned ofs;
395 	const char *def;
396 };
397 
398 #define OFS(field) offsetof(struct server_data_t, field)
399 
400 static const struct config_keyword keywords[] ALIGN_PTR = {
401 	/* keyword        handler           variable address    default */
402 	{"start"        , udhcp_str2nip   , OFS(start_ip     ), "192.168.0.20"},
403 	{"end"          , udhcp_str2nip   , OFS(end_ip       ), "192.168.0.254"},
404 	{"interface"    , read_str        , OFS(interface    ), "eth0"},
405 	/* Avoid "max_leases value not sane" warning by setting default
406 	 * to default_end_ip - default_start_ip + 1: */
407 	{"max_leases"   , read_u32        , OFS(max_leases   ), "235"},
408 	{"auto_time"    , read_u32        , OFS(auto_time    ), "7200"},
409 	{"decline_time" , read_u32        , OFS(decline_time ), "3600"},
410 	{"conflict_time", read_u32        , OFS(conflict_time), "3600"},
411 	{"offer_time"   , read_u32        , OFS(offer_time   ), "60"},
412 	{"min_lease"    , read_u32        , OFS(min_lease_sec), "60"},
413 	{"lease_file"   , read_str        , OFS(lease_file   ), LEASES_FILE},
414 	{"pidfile"      , read_str        , OFS(pidfile      ), PID_FILE_PATH "/udhcpd.pid"},
415 	{"siaddr"       , udhcp_str2nip   , OFS(siaddr_nip   ), "0.0.0.0"},
416 	/* keywords with no defaults must be last! */
417 	{"option"       , read_optset     , OFS(options      ), ""},
418 	{"opt"          , read_optset     , OFS(options      ), ""},
419 	{"notify_file"  , read_str        , OFS(notify_file  ), NULL},
420 	{"sname"        , read_str        , OFS(sname        ), NULL},
421 	{"boot_file"    , read_str        , OFS(boot_file    ), NULL},
422 	{"static_lease" , read_staticlease, OFS(static_leases), ""},
423 };
424 enum { KWS_WITH_DEFAULTS = ARRAY_SIZE(keywords) - 6 };
425 
read_config(const char * file)426 static NOINLINE void read_config(const char *file)
427 {
428 	parser_t *parser;
429 	const struct config_keyword *k;
430 	unsigned i;
431 	char *token[2];
432 
433 	for (i = 0; i < KWS_WITH_DEFAULTS; i++)
434 		keywords[i].handler(keywords[i].def, (char*)&server_data + keywords[i].ofs);
435 
436 	parser = config_open(file);
437 	while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) {
438 		for (k = keywords, i = 0; i < ARRAY_SIZE(keywords); k++, i++) {
439 			if (strcasecmp(token[0], k->keyword) == 0) {
440 				if (!k->handler(token[1], (char*)&server_data + k->ofs)) {
441 					bb_error_msg("can't parse line %u in %s",
442 							parser->lineno, file);
443 					/* reset back to the default value */
444 					k->handler(k->def, (char*)&server_data + k->ofs);
445 				}
446 				break;
447 			}
448 		}
449 	}
450 	config_close(parser);
451 
452 	server_data.start_ip = ntohl(server_data.start_ip);
453 	server_data.end_ip = ntohl(server_data.end_ip);
454 	if (server_data.start_ip > server_data.end_ip)
455 		bb_error_msg_and_die("bad start/end IP range in %s", file);
456 }
457 
write_leases(void)458 static void write_leases(void)
459 {
460 	int fd;
461 	unsigned i;
462 	leasetime_t curr;
463 	int64_t written_at;
464 
465 	fd = open_or_warn(server_data.lease_file, O_WRONLY|O_CREAT|O_TRUNC);
466 	if (fd < 0)
467 		return;
468 
469 	curr = written_at = time(NULL);
470 
471 	written_at = SWAP_BE64(written_at);
472 	full_write(fd, &written_at, sizeof(written_at));
473 
474 	for (i = 0; i < server_data.max_leases; i++) {
475 		leasetime_t tmp_time;
476 
477 		if (g_leases[i].lease_nip == 0)
478 			continue;
479 
480 		/* Screw with the time in the struct, for easier writing */
481 		tmp_time = g_leases[i].expires;
482 
483 		g_leases[i].expires -= curr;
484 		if ((signed_leasetime_t) g_leases[i].expires < 0)
485 			g_leases[i].expires = 0;
486 		g_leases[i].expires = htonl(g_leases[i].expires);
487 
488 		/* No error check. If the file gets truncated,
489 		 * we lose some leases on restart. Oh well. */
490 		full_write(fd, &g_leases[i], sizeof(g_leases[i]));
491 
492 		/* Then restore it when done */
493 		g_leases[i].expires = tmp_time;
494 	}
495 	close(fd);
496 
497 	if (server_data.notify_file) {
498 		char *argv[3];
499 		argv[0] = server_data.notify_file;
500 		argv[1] = server_data.lease_file;
501 		argv[2] = NULL;
502 		spawn_and_wait(argv);
503 	}
504 }
505 
read_leases(const char * file)506 static NOINLINE void read_leases(const char *file)
507 {
508 	struct dyn_lease lease;
509 	int64_t written_at, time_passed;
510 	int fd;
511 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
512 	unsigned i = 0;
513 #endif
514 
515 	fd = open_or_warn(file, O_RDONLY);
516 	if (fd < 0)
517 		return;
518 
519 	if (full_read(fd, &written_at, sizeof(written_at)) != sizeof(written_at))
520 		goto ret;
521 	written_at = SWAP_BE64(written_at);
522 
523 	time_passed = time(NULL) - written_at;
524 	/* Strange written_at, or lease file from old version of udhcpd
525 	 * which had no "written_at" field? */
526 	if ((uint64_t)time_passed > 12 * 60 * 60)
527 		goto ret;
528 
529 	while (full_read(fd, &lease, sizeof(lease)) == sizeof(lease)) {
530 		uint32_t y = ntohl(lease.lease_nip);
531 		if (y >= server_data.start_ip && y <= server_data.end_ip) {
532 			signed_leasetime_t expires = ntohl(lease.expires) - (signed_leasetime_t)time_passed;
533 			uint32_t static_nip;
534 
535 			if (expires <= 0)
536 				/* We keep expired leases: add_lease() will add
537 				 * a lease with 0 seconds remaining.
538 				 * Fewer IP address changes this way for mass reboot scenario.
539 				 */
540 				expires = 0;
541 
542 			/* Check if there is a different static lease for this IP or MAC */
543 			static_nip = get_static_nip_by_mac(lease.lease_mac);
544 			if (static_nip) {
545 				/* NB: we do not add lease even if static_nip == lease.lease_nip.
546 				 */
547 				continue;
548 			}
549 			if (is_nip_reserved_as_static(lease.lease_nip))
550 				continue;
551 
552 			/* NB: add_lease takes "relative time", IOW,
553 			 * lease duration, not lease deadline. */
554 			if (add_lease(lease.lease_mac, lease.lease_nip,
555 					expires,
556 					lease.hostname, sizeof(lease.hostname)
557 				) == 0
558 			) {
559 				bb_error_msg("too many leases while loading %s", file);
560 				break;
561 			}
562 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
563 			i++;
564 #endif
565 		}
566 	}
567 	log1("read %d leases", i);
568  ret:
569 	close(fd);
570 }
571 
572 /* Send a packet to a specific mac address and ip address by creating our own ip packet */
send_packet_to_client(struct dhcp_packet * dhcp_pkt,int force_broadcast)573 static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
574 {
575 	const uint8_t *chaddr;
576 	uint32_t ciaddr;
577 
578 	// Was:
579 	//if (force_broadcast) { /* broadcast */ }
580 	//else if (dhcp_pkt->ciaddr) { /* unicast to dhcp_pkt->ciaddr */ }
581 	//else if (dhcp_pkt->flags & htons(BROADCAST_FLAG)) { /* broadcast */ }
582 	//else { /* unicast to dhcp_pkt->yiaddr */ }
583 	// But this is wrong: yiaddr is _our_ idea what client's IP is
584 	// (for example, from lease file). Client may not know that,
585 	// and may not have UDP socket listening on that IP!
586 	// We should never unicast to dhcp_pkt->yiaddr!
587 	// dhcp_pkt->ciaddr, OTOH, comes from client's request packet,
588 	// and can be used.
589 
590 	if (force_broadcast
591 	 || (dhcp_pkt->flags & htons(BROADCAST_FLAG))
592 	 || dhcp_pkt->ciaddr == 0
593 	) {
594 		log1s("broadcasting packet to client");
595 		ciaddr = INADDR_BROADCAST;
596 		chaddr = MAC_BCAST_ADDR;
597 	} else {
598 		log1s("unicasting packet to client ciaddr");
599 		ciaddr = dhcp_pkt->ciaddr;
600 		chaddr = dhcp_pkt->chaddr;
601 	}
602 
603 	udhcp_send_raw_packet(dhcp_pkt,
604 		/*src*/ server_data.server_nip, SERVER_PORT,
605 		/*dst*/ ciaddr, CLIENT_PORT, chaddr,
606 		server_data.ifindex);
607 }
608 
609 /* Send a packet to gateway_nip using the kernel ip stack */
send_packet_to_relay(struct dhcp_packet * dhcp_pkt)610 static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
611 {
612 	log1s("forwarding packet to relay");
613 
614 	udhcp_send_kernel_packet(dhcp_pkt,
615 			server_data.server_nip, SERVER_PORT,
616 			dhcp_pkt->gateway_nip, SERVER_PORT,
617 	/* Yes, relay agents receive (and send) all their packets on SERVER_PORT,
618 	 * even those which are clients' requests and would normally
619 	 * (i.e. without relay) use CLIENT_PORT. See RFC 1542.
620 	 */
621 			server_data.interface);
622 }
623 
send_packet(struct dhcp_packet * dhcp_pkt,int force_broadcast)624 static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast)
625 {
626 	if (dhcp_pkt->gateway_nip)
627 		send_packet_to_relay(dhcp_pkt);
628 	else
629 		send_packet_to_client(dhcp_pkt, force_broadcast);
630 }
631 
send_packet_verbose(struct dhcp_packet * dhcp_pkt,const char * fmt)632 static void send_packet_verbose(struct dhcp_packet *dhcp_pkt, const char *fmt)
633 {
634 	struct in_addr addr;
635 	addr.s_addr = dhcp_pkt->yiaddr;
636 	bb_info_msg(fmt, inet_ntoa(addr));
637 	/* send_packet emits error message itself if it detects failure */
638 	send_packet(dhcp_pkt, /*force_bcast:*/ 0);
639 }
640 
init_packet(struct dhcp_packet * packet,struct dhcp_packet * oldpacket,char type)641 static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacket, char type)
642 {
643 	/* Sets op, htype, hlen, cookie fields
644 	 * and adds DHCP_MESSAGE_TYPE option */
645 	udhcp_init_header(packet, type);
646 
647 	packet->xid = oldpacket->xid;
648 	memcpy(packet->chaddr, oldpacket->chaddr, sizeof(oldpacket->chaddr));
649 	packet->flags = oldpacket->flags;
650 	packet->gateway_nip = oldpacket->gateway_nip;
651 	packet->ciaddr = oldpacket->ciaddr;
652 	udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_data.server_nip);
653 }
654 
655 /* Fill options field, siaddr_nip, and sname and boot_file fields.
656  * TODO: teach this code to use overload option.
657  */
add_server_options(struct dhcp_packet * packet)658 static void add_server_options(struct dhcp_packet *packet)
659 {
660 	struct option_set *config_opts;
661 	uint8_t *client_hostname_opt;
662 
663 	client_hostname_opt = NULL;
664 	if (packet->yiaddr) { /* if we aren't from send_inform()... */
665 		struct static_lease *st_lease = server_data.static_leases;
666 		while (st_lease) {
667 			if (st_lease->nip == packet->yiaddr) {
668 				if (st_lease->opt[0] != 0)
669 					client_hostname_opt = st_lease->opt;
670 				break;
671 			}
672 			st_lease = st_lease->next;
673 		}
674 	}
675 
676 	config_opts = server_data.options;
677 	while (config_opts) {
678 		if (config_opts->data[OPT_CODE] != DHCP_LEASE_TIME) {
679 			/* ^^^^
680 			 * DHCP_LEASE_TIME is already filled, or in case of
681 			 * send_inform(), should not be filled at all.
682 			 */
683 			if (config_opts->data[OPT_CODE] != DHCP_HOST_NAME
684 			 || !client_hostname_opt
685 			) {
686 				/* Why "!client_hostname_opt":
687 				 * add hostname only if client has no hostname
688 				 * on its static lease line.
689 				 * (Not that "opt hostname HOST"
690 				 * makes much sense in udhcpd.conf,
691 				 * that'd give all clients the same hostname,
692 				 * but it's a valid configuration).
693 				 */
694 				udhcp_add_binary_option(packet, config_opts->data);
695 			}
696 		}
697 		config_opts = config_opts->next;
698 	}
699 
700 	if (client_hostname_opt)
701 		udhcp_add_binary_option(packet, client_hostname_opt);
702 
703 	packet->siaddr_nip = server_data.siaddr_nip;
704 
705 	if (server_data.sname)
706 		strncpy((char*)packet->sname, server_data.sname, sizeof(packet->sname) - 1);
707 	if (server_data.boot_file)
708 		strncpy((char*)packet->file, server_data.boot_file, sizeof(packet->file) - 1);
709 }
710 
select_lease_time(struct dhcp_packet * packet)711 static uint32_t select_lease_time(struct dhcp_packet *packet)
712 {
713 	uint32_t lease_time_sec = server_data.max_lease_sec;
714 	uint8_t *lease_time_opt = udhcp_get_option32(packet, DHCP_LEASE_TIME);
715 	if (lease_time_opt) {
716 		move_from_unaligned32(lease_time_sec, lease_time_opt);
717 		lease_time_sec = ntohl(lease_time_sec);
718 		if (lease_time_sec > server_data.max_lease_sec)
719 			lease_time_sec = server_data.max_lease_sec;
720 		if (lease_time_sec < server_data.min_lease_sec)
721 			lease_time_sec = server_data.min_lease_sec;
722 	}
723 	return lease_time_sec;
724 }
725 
726 /* We got a DHCP DISCOVER. Send an OFFER. */
727 /* NOINLINE: limit stack usage in caller */
send_offer(struct dhcp_packet * oldpacket,uint32_t static_lease_nip,struct dyn_lease * lease,uint32_t requested_nip,unsigned arpping_ms)728 static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
729 		uint32_t static_lease_nip,
730 		struct dyn_lease *lease,
731 		uint32_t requested_nip,
732 		unsigned arpping_ms)
733 {
734 	struct dhcp_packet packet;
735 	uint32_t lease_time_sec;
736 
737 	init_packet(&packet, oldpacket, DHCPOFFER);
738 
739 	/* If it is a static lease, use its IP */
740 	packet.yiaddr = static_lease_nip;
741 	/* Else: */
742 	if (!static_lease_nip) {
743 		/* We have no static lease for client's chaddr */
744 		const char *p_host_name;
745 
746 		if (lease) {
747 			/* We have a dynamic lease for client's chaddr.
748 			 * Reuse its IP (even if lease is expired).
749 			 * Note that we ignore requested IP in this case.
750 			 */
751 			packet.yiaddr = lease->lease_nip;
752 		}
753 		/* Or: if client has requested an IP */
754 		else if (requested_nip != 0
755 		 /* and the IP is in the lease range */
756 		 && ntohl(requested_nip) >= server_data.start_ip
757 		 && ntohl(requested_nip) <= server_data.end_ip
758 		 /* and */
759 		 && (  !(lease = find_lease_by_nip(requested_nip)) /* is not already taken */
760 		    || is_expired_lease(lease) /* or is taken, but expired */
761 		    )
762 		) {
763 			packet.yiaddr = requested_nip;
764 		}
765 		else {
766 			/* Otherwise, find a free IP */
767 			packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr, arpping_ms);
768 		}
769 
770 		if (!packet.yiaddr) {
771 			bb_simple_error_msg("no free IP addresses. OFFER abandoned");
772 			return;
773 		}
774 		/* Reserve the IP for a short time hoping to get DHCPREQUEST soon */
775 		p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
776 		lease = add_lease(packet.chaddr, packet.yiaddr,
777 				server_data.offer_time,
778 				p_host_name,
779 				p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0
780 		);
781 		if (!lease) {
782 			bb_simple_error_msg("no free IP addresses. OFFER abandoned");
783 			return;
784 		}
785 	}
786 
787 	lease_time_sec = select_lease_time(oldpacket);
788 	udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
789 	add_server_options(&packet);
790 
791 	/* send_packet emits error message itself if it detects failure */
792 	send_packet_verbose(&packet, "sending OFFER to %s");
793 }
794 
795 /* NOINLINE: limit stack usage in caller */
send_NAK(struct dhcp_packet * oldpacket)796 static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
797 {
798 	struct dhcp_packet packet;
799 
800 	init_packet(&packet, oldpacket, DHCPNAK);
801 
802 	log1("sending %s", "NAK");
803 	send_packet(&packet, /*force_bcast:*/ 1);
804 }
805 
806 /* NOINLINE: limit stack usage in caller */
send_ACK(struct dhcp_packet * oldpacket,uint32_t yiaddr)807 static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
808 {
809 	struct dhcp_packet packet;
810 	uint32_t lease_time_sec;
811 	const char *p_host_name;
812 
813 	init_packet(&packet, oldpacket, DHCPACK);
814 	packet.yiaddr = yiaddr;
815 
816 	lease_time_sec = select_lease_time(oldpacket);
817 	udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
818 	add_server_options(&packet);
819 
820 	send_packet_verbose(&packet, "sending ACK to %s");
821 
822 	p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
823 	add_lease(packet.chaddr, packet.yiaddr,
824 		lease_time_sec,
825 		p_host_name,
826 		p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0
827 	);
828 	if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) {
829 		/* rewrite the file with leases at every new acceptance */
830 		write_leases();
831 	}
832 }
833 
834 /* NOINLINE: limit stack usage in caller */
send_inform(struct dhcp_packet * oldpacket)835 static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
836 {
837 	struct dhcp_packet packet;
838 
839 	/* "If a client has obtained a network address through some other means
840 	 * (e.g., manual configuration), it may use a DHCPINFORM request message
841 	 * to obtain other local configuration parameters.  Servers receiving a
842 	 * DHCPINFORM message construct a DHCPACK message with any local
843 	 * configuration parameters appropriate for the client without:
844 	 * allocating a new address, checking for an existing binding, filling
845 	 * in 'yiaddr' or including lease time parameters.  The servers SHOULD
846 	 * unicast the DHCPACK reply to the address given in the 'ciaddr' field
847 	 * of the DHCPINFORM message.
848 	 * ...
849 	 * The server responds to a DHCPINFORM message by sending a DHCPACK
850 	 * message directly to the address given in the 'ciaddr' field
851 	 * of the DHCPINFORM message.  The server MUST NOT send a lease
852 	 * expiration time to the client and SHOULD NOT fill in 'yiaddr'."
853 	 */
854 //TODO: do a few sanity checks: is ciaddr set?
855 //Better yet: is ciaddr == IP source addr?
856 	init_packet(&packet, oldpacket, DHCPACK);
857 	add_server_options(&packet);
858 
859 	send_packet(&packet, /*force_bcast:*/ 0);
860 	// or maybe? send_packet_verbose(&packet, "sending ACK to %s");
861 }
862 
863 int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
udhcpd_main(int argc UNUSED_PARAM,char ** argv)864 int udhcpd_main(int argc UNUSED_PARAM, char **argv)
865 {
866 	int server_socket = -1, retval;
867 	unsigned timeout_end;
868 	unsigned num_ips;
869 	unsigned opt;
870 	struct option_set *option;
871 	char *str_I = str_I;
872 	const char *str_a = "2000";
873 	unsigned arpping_ms;
874 	IF_FEATURE_UDHCP_PORT(char *str_P;)
875 
876 	setup_common_bufsiz();
877 
878 	IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
879 	IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
880 
881 	/* Make sure fd 0,1,2 are open */
882 	/* Setup the signal pipe on fds 3,4 - must be before openlog() */
883 	udhcp_sp_setup();
884 
885 #define OPT_f (1 << 0)
886 #define OPT_S (1 << 1)
887 #define OPT_I (1 << 2)
888 #define OPT_v (1 << 3)
889 #define OPT_a (1 << 4)
890 #define OPT_P (1 << 5)
891 	opt = getopt32(argv, "^"
892 		"fSI:va:"IF_FEATURE_UDHCP_PORT("P:")
893 		"\0"
894 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
895 		"vv"
896 #endif
897 		, &str_I
898 		, &str_a
899 		IF_FEATURE_UDHCP_PORT(, &str_P)
900 		IF_UDHCP_VERBOSE(, &dhcp_verbose)
901 	);
902 	if (!(opt & OPT_f)) { /* no -f */
903 		bb_daemonize_or_rexec(0, argv);
904 		logmode = LOGMODE_NONE;
905 	}
906 	/* update argv after the possible vfork+exec in daemonize */
907 	argv += optind;
908 	if (opt & OPT_S) {
909 		openlog(applet_name, LOG_PID, LOG_DAEMON);
910 		logmode |= LOGMODE_SYSLOG;
911 	}
912 	if (opt & OPT_I) {
913 		len_and_sockaddr *lsa = xhost_and_af2sockaddr(str_I, 0, AF_INET);
914 		server_data.server_nip = lsa->u.sin.sin_addr.s_addr;
915 		free(lsa);
916 	}
917 #if ENABLE_FEATURE_UDHCP_PORT
918 	if (opt & OPT_P) {
919 		SERVER_PORT = xatou16(str_P);
920 		CLIENT_PORT = SERVER_PORT + 1;
921 	}
922 #endif
923 	arpping_ms = xatou(str_a);
924 
925 	/* Would rather not do read_config before daemonization -
926 	 * otherwise NOMMU machines will parse config twice */
927 	read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
928 	/* prevent poll timeout overflow */
929 	if (server_data.auto_time > INT_MAX / 1000)
930 		server_data.auto_time = INT_MAX / 1000;
931 
932 	/* Create pidfile */
933 	write_pidfile(server_data.pidfile);
934 	/* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
935 
936 	bb_simple_info_msg("started, v"BB_VER);
937 
938 	option = udhcp_find_option(server_data.options, DHCP_LEASE_TIME, /*dhcpv6:*/ 0);
939 	server_data.max_lease_sec = DEFAULT_LEASE_TIME;
940 	if (option) {
941 		move_from_unaligned32(server_data.max_lease_sec, option->data + OPT_DATA);
942 		server_data.max_lease_sec = ntohl(server_data.max_lease_sec);
943 	}
944 
945 	/* Sanity check */
946 	num_ips = server_data.end_ip - server_data.start_ip + 1;
947 	if (server_data.max_leases > num_ips) {
948 		bb_error_msg("max_leases=%u is too big, setting to %u",
949 			(unsigned)server_data.max_leases, num_ips);
950 		server_data.max_leases = num_ips;
951 	}
952 
953 	/* this sets g_leases */
954 	SET_PTR_TO_GLOBALS(xzalloc(server_data.max_leases * sizeof(g_leases[0])));
955 
956 	read_leases(server_data.lease_file);
957 
958 	if (udhcp_read_interface(server_data.interface,
959 			&server_data.ifindex,
960 			(server_data.server_nip == 0 ? &server_data.server_nip : NULL),
961 			server_data.server_mac)
962 	) {
963 		retval = 1;
964 		goto ret;
965 	}
966 
967  continue_with_autotime:
968 	timeout_end = monotonic_sec() + server_data.auto_time;
969 	while (1) { /* loop until universe collapses */
970 		struct pollfd pfds[2];
971 		struct dhcp_packet packet;
972 		int bytes;
973 		int tv;
974 		uint8_t *msg_type;
975 		uint8_t *server_id_opt;
976 		uint8_t *requested_ip_opt;
977 		uint32_t requested_nip;
978 		uint32_t static_lease_nip;
979 		struct dyn_lease *lease, fake_lease;
980 
981 		if (server_socket < 0) {
982 			server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,
983 					server_data.interface);
984 		}
985 
986 		udhcp_sp_fd_set(pfds, server_socket);
987 
988  new_tv:
989 		tv = -1;
990 		if (server_data.auto_time) {
991 			tv = timeout_end - monotonic_sec();
992 			if (tv <= 0) {
993  write_leases:
994 				write_leases();
995 				goto continue_with_autotime;
996 			}
997 			tv *= 1000;
998 		}
999 
1000 		/* Block here waiting for either signal or packet */
1001 		retval = poll(pfds, 2, tv);
1002 		if (retval <= 0) {
1003 			if (retval == 0)
1004 				goto write_leases;
1005 			if (errno == EINTR)
1006 				goto new_tv;
1007 			/* < 0 and not EINTR: should not happen */
1008 			bb_simple_perror_msg_and_die("poll");
1009 		}
1010 
1011 		if (pfds[0].revents) switch (udhcp_sp_read()) {
1012 		case SIGUSR1:
1013 			bb_info_msg("received %s", "SIGUSR1");
1014 			write_leases();
1015 			/* why not just reset the timeout, eh */
1016 			goto continue_with_autotime;
1017 		case SIGTERM:
1018 			bb_info_msg("received %s", "SIGTERM");
1019 			write_leases();
1020 			goto ret0;
1021 		}
1022 
1023 		/* Is it a packet? */
1024 		if (!pfds[1].revents)
1025 			continue; /* no */
1026 
1027 		/* Note: we do not block here, we block on poll() instead.
1028 		 * Blocking here would prevent SIGTERM from working:
1029 		 * socket read inside this call is restarted on caught signals.
1030 		 */
1031 		bytes = udhcp_recv_kernel_packet(&packet, server_socket);
1032 //NB: we do not check source port here. Should we?
1033 //It should be CLIENT_PORT for clients,
1034 //or SERVER_PORT for relay agents (in which case giaddr must be != 0.0.0.0)
1035 		if (bytes < 0) {
1036 			/* bytes can also be -2 ("bad packet data") */
1037 			if (bytes == -1 && errno != EINTR) {
1038 				log1("read error: "STRERROR_FMT", reopening socket" STRERROR_ERRNO);
1039 				close(server_socket);
1040 				server_socket = -1;
1041 			}
1042 			continue;
1043 		}
1044 		if (packet.hlen != 6) {
1045 			bb_info_msg("MAC length != 6%s", ", ignoring packet");
1046 			continue;
1047 		}
1048 		if (packet.op != BOOTREQUEST) {
1049 			bb_info_msg("not a REQUEST%s", ", ignoring packet");
1050 			continue;
1051 		}
1052 		msg_type = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
1053 		if (!msg_type || msg_type[0] < DHCP_MINTYPE || msg_type[0] > DHCP_MAXTYPE) {
1054 			bb_info_msg("no or bad message type option%s", ", ignoring packet");
1055 			continue;
1056 		}
1057 
1058 		/* Get SERVER_ID if present */
1059 		server_id_opt = udhcp_get_option32(&packet, DHCP_SERVER_ID);
1060 		if (server_id_opt) {
1061 			uint32_t server_id_network_order;
1062 			move_from_unaligned32(server_id_network_order, server_id_opt);
1063 			if (server_id_network_order != server_data.server_nip) {
1064 				/* client talks to somebody else */
1065 				log1("server ID doesn't match%s", ", ignoring packet");
1066 				continue;
1067 			}
1068 		}
1069 
1070 		/* Look for a static/dynamic lease */
1071 		static_lease_nip = get_static_nip_by_mac(&packet.chaddr);
1072 		if (static_lease_nip) {
1073 			bb_info_msg("found static lease: %x", static_lease_nip);
1074 			memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
1075 			fake_lease.lease_nip = static_lease_nip;
1076 			fake_lease.expires = 0;
1077 			lease = &fake_lease;
1078 		} else {
1079 			lease = find_lease_by_mac(packet.chaddr);
1080 		}
1081 
1082 		/* Get REQUESTED_IP if present */
1083 		requested_nip = 0;
1084 		requested_ip_opt = udhcp_get_option32(&packet, DHCP_REQUESTED_IP);
1085 		if (requested_ip_opt) {
1086 			move_from_unaligned32(requested_nip, requested_ip_opt);
1087 		}
1088 
1089 		switch (msg_type[0]) {
1090 
1091 		case DHCPDISCOVER:
1092 			log1("received %s", "DISCOVER");
1093 
1094 			send_offer(&packet, static_lease_nip, lease, requested_nip, arpping_ms);
1095 			break;
1096 
1097 		case DHCPREQUEST:
1098 			log1("received %s", "REQUEST");
1099 /* RFC 2131:
1100 
1101 o DHCPREQUEST generated during SELECTING state:
1102 
1103    Client inserts the address of the selected server in 'server
1104    identifier', 'ciaddr' MUST be zero, 'requested IP address' MUST be
1105    filled in with the yiaddr value from the chosen DHCPOFFER.
1106 
1107    Note that the client may choose to collect several DHCPOFFER
1108    messages and select the "best" offer.  The client indicates its
1109    selection by identifying the offering server in the DHCPREQUEST
1110    message.  If the client receives no acceptable offers, the client
1111    may choose to try another DHCPDISCOVER message.  Therefore, the
1112    servers may not receive a specific DHCPREQUEST from which they can
1113    decide whether or not the client has accepted the offer.
1114 
1115 o DHCPREQUEST generated during INIT-REBOOT state:
1116 
1117    'server identifier' MUST NOT be filled in, 'requested IP address'
1118    option MUST be filled in with client's notion of its previously
1119    assigned address. 'ciaddr' MUST be zero. The client is seeking to
1120    verify a previously allocated, cached configuration. Server SHOULD
1121    send a DHCPNAK message to the client if the 'requested IP address'
1122    is incorrect, or is on the wrong network.
1123 
1124    Determining whether a client in the INIT-REBOOT state is on the
1125    correct network is done by examining the contents of 'giaddr', the
1126    'requested IP address' option, and a database lookup. If the DHCP
1127    server detects that the client is on the wrong net (i.e., the
1128    result of applying the local subnet mask or remote subnet mask (if
1129    'giaddr' is not zero) to 'requested IP address' option value
1130    doesn't match reality), then the server SHOULD send a DHCPNAK
1131    message to the client.
1132 
1133    If the network is correct, then the DHCP server should check if
1134    the client's notion of its IP address is correct. If not, then the
1135    server SHOULD send a DHCPNAK message to the client. If the DHCP
1136    server has no record of this client, then it MUST remain silent,
1137    and MAY output a warning to the network administrator. This
1138    behavior is necessary for peaceful coexistence of non-
1139    communicating DHCP servers on the same wire.
1140 
1141    If 'giaddr' is 0x0 in the DHCPREQUEST message, the client is on
1142    the same subnet as the server.  The server MUST broadcast the
1143    DHCPNAK message to the 0xffffffff broadcast address because the
1144    client may not have a correct network address or subnet mask, and
1145    the client may not be answering ARP requests.
1146 
1147    If 'giaddr' is set in the DHCPREQUEST message, the client is on a
1148    different subnet.  The server MUST set the broadcast bit in the
1149    DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
1150    client, because the client may not have a correct network address
1151    or subnet mask, and the client may not be answering ARP requests.
1152 
1153 o DHCPREQUEST generated during RENEWING state:
1154 
1155    'server identifier' MUST NOT be filled in, 'requested IP address'
1156    option MUST NOT be filled in, 'ciaddr' MUST be filled in with
1157    client's IP address. In this situation, the client is completely
1158    configured, and is trying to extend its lease. This message will
1159    be unicast, so no relay agents will be involved in its
1160    transmission.  Because 'giaddr' is therefore not filled in, the
1161    DHCP server will trust the value in 'ciaddr', and use it when
1162    replying to the client.
1163 
1164    A client MAY choose to renew or extend its lease prior to T1.  The
1165    server may choose not to extend the lease (as a policy decision by
1166    the network administrator), but should return a DHCPACK message
1167    regardless.
1168 
1169 o DHCPREQUEST generated during REBINDING state:
1170 
1171    'server identifier' MUST NOT be filled in, 'requested IP address'
1172    option MUST NOT be filled in, 'ciaddr' MUST be filled in with
1173    client's IP address. In this situation, the client is completely
1174    configured, and is trying to extend its lease. This message MUST
1175    be broadcast to the 0xffffffff IP broadcast address.  The DHCP
1176    server SHOULD check 'ciaddr' for correctness before replying to
1177    the DHCPREQUEST.
1178 
1179    The DHCPREQUEST from a REBINDING client is intended to accommodate
1180    sites that have multiple DHCP servers and a mechanism for
1181    maintaining consistency among leases managed by multiple servers.
1182    A DHCP server MAY extend a client's lease only if it has local
1183    administrative authority to do so.
1184 */
1185 			if (!requested_ip_opt) {
1186 				requested_nip = packet.ciaddr;
1187 				if (requested_nip == 0) {
1188 					log1("no requested IP and no ciaddr%s", ", ignoring packet");
1189 					break;
1190 				}
1191 			}
1192 			if (lease && requested_nip == lease->lease_nip) {
1193 				/* client requested or configured IP matches the lease.
1194 				 * ACK it, and bump lease expiration time. */
1195 				send_ACK(&packet, lease->lease_nip);
1196 				break;
1197 			}
1198 			/* No lease for this MAC, or lease IP != requested IP */
1199 
1200 			if (server_id_opt    /* client is in SELECTING state */
1201 			 || requested_ip_opt /* client is in INIT-REBOOT state */
1202 			) {
1203 				/* "No, we don't have this IP for you" */
1204 				send_NAK(&packet);
1205 			} /* else: client is in RENEWING or REBINDING, do not answer */
1206 
1207 			break;
1208 
1209 		case DHCPDECLINE:
1210 			/* RFC 2131:
1211 			 * "If the server receives a DHCPDECLINE message,
1212 			 * the client has discovered through some other means
1213 			 * that the suggested network address is already
1214 			 * in use. The server MUST mark the network address
1215 			 * as not available and SHOULD notify the local
1216 			 * sysadmin of a possible configuration problem."
1217 			 *
1218 			 * SERVER_ID must be present,
1219 			 * REQUESTED_IP must be present,
1220 			 * chaddr must be filled in,
1221 			 * ciaddr must be 0 (we do not check this)
1222 			 */
1223 			log1("received %s", "DECLINE");
1224 			if (server_id_opt
1225 			 && requested_ip_opt
1226 			 && lease  /* chaddr matches this lease */
1227 			 && requested_nip == lease->lease_nip
1228 			) {
1229 				memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
1230 				lease->expires = time(NULL) + server_data.decline_time;
1231 			}
1232 			break;
1233 
1234 		case DHCPRELEASE:
1235 			/* "Upon receipt of a DHCPRELEASE message, the server
1236 			 * marks the network address as not allocated."
1237 			 *
1238 			 * SERVER_ID must be present,
1239 			 * REQUESTED_IP must not be present (we do not check this),
1240 			 * chaddr must be filled in,
1241 			 * ciaddr must be filled in
1242 			 */
1243 			log1("received %s", "RELEASE");
1244 			if (server_id_opt
1245 			 && lease  /* chaddr matches this lease */
1246 			 && packet.ciaddr == lease->lease_nip
1247 			) {
1248 				lease->expires = time(NULL);
1249 			}
1250 			break;
1251 
1252 		case DHCPINFORM:
1253 			log1("received %s", "INFORM");
1254 			send_inform(&packet);
1255 			break;
1256 		}
1257 	}
1258  ret0:
1259 	retval = 0;
1260  ret:
1261 	/*if (server_data.pidfile) - server_data.pidfile is never NULL */
1262 		remove_pidfile(server_data.pidfile);
1263 	return retval;
1264 }
1265