udhcp: add PXELINUX config file option (code 209) definition
[oweals/busybox.git] / networking / udhcp / dhcpd.c
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
24 //usage:#define udhcpd_trivial_usage
25 //usage:       "[-fS] [-I ADDR]" IF_FEATURE_UDHCP_PORT(" [-P N]") " [CONFFILE]"
26 //usage:#define udhcpd_full_usage "\n\n"
27 //usage:       "DHCP server\n"
28 //usage:     "\n        -f      Run in foreground"
29 //usage:     "\n        -S      Log to syslog too"
30 //usage:     "\n        -I ADDR Local address"
31 //usage:        IF_FEATURE_UDHCP_PORT(
32 //usage:     "\n        -P N    Use port N (default 67)"
33 //usage:        )
34
35 #include <syslog.h>
36 #include "common.h"
37 #include "dhcpc.h"
38 #include "dhcpd.h"
39
40
41 /* Send a packet to a specific mac address and ip address by creating our own ip packet */
42 static void send_packet_to_client(struct dhcp_packet *dhcp_pkt, int force_broadcast)
43 {
44         const uint8_t *chaddr;
45         uint32_t ciaddr;
46
47         // Was:
48         //if (force_broadcast) { /* broadcast */ }
49         //else if (dhcp_pkt->ciaddr) { /* unicast to dhcp_pkt->ciaddr */ }
50         //else if (dhcp_pkt->flags & htons(BROADCAST_FLAG)) { /* broadcast */ }
51         //else { /* unicast to dhcp_pkt->yiaddr */ }
52         // But this is wrong: yiaddr is _our_ idea what client's IP is
53         // (for example, from lease file). Client may not know that,
54         // and may not have UDP socket listening on that IP!
55         // We should never unicast to dhcp_pkt->yiaddr!
56         // dhcp_pkt->ciaddr, OTOH, comes from client's request packet,
57         // and can be used.
58
59         if (force_broadcast
60          || (dhcp_pkt->flags & htons(BROADCAST_FLAG))
61          || dhcp_pkt->ciaddr == 0
62         ) {
63                 log1("Broadcasting packet to client");
64                 ciaddr = INADDR_BROADCAST;
65                 chaddr = MAC_BCAST_ADDR;
66         } else {
67                 log1("Unicasting packet to client ciaddr");
68                 ciaddr = dhcp_pkt->ciaddr;
69                 chaddr = dhcp_pkt->chaddr;
70         }
71
72         udhcp_send_raw_packet(dhcp_pkt,
73                 /*src*/ server_config.server_nip, SERVER_PORT,
74                 /*dst*/ ciaddr, CLIENT_PORT, chaddr,
75                 server_config.ifindex);
76 }
77
78 /* Send a packet to gateway_nip using the kernel ip stack */
79 static void send_packet_to_relay(struct dhcp_packet *dhcp_pkt)
80 {
81         log1("Forwarding packet to relay");
82
83         udhcp_send_kernel_packet(dhcp_pkt,
84                         server_config.server_nip, SERVER_PORT,
85                         dhcp_pkt->gateway_nip, SERVER_PORT);
86 }
87
88 static void send_packet(struct dhcp_packet *dhcp_pkt, int force_broadcast)
89 {
90         if (dhcp_pkt->gateway_nip)
91                 send_packet_to_relay(dhcp_pkt);
92         else
93                 send_packet_to_client(dhcp_pkt, force_broadcast);
94 }
95
96 static void init_packet(struct dhcp_packet *packet, struct dhcp_packet *oldpacket, char type)
97 {
98         /* Sets op, htype, hlen, cookie fields
99          * and adds DHCP_MESSAGE_TYPE option */
100         udhcp_init_header(packet, type);
101
102         packet->xid = oldpacket->xid;
103         memcpy(packet->chaddr, oldpacket->chaddr, sizeof(oldpacket->chaddr));
104         packet->flags = oldpacket->flags;
105         packet->gateway_nip = oldpacket->gateway_nip;
106         packet->ciaddr = oldpacket->ciaddr;
107         udhcp_add_simple_option(packet, DHCP_SERVER_ID, server_config.server_nip);
108 }
109
110 /* Fill options field, siaddr_nip, and sname and boot_file fields.
111  * TODO: teach this code to use overload option.
112  */
113 static void add_server_options(struct dhcp_packet *packet)
114 {
115         struct option_set *curr = server_config.options;
116
117         while (curr) {
118                 if (curr->data[OPT_CODE] != DHCP_LEASE_TIME)
119                         udhcp_add_binary_option(packet, curr->data);
120                 curr = curr->next;
121         }
122
123         packet->siaddr_nip = server_config.siaddr_nip;
124
125         if (server_config.sname)
126                 strncpy((char*)packet->sname, server_config.sname, sizeof(packet->sname) - 1);
127         if (server_config.boot_file)
128                 strncpy((char*)packet->file, server_config.boot_file, sizeof(packet->file) - 1);
129 }
130
131 static uint32_t select_lease_time(struct dhcp_packet *packet)
132 {
133         uint32_t lease_time_sec = server_config.max_lease_sec;
134         uint8_t *lease_time_opt = udhcp_get_option(packet, DHCP_LEASE_TIME);
135         if (lease_time_opt) {
136                 move_from_unaligned32(lease_time_sec, lease_time_opt);
137                 lease_time_sec = ntohl(lease_time_sec);
138                 if (lease_time_sec > server_config.max_lease_sec)
139                         lease_time_sec = server_config.max_lease_sec;
140                 if (lease_time_sec < server_config.min_lease_sec)
141                         lease_time_sec = server_config.min_lease_sec;
142         }
143         return lease_time_sec;
144 }
145
146 /* We got a DHCP DISCOVER. Send an OFFER. */
147 /* NOINLINE: limit stack usage in caller */
148 static NOINLINE void send_offer(struct dhcp_packet *oldpacket,
149                 uint32_t static_lease_nip,
150                 struct dyn_lease *lease,
151                 uint8_t *requested_ip_opt)
152 {
153         struct dhcp_packet packet;
154         uint32_t lease_time_sec;
155         struct in_addr addr;
156
157         init_packet(&packet, oldpacket, DHCPOFFER);
158
159         /* If it is a static lease, use its IP */
160         packet.yiaddr = static_lease_nip;
161         /* Else: */
162         if (!static_lease_nip) {
163                 /* We have no static lease for client's chaddr */
164                 uint32_t req_nip;
165                 const char *p_host_name;
166
167                 if (lease) {
168                         /* We have a dynamic lease for client's chaddr.
169                          * Reuse its IP (even if lease is expired).
170                          * Note that we ignore requested IP in this case.
171                          */
172                         packet.yiaddr = lease->lease_nip;
173                 }
174                 /* Or: if client has requested an IP */
175                 else if (requested_ip_opt != NULL
176                  /* (read IP) */
177                  && (move_from_unaligned32(req_nip, requested_ip_opt), 1)
178                  /* and the IP is in the lease range */
179                  && ntohl(req_nip) >= server_config.start_ip
180                  && ntohl(req_nip) <= server_config.end_ip
181                  /* and */
182                  && (  !(lease = find_lease_by_nip(req_nip)) /* is not already taken */
183                     || is_expired_lease(lease) /* or is taken, but expired */
184                     )
185                 ) {
186                         packet.yiaddr = req_nip;
187                 }
188                 else {
189                         /* Otherwise, find a free IP */
190                         packet.yiaddr = find_free_or_expired_nip(oldpacket->chaddr);
191                 }
192
193                 if (!packet.yiaddr) {
194                         bb_error_msg("no free IP addresses. OFFER abandoned");
195                         return;
196                 }
197                 /* Reserve the IP for a short time hoping to get DHCPREQUEST soon */
198                 p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
199                 lease = add_lease(packet.chaddr, packet.yiaddr,
200                                 server_config.offer_time,
201                                 p_host_name,
202                                 p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0
203                 );
204                 if (!lease) {
205                         bb_error_msg("no free IP addresses. OFFER abandoned");
206                         return;
207                 }
208         }
209
210         lease_time_sec = select_lease_time(oldpacket);
211         udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
212         add_server_options(&packet);
213
214         addr.s_addr = packet.yiaddr;
215         bb_info_msg("Sending OFFER of %s", inet_ntoa(addr));
216         /* send_packet emits error message itself if it detects failure */
217         send_packet(&packet, /*force_bcast:*/ 0);
218 }
219
220 /* NOINLINE: limit stack usage in caller */
221 static NOINLINE void send_NAK(struct dhcp_packet *oldpacket)
222 {
223         struct dhcp_packet packet;
224
225         init_packet(&packet, oldpacket, DHCPNAK);
226
227         log1("Sending NAK");
228         send_packet(&packet, /*force_bcast:*/ 1);
229 }
230
231 /* NOINLINE: limit stack usage in caller */
232 static NOINLINE void send_ACK(struct dhcp_packet *oldpacket, uint32_t yiaddr)
233 {
234         struct dhcp_packet packet;
235         uint32_t lease_time_sec;
236         struct in_addr addr;
237         const char *p_host_name;
238
239         init_packet(&packet, oldpacket, DHCPACK);
240         packet.yiaddr = yiaddr;
241
242         lease_time_sec = select_lease_time(oldpacket);
243         udhcp_add_simple_option(&packet, DHCP_LEASE_TIME, htonl(lease_time_sec));
244
245         add_server_options(&packet);
246
247         addr.s_addr = yiaddr;
248         bb_info_msg("Sending ACK to %s", inet_ntoa(addr));
249         send_packet(&packet, /*force_bcast:*/ 0);
250
251         p_host_name = (const char*) udhcp_get_option(oldpacket, DHCP_HOST_NAME);
252         add_lease(packet.chaddr, packet.yiaddr,
253                 lease_time_sec,
254                 p_host_name,
255                 p_host_name ? (unsigned char)p_host_name[OPT_LEN - OPT_DATA] : 0
256         );
257         if (ENABLE_FEATURE_UDHCPD_WRITE_LEASES_EARLY) {
258                 /* rewrite the file with leases at every new acceptance */
259                 write_leases();
260         }
261 }
262
263 /* NOINLINE: limit stack usage in caller */
264 static NOINLINE void send_inform(struct dhcp_packet *oldpacket)
265 {
266         struct dhcp_packet packet;
267
268         /* "If a client has obtained a network address through some other means
269          * (e.g., manual configuration), it may use a DHCPINFORM request message
270          * to obtain other local configuration parameters.  Servers receiving a
271          * DHCPINFORM message construct a DHCPACK message with any local
272          * configuration parameters appropriate for the client without:
273          * allocating a new address, checking for an existing binding, filling
274          * in 'yiaddr' or including lease time parameters.  The servers SHOULD
275          * unicast the DHCPACK reply to the address given in the 'ciaddr' field
276          * of the DHCPINFORM message.
277          * ...
278          * The server responds to a DHCPINFORM message by sending a DHCPACK
279          * message directly to the address given in the 'ciaddr' field
280          * of the DHCPINFORM message.  The server MUST NOT send a lease
281          * expiration time to the client and SHOULD NOT fill in 'yiaddr'."
282          */
283 //TODO: do a few sanity checks: is ciaddr set?
284 //Better yet: is ciaddr == IP source addr?
285         init_packet(&packet, oldpacket, DHCPACK);
286         add_server_options(&packet);
287
288         send_packet(&packet, /*force_bcast:*/ 0);
289 }
290
291
292 /* globals */
293 struct dyn_lease *g_leases;
294 /* struct server_config_t server_config is in bb_common_bufsiz1 */
295
296
297 int udhcpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
298 int udhcpd_main(int argc UNUSED_PARAM, char **argv)
299 {
300         int server_socket = -1, retval, max_sock;
301         uint8_t *state;
302         unsigned timeout_end;
303         unsigned num_ips;
304         unsigned opt;
305         struct option_set *option;
306         char *str_I = str_I;
307         IF_FEATURE_UDHCP_PORT(char *str_P;)
308
309 #if ENABLE_FEATURE_UDHCP_PORT
310         SERVER_PORT = 67;
311         CLIENT_PORT = 68;
312 #endif
313
314 #if defined CONFIG_UDHCP_DEBUG && CONFIG_UDHCP_DEBUG >= 1
315         opt_complementary = "vv";
316 #endif
317         opt = getopt32(argv, "fSI:v"
318                 IF_FEATURE_UDHCP_PORT("P:")
319                 , &str_I
320                 IF_FEATURE_UDHCP_PORT(, &str_P)
321                 IF_UDHCP_VERBOSE(, &dhcp_verbose)
322                 );
323         if (!(opt & 1)) { /* no -f */
324                 bb_daemonize_or_rexec(0, argv);
325                 logmode = LOGMODE_NONE;
326         }
327         /* update argv after the possible vfork+exec in daemonize */
328         argv += optind;
329         if (opt & 2) { /* -S */
330                 openlog(applet_name, LOG_PID, LOG_DAEMON);
331                 logmode |= LOGMODE_SYSLOG;
332         }
333         if (opt & 4) { /* -I */
334                 len_and_sockaddr *lsa = xhost_and_af2sockaddr(str_I, 0, AF_INET);
335                 server_config.server_nip = lsa->u.sin.sin_addr.s_addr;
336                 free(lsa);
337         }
338 #if ENABLE_FEATURE_UDHCP_PORT
339         if (opt & 16) { /* -P */
340                 SERVER_PORT = xatou16(str_P);
341                 CLIENT_PORT = SERVER_PORT + 1;
342         }
343 #endif
344         /* Would rather not do read_config before daemonization -
345          * otherwise NOMMU machines will parse config twice */
346         read_config(argv[0] ? argv[0] : DHCPD_CONF_FILE);
347
348         /* Make sure fd 0,1,2 are open */
349         bb_sanitize_stdio();
350         /* Equivalent of doing a fflush after every \n */
351         setlinebuf(stdout);
352
353         /* Create pidfile */
354         write_pidfile(server_config.pidfile);
355         /* if (!..) bb_perror_msg("can't create pidfile %s", pidfile); */
356
357         bb_info_msg("%s (v"BB_VER") started", applet_name);
358
359         option = udhcp_find_option(server_config.options, DHCP_LEASE_TIME);
360         server_config.max_lease_sec = DEFAULT_LEASE_TIME;
361         if (option) {
362                 move_from_unaligned32(server_config.max_lease_sec, option->data + OPT_DATA);
363                 server_config.max_lease_sec = ntohl(server_config.max_lease_sec);
364         }
365
366         /* Sanity check */
367         num_ips = server_config.end_ip - server_config.start_ip + 1;
368         if (server_config.max_leases > num_ips) {
369                 bb_error_msg("max_leases=%u is too big, setting to %u",
370                         (unsigned)server_config.max_leases, num_ips);
371                 server_config.max_leases = num_ips;
372         }
373
374         g_leases = xzalloc(server_config.max_leases * sizeof(g_leases[0]));
375         read_leases(server_config.lease_file);
376
377         if (udhcp_read_interface(server_config.interface,
378                         &server_config.ifindex,
379                         (server_config.server_nip == 0 ? &server_config.server_nip : NULL),
380                         server_config.server_mac)
381         ) {
382                 retval = 1;
383                 goto ret;
384         }
385
386         /* Setup the signal pipe */
387         udhcp_sp_setup();
388
389  continue_with_autotime:
390         timeout_end = monotonic_sec() + server_config.auto_time;
391         while (1) { /* loop until universe collapses */
392                 fd_set rfds;
393                 struct dhcp_packet packet;
394                 int bytes;
395                 struct timeval tv;
396                 uint8_t *server_id_opt;
397                 uint8_t *requested_ip_opt;
398                 uint32_t requested_nip = requested_nip; /* for compiler */
399                 uint32_t static_lease_nip;
400                 struct dyn_lease *lease, fake_lease;
401
402                 if (server_socket < 0) {
403                         server_socket = udhcp_listen_socket(/*INADDR_ANY,*/ SERVER_PORT,
404                                         server_config.interface);
405                 }
406
407                 max_sock = udhcp_sp_fd_set(&rfds, server_socket);
408                 if (server_config.auto_time) {
409                         tv.tv_sec = timeout_end - monotonic_sec();
410                         tv.tv_usec = 0;
411                 }
412                 retval = 0;
413                 if (!server_config.auto_time || tv.tv_sec > 0) {
414                         retval = select(max_sock + 1, &rfds, NULL, NULL,
415                                         server_config.auto_time ? &tv : NULL);
416                 }
417                 if (retval == 0) {
418                         write_leases();
419                         goto continue_with_autotime;
420                 }
421                 if (retval < 0 && errno != EINTR) {
422                         log1("Error on select");
423                         continue;
424                 }
425
426                 switch (udhcp_sp_read(&rfds)) {
427                 case SIGUSR1:
428                         bb_info_msg("Received SIGUSR1");
429                         write_leases();
430                         /* why not just reset the timeout, eh */
431                         goto continue_with_autotime;
432                 case SIGTERM:
433                         bb_info_msg("Received SIGTERM");
434                         write_leases();
435                         goto ret0;
436                 case 0: /* no signal: read a packet */
437                         break;
438                 default: /* signal or error (probably EINTR): back to select */
439                         continue;
440                 }
441
442                 bytes = udhcp_recv_kernel_packet(&packet, server_socket);
443                 if (bytes < 0) {
444                         /* bytes can also be -2 ("bad packet data") */
445                         if (bytes == -1 && errno != EINTR) {
446                                 log1("Read error: %s, reopening socket", strerror(errno));
447                                 close(server_socket);
448                                 server_socket = -1;
449                         }
450                         continue;
451                 }
452                 if (packet.hlen != 6) {
453                         bb_error_msg("MAC length != 6, ignoring packet");
454                         continue;
455                 }
456                 if (packet.op != BOOTREQUEST) {
457                         bb_error_msg("not a REQUEST, ignoring packet");
458                         continue;
459                 }
460                 state = udhcp_get_option(&packet, DHCP_MESSAGE_TYPE);
461                 if (state == NULL || state[0] < DHCP_MINTYPE || state[0] > DHCP_MAXTYPE) {
462                         bb_error_msg("no or bad message type option, ignoring packet");
463                         continue;
464                 }
465
466                 /* Get SERVER_ID if present */
467                 server_id_opt = udhcp_get_option(&packet, DHCP_SERVER_ID);
468                 if (server_id_opt) {
469                         uint32_t server_id_network_order;
470                         move_from_unaligned32(server_id_network_order, server_id_opt);
471                         if (server_id_network_order != server_config.server_nip) {
472                                 /* client talks to somebody else */
473                                 log1("server ID doesn't match, ignoring");
474                                 continue;
475                         }
476                 }
477
478                 /* Look for a static/dynamic lease */
479                 static_lease_nip = get_static_nip_by_mac(server_config.static_leases, &packet.chaddr);
480                 if (static_lease_nip) {
481                         bb_info_msg("Found static lease: %x", static_lease_nip);
482                         memcpy(&fake_lease.lease_mac, &packet.chaddr, 6);
483                         fake_lease.lease_nip = static_lease_nip;
484                         fake_lease.expires = 0;
485                         lease = &fake_lease;
486                 } else {
487                         lease = find_lease_by_mac(packet.chaddr);
488                 }
489
490                 /* Get REQUESTED_IP if present */
491                 requested_ip_opt = udhcp_get_option(&packet, DHCP_REQUESTED_IP);
492                 if (requested_ip_opt) {
493                         move_from_unaligned32(requested_nip, requested_ip_opt);
494                 }
495
496                 switch (state[0]) {
497
498                 case DHCPDISCOVER:
499                         log1("Received DISCOVER");
500
501                         send_offer(&packet, static_lease_nip, lease, requested_ip_opt);
502                         break;
503
504                 case DHCPREQUEST:
505                         log1("Received REQUEST");
506 /* RFC 2131:
507
508 o DHCPREQUEST generated during SELECTING state:
509
510    Client inserts the address of the selected server in 'server
511    identifier', 'ciaddr' MUST be zero, 'requested IP address' MUST be
512    filled in with the yiaddr value from the chosen DHCPOFFER.
513
514    Note that the client may choose to collect several DHCPOFFER
515    messages and select the "best" offer.  The client indicates its
516    selection by identifying the offering server in the DHCPREQUEST
517    message.  If the client receives no acceptable offers, the client
518    may choose to try another DHCPDISCOVER message.  Therefore, the
519    servers may not receive a specific DHCPREQUEST from which they can
520    decide whether or not the client has accepted the offer.
521
522 o DHCPREQUEST generated during INIT-REBOOT state:
523
524    'server identifier' MUST NOT be filled in, 'requested IP address'
525    option MUST be filled in with client's notion of its previously
526    assigned address. 'ciaddr' MUST be zero. The client is seeking to
527    verify a previously allocated, cached configuration. Server SHOULD
528    send a DHCPNAK message to the client if the 'requested IP address'
529    is incorrect, or is on the wrong network.
530
531    Determining whether a client in the INIT-REBOOT state is on the
532    correct network is done by examining the contents of 'giaddr', the
533    'requested IP address' option, and a database lookup. If the DHCP
534    server detects that the client is on the wrong net (i.e., the
535    result of applying the local subnet mask or remote subnet mask (if
536    'giaddr' is not zero) to 'requested IP address' option value
537    doesn't match reality), then the server SHOULD send a DHCPNAK
538    message to the client.
539
540    If the network is correct, then the DHCP server should check if
541    the client's notion of its IP address is correct. If not, then the
542    server SHOULD send a DHCPNAK message to the client. If the DHCP
543    server has no record of this client, then it MUST remain silent,
544    and MAY output a warning to the network administrator. This
545    behavior is necessary for peaceful coexistence of non-
546    communicating DHCP servers on the same wire.
547
548    If 'giaddr' is 0x0 in the DHCPREQUEST message, the client is on
549    the same subnet as the server.  The server MUST broadcast the
550    DHCPNAK message to the 0xffffffff broadcast address because the
551    client may not have a correct network address or subnet mask, and
552    the client may not be answering ARP requests.
553
554    If 'giaddr' is set in the DHCPREQUEST message, the client is on a
555    different subnet.  The server MUST set the broadcast bit in the
556    DHCPNAK, so that the relay agent will broadcast the DHCPNAK to the
557    client, because the client may not have a correct network address
558    or subnet mask, and the client may not be answering ARP requests.
559
560 o DHCPREQUEST generated during RENEWING state:
561
562    'server identifier' MUST NOT be filled in, 'requested IP address'
563    option MUST NOT be filled in, 'ciaddr' MUST be filled in with
564    client's IP address. In this situation, the client is completely
565    configured, and is trying to extend its lease. This message will
566    be unicast, so no relay agents will be involved in its
567    transmission.  Because 'giaddr' is therefore not filled in, the
568    DHCP server will trust the value in 'ciaddr', and use it when
569    replying to the client.
570
571    A client MAY choose to renew or extend its lease prior to T1.  The
572    server may choose not to extend the lease (as a policy decision by
573    the network administrator), but should return a DHCPACK message
574    regardless.
575
576 o DHCPREQUEST generated during REBINDING state:
577
578    'server identifier' MUST NOT be filled in, 'requested IP address'
579    option MUST NOT be filled in, 'ciaddr' MUST be filled in with
580    client's IP address. In this situation, the client is completely
581    configured, and is trying to extend its lease. This message MUST
582    be broadcast to the 0xffffffff IP broadcast address.  The DHCP
583    server SHOULD check 'ciaddr' for correctness before replying to
584    the DHCPREQUEST.
585
586    The DHCPREQUEST from a REBINDING client is intended to accommodate
587    sites that have multiple DHCP servers and a mechanism for
588    maintaining consistency among leases managed by multiple servers.
589    A DHCP server MAY extend a client's lease only if it has local
590    administrative authority to do so.
591 */
592                         if (!requested_ip_opt) {
593                                 requested_nip = packet.ciaddr;
594                                 if (requested_nip == 0) {
595                                         log1("no requested IP and no ciaddr, ignoring");
596                                         break;
597                                 }
598                         }
599                         if (lease && requested_nip == lease->lease_nip) {
600                                 /* client requested or configured IP matches the lease.
601                                  * ACK it, and bump lease expiration time. */
602                                 send_ACK(&packet, lease->lease_nip);
603                                 break;
604                         }
605                         /* No lease for this MAC, or lease IP != requested IP */
606
607                         if (server_id_opt    /* client is in SELECTING state */
608                          || requested_ip_opt /* client is in INIT-REBOOT state */
609                         ) {
610                                 /* "No, we don't have this IP for you" */
611                                 send_NAK(&packet);
612                         } /* else: client is in RENEWING or REBINDING, do not answer */
613
614                         break;
615
616                 case DHCPDECLINE:
617                         /* RFC 2131:
618                          * "If the server receives a DHCPDECLINE message,
619                          * the client has discovered through some other means
620                          * that the suggested network address is already
621                          * in use. The server MUST mark the network address
622                          * as not available and SHOULD notify the local
623                          * sysadmin of a possible configuration problem."
624                          *
625                          * SERVER_ID must be present,
626                          * REQUESTED_IP must be present,
627                          * chaddr must be filled in,
628                          * ciaddr must be 0 (we do not check this)
629                          */
630                         log1("Received DECLINE");
631                         if (server_id_opt
632                          && requested_ip_opt
633                          && lease  /* chaddr matches this lease */
634                          && requested_nip == lease->lease_nip
635                         ) {
636                                 memset(lease->lease_mac, 0, sizeof(lease->lease_mac));
637                                 lease->expires = time(NULL) + server_config.decline_time;
638                         }
639                         break;
640
641                 case DHCPRELEASE:
642                         /* "Upon receipt of a DHCPRELEASE message, the server
643                          * marks the network address as not allocated."
644                          *
645                          * SERVER_ID must be present,
646                          * REQUESTED_IP must not be present (we do not check this),
647                          * chaddr must be filled in,
648                          * ciaddr must be filled in
649                          */
650                         log1("Received RELEASE");
651                         if (server_id_opt
652                          && lease  /* chaddr matches this lease */
653                          && packet.ciaddr == lease->lease_nip
654                         ) {
655                                 lease->expires = time(NULL);
656                         }
657                         break;
658
659                 case DHCPINFORM:
660                         log1("Received INFORM");
661                         send_inform(&packet);
662                         break;
663                 }
664         }
665  ret0:
666         retval = 0;
667  ret:
668         /*if (server_config.pidfile) - server_config.pidfile is never NULL */
669                 remove_pidfile(server_config.pidfile);
670         return retval;
671 }