1 /* $OpenBSD: dhcp.c,v 1.57 2017/07/11 10:28:24 reyk Exp $ */
2
3 /*
4 * Copyright (c) 1995, 1996, 1997, 1998, 1999
5 * The Internet Software Consortium. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of The Internet Software Consortium nor the names
17 * of its contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
21 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
22 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
23 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
25 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
28 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
29 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * SUCH DAMAGE.
33 *
34 * This software has been written for the Internet Software Consortium
35 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
36 * Enterprises. To learn more about the Internet Software Consortium,
37 * see ``http://www.vix.com/isc''. To learn more about Vixie
38 * Enterprises, see ``http://www.vix.com''.
39 */
40
41 #include <sys/types.h>
42 #include <sys/socket.h>
43
44 #include <arpa/inet.h>
45
46 #include <net/if.h>
47
48 #include <netinet/in.h>
49
50 #include <errno.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54
55 #include "dhcp.h"
56 #include "tree.h"
57 #include "dhcpd.h"
58 #include "log.h"
59 #include "sync.h"
60
61 int outstanding_pings;
62
63 static char dhcp_message[256];
64
65 void
dhcp(struct packet * packet,int is_udpsock)66 dhcp(struct packet *packet, int is_udpsock)
67 {
68 if (!locate_network(packet) && packet->packet_type != DHCPREQUEST)
69 return;
70
71 if (is_udpsock && packet->packet_type != DHCPINFORM) {
72 log_info("Unable to handle a DHCP message type=%d on UDP "
73 "socket", packet->packet_type);
74 return;
75 }
76
77 switch (packet->packet_type) {
78 case DHCPDISCOVER:
79 dhcpdiscover(packet);
80 break;
81
82 case DHCPREQUEST:
83 dhcprequest(packet);
84 break;
85
86 case DHCPRELEASE:
87 dhcprelease(packet);
88 break;
89
90 case DHCPDECLINE:
91 dhcpdecline(packet);
92 break;
93
94 case DHCPINFORM:
95 dhcpinform(packet);
96 break;
97
98 default:
99 break;
100 }
101 }
102
103 void
dhcpdiscover(struct packet * packet)104 dhcpdiscover(struct packet *packet)
105 {
106 struct lease *lease = find_lease(packet, packet->shared_network, 0);
107 struct host_decl *hp;
108
109 log_info("DHCPDISCOVER from %s via %s",
110 print_hw_addr(packet->raw->htype, packet->raw->hlen,
111 packet->raw->chaddr),
112 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) :
113 packet->interface->name);
114
115 /* Sourceless packets don't make sense here. */
116 if (!packet->shared_network) {
117 log_info("Packet from unknown subnet: %s",
118 inet_ntoa(packet->raw->giaddr));
119 return;
120 }
121
122 /* If we didn't find a lease, try to allocate one... */
123 if (!lease) {
124 lease = packet->shared_network->last_lease;
125
126 /*
127 * If there are no leases in that subnet that have
128 * expired, we have nothing to offer this client.
129 */
130 if (!lease || lease->ends > cur_time) {
131 log_info("no free leases on subnet %s",
132 packet->shared_network->name);
133 return;
134 }
135
136 /*
137 * If we find an abandoned lease, take it, but print a
138 * warning message, so that if it continues to lose,
139 * the administrator will eventually investigate.
140 */
141 if ((lease->flags & ABANDONED_LEASE)) {
142 struct lease *lp;
143
144 /* See if we can find an unabandoned lease first. */
145 for (lp = lease; lp; lp = lp->prev) {
146 if (lp->ends > cur_time)
147 break;
148 if (!(lp->flags & ABANDONED_LEASE)) {
149 lease = lp;
150 break;
151 }
152 }
153
154 /*
155 * If we can't find an unabandoned lease,
156 * reclaim the abandoned lease.
157 */
158 if ((lease->flags & ABANDONED_LEASE)) {
159 log_warnx("Reclaiming abandoned IP address %s.",
160 piaddr(lease->ip_addr));
161 lease->flags &= ~ABANDONED_LEASE;
162
163 pfmsg('L', lease); /* unabandon address */
164 }
165 }
166
167 /* Try to find a host_decl that matches the client
168 identifier or hardware address on the packet, and
169 has no fixed IP address. If there is one, hang
170 it off the lease so that its option definitions
171 can be used. */
172 if (((packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len != 0) &&
173 ((hp = find_hosts_by_uid(
174 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
175 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len)) !=
176 NULL)) ||
177 ((hp = find_hosts_by_haddr(packet->raw->htype,
178 packet->raw->chaddr, packet->raw->hlen)) != NULL)) {
179 for (; hp; hp = hp->n_ipaddr) {
180 if (!hp->fixed_addr) {
181 lease->host = hp;
182 break;
183 }
184 }
185 } else
186 lease->host = NULL;
187 }
188
189 /* If this subnet won't boot unknown clients, ignore the
190 request. */
191 if (!lease->host &&
192 !lease->subnet->group->boot_unknown_clients) {
193 log_info("Ignoring unknown client %s",
194 print_hw_addr(packet->raw->htype, packet->raw->hlen,
195 packet->raw->chaddr));
196 } else if (lease->host && !lease->host->group->allow_booting) {
197 log_info("Declining to boot client %s",
198 lease->host->name ? lease->host->name :
199 print_hw_addr(packet->raw->htype, packet->raw->hlen,
200 packet->raw->chaddr));
201 } else
202 ack_lease(packet, lease, DHCPOFFER, cur_time + 120);
203 }
204
205 void
dhcprequest(struct packet * packet)206 dhcprequest(struct packet *packet)
207 {
208 struct lease *lease;
209 struct iaddr cip;
210 struct subnet *subnet;
211 int ours = 0;
212
213 cip.len = 4;
214 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len == 4)
215 memcpy(cip.iabuf,
216 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data, 4);
217 else
218 memcpy(cip.iabuf, &packet->raw->ciaddr.s_addr, 4);
219 subnet = find_subnet(cip);
220
221 /* Find the lease that matches the address requested by the client. */
222
223 if (subnet)
224 lease = find_lease(packet, subnet->shared_network, &ours);
225 else
226 lease = NULL;
227
228 log_info("DHCPREQUEST for %s from %s via %s", piaddr(cip),
229 print_hw_addr(packet->raw->htype, packet->raw->hlen,
230 packet->raw->chaddr),
231 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) :
232 packet->interface->name);
233
234 /* If a client on a given network REQUESTs a lease on an
235 * address on a different network, NAK it. If the Requested
236 * Address option was used, the protocol says that it must
237 * have been broadcast, so we can trust the source network
238 * information.
239 *
240 * If ciaddr was specified and Requested Address was not, then
241 * we really only know for sure what network a packet came from
242 * if it came through a BOOTP gateway - if it came through an
243 * IP router, we'll just have to assume that it's cool.
244 *
245 * If we don't think we know where the packet came from, it
246 * came through a gateway from an unknown network, so it's not
247 * from a RENEWING client. If we recognize the network it
248 * *thinks* it's on, we can NAK it even though we don't
249 * recognize the network it's *actually* on; otherwise we just
250 * have to ignore it.
251 *
252 * We don't currently try to take advantage of access to the
253 * raw packet, because it's not available on all platforms.
254 * So a packet that was unicast to us through a router from a
255 * RENEWING client is going to look exactly like a packet that
256 * was broadcast to us from an INIT-REBOOT client.
257 *
258 * Since we can't tell the difference between these two kinds
259 * of packets, if the packet appears to have come in off the
260 * local wire, we have to treat it as if it's a RENEWING
261 * client. This means that we can't NAK a RENEWING client on
262 * the local wire that has a bogus address. The good news is
263 * that we won't ACK it either, so it should revert to INIT
264 * state and send us a DHCPDISCOVER, which we *can* work with.
265 *
266 * Because we can't detect that a RENEWING client is on the
267 * wrong wire, it's going to sit there trying to renew until
268 * it gets to the REBIND state, when we *can* NAK it because
269 * the packet will get to us through a BOOTP gateway. We
270 * shouldn't actually see DHCPREQUEST packets from RENEWING
271 * clients on the wrong wire anyway, since their idea of their
272 * local router will be wrong. In any case, the protocol
273 * doesn't really allow us to NAK a DHCPREQUEST from a
274 * RENEWING client, so we can punt on this issue.
275 */
276 if (!packet->shared_network ||
277 (packet->raw->ciaddr.s_addr && packet->raw->giaddr.s_addr) ||
278 (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len == 4 &&
279 !packet->raw->ciaddr.s_addr)) {
280
281 /*
282 * If we don't know where it came from but we do know
283 * where it claims to have come from, it didn't come
284 * from there. Fry it.
285 */
286 if (!packet->shared_network) {
287 if (subnet &&
288 subnet->shared_network->group->authoritative) {
289 nak_lease(packet, &cip);
290 return;
291 }
292 /* Otherwise, ignore it. */
293 return;
294 }
295
296 /*
297 * If we do know where it came from and it asked for an
298 * address that is not on that shared network, nak it.
299 */
300 subnet = find_grouped_subnet(packet->shared_network, cip);
301 if (!subnet) {
302 if (packet->shared_network->group->authoritative)
303 nak_lease(packet, &cip);
304 return;
305 }
306 }
307
308 /*
309 * If we found a lease for the client but it's not the one the
310 * client asked for, don't send it - some other server probably
311 * made the cut.
312 */
313 if (lease && !addr_eq(lease->ip_addr, cip)) {
314 /*
315 * If we found the address the client asked for, but
316 * it wasn't what got picked, the lease belongs to us,
317 * so we should NAK it.
318 */
319 if (ours)
320 nak_lease(packet, &cip);
321 return;
322 }
323
324 /*
325 * If the address the client asked for is ours, but it wasn't
326 * available for the client, NAK it.
327 */
328 if (!lease && ours) {
329 nak_lease(packet, &cip);
330 return;
331 }
332
333 /* If we're not allowed to serve this client anymore, don't. */
334 if (lease && !lease->host &&
335 !lease->subnet->group->boot_unknown_clients) {
336 log_info("Ignoring unknown client %s",
337 print_hw_addr(packet->raw->htype, packet->raw->hlen,
338 packet->raw->chaddr));
339 return;
340 } else if (lease && lease->host && !lease->host->group->allow_booting)
341 {
342 log_info("Declining to renew client %s",
343 lease->host->name ? lease->host->name :
344 print_hw_addr(packet->raw->htype, packet->raw->hlen,
345 packet->raw->chaddr));
346 return;
347 }
348
349 /*
350 * If we own the lease that the client is asking for,
351 * and it's already been assigned to the client, ack it.
352 */
353 if (lease &&
354 ((lease->uid_len && lease->uid_len ==
355 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len &&
356 !memcmp(packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
357 lease->uid, lease->uid_len)) ||
358 (lease->hardware_addr.hlen == packet->raw->hlen &&
359 lease->hardware_addr.htype == packet->raw->htype &&
360 !memcmp(lease->hardware_addr.haddr, packet->raw->chaddr,
361 packet->raw->hlen)))) {
362 ack_lease(packet, lease, DHCPACK, 0);
363 sync_lease(lease);
364 return;
365 }
366
367 /*
368 * At this point, the client has requested a lease, and it's
369 * available, but it wasn't assigned to the client, which
370 * means that the client probably hasn't gone through the
371 * DHCPDISCOVER part of the protocol. We are within our
372 * rights to send a DHCPNAK. We can also send a DHCPACK.
373 * The thing we probably should not do is to remain silent.
374 * For now, we'll just assign the lease to the client anyway.
375 */
376 if (lease) {
377 ack_lease(packet, lease, DHCPACK, 0);
378 sync_lease(lease);
379 }
380 }
381
382 void
dhcprelease(struct packet * packet)383 dhcprelease(struct packet *packet)
384 {
385 char ciaddrbuf[INET_ADDRSTRLEN];
386 struct lease *lease;
387 struct iaddr cip;
388 int i;
389
390 /*
391 * DHCPRELEASE must not specify address in requested-address
392 * option, but old protocol specs weren't explicit about this,
393 * so let it go.
394 */
395 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len) {
396 log_info("DHCPRELEASE from %s specified requested-address.",
397 print_hw_addr(packet->raw->htype, packet->raw->hlen,
398 packet->raw->chaddr));
399 }
400
401 i = DHO_DHCP_CLIENT_IDENTIFIER;
402 if (packet->options[i].len) {
403 lease = find_lease_by_uid(packet->options[i].data,
404 packet->options[i].len);
405
406 /*
407 * See if we can find a lease that matches the
408 * IP address the client is claiming.
409 */
410 for (; lease; lease = lease->n_uid) {
411 if (!memcmp(&packet->raw->ciaddr,
412 lease->ip_addr.iabuf, 4)) {
413 break;
414 }
415 }
416 } else {
417 /*
418 * The client is supposed to pass a valid client-identifier,
419 * but the spec on this has changed historically, so try the
420 * IP address in ciaddr if the client-identifier fails.
421 */
422 cip.len = 4;
423 memcpy(cip.iabuf, &packet->raw->ciaddr, 4);
424 lease = find_lease_by_ip_addr(cip);
425 }
426
427 /* Can't do >1 inet_ntoa() in a printf()! */
428 strlcpy(ciaddrbuf, inet_ntoa(packet->raw->ciaddr), sizeof(ciaddrbuf));
429
430 log_info("DHCPRELEASE of %s from %s via %s (%sfound)",
431 ciaddrbuf,
432 print_hw_addr(packet->raw->htype, packet->raw->hlen,
433 packet->raw->chaddr),
434 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) :
435 packet->interface->name,
436 lease ? "" : "not ");
437
438 /* If we're already acking this lease, don't do it again. */
439 if (lease && lease->state) {
440 log_info("DHCPRELEASE already acking lease %s",
441 piaddr(lease->ip_addr));
442 return;
443 }
444
445 /* If we found a lease, release it. */
446 if (lease && lease->ends > cur_time) {
447 /*
448 * First, we ping this lease to see if it's still
449 * there. if it is, we don't release it. This avoids
450 * the problem of spoofed releases being used to liberate
451 * addresses from the server.
452 */
453 if (!lease->releasing) {
454 log_info("DHCPRELEASE of %s from %s via %s (found)",
455 ciaddrbuf,
456 print_hw_addr(packet->raw->htype,
457 packet->raw->hlen, packet->raw->chaddr),
458 packet->raw->giaddr.s_addr ?
459 inet_ntoa(packet->raw->giaddr) :
460 packet->interface->name);
461
462 lease->releasing = 1;
463 add_timeout(cur_time + 1, lease_ping_timeout, lease);
464 icmp_echorequest(&(lease->ip_addr));
465 ++outstanding_pings;
466 } else {
467 log_info("DHCPRELEASE of %s from %s via %s ignored "
468 "(release already pending)",
469 ciaddrbuf,
470 print_hw_addr(packet->raw->htype,
471 packet->raw->hlen, packet->raw->chaddr),
472 packet->raw->giaddr.s_addr ?
473 inet_ntoa(packet->raw->giaddr) :
474 packet->interface->name);
475 }
476 } else {
477 log_info("DHCPRELEASE of %s from %s via %s for nonexistent "
478 "lease", ciaddrbuf, print_hw_addr(packet->raw->htype,
479 packet->raw->hlen, packet->raw->chaddr),
480 packet->raw->giaddr.s_addr ?
481 inet_ntoa(packet->raw->giaddr) : packet->interface->name);
482 }
483 }
484
485 void
dhcpdecline(struct packet * packet)486 dhcpdecline(struct packet *packet)
487 {
488 struct lease *lease;
489 struct iaddr cip;
490
491 /* DHCPDECLINE must specify address. */
492 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len != 4)
493 return;
494
495 cip.len = 4;
496 memcpy(cip.iabuf,
497 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data, 4);
498 lease = find_lease_by_ip_addr(cip);
499
500 log_info("DHCPDECLINE on %s from %s via %s",
501 piaddr(cip), print_hw_addr(packet->raw->htype,
502 packet->raw->hlen, packet->raw->chaddr),
503 packet->raw->giaddr.s_addr ? inet_ntoa(packet->raw->giaddr) :
504 packet->interface->name);
505
506 /* If we're already acking this lease, don't do it again. */
507 if (lease && lease->state) {
508 log_info("DHCPDECLINE already acking lease %s",
509 piaddr(lease->ip_addr));
510 return;
511 }
512
513 /* If we found a lease, mark it as unusable and complain. */
514 if (lease)
515 abandon_lease(lease, "declined.");
516 }
517
518 void
dhcpinform(struct packet * packet)519 dhcpinform(struct packet *packet)
520 {
521 struct lease lease;
522 struct iaddr cip;
523 struct subnet *subnet;
524
525 /*
526 * ciaddr should be set to client's IP address but
527 * not all clients are standards compliant.
528 */
529 cip.len = 4;
530 if (packet->raw->ciaddr.s_addr && !packet->raw->giaddr.s_addr) {
531 if (memcmp(&packet->raw->ciaddr.s_addr,
532 packet->client_addr.iabuf, 4) != 0) {
533 log_info("DHCPINFORM from %s but ciaddr %s is not "
534 "consistent with actual address",
535 piaddr(packet->client_addr),
536 inet_ntoa(packet->raw->ciaddr));
537 return;
538 }
539 memcpy(cip.iabuf, &packet->raw->ciaddr.s_addr, 4);
540 } else
541 memcpy(cip.iabuf, &packet->client_addr.iabuf, 4);
542
543 log_info("DHCPINFORM from %s", piaddr(cip));
544
545 /* Find the lease that matches the address requested by the client. */
546 subnet = find_subnet(cip);
547 if (!subnet)
548 return;
549
550 /* Sourceless packets don't make sense here. */
551 if (!subnet->shared_network) {
552 log_info("Packet from unknown subnet: %s",
553 inet_ntoa(packet->raw->giaddr));
554 return;
555 }
556
557 /* Use a fake lease entry */
558 memset(&lease, 0, sizeof(lease));
559 lease.subnet = subnet;
560 lease.shared_network = subnet->shared_network;
561
562 if (packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len)
563 lease.host = find_hosts_by_uid(
564 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
565 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len);
566
567 lease.starts = lease.timestamp = lease.ends = MIN_TIME;
568 lease.flags = INFORM_NOLEASE;
569 ack_lease(packet, &lease, DHCPACK, 0);
570 if (lease.state != NULL)
571 free_lease_state(lease.state, "ack_lease");
572 }
573
574 void
nak_lease(struct packet * packet,struct iaddr * cip)575 nak_lease(struct packet *packet, struct iaddr *cip)
576 {
577 struct sockaddr_in to;
578 struct in_addr from;
579 ssize_t result;
580 int i;
581 struct dhcp_packet raw;
582 unsigned char nak = DHCPNAK;
583 struct packet outgoing;
584 struct tree_cache *options[256];
585 struct tree_cache dhcpnak_tree, dhcpmsg_tree;
586 struct tree_cache client_tree, server_tree;
587
588 memset(options, 0, sizeof options);
589 memset(&outgoing, 0, sizeof outgoing);
590 memset(&raw, 0, sizeof raw);
591 outgoing.raw = &raw;
592
593 /* Set DHCP_MESSAGE_TYPE to DHCPNAK */
594 i = DHO_DHCP_MESSAGE_TYPE;
595 options[i] = &dhcpnak_tree;
596 options[i]->value = &nak;
597 options[i]->len = sizeof nak;
598 options[i]->buf_size = sizeof nak;
599 options[i]->timeout = -1;
600 options[i]->tree = NULL;
601 options[i]->flags = 0;
602
603 /* Set DHCP_MESSAGE to whatever the message is */
604 i = DHO_DHCP_MESSAGE;
605 options[i] = &dhcpmsg_tree;
606 options[i]->value = (unsigned char *)dhcp_message;
607 options[i]->len = strlen(dhcp_message);
608 options[i]->buf_size = strlen(dhcp_message);
609 options[i]->timeout = -1;
610 options[i]->tree = NULL;
611 options[i]->flags = 0;
612
613 /* Include server identifier in the NAK. At least one
614 * router vendor depends on it when using dhcp relay proxy mode.
615 */
616 i = DHO_DHCP_SERVER_IDENTIFIER;
617 if (packet->options[i].len) {
618 options[i] = &server_tree;
619 options[i]->value = packet->options[i].data,
620 options[i]->len = packet->options[i].len;
621 options[i]->buf_size = packet->options[i].len;
622 options[i]->timeout = -1;
623 options[i]->tree = NULL;
624 options[i]->flags = 0;
625 }
626
627 /* Echo back the client-identifier as RFC 6842 mandates. */
628 i = DHO_DHCP_CLIENT_IDENTIFIER;
629 if (packet->options[i].len) {
630 options[i] = &client_tree;
631 options[i]->value = packet->options[i].data,
632 options[i]->len = packet->options[i].len;
633 options[i]->buf_size = packet->options[i].len;
634 options[i]->timeout = -1;
635 options[i]->tree = NULL;
636 options[i]->flags = 0;
637 }
638
639 /* Do not use the client's requested parameter list. */
640 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
641 if (packet->options[i].data) {
642 packet->options[i].len = 0;
643 free(packet->options[i].data);
644 packet->options[i].data = NULL;
645 }
646
647 /* Set up the option buffer... */
648 outgoing.packet_length = cons_options(packet, outgoing.raw,
649 0, options, 0, 0, 0, NULL, 0);
650
651 /* memset(&raw.ciaddr, 0, sizeof raw.ciaddr);*/
652 raw.siaddr = packet->interface->primary_address;
653 raw.giaddr = packet->raw->giaddr;
654 memcpy(raw.chaddr, packet->raw->chaddr, sizeof raw.chaddr);
655 raw.hlen = packet->raw->hlen;
656 raw.htype = packet->raw->htype;
657 raw.xid = packet->raw->xid;
658 raw.secs = packet->raw->secs;
659 raw.flags = packet->raw->flags | htons(BOOTP_BROADCAST);
660 raw.hops = packet->raw->hops;
661 raw.op = BOOTREPLY;
662
663 /* Report what we're sending... */
664 log_info("DHCPNAK on %s to %s via %s", piaddr(*cip),
665 print_hw_addr(packet->raw->htype, packet->raw->hlen,
666 packet->raw->chaddr), packet->raw->giaddr.s_addr ?
667 inet_ntoa(packet->raw->giaddr) : packet->interface->name);
668
669 /* Set up the common stuff... */
670 memset(&to, 0, sizeof to);
671 to.sin_family = AF_INET;
672 to.sin_len = sizeof to;
673
674 from = packet->interface->primary_address;
675
676 /* Make sure that the packet is at least as big as a BOOTP packet. */
677 if (outgoing.packet_length < BOOTP_MIN_LEN)
678 outgoing.packet_length = BOOTP_MIN_LEN;
679
680 /*
681 * If this was gatewayed, send it back to the gateway.
682 * Otherwise, broadcast it on the local network.
683 */
684 if (raw.giaddr.s_addr) {
685 to.sin_addr = raw.giaddr;
686 to.sin_port = server_port;
687
688 result = packet->interface->send_packet(packet->interface, &raw,
689 outgoing.packet_length, from, &to, packet->haddr);
690 if (result == -1)
691 log_warn("send_fallback");
692 return;
693 } else {
694 to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
695 to.sin_port = client_port;
696 }
697
698 errno = 0;
699 result = packet->interface->send_packet(packet->interface, &raw,
700 outgoing.packet_length, from, &to, NULL);
701 }
702
703 void
ack_lease(struct packet * packet,struct lease * lease,unsigned int offer,time_t when)704 ack_lease(struct packet *packet, struct lease *lease, unsigned int offer,
705 time_t when)
706 {
707 struct lease lt;
708 struct lease_state *state;
709 time_t lease_time, offered_lease_time, max_lease_time, default_lease_time;
710 struct class *vendor_class, *user_class;
711 int ulafdr, echo_client_id, i;
712
713 /* If we're already acking this lease, don't do it again. */
714 if (lease->state) {
715 if ((lease->flags & STATIC_LEASE) ||
716 cur_time - lease->timestamp < 60) {
717 log_info("already acking lease %s",
718 piaddr(lease->ip_addr));
719 return;
720 }
721 free_lease_state(lease->state, "ACK timed out");
722 lease->state = NULL;
723 }
724
725 i = DHO_DHCP_CLASS_IDENTIFIER;
726 if (packet->options[i].len) {
727 vendor_class = find_class(0, packet->options[i].data,
728 packet->options[i].len);
729 } else
730 vendor_class = NULL;
731
732 i = DHO_DHCP_USER_CLASS_ID;
733 if (packet->options[i].len) {
734 user_class = find_class(1, packet->options[i].data,
735 packet->options[i].len);
736 } else
737 user_class = NULL;
738
739 /*
740 * If there is not a specific host entry, and either the
741 * vendor class or user class (if they exist) deny booting,
742 * then bug out.
743 */
744 if (!lease->host) {
745 if (vendor_class && !vendor_class->group->allow_booting) {
746 log_debug("Booting denied by vendor class");
747 return;
748 }
749
750 if (user_class && !user_class->group->allow_booting) {
751 log_debug("Booting denied by user class");
752 return;
753 }
754 }
755
756 /* Allocate a lease state structure... */
757 state = new_lease_state("ack_lease");
758 if (!state)
759 fatalx("unable to allocate lease state!");
760 memset(state, 0, sizeof *state);
761 state->got_requested_address = packet->got_requested_address;
762 state->shared_network = packet->interface->shared_network;
763
764 /* Remember if we got a server identifier option. */
765 i = DHO_DHCP_SERVER_IDENTIFIER;
766 if (packet->options[i].len)
767 state->got_server_identifier = 1;
768
769 /* Replace the old lease hostname with the new one, if it's changed. */
770 i = DHO_HOST_NAME;
771 if (packet->options[i].len && lease->client_hostname &&
772 (strlen(lease->client_hostname) == packet->options[i].len) &&
773 !memcmp(lease->client_hostname, packet->options[i].data,
774 packet->options[i].len)) {
775 } else if (packet->options[i].len) {
776 free(lease->client_hostname);
777 lease->client_hostname = malloc( packet->options[i].len + 1);
778 if (!lease->client_hostname)
779 fatalx("no memory for client hostname.\n");
780 memcpy(lease->client_hostname, packet->options[i].data,
781 packet->options[i].len);
782 lease->client_hostname[packet->options[i].len] = 0;
783 } else if (lease->client_hostname) {
784 free(lease->client_hostname);
785 lease->client_hostname = 0;
786 }
787
788 /* Replace the lease client identifier with a new one. */
789 i = DHO_DHCP_CLIENT_IDENTIFIER;
790 if (packet->options[i].len && lease->client_identifier &&
791 lease->client_identifier_len == packet->options[i].len &&
792 !memcmp(lease->client_identifier, packet->options[i].data,
793 packet->options[i].len)) {
794 /* Same client identifier. */
795 } else if (packet->options[i].len) {
796 free(lease->client_identifier);
797 lease->client_identifier = malloc(packet->options[i].len);
798 if (!lease->client_identifier)
799 fatalx("no memory for client identifier.\n");
800 lease->client_identifier_len = packet->options[i].len;
801 memcpy(lease->client_identifier, packet->options[i].data,
802 packet->options[i].len);
803 } else if (lease->client_identifier) {
804 free(lease->client_identifier);
805 lease->client_identifier = NULL;
806 lease->client_identifier_len = 0;
807 }
808
809 /*
810 * Choose a filename; first from the host_decl, if any, then from
811 * the user class, then from the vendor class.
812 */
813 if (lease->host && lease->host->group->filename)
814 strlcpy(state->filename, lease->host->group->filename,
815 sizeof state->filename);
816 else if (user_class && user_class->group->filename)
817 strlcpy(state->filename, user_class->group->filename,
818 sizeof state->filename);
819 else if (vendor_class && vendor_class->group->filename)
820 strlcpy(state->filename, vendor_class->group->filename,
821 sizeof state->filename);
822 else if (packet->raw->file[0])
823 strlcpy(state->filename, packet->raw->file,
824 sizeof state->filename);
825 else if (lease->subnet->group->filename)
826 strlcpy(state->filename, lease->subnet->group->filename,
827 sizeof state->filename);
828 else
829 strlcpy(state->filename, "", sizeof state->filename);
830
831 /* Choose a server name as above. */
832 if (lease->host && lease->host->group->server_name)
833 state->server_name = lease->host->group->server_name;
834 else if (user_class && user_class->group->server_name)
835 state->server_name = user_class->group->server_name;
836 else if (vendor_class && vendor_class->group->server_name)
837 state->server_name = vendor_class->group->server_name;
838 else if (lease->subnet->group->server_name)
839 state->server_name = lease->subnet->group->server_name;
840 else state->server_name = NULL;
841
842 /*
843 * At this point, we have a lease that we can offer the client.
844 * Now we construct a lease structure that contains what we want,
845 * and call supersede_lease to do the right thing with it.
846 */
847 memset(<, 0, sizeof lt);
848
849 /*
850 * Use the ip address of the lease that we finally found in
851 * the database.
852 */
853 lt.ip_addr = lease->ip_addr;
854
855 /* Start now. */
856 lt.starts = cur_time;
857
858 /* Figure out maximum lease time. */
859 if (lease->host && lease->host->group->max_lease_time)
860 max_lease_time = lease->host->group->max_lease_time;
861 else
862 max_lease_time = lease->subnet->group->max_lease_time;
863
864 /* Figure out default lease time. */
865 if (lease->host && lease->host->group->default_lease_time)
866 default_lease_time = lease->host->group->default_lease_time;
867 else
868 default_lease_time = lease->subnet->group->default_lease_time;
869
870 /*
871 * Figure out how long a lease to assign. If this is a
872 * dynamic BOOTP lease, its duration must be infinite.
873 */
874 if (offer) {
875 i = DHO_DHCP_LEASE_TIME;
876 if (packet->options[i].len == 4) {
877 lease_time = getULong( packet->options[i].data);
878
879 /*
880 * Don't let the client ask for a longer lease than
881 * is supported for this subnet or host.
882 *
883 * time_t is signed, so really large numbers come
884 * back as negative. Don't allow lease_time of 0,
885 * either.
886 */
887 if (lease_time < 1 || lease_time > max_lease_time)
888 lease_time = max_lease_time;
889 } else
890 lease_time = default_lease_time;
891
892 state->offered_expiry = cur_time + lease_time;
893 if (when)
894 lt.ends = when;
895 else
896 lt.ends = state->offered_expiry;
897 } else {
898 if (lease->host &&
899 lease->host->group->bootp_lease_length)
900 lt.ends = (cur_time +
901 lease->host->group->bootp_lease_length);
902 else if (lease->subnet->group->bootp_lease_length)
903 lt.ends = (cur_time +
904 lease->subnet->group->bootp_lease_length);
905 else if (lease->host &&
906 lease->host->group->bootp_lease_cutoff)
907 lt.ends = lease->host->group->bootp_lease_cutoff;
908 else
909 lt.ends = lease->subnet->group->bootp_lease_cutoff;
910 state->offered_expiry = lt.ends;
911 lt.flags = BOOTP_LEASE;
912 }
913
914 /* Record the uid, if given... */
915 i = DHO_DHCP_CLIENT_IDENTIFIER;
916 if (packet->options[i].len) {
917 if (packet->options[i].len <= sizeof lt.uid_buf) {
918 memcpy(lt.uid_buf, packet->options[i].data,
919 packet->options[i].len);
920 lt.uid = lt.uid_buf;
921 lt.uid_max = sizeof lt.uid_buf;
922 lt.uid_len = packet->options[i].len;
923 } else {
924 lt.uid_max = lt.uid_len = packet->options[i].len;
925 lt.uid = malloc(lt.uid_max);
926 if (!lt.uid)
927 fatalx("can't allocate memory for large uid.");
928 memcpy(lt.uid, packet->options[i].data, lt.uid_len);
929 }
930 }
931
932 lt.host = lease->host;
933 lt.subnet = lease->subnet;
934 lt.shared_network = lease->shared_network;
935
936 /* Don't call supersede_lease on a mocked-up lease. */
937 if (lease->flags & (STATIC_LEASE | INFORM_NOLEASE)) {
938 /* Copy the hardware address into the static lease
939 structure. */
940 lease->hardware_addr.hlen = packet->raw->hlen;
941 lease->hardware_addr.htype = packet->raw->htype;
942 memcpy(lease->hardware_addr.haddr, packet->raw->chaddr,
943 sizeof packet->raw->chaddr); /* XXX */
944 } else {
945 /* Record the hardware address, if given... */
946 lt.hardware_addr.hlen = packet->raw->hlen;
947 lt.hardware_addr.htype = packet->raw->htype;
948 memcpy(lt.hardware_addr.haddr, packet->raw->chaddr,
949 sizeof packet->raw->chaddr);
950
951 /* Install the new information about this lease in the
952 database. If this is a DHCPACK or a dynamic BOOTREPLY
953 and we can't write the lease, don't ACK it (or BOOTREPLY
954 it) either. */
955
956 if (!(supersede_lease(lease, <, !offer ||
957 offer == DHCPACK) || (offer && offer != DHCPACK))) {
958 free_lease_state(state, "ack_lease: !supersede_lease");
959 return;
960 }
961 }
962
963 /* Remember the interface on which the packet arrived. */
964 state->ip = packet->interface;
965
966 /* Set a flag if this client is a lame Microsoft client that NUL
967 terminates string options and expects us to do likewise. */
968 i = DHO_HOST_NAME;
969 if (packet->options[i].len &&
970 packet->options[i].data[packet->options[i].len - 1] == '\0')
971 lease->flags |= MS_NULL_TERMINATION;
972 else
973 lease->flags &= ~MS_NULL_TERMINATION;
974
975 /* Remember the giaddr, xid, secs, flags and hops. */
976 state->giaddr = packet->raw->giaddr;
977 state->ciaddr = packet->raw->ciaddr;
978 state->xid = packet->raw->xid;
979 state->secs = packet->raw->secs;
980 state->bootp_flags = packet->raw->flags;
981 state->hops = packet->raw->hops;
982 state->offer = offer;
983 memcpy(&state->haddr, packet->haddr, sizeof state->haddr);
984
985 /* Figure out what options to send to the client: */
986
987 /* Start out with the subnet options... */
988 memcpy(state->options, lease->subnet->group->options,
989 sizeof state->options);
990
991 /* Vendor and user classes are only supported for DHCP clients. */
992 if (state->offer) {
993 /* If we have a vendor class, install those options,
994 superseding any subnet options. */
995 if (vendor_class) {
996 for (i = 0; i < 256; i++)
997 if (vendor_class->group->options[i])
998 state->options[i] =
999 vendor_class->group->options[i];
1000 }
1001
1002 /* If we have a user class, install those options,
1003 superseding any subnet and vendor class options. */
1004 if (user_class) {
1005 for (i = 0; i < 256; i++)
1006 if (user_class->group->options[i])
1007 state->options[i] =
1008 user_class->group->options[i];
1009 }
1010
1011 }
1012
1013 /* If we have a host_decl structure, install the associated
1014 options, superseding anything that's in the way. */
1015 if (lease->host) {
1016 for (i = 0; i < 256; i++)
1017 if (lease->host->group->options[i])
1018 state->options[i] =
1019 lease->host->group->options[i];
1020 }
1021
1022 /* Get the Maximum Message Size option from the packet, if one
1023 was sent. */
1024 i = DHO_DHCP_MAX_MESSAGE_SIZE;
1025 if (packet->options[i].data &&
1026 packet->options[i].len == sizeof(u_int16_t))
1027 state->max_message_size = getUShort(packet->options[i].data);
1028 /* Otherwise, if a maximum message size was specified, use that. */
1029 else if (state->options[i] && state->options[i]->value)
1030 state->max_message_size = getUShort(state->options[i]->value);
1031
1032 /* Save the parameter request list if there is one. */
1033 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1034 if (packet->options[i].data) {
1035 state->prl = calloc(1, packet->options[i].len);
1036 if (!state->prl)
1037 log_warnx("no memory for parameter request list");
1038 else {
1039 memcpy(state->prl, packet->options[i].data,
1040 packet->options[i].len);
1041 state->prl_len = packet->options[i].len;
1042 }
1043 }
1044
1045 /* If we didn't get a hostname from an option somewhere, see if
1046 we can get one from the lease. */
1047 i = DHO_HOST_NAME;
1048 if (!state->options[i] && lease->hostname) {
1049 state->options[i] = new_tree_cache("hostname");
1050 state->options[i]->flags = TC_TEMPORARY;
1051 state->options[i]->value = (unsigned char *)lease->hostname;
1052 state->options[i]->len = strlen(lease->hostname);
1053 state->options[i]->buf_size = state->options[i]->len;
1054 state->options[i]->timeout = -1;
1055 state->options[i]->tree = NULL;
1056 }
1057
1058 /*
1059 * Now, if appropriate, put in DHCP-specific options that
1060 * override those.
1061 */
1062 if (state->offer) {
1063 i = DHO_DHCP_MESSAGE_TYPE;
1064 state->options[i] = new_tree_cache("message-type");
1065 state->options[i]->flags = TC_TEMPORARY;
1066 state->options[i]->value = &state->offer;
1067 state->options[i]->len = sizeof state->offer;
1068 state->options[i]->buf_size = sizeof state->offer;
1069 state->options[i]->timeout = -1;
1070 state->options[i]->tree = NULL;
1071
1072 i = DHO_DHCP_SERVER_IDENTIFIER;
1073 if (!state->options[i]) {
1074 use_primary:
1075 state->options[i] = new_tree_cache("server-id");
1076 state->options[i]->value =
1077 (unsigned char *)&state->ip->primary_address;
1078 state->options[i]->len =
1079 sizeof state->ip->primary_address;
1080 state->options[i]->buf_size = state->options[i]->len;
1081 state->options[i]->timeout = -1;
1082 state->options[i]->tree = NULL;
1083 state->from.len = sizeof state->ip->primary_address;
1084 memcpy(state->from.iabuf, &state->ip->primary_address,
1085 state->from.len);
1086 } else {
1087 /* Find the value of the server identifier... */
1088 if (!tree_evaluate(state->options[i]))
1089 goto use_primary;
1090 if (!state->options[i]->value ||
1091 (state->options[i]->len >
1092 sizeof state->from.iabuf))
1093 goto use_primary;
1094
1095 state->from.len = state->options[i]->len;
1096 memcpy(state->from.iabuf, state->options[i]->value,
1097 state->from.len);
1098 }
1099 /*
1100 * Do not ACK a REQUEST intended for another server.
1101 */
1102 if (packet->options[i].len == 4) {
1103 if (state->options[i]->len != 4 ||
1104 memcmp(packet->options[i].data,
1105 state->options[i]->value, 4) != 0) {
1106 free_lease_state(state, "ack_lease: "
1107 "server identifier");
1108 return;
1109 }
1110 }
1111
1112 /* If we used the vendor class the client specified, we
1113 have to return it. */
1114 if (vendor_class) {
1115 i = DHO_DHCP_CLASS_IDENTIFIER;
1116 state->options[i] = new_tree_cache("class-identifier");
1117 state->options[i]->flags = TC_TEMPORARY;
1118 state->options[i]->value =
1119 (unsigned char *)vendor_class->name;
1120 state->options[i]->len = strlen(vendor_class->name);
1121 state->options[i]->buf_size = state->options[i]->len;
1122 state->options[i]->timeout = -1;
1123 state->options[i]->tree = NULL;
1124 }
1125
1126 /* If we used the user class the client specified, we
1127 have to return it. */
1128 if (user_class) {
1129 i = DHO_DHCP_USER_CLASS_ID;
1130 state->options[i] = new_tree_cache("user-class");
1131 state->options[i]->flags = TC_TEMPORARY;
1132 state->options[i]->value =
1133 (unsigned char *)user_class->name;
1134 state->options[i]->len = strlen(user_class->name);
1135 state->options[i]->buf_size = state->options[i]->len;
1136 state->options[i]->timeout = -1;
1137 state->options[i]->tree = NULL;
1138 }
1139 }
1140
1141 /* for DHCPINFORM, don't include lease time parameters */
1142 if (state->offer && (lease->flags & INFORM_NOLEASE) == 0) {
1143
1144 /* Sanity check the lease time. */
1145 if ((state->offered_expiry - cur_time) < 15)
1146 offered_lease_time = default_lease_time;
1147 else if (state->offered_expiry - cur_time > max_lease_time)
1148 offered_lease_time = max_lease_time;
1149 else
1150 offered_lease_time =
1151 state->offered_expiry - cur_time;
1152
1153 putULong((unsigned char *)&state->expiry, offered_lease_time);
1154 i = DHO_DHCP_LEASE_TIME;
1155 state->options[i] = new_tree_cache("lease-expiry");
1156 state->options[i]->flags = TC_TEMPORARY;
1157 state->options[i]->value = (unsigned char *)&state->expiry;
1158 state->options[i]->len = sizeof state->expiry;
1159 state->options[i]->buf_size = sizeof state->expiry;
1160 state->options[i]->timeout = -1;
1161 state->options[i]->tree = NULL;
1162
1163 /* Renewal time is lease time * 0.5. */
1164 offered_lease_time /= 2;
1165 putULong((unsigned char *)&state->renewal, offered_lease_time);
1166 i = DHO_DHCP_RENEWAL_TIME;
1167 state->options[i] = new_tree_cache("renewal-time");
1168 state->options[i]->flags = TC_TEMPORARY;
1169 state->options[i]->value =
1170 (unsigned char *)&state->renewal;
1171 state->options[i]->len = sizeof state->renewal;
1172 state->options[i]->buf_size = sizeof state->renewal;
1173 state->options[i]->timeout = -1;
1174 state->options[i]->tree = NULL;
1175
1176
1177 /* Rebinding time is lease time * 0.875. */
1178 offered_lease_time += (offered_lease_time / 2 +
1179 offered_lease_time / 4);
1180 putULong((unsigned char *)&state->rebind, offered_lease_time);
1181 i = DHO_DHCP_REBINDING_TIME;
1182 state->options[i] = new_tree_cache("rebind-time");
1183 state->options[i]->flags = TC_TEMPORARY;
1184 state->options[i]->value = (unsigned char *)&state->rebind;
1185 state->options[i]->len = sizeof state->rebind;
1186 state->options[i]->buf_size = sizeof state->rebind;
1187 state->options[i]->timeout = -1;
1188 state->options[i]->tree = NULL;
1189 }
1190
1191 /* Use the subnet mask from the subnet declaration if no other
1192 mask has been provided. */
1193 i = DHO_SUBNET_MASK;
1194 if (!state->options[i]) {
1195 state->options[i] = new_tree_cache("subnet-mask");
1196 state->options[i]->flags = TC_TEMPORARY;
1197 state->options[i]->value = lease->subnet->netmask.iabuf;
1198 state->options[i]->len = lease->subnet->netmask.len;
1199 state->options[i]->buf_size = lease->subnet->netmask.len;
1200 state->options[i]->timeout = -1;
1201 state->options[i]->tree = NULL;
1202 }
1203
1204 /* If so directed, use the leased IP address as the router address.
1205 This supposedly makes Win95 machines ARP for all IP addresses,
1206 so if the local router does proxy arp, you win. */
1207
1208 ulafdr = 0;
1209 if (lease->host) {
1210 if (lease->host->group->use_lease_addr_for_default_route)
1211 ulafdr = 1;
1212 } else if (user_class) {
1213 if (user_class->group->use_lease_addr_for_default_route)
1214 ulafdr = 1;
1215 } else if (vendor_class) {
1216 if (vendor_class->group->use_lease_addr_for_default_route)
1217 ulafdr = 1;
1218 } else if (lease->subnet->group->use_lease_addr_for_default_route)
1219 ulafdr = 1;
1220 else
1221 ulafdr = 0;
1222
1223 i = DHO_ROUTERS;
1224 if (ulafdr && !state->options[i]) {
1225 state->options[i] = new_tree_cache("routers");
1226 state->options[i]->flags = TC_TEMPORARY;
1227 state->options[i]->value = lease->ip_addr.iabuf;
1228 state->options[i]->len = lease->ip_addr.len;
1229 state->options[i]->buf_size = lease->ip_addr.len;
1230 state->options[i]->timeout = -1;
1231 state->options[i]->tree = NULL;
1232 }
1233
1234 /*
1235 * RFC 3046: MUST NOT echo relay agent information if the server
1236 * does not understand/use the data. We don't.
1237 */
1238 i = DHO_RELAY_AGENT_INFORMATION;
1239 memset(&state->options[i], 0, sizeof(state->options[i]));
1240
1241 /* Echo back the client-identifier as RFC 6842 mandates. */
1242 if (lease->host)
1243 echo_client_id = lease->host->group->echo_client_id;
1244 else if (user_class)
1245 echo_client_id = user_class->group->echo_client_id;
1246 else if (vendor_class)
1247 echo_client_id = vendor_class->group->echo_client_id;
1248 else
1249 echo_client_id = lease->subnet->group->echo_client_id;
1250 i = DHO_DHCP_CLIENT_IDENTIFIER;
1251 if (lease->client_identifier && echo_client_id) {
1252 state->options[i] = new_tree_cache("dhcp-client-identifier");
1253 state->options[i]->flags = TC_TEMPORARY;
1254 state->options[i]->value = lease->client_identifier;
1255 state->options[i]->len = lease->client_identifier_len;
1256 state->options[i]->buf_size = lease->client_identifier_len;
1257 state->options[i]->timeout = -1;
1258 state->options[i]->tree = NULL;
1259 } else
1260 memset(&state->options[i], 0, sizeof(state->options[i]));
1261
1262 lease->state = state;
1263
1264 /* If this is a DHCPOFFER, ping the lease address before actually
1265 sending the offer. */
1266 if (offer == DHCPOFFER && !(lease->flags & STATIC_LEASE) &&
1267 cur_time - lease->timestamp > 60) {
1268 lease->timestamp = cur_time;
1269 icmp_echorequest(&lease->ip_addr);
1270 add_timeout(cur_time + 1, lease_ping_timeout, lease);
1271 ++outstanding_pings;
1272 } else {
1273 lease->timestamp = cur_time;
1274 dhcp_reply(lease);
1275 }
1276 }
1277
1278 void
dhcp_reply(struct lease * lease)1279 dhcp_reply(struct lease *lease)
1280 {
1281 char ciaddrbuf[INET_ADDRSTRLEN];
1282 int bufs = 0, packet_length, i;
1283 struct dhcp_packet raw;
1284 struct sockaddr_in to;
1285 struct in_addr from;
1286 struct lease_state *state = lease->state;
1287 int nulltp, bootpp;
1288 u_int8_t *prl;
1289 int prl_len;
1290
1291 if (!state)
1292 fatalx("dhcp_reply was supplied lease with no state!");
1293
1294 /* Compose a response for the client... */
1295 memset(&raw, 0, sizeof raw);
1296
1297 /* Copy in the filename if given; otherwise, flag the filename
1298 buffer as available for options. */
1299 if (state->filename[0])
1300 strlcpy(raw.file, state->filename, sizeof raw.file);
1301 else
1302 bufs |= 1;
1303
1304 /* Copy in the server name if given; otherwise, flag the
1305 server_name buffer as available for options. */
1306 if (state->server_name)
1307 strlcpy(raw.sname, state->server_name, sizeof raw.sname);
1308 else
1309 bufs |= 2; /* XXX */
1310
1311 memcpy(raw.chaddr, lease->hardware_addr.haddr, sizeof raw.chaddr);
1312 raw.hlen = lease->hardware_addr.hlen;
1313 raw.htype = lease->hardware_addr.htype;
1314
1315 /* See if this is a Microsoft client that NUL-terminates its
1316 strings and expects us to do likewise... */
1317 if (lease->flags & MS_NULL_TERMINATION)
1318 nulltp = 1;
1319 else
1320 nulltp = 0;
1321
1322 /* See if this is a bootp client... */
1323 if (state->offer)
1324 bootpp = 0;
1325 else
1326 bootpp = 1;
1327
1328 if (state->options[DHO_DHCP_PARAMETER_REQUEST_LIST] &&
1329 state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->value) {
1330 prl = state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->value;
1331 prl_len = state->options[DHO_DHCP_PARAMETER_REQUEST_LIST]->len;
1332 } else if (state->prl) {
1333 prl = state->prl;
1334 prl_len = state->prl_len;
1335 } else {
1336 prl = NULL;
1337 prl_len = 0;
1338 }
1339
1340 /* Insert such options as will fit into the buffer. */
1341 packet_length = cons_options(NULL, &raw, state->max_message_size,
1342 state->options, bufs, nulltp, bootpp, prl, prl_len);
1343
1344 /* Having done the cons_options(), we can release the tree_cache
1345 entries. */
1346 for (i = 0; i < 256; i++) {
1347 if (state->options[i] &&
1348 state->options[i]->flags & TC_TEMPORARY)
1349 free_tree_cache(state->options[i]);
1350 }
1351
1352 memcpy(&raw.ciaddr, &state->ciaddr, sizeof raw.ciaddr);
1353 if ((lease->flags & INFORM_NOLEASE) == 0)
1354 memcpy(&raw.yiaddr, lease->ip_addr.iabuf, 4);
1355
1356 /* Figure out the address of the next server. */
1357 if (lease->host && lease->host->group->next_server.len)
1358 memcpy(&raw.siaddr, lease->host->group->next_server.iabuf, 4);
1359 else if (lease->subnet->group->next_server.len)
1360 memcpy(&raw.siaddr, lease->subnet->group->next_server.iabuf,
1361 4);
1362 else if (lease->subnet->interface_address.len)
1363 memcpy(&raw.siaddr, lease->subnet->interface_address.iabuf, 4);
1364 else
1365 raw.siaddr = state->ip->primary_address;
1366
1367 raw.giaddr = state->giaddr;
1368
1369 raw.xid = state->xid;
1370 raw.secs = state->secs;
1371 raw.flags = state->bootp_flags;
1372 raw.hops = state->hops;
1373 raw.op = BOOTREPLY;
1374
1375 /* Can't do >1 inet_ntoa() in a printf()! */
1376 strlcpy(ciaddrbuf, inet_ntoa(state->ciaddr), sizeof(ciaddrbuf));
1377
1378 /* Say what we're doing... */
1379 if ((state->offer == DHCPACK) && (lease->flags & INFORM_NOLEASE))
1380 log_info("DHCPACK to %s (%s) via %s",
1381 ciaddrbuf,
1382 print_hw_addr(lease->hardware_addr.htype,
1383 lease->hardware_addr.hlen, lease->hardware_addr.haddr),
1384 state->giaddr.s_addr ? inet_ntoa(state->giaddr) :
1385 state->ip->name);
1386 else
1387 log_info("%s on %s to %s via %s",
1388 (state->offer ? (state->offer == DHCPACK ? "DHCPACK" :
1389 "DHCPOFFER") : "BOOTREPLY"),
1390 piaddr(lease->ip_addr),
1391 print_hw_addr(lease->hardware_addr.htype,
1392 lease->hardware_addr.hlen, lease->hardware_addr.haddr),
1393 state->giaddr.s_addr ? inet_ntoa(state->giaddr) :
1394 state->ip->name);
1395
1396 memset(&to, 0, sizeof to);
1397 to.sin_family = AF_INET;
1398 #ifdef HAVE_SA_LEN
1399 to.sin_len = sizeof to;
1400 #endif
1401
1402 /* Make sure outgoing packets are at least as big
1403 as a BOOTP packet. */
1404 if (packet_length < BOOTP_MIN_LEN)
1405 packet_length = BOOTP_MIN_LEN;
1406
1407 /* If this was gatewayed, send it back to the gateway... */
1408 if (raw.giaddr.s_addr) {
1409 to.sin_addr = raw.giaddr;
1410 to.sin_port = server_port;
1411
1412 memcpy(&from, state->from.iabuf, sizeof from);
1413
1414 (void) state->ip->send_packet(state->ip, &raw,
1415 packet_length, from, &to, &state->haddr);
1416
1417 free_lease_state(state, "dhcp_reply gateway");
1418 lease->state = NULL;
1419 return;
1420
1421 /* If the client is RENEWING, unicast to the client using the
1422 regular IP stack. Some clients, particularly those that
1423 follow RFC1541, are buggy, and send both ciaddr and
1424 server-identifier. We deal with this situation by assuming
1425 that if we got both dhcp-server-identifier and ciaddr, and
1426 giaddr was not set, then the client is on the local
1427 network, and we can therefore unicast or broadcast to it
1428 successfully. A client in REQUESTING state on another
1429 network that's making this mistake will have set giaddr,
1430 and will therefore get a relayed response from the above
1431 code. */
1432 } else if (raw.ciaddr.s_addr &&
1433 !((state->got_server_identifier ||
1434 (raw.flags & htons(BOOTP_BROADCAST))) &&
1435 /* XXX This won't work if giaddr isn't zero, but it is: */
1436 (state->shared_network == lease->shared_network)) &&
1437 state->offer == DHCPACK) {
1438 to.sin_addr = raw.ciaddr;
1439 to.sin_port = client_port;
1440
1441 /* If it comes from a client that already knows its address
1442 and is not requesting a broadcast response, and we can
1443 unicast to a client without using the ARP protocol, sent it
1444 directly to that client. */
1445 } else if (!(raw.flags & htons(BOOTP_BROADCAST))) {
1446 to.sin_addr = raw.yiaddr;
1447 to.sin_port = client_port;
1448
1449 /* Otherwise, broadcast it on the local network. */
1450 } else {
1451 to.sin_addr.s_addr = htonl(INADDR_BROADCAST);
1452 to.sin_port = client_port;
1453 memset(&state->haddr, 0xff, sizeof state->haddr);
1454 }
1455
1456 memcpy(&from, state->from.iabuf, sizeof from);
1457
1458 (void) state->ip->send_packet(state->ip, &raw, packet_length,
1459 from, &to, &state->haddr);
1460
1461 free_lease_state(state, "dhcp_reply");
1462 lease->state = NULL;
1463 }
1464
1465 struct lease *
find_lease(struct packet * packet,struct shared_network * share,int * ours)1466 find_lease(struct packet *packet, struct shared_network *share,
1467 int *ours)
1468 {
1469 struct lease *uid_lease, *ip_lease, *hw_lease;
1470 struct lease *lease = NULL;
1471 struct iaddr cip;
1472 struct host_decl *hp, *host = NULL;
1473 struct lease *fixed_lease;
1474
1475 /* Figure out what IP address the client is requesting, if any. */
1476 if (packet->options[DHO_DHCP_REQUESTED_ADDRESS].len == 4) {
1477 packet->got_requested_address = 1;
1478 cip.len = 4;
1479 memcpy(cip.iabuf,
1480 packet->options[DHO_DHCP_REQUESTED_ADDRESS].data,
1481 cip.len);
1482 } else if (packet->raw->ciaddr.s_addr) {
1483 cip.len = 4;
1484 memcpy(cip.iabuf, &packet->raw->ciaddr, 4);
1485 } else
1486 cip.len = 0;
1487
1488 /* Try to find a host or lease that's been assigned to the
1489 specified unique client identifier. */
1490 if (packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len) {
1491 /* First, try to find a fixed host entry for the specified
1492 client identifier... */
1493 hp = find_hosts_by_uid(
1494 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
1495 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len);
1496 if (hp) {
1497 host = hp;
1498 fixed_lease = mockup_lease(packet, share, hp);
1499 uid_lease = NULL;
1500 } else {
1501 uid_lease = find_lease_by_uid(
1502 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].data,
1503 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len);
1504 /* Find the lease matching this uid that's on the
1505 network the packet came from (if any). */
1506 for (; uid_lease; uid_lease = uid_lease->n_uid)
1507 if (uid_lease->shared_network == share)
1508 break;
1509 fixed_lease = NULL;
1510 if (uid_lease && (uid_lease->flags & ABANDONED_LEASE))
1511 uid_lease = NULL;
1512 }
1513 } else {
1514 uid_lease = NULL;
1515 fixed_lease = NULL;
1516 }
1517
1518 /* If we didn't find a fixed lease using the uid, try doing
1519 it with the hardware address... */
1520 if (!fixed_lease) {
1521 hp = find_hosts_by_haddr(packet->raw->htype,
1522 packet->raw->chaddr, packet->raw->hlen);
1523 if (hp) {
1524 host = hp; /* Save it for later. */
1525 fixed_lease = mockup_lease(packet, share, hp);
1526 }
1527 }
1528
1529 /* If fixed_lease is present but does not match the requested
1530 IP address, and this is a DHCPREQUEST, then we can't return
1531 any other lease, so we might as well return now. */
1532 if (packet->packet_type == DHCPREQUEST && fixed_lease &&
1533 (fixed_lease->ip_addr.len != cip.len ||
1534 memcmp(fixed_lease->ip_addr.iabuf, cip.iabuf, cip.len))) {
1535 if (ours)
1536 *ours = 1;
1537 strlcpy(dhcp_message, "requested address is incorrect",
1538 sizeof(dhcp_message));
1539 return NULL;
1540 }
1541
1542 /* Try to find a lease that's been attached to the client's
1543 hardware address... */
1544 hw_lease = find_lease_by_hw_addr(packet->raw->chaddr,
1545 packet->raw->hlen);
1546 /* Find the lease that's on the network the packet came from
1547 (if any). */
1548 for (; hw_lease; hw_lease = hw_lease->n_hw) {
1549 if (hw_lease->shared_network == share) {
1550 if ((hw_lease->flags & ABANDONED_LEASE))
1551 continue;
1552 if (packet->packet_type)
1553 break;
1554 if (hw_lease->flags &
1555 (BOOTP_LEASE | DYNAMIC_BOOTP_OK))
1556 break;
1557 }
1558 }
1559
1560 /* Try to find a lease that's been allocated to the client's
1561 IP address. */
1562 if (cip.len)
1563 ip_lease = find_lease_by_ip_addr(cip);
1564 else
1565 ip_lease = NULL;
1566
1567 /* If ip_lease is valid at this point, set ours to one, so that
1568 even if we choose a different lease, we know that the address
1569 the client was requesting was ours, and thus we can NAK it. */
1570 if (ip_lease && ours)
1571 *ours = 1;
1572
1573 /* If the requested IP address isn't on the network the packet
1574 came from, don't use it. Allow abandoned leases to be matched
1575 here - if the client is requesting it, there's a decent chance
1576 that it's because the lease database got trashed and a client
1577 that thought it had this lease answered an ARP or PING, causing the
1578 lease to be abandoned. If so, this request probably came from
1579 that client. */
1580 if (ip_lease && (ip_lease->shared_network != share)) {
1581 ip_lease = NULL;
1582 strlcpy(dhcp_message, "requested address on bad subnet",
1583 sizeof(dhcp_message));
1584 }
1585
1586 /* Toss ip_lease if it hasn't yet expired and isn't owned by the
1587 client. */
1588 if (ip_lease && ip_lease->ends >= cur_time && ip_lease != uid_lease) {
1589 int i = DHO_DHCP_CLIENT_IDENTIFIER;
1590
1591 /* Make sure that ip_lease actually belongs to the client,
1592 and toss it if not. */
1593 if ((ip_lease->uid_len && packet->options[i].data &&
1594 ip_lease->uid_len == packet->options[i].len &&
1595 !memcmp(packet->options[i].data, ip_lease->uid,
1596 ip_lease->uid_len)) ||
1597 (!ip_lease->uid_len &&
1598 ip_lease->hardware_addr.htype == packet->raw->htype &&
1599 ip_lease->hardware_addr.hlen == packet->raw->hlen &&
1600 !memcmp(ip_lease->hardware_addr.haddr, packet->raw->chaddr,
1601 ip_lease->hardware_addr.hlen))) {
1602 if (uid_lease) {
1603 if (uid_lease->ends > cur_time) {
1604 log_warnx("client %s has duplicate "
1605 "leases on %s",
1606 print_hw_addr(packet->raw->htype,
1607 packet->raw->hlen,
1608 packet->raw->chaddr),
1609 ip_lease->shared_network->name);
1610
1611 if (uid_lease &&
1612 !packet->raw->ciaddr.s_addr)
1613 release_lease(uid_lease);
1614 }
1615 uid_lease = ip_lease;
1616 }
1617 } else {
1618 strlcpy(dhcp_message, "requested address is not "
1619 "available", sizeof(dhcp_message));
1620 ip_lease = NULL;
1621 }
1622
1623 /* If we get to here and fixed_lease is not null, that means
1624 that there are both a dynamic lease and a fixed-address
1625 declaration for the same IP address. */
1626 if (packet->packet_type == DHCPREQUEST && fixed_lease) {
1627 fixed_lease = NULL;
1628 db_conflict:
1629 log_warnx("Both dynamic and static leases present for "
1630 "%s.", piaddr(cip));
1631 log_warnx("Either remove host declaration %s or "
1632 "remove %s", (fixed_lease && fixed_lease->host ?
1633 (fixed_lease->host->name ?
1634 fixed_lease->host->name : piaddr(cip)) :
1635 piaddr(cip)), piaddr(cip));
1636 log_warnx("from the dynamic address pool for %s",
1637 share->name);
1638 if (fixed_lease)
1639 ip_lease = NULL;
1640 strlcpy(dhcp_message, "database conflict - call for "
1641 "help!", sizeof(dhcp_message));
1642 }
1643 }
1644
1645 /* If we get to here with both fixed_lease and ip_lease not
1646 null, then we have a configuration file bug. */
1647 if (packet->packet_type == DHCPREQUEST && fixed_lease && ip_lease)
1648 goto db_conflict;
1649
1650 /* Toss hw_lease if it hasn't yet expired and the uid doesn't
1651 match, except that if the hardware address matches and the
1652 client is now doing dynamic BOOTP (and thus hasn't provided
1653 a uid) we let the client get away with it. */
1654 if (hw_lease && hw_lease->ends >= cur_time && hw_lease->uid &&
1655 packet->options[DHO_DHCP_CLIENT_IDENTIFIER].len &&
1656 hw_lease != uid_lease)
1657 hw_lease = NULL;
1658
1659 /* Toss extra pointers to the same lease... */
1660 if (hw_lease == uid_lease)
1661 hw_lease = NULL;
1662 if (ip_lease == hw_lease)
1663 hw_lease = NULL;
1664 if (ip_lease == uid_lease)
1665 uid_lease = NULL;
1666
1667 /* If we've already eliminated the lease, it wasn't there to
1668 begin with. If we have come up with a matching lease,
1669 set the message to bad network in case we have to throw it out. */
1670 if (!ip_lease) {
1671 strlcpy(dhcp_message, "requested address not available",
1672 sizeof(dhcp_message));
1673 }
1674
1675 /* Now eliminate leases that are on the wrong network... */
1676 if (ip_lease && share != ip_lease->shared_network) {
1677 if (packet->packet_type == DHCPREQUEST)
1678 release_lease(ip_lease);
1679 ip_lease = NULL;
1680 }
1681 if (uid_lease && share != uid_lease->shared_network) {
1682 if (packet->packet_type == DHCPREQUEST)
1683 release_lease(uid_lease);
1684 uid_lease = NULL;
1685 }
1686 if (hw_lease && share != hw_lease->shared_network) {
1687 if (packet->packet_type == DHCPREQUEST)
1688 release_lease(hw_lease);
1689 hw_lease = NULL;
1690 }
1691
1692 /* If this is a DHCPREQUEST, make sure the lease we're going to return
1693 matches the requested IP address. If it doesn't, don't return a
1694 lease at all. */
1695 if (packet->packet_type == DHCPREQUEST && !ip_lease && !fixed_lease)
1696 return NULL;
1697
1698 /* At this point, if fixed_lease is nonzero, we can assign it to
1699 this client. */
1700 if (fixed_lease)
1701 lease = fixed_lease;
1702
1703 /* If we got a lease that matched the ip address and don't have
1704 a better offer, use that; otherwise, release it. */
1705 if (ip_lease) {
1706 if (lease) {
1707 if (packet->packet_type == DHCPREQUEST)
1708 release_lease(ip_lease);
1709 } else {
1710 lease = ip_lease;
1711 lease->host = NULL;
1712 }
1713 }
1714
1715 /* If we got a lease that matched the client identifier, we may want
1716 to use it, but if we already have a lease we like, we must free
1717 the lease that matched the client identifier. */
1718 if (uid_lease) {
1719 if (lease) {
1720 if (packet->packet_type == DHCPREQUEST)
1721 release_lease(uid_lease);
1722 } else {
1723 lease = uid_lease;
1724 lease->host = NULL;
1725 }
1726 }
1727
1728 /* The lease that matched the hardware address is treated likewise. */
1729 if (hw_lease) {
1730 if (lease) {
1731 if (packet->packet_type == DHCPREQUEST)
1732 release_lease(hw_lease);
1733 } else {
1734 lease = hw_lease;
1735 lease->host = NULL;
1736 }
1737 }
1738
1739 /* If we found a host_decl but no matching address, try to
1740 find a host_decl that has no address, and if there is one,
1741 hang it off the lease so that we can use the supplied
1742 options. */
1743 if (lease && host && !lease->host) {
1744 for (; host; host = host->n_ipaddr) {
1745 if (!host->fixed_addr) {
1746 lease->host = host;
1747 break;
1748 }
1749 }
1750 }
1751
1752 /* If we find an abandoned lease, take it, but print a
1753 warning message, so that if it continues to lose,
1754 the administrator will eventually investigate. */
1755 if (lease && (lease->flags & ABANDONED_LEASE)) {
1756 if (packet->packet_type == DHCPREQUEST) {
1757 log_warnx("Reclaiming REQUESTed abandoned IP address "
1758 "%s.", piaddr(lease->ip_addr));
1759 lease->flags &= ~ABANDONED_LEASE;
1760 } else
1761 lease = NULL;
1762 }
1763 return lease;
1764 }
1765
1766 /*
1767 * Search the provided host_decl structure list for an address that's on
1768 * the specified shared network. If one is found, mock up and return a
1769 * lease structure for it; otherwise return the null pointer.
1770 */
1771 struct lease *
mockup_lease(struct packet * packet,struct shared_network * share,struct host_decl * hp)1772 mockup_lease(struct packet *packet, struct shared_network *share,
1773 struct host_decl *hp)
1774 {
1775 static struct lease mock;
1776
1777 mock.subnet = find_host_for_network(&hp, &mock.ip_addr, share);
1778 if (!mock.subnet)
1779 return (NULL);
1780 mock.next = mock.prev = NULL;
1781 mock.shared_network = mock.subnet->shared_network;
1782 mock.host = hp;
1783
1784 if (hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1785 mock.uid =
1786 hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->value;
1787 mock.uid_len =
1788 hp->group->options[DHO_DHCP_CLIENT_IDENTIFIER]->len;
1789 } else {
1790 mock.uid = NULL;
1791 mock.uid_len = 0;
1792 }
1793
1794 mock.hardware_addr = hp->interface;
1795 mock.starts = mock.timestamp = mock.ends = MIN_TIME;
1796 mock.flags = STATIC_LEASE;
1797 return &mock;
1798 }
1799