blob: c902eb70cae5bf00aa2b3f9e972e3c052eb649fc [file] [log] [blame]
lh9ed821d2023-04-07 01:36:19 -07001/* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991, or
6 (at your option) version 3 dated 29 June, 2007.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12
13 You should have received a copy of the GNU General Public License
14 along with this program. If not, see <http://www.gnu.org/licenses/>.
15*/
16
17#include "dnsmasq.h"
18
19#ifdef HAVE_DHCP
20
21#define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22#define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
23
24#ifdef HAVE_SCRIPT
25static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
26#endif
27
28static int sanitise(unsigned char *opt, char *buf);
29static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
30static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
31static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
32static void option_put_string(struct dhcp_packet *mess, unsigned char *end,
33 int opt, const char *string, int null_term);
34static struct in_addr option_addr(unsigned char *opt);
35static unsigned int option_uint(unsigned char *opt, int offset, int size);
36static void log_packet(char *type, void *addr, unsigned char *ext_mac,
37 int mac_len, char *interface, char *string, char *err, u32 xid);
38static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
39static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
40static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
41static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
42static int in_list(unsigned char *list, int opt);
43static void do_options(struct dhcp_context *context,
44 struct dhcp_packet *mess,
45 unsigned char *end,
46 unsigned char *req_options,
47 char *hostname,
48 char *domain,
49 struct dhcp_netid *netid,
50 struct in_addr subnet_addr,
51 unsigned char fqdn_flags,
52 int null_term, int pxe_arch,
53 unsigned char *uuid,
54 int vendor_class_len,
55 time_t now,
56 unsigned int lease_time,
57 unsigned short fuzz,
58 const char *pxevendor);
59
60
61static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt);
62static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
63static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor);
64static int prune_vendor_opts(struct dhcp_netid *netid);
65static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
66struct dhcp_boot *find_boot(struct dhcp_netid *netid);
67static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
68static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
69static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor);
70
71size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
72 size_t sz, time_t now, int unicast_dest, int loopback,
73 int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
74{
75 unsigned char *opt, *clid = NULL;
76 struct dhcp_lease *ltmp, *lease = NULL;
77 struct dhcp_vendor *vendor;
78 struct dhcp_mac *mac;
79 struct dhcp_netid_list *id_list;
80 int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
81 const char *pxevendor = NULL;
82 struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
83 unsigned char *end = (unsigned char *)(mess + 1);
84 unsigned char *real_end = (unsigned char *)(mess + 1);
85 char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
86 int hostname_auth = 0, borken_opt = 0;
87 unsigned char *req_options = NULL;
88 char *message = NULL;
89 unsigned int time;
90 struct dhcp_config *config;
91 struct dhcp_netid *netid, *tagif_netid;
92 struct in_addr subnet_addr, override;
93 unsigned short fuzz = 0;
94 unsigned int mess_type = 0;
95 unsigned char fqdn_flags = 0;
96 unsigned char *agent_id = NULL, *uuid = NULL;
97 unsigned char *emac = NULL;
98 int vendor_class_len = 0, emac_len = 0;
99 struct dhcp_netid known_id, iface_id, cpewan_id;
100 struct dhcp_opt *o;
101 unsigned char pxe_uuid[17];
102 unsigned char *oui = NULL, *serial = NULL;
103#ifdef HAVE_SCRIPT
104 unsigned char *class = NULL;
105#endif
106
107 subnet_addr.s_addr = override.s_addr = 0;
108
109 /* set tag with name == interface */
110 iface_id.net = iface_name;
111 iface_id.next = NULL;
112 netid = &iface_id;
113
114 if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
115 return 0;
116
117 if (mess->htype == 0 && mess->hlen != 0)
118 return 0;
119
120 /* check for DHCP rather than BOOTP */
121 if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
122 {
123 u32 cookie = htonl(DHCP_COOKIE);
124
125 /* only insist on a cookie for DHCP. */
126 if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
127 return 0;
128
129 mess_type = option_uint(opt, 0, 1);
130
131 /* two things to note here: expand_buf may move the packet,
132 so reassign mess from daemon->packet. Also, the size
133 sent includes the IP and UDP headers, hence the magic "-28" */
134 if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
135 {
136 size_t size = (size_t)option_uint(opt, 0, 2) - 28;
137
138 if (size > DHCP_PACKET_MAX)
139 size = DHCP_PACKET_MAX;
140 else if (size < sizeof(struct dhcp_packet))
141 size = sizeof(struct dhcp_packet);
142
143 if (expand_buf(&daemon->dhcp_packet, size))
144 {
145 mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
146 real_end = end = ((unsigned char *)mess) + size;
147 }
148 }
149
150 /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
151 it can affect the context-determination code. */
152 if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
153 mess->ciaddr.s_addr = 0;
154
155 /* search for device identity from CPEWAN devices, we pass this through to the script */
156 if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
157 {
158 unsigned int elen, offset, len = option_len(opt);
159
160 for (offset = 0; offset < (len - 5); offset += elen + 5)
161 {
162 elen = option_uint(opt, offset + 4 , 1);
163 if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
164 {
165 unsigned char *x = option_ptr(opt, offset + 5);
166 unsigned char *y = option_ptr(opt, offset + elen + 5);
167 oui = option_find1(x, y, 1, 1);
168 serial = option_find1(x, y, 2, 1);
169#ifdef HAVE_SCRIPT
170 class = option_find1(x, y, 3, 1);
171#endif
172 /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing
173 the gateway id back. Note that the device class is optional */
174 if (oui && serial)
175 {
176 cpewan_id.net = "cpewan-id";
177 cpewan_id.next = netid;
178 netid = &cpewan_id;
179 }
180 break;
181 }
182 }
183 }
184
185 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
186 {
187 /* Any agent-id needs to be copied back out, verbatim, as the last option
188 in the packet. Here, we shift it to the very end of the buffer, if it doesn't
189 get overwritten, then it will be shuffled back at the end of processing.
190 Note that the incoming options must not be overwritten here, so there has to
191 be enough free space at the end of the packet to copy the option. */
192 unsigned char *sopt;
193 unsigned int total = option_len(opt) + 2;
194 unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
195 OPTION_END, 0);
196 if (last_opt && last_opt < end - total)
197 {
198 end -= total;
199 agent_id = end;
200 memcpy(agent_id, opt, total);
201 }
202
203 /* look for RFC3527 Link selection sub-option */
204 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
205 subnet_addr = option_addr(sopt);
206
207 /* look for RFC5107 server-identifier-override */
208 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
209 override = option_addr(sopt);
210
211 /* if a circuit-id or remote-is option is provided, exact-match to options. */
212 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
213 {
214 int search;
215
216 if (vendor->match_type == MATCH_CIRCUIT)
217 search = SUBOPT_CIRCUIT_ID;
218 else if (vendor->match_type == MATCH_REMOTE)
219 search = SUBOPT_REMOTE_ID;
220 else if (vendor->match_type == MATCH_SUBSCRIBER)
221 search = SUBOPT_SUBSCR_ID;
222 else
223 continue;
224
225 if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
226 vendor->len == option_len(sopt) &&
227 memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
228 {
229 vendor->netid.next = netid;
230 netid = &vendor->netid;
231 }
232 }
233 }
234
235 /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
236 if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
237 subnet_addr = option_addr(opt);
238
239 /* If there is no client identifier option, use the hardware address */
240 if (!option_bool(OPT_IGNORE_CLID) && (opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
241 {
242 clid_len = option_len(opt);
243 clid = option_ptr(opt, 0);
244 }
245
246 /* do we have a lease in store? */
247 lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
248
249 /* If this request is missing a clid, but we've seen one before,
250 use it again for option matching etc. */
251 if (lease && !clid && lease->clid)
252 {
253 clid_len = lease->clid_len;
254 clid = lease->clid;
255 }
256
257 /* find mac to use for logging and hashing */
258 emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
259 }
260
261 for (mac = daemon->dhcp_macs; mac; mac = mac->next)
262 if (mac->hwaddr_len == mess->hlen &&
263 (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
264 memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
265 {
266 mac->netid.next = netid;
267 netid = &mac->netid;
268 }
269
270 /* Determine network for this packet. Our caller will have already linked all the
271 contexts which match the addresses of the receiving interface but if the
272 machine has an address already, or came via a relay, or we have a subnet selector,
273 we search again. If we don't have have a giaddr or explicit subnet selector,
274 use the ciaddr. This is necessary because a machine which got a lease via a
275 relay won't use the relay to renew. If matching a ciaddr fails but we have a context
276 from the physical network, continue using that to allow correct DHCPNAK generation later. */
277 if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
278 {
279 struct dhcp_context *context_tmp, *context_new = NULL;
280 struct shared_network *share = NULL;
281 struct in_addr addr;
282 int force = 0, via_relay = 0;
283
284 if (subnet_addr.s_addr)
285 {
286 addr = subnet_addr;
287 force = 1;
288 }
289 else if (mess->giaddr.s_addr)
290 {
291 addr = mess->giaddr;
292 force = 1;
293 via_relay = 1;
294 }
295 else
296 {
297 /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
298 addr = mess->ciaddr;
299 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
300 if (context_tmp->netmask.s_addr &&
301 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
302 is_same_net(addr, context_tmp->end, context_tmp->netmask))
303 {
304 context_new = context;
305 break;
306 }
307 }
308
309 if (!context_new)
310 {
311 for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
312 {
313 struct in_addr netmask = context_tmp->netmask;
314
315 /* guess the netmask for relayed networks */
316 if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
317 {
318 if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
319 netmask.s_addr = htonl(0xff000000);
320 else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
321 netmask.s_addr = htonl(0xffff0000);
322 else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
323 netmask.s_addr = htonl(0xffffff00);
324 }
325
326 /* check to see is a context is OK because of a shared address on
327 the relayed subnet. */
328 if (via_relay)
329 for (share = daemon->shared_networks; share; share = share->next)
330 {
331#ifdef HAVE_DHCP6
332 if (share->shared_addr.s_addr == 0)
333 continue;
334#endif
335 if (share->if_index != 0 ||
336 share->match_addr.s_addr != mess->giaddr.s_addr)
337 continue;
338
339 if (netmask.s_addr != 0 &&
340 is_same_net(share->shared_addr, context_tmp->start, netmask) &&
341 is_same_net(share->shared_addr, context_tmp->end, netmask))
342 break;
343 }
344
345 /* This section fills in context mainly when a client which is on a remote (relayed)
346 network renews a lease without using the relay, after dnsmasq has restarted. */
347 if (share ||
348 (netmask.s_addr != 0 &&
349 is_same_net(addr, context_tmp->start, netmask) &&
350 is_same_net(addr, context_tmp->end, netmask)))
351 {
352 context_tmp->netmask = netmask;
353 if (context_tmp->local.s_addr == 0)
354 context_tmp->local = fallback;
355 if (context_tmp->router.s_addr == 0 && !share)
356 context_tmp->router = mess->giaddr;
357
358 /* fill in missing broadcast addresses for relayed ranges */
359 if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
360 context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
361
362 context_tmp->current = context_new;
363 context_new = context_tmp;
364 }
365
366 }
367 }
368
369 if (context_new || force)
370 context = context_new;
371 }
372
373 if (!context)
374 {
375 const char *via;
376 if (subnet_addr.s_addr)
377 {
378 via = _("with subnet selector");
379 inet_ntop(AF_INET, &subnet_addr, daemon->addrbuff, ADDRSTRLEN);
380 }
381 else
382 {
383 via = _("via");
384 if (mess->giaddr.s_addr)
385 inet_ntop(AF_INET, &mess->giaddr, daemon->addrbuff, ADDRSTRLEN);
386 else
387 safe_strncpy(daemon->addrbuff, iface_name, ADDRSTRLEN);
388 }
389 my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
390 via, daemon->addrbuff);
391 return 0;
392 }
393
394 if (option_bool(OPT_LOG_OPTS))
395 {
396 struct dhcp_context *context_tmp;
397 for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
398 {
399 inet_ntop(AF_INET, &context_tmp->start, daemon->namebuff, MAXDNAME);
400 if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
401 {
402 inet_ntop(AF_INET, &context_tmp->netmask, daemon->addrbuff, ADDRSTRLEN);
403 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
404 ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
405 }
406 else
407 {
408 inet_ntop(AF_INET, &context_tmp->end, daemon->addrbuff, ADDRSTRLEN);
409 my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
410 ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
411 }
412 }
413 }
414
415 /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
416 Otherwise assume the option is an array, and look for a matching element.
417 If no data given, existence of the option is enough. This code handles
418 rfc3925 V-I classes too. */
419 for (o = daemon->dhcp_match; o; o = o->next)
420 {
421 unsigned int len, elen, match = 0;
422 size_t offset, o2;
423
424 if (o->flags & DHOPT_RFC3925)
425 {
426 if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
427 continue;
428
429 for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
430 {
431 len = option_uint(opt, offset + 4 , 1);
432 /* Need to take care that bad data can't run us off the end of the packet */
433 if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
434 (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
435 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
436 {
437 elen = option_uint(opt, o2, 1);
438 if ((o2 + elen + 1 <= (unsigned)option_len(opt)) &&
439 (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
440 break;
441 }
442 if (match)
443 break;
444 }
445 }
446 else
447 {
448 if (!(opt = option_find(mess, sz, o->opt, 1)))
449 continue;
450
451 match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
452 }
453
454 if (match)
455 {
456 o->netid->next = netid;
457 netid = o->netid;
458 }
459 }
460
461 /* user-class options are, according to RFC3004, supposed to contain
462 a set of counted strings. Here we check that this is so (by seeing
463 if the counts are consistent with the overall option length) and if
464 so zero the counts so that we don't get spurious matches between
465 the vendor string and the counts. If the lengths don't add up, we
466 assume that the option is a single string and non RFC3004 compliant
467 and just do the substring match. dhclient provides these broken options.
468 The code, later, which sends user-class data to the lease-change script
469 relies on the transformation done here.
470 */
471
472 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
473 {
474 unsigned char *ucp = option_ptr(opt, 0);
475 int tmp, j;
476 for (j = 0; j < option_len(opt); j += ucp[j] + 1);
477 if (j == option_len(opt))
478 for (j = 0; j < option_len(opt); j = tmp)
479 {
480 tmp = j + ucp[j] + 1;
481 ucp[j] = 0;
482 }
483 }
484
485 for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
486 {
487 int mopt;
488
489 if (vendor->match_type == MATCH_VENDOR)
490 mopt = OPTION_VENDOR_ID;
491 else if (vendor->match_type == MATCH_USER)
492 mopt = OPTION_USER_CLASS;
493 else
494 continue;
495
496 if ((opt = option_find(mess, sz, mopt, 1)))
497 {
498 int i;
499 for (i = 0; i <= (option_len(opt) - vendor->len); i++)
500 if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
501 {
502 vendor->netid.next = netid;
503 netid = &vendor->netid;
504 break;
505 }
506 }
507 }
508
509 /* mark vendor-encapsulated options which match the client-supplied vendor class,
510 save client-supplied vendor class */
511 if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
512 {
513 memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
514 vendor_class_len = option_len(opt);
515 }
516 match_vendor_opts(opt, daemon->dhcp_opts);
517
518 if (option_bool(OPT_LOG_OPTS))
519 {
520 if (sanitise(opt, daemon->namebuff))
521 my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
522 if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
523 my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
524 }
525
526 mess->op = BOOTREPLY;
527
528 config = find_config(daemon->dhcp_conf, context, clid, clid_len,
529 mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid));
530
531 /* set "known" tag for known hosts */
532 if (config)
533 {
534 known_id.net = "known";
535 known_id.next = netid;
536 netid = &known_id;
537 }
538 else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len,
539 mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid)))
540 {
541 known_id.net = "known-othernet";
542 known_id.next = netid;
543 netid = &known_id;
544 }
545
546 if (mess_type == 0 && !pxe)
547 {
548 /* BOOTP request */
549 struct dhcp_netid id, bootp_id;
550 struct in_addr *logaddr = NULL;
551
552 /* must have a MAC addr for bootp */
553 if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
554 return 0;
555
556 if (have_config(config, CONFIG_DISABLE))
557 message = _("disabled");
558
559 end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
560
561 if (have_config(config, CONFIG_NAME))
562 {
563 hostname = config->hostname;
564 domain = config->domain;
565 }
566
567 if (config)
568 {
569 struct dhcp_netid_list *list;
570
571 for (list = config->netid; list; list = list->next)
572 {
573 list->list->next = netid;
574 netid = list->list;
575 }
576 }
577
578 /* Match incoming filename field as a netid. */
579 if (mess->file[0])
580 {
581 memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
582 daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
583 id.net = (char *)daemon->dhcp_buff2;
584 id.next = netid;
585 netid = &id;
586 }
587
588 /* Add "bootp" as a tag to allow different options, address ranges etc
589 for BOOTP clients */
590 bootp_id.net = "bootp";
591 bootp_id.next = netid;
592 netid = &bootp_id;
593
594 tagif_netid = run_tag_if(netid);
595
596 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
597 if (match_netid(id_list->list, tagif_netid, 0))
598 message = _("ignored");
599
600 if (!message)
601 {
602 int nailed = 0;
603
604 if (have_config(config, CONFIG_ADDR))
605 {
606 nailed = 1;
607 logaddr = &config->addr;
608 mess->yiaddr = config->addr;
609 if ((lease = lease_find_by_addr(config->addr)) &&
610 (lease->hwaddr_len != mess->hlen ||
611 lease->hwaddr_type != mess->htype ||
612 memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
613 message = _("address in use");
614 }
615 else
616 {
617 if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
618 !address_available(context, lease->addr, tagif_netid))
619 {
620 if (lease)
621 {
622 /* lease exists, wrong network. */
623 lease_prune(lease, now);
624 lease = NULL;
625 }
626 if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
627 message = _("no address available");
628 }
629 else
630 mess->yiaddr = lease->addr;
631 }
632
633 if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
634 message = _("wrong network");
635 else if (context->netid.net)
636 {
637 context->netid.next = netid;
638 tagif_netid = run_tag_if(&context->netid);
639 }
640
641 log_tags(tagif_netid, ntohl(mess->xid));
642
643 if (!message && !nailed)
644 {
645 for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
646 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
647 break;
648 if (!id_list)
649 message = _("no address configured");
650 }
651
652 if (!message &&
653 !lease &&
654 (!(lease = lease4_allocate(mess->yiaddr))))
655 message = _("no leases left");
656
657 if (!message)
658 {
659 logaddr = &mess->yiaddr;
660
661 lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
662 if (hostname)
663 lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain);
664 /* infinite lease unless nailed in dhcp-host line. */
665 lease_set_expires(lease,
666 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff,
667 now);
668 lease_set_interface(lease, int_index, now);
669
670 clear_packet(mess, end);
671 do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr),
672 netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0, NULL);
673 }
674 }
675
676 daemon->metrics[METRIC_BOOTP]++;
677 log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
678
679 return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
680 }
681
682 if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
683 {
684 /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
685 int len = option_len(opt);
686 char *pq = daemon->dhcp_buff;
687 unsigned char *pp, *op = option_ptr(opt, 0);
688
689 fqdn_flags = *op;
690 len -= 3;
691 op += 3;
692 pp = op;
693
694 /* NB, the following always sets at least one bit */
695 if (option_bool(OPT_FQDN_UPDATE))
696 {
697 if (fqdn_flags & 0x01)
698 {
699 fqdn_flags |= 0x02; /* set O */
700 fqdn_flags &= ~0x01; /* clear S */
701 }
702 fqdn_flags |= 0x08; /* set N */
703 }
704 else
705 {
706 if (!(fqdn_flags & 0x01))
707 fqdn_flags |= 0x03; /* set S and O */
708 fqdn_flags &= ~0x08; /* clear N */
709 }
710
711 if (fqdn_flags & 0x04)
712 while (*op != 0 && ((op + (*op)) - pp) < len)
713 {
714 memcpy(pq, op+1, *op);
715 pq += *op;
716 op += (*op)+1;
717 *(pq++) = '.';
718 }
719 else
720 {
721 memcpy(pq, op, len);
722 if (len > 0 && op[len-1] == 0)
723 borken_opt = 1;
724 pq += len + 1;
725 }
726
727 if (pq != daemon->dhcp_buff)
728 pq--;
729
730 *pq = 0;
731
732 if (legal_hostname(daemon->dhcp_buff))
733 offer_hostname = client_hostname = daemon->dhcp_buff;
734 }
735 else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
736 {
737 int len = option_len(opt);
738 memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
739 /* Microsoft clients are broken, and need zero-terminated strings
740 in options. We detect this state here, and do the same in
741 any options we send */
742 if (len > 0 && daemon->dhcp_buff[len-1] == 0)
743 borken_opt = 1;
744 else
745 daemon->dhcp_buff[len] = 0;
746 if (legal_hostname(daemon->dhcp_buff))
747 client_hostname = daemon->dhcp_buff;
748 }
749
750 if (client_hostname)
751 {
752 struct dhcp_match_name *m;
753 size_t nl = strlen(client_hostname);
754
755 if (option_bool(OPT_LOG_OPTS))
756 my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
757 for (m = daemon->dhcp_name_match; m; m = m->next)
758 {
759 size_t ml = strlen(m->name);
760 char save = 0;
761
762 if (nl < ml)
763 continue;
764 if (nl > ml)
765 {
766 save = client_hostname[ml];
767 client_hostname[ml] = 0;
768 }
769
770 if (hostname_isequal(client_hostname, m->name) &&
771 (save == 0 || m->wildcard))
772 {
773 m->netid->next = netid;
774 netid = m->netid;
775 }
776
777 if (save != 0)
778 client_hostname[ml] = save;
779 }
780 }
781
782 if (have_config(config, CONFIG_NAME))
783 {
784 hostname = config->hostname;
785 domain = config->domain;
786 hostname_auth = 1;
787 /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
788 if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
789 offer_hostname = hostname;
790 }
791 else if (client_hostname)
792 {
793 domain = strip_hostname(client_hostname);
794
795 if (strlen(client_hostname) != 0)
796 {
797 hostname = client_hostname;
798
799 if (!config)
800 {
801 /* Search again now we have a hostname.
802 Only accept configs without CLID and HWADDR here, (they won't match)
803 to avoid impersonation by name. */
804 struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
805 mess->chaddr, mess->hlen,
806 mess->htype, hostname, run_tag_if(netid));
807 if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
808 {
809 config = new;
810 /* set "known" tag for known hosts */
811 known_id.net = "known";
812 known_id.next = netid;
813 netid = &known_id;
814 }
815 }
816 }
817 }
818
819 if (config)
820 {
821 struct dhcp_netid_list *list;
822
823 for (list = config->netid; list; list = list->next)
824 {
825 list->list->next = netid;
826 netid = list->list;
827 }
828 }
829
830 tagif_netid = run_tag_if(netid);
831
832 /* if all the netids in the ignore list are present, ignore this client */
833 for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
834 if (match_netid(id_list->list, tagif_netid, 0))
835 ignore = 1;
836
837 /* If configured, we can override the server-id to be the address of the relay,
838 so that all traffic goes via the relay and can pick up agent-id info. This can be
839 configured for all relays, or by address. */
840 if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
841 {
842 if (!daemon->override_relays)
843 override = mess->giaddr;
844 else
845 {
846 struct addr_list *l;
847 for (l = daemon->override_relays; l; l = l->next)
848 if (l->addr.s_addr == mess->giaddr.s_addr)
849 break;
850 if (l)
851 override = mess->giaddr;
852 }
853 }
854
855 /* Can have setting to ignore the client ID for a particular MAC address or hostname */
856 if (have_config(config, CONFIG_NOCLID))
857 clid = NULL;
858
859 /* Check if client is PXE client. */
860 if (daemon->enable_pxe &&
861 is_pxe_client(mess, sz, &pxevendor))
862 {
863 if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
864 {
865 memcpy(pxe_uuid, option_ptr(opt, 0), 17);
866 uuid = pxe_uuid;
867 }
868
869 /* Check if this is really a PXE bootserver request, and handle specially if so. */
870 if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
871 (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
872 (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
873 {
874 struct pxe_service *service;
875 int type = option_uint(opt, 0, 2);
876 int layer = option_uint(opt, 2, 2);
877 unsigned char save71[4];
878 struct dhcp_opt opt71;
879
880 if (ignore)
881 return 0;
882
883 if (layer & 0x8000)
884 {
885 my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
886 return 0;
887 }
888
889 memcpy(save71, option_ptr(opt, 0), 4);
890
891 for (service = daemon->pxe_services; service; service = service->next)
892 if (service->type == type)
893 break;
894
895 for (; context; context = context->current)
896 if (match_netid(context->filter, tagif_netid, 1) &&
897 is_same_net(mess->ciaddr, context->start, context->netmask))
898 break;
899
900 if (!service || !service->basename || !context)
901 return 0;
902
903 clear_packet(mess, end);
904
905 mess->yiaddr = mess->ciaddr;
906 mess->ciaddr.s_addr = 0;
907 if (service->sname)
908 mess->siaddr = a_record_from_hosts(service->sname, now);
909 else if (service->server.s_addr != 0)
910 mess->siaddr = service->server;
911 else
912 mess->siaddr = context->local;
913
914 if (strchr(service->basename, '.'))
915 snprintf((char *)mess->file, sizeof(mess->file),
916 "%s", service->basename);
917 else
918 snprintf((char *)mess->file, sizeof(mess->file),
919 "%s.%d", service->basename, layer);
920
921 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
922 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
923 pxe_misc(mess, end, uuid, pxevendor);
924
925 prune_vendor_opts(tagif_netid);
926 opt71.val = save71;
927 opt71.opt = SUBOPT_PXE_BOOT_ITEM;
928 opt71.len = 4;
929 opt71.flags = DHOPT_VENDOR_MATCH;
930 opt71.netid = NULL;
931 opt71.next = daemon->dhcp_opts;
932 do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
933
934 log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
935 log_tags(tagif_netid, ntohl(mess->xid));
936 return dhcp_packet_size(mess, agent_id, real_end);
937 }
938
939 if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
940 {
941 pxearch = option_uint(opt, 0, 2);
942
943 /* proxy DHCP here. */
944 if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
945 {
946 struct dhcp_context *tmp;
947 int workaround = 0;
948
949 for (tmp = context; tmp; tmp = tmp->current)
950 if ((tmp->flags & CONTEXT_PROXY) &&
951 match_netid(tmp->filter, tagif_netid, 1))
952 break;
953
954 if (tmp)
955 {
956 struct dhcp_boot *boot;
957 int redirect4011 = 0;
958
959 if (tmp->netid.net)
960 {
961 tmp->netid.next = netid;
962 tagif_netid = run_tag_if(&tmp->netid);
963 }
964
965 boot = find_boot(tagif_netid);
966
967 mess->yiaddr.s_addr = 0;
968 if (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
969 {
970 mess->ciaddr.s_addr = 0;
971 mess->flags |= htons(0x8000); /* broadcast */
972 }
973
974 clear_packet(mess, end);
975
976 /* Redirect EFI clients to port 4011 */
977 if (pxearch >= 6)
978 {
979 redirect4011 = 1;
980 mess->siaddr = tmp->local;
981 }
982
983 /* Returns true if only one matching service is available. On port 4011,
984 it also inserts the boot file and server name. */
985 workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
986
987 if (!workaround && boot)
988 {
989 /* Provide the bootfile here, for iPXE, and in case we have no menu items
990 and set discovery_control = 8 */
991 if (boot->next_server.s_addr)
992 mess->siaddr = boot->next_server;
993 else if (boot->tftp_sname)
994 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
995
996 if (boot->file)
997 safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
998 }
999
1000 option_put(mess, end, OPTION_MESSAGE_TYPE, 1,
1001 mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
1002 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
1003 pxe_misc(mess, end, uuid, pxevendor);
1004 prune_vendor_opts(tagif_netid);
1005 if ((pxe && !workaround) || !redirect4011)
1006 do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
1007
1008 daemon->metrics[METRIC_PXE]++;
1009 log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
1010 log_tags(tagif_netid, ntohl(mess->xid));
1011 if (!ignore)
1012 apply_delay(mess->xid, recvtime, tagif_netid);
1013 return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);
1014 }
1015 }
1016 }
1017 }
1018
1019 /* if we're just a proxy server, go no further */
1020 if ((context->flags & CONTEXT_PROXY) || pxe)
1021 return 0;
1022
1023 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
1024 {
1025 req_options = (unsigned char *)daemon->dhcp_buff2;
1026 memcpy(req_options, option_ptr(opt, 0), option_len(opt));
1027 req_options[option_len(opt)] = OPTION_END;
1028 }
1029
1030 switch (mess_type)
1031 {
1032 case DHCPDECLINE:
1033 if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
1034 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
1035 return 0;
1036
1037 /* sanitise any message. Paranoid? Moi? */
1038 sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
1039
1040 if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1041 return 0;
1042
1043 daemon->metrics[METRIC_DHCPDECLINE]++;
1044 log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
1045
1046 if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
1047 lease_prune(lease, now);
1048
1049 if (have_config(config, CONFIG_ADDR) &&
1050 config->addr.s_addr == option_addr(opt).s_addr)
1051 {
1052 prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
1053 inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
1054 my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"),
1055 daemon->addrbuff, daemon->dhcp_buff);
1056 config->flags |= CONFIG_DECLINED;
1057 config->decline_time = now;
1058 }
1059 else
1060 /* make sure this host gets a different address next time. */
1061 for (; context; context = context->current)
1062 context->addr_epoch++;
1063
1064 return 0;
1065
1066 case DHCPRELEASE:
1067 if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
1068 !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
1069 option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
1070 return 0;
1071
1072 if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
1073 lease_prune(lease, now);
1074 else
1075 message = _("unknown lease");
1076
1077 daemon->metrics[METRIC_DHCPRELEASE]++;
1078 log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1079
1080 return 0;
1081
1082 case DHCPDISCOVER:
1083 if (ignore || have_config(config, CONFIG_DISABLE))
1084 {
1085 if (option_bool(OPT_QUIET_DHCP))
1086 return 0;
1087 message = _("ignored");
1088 opt = NULL;
1089 }
1090 else
1091 {
1092 struct in_addr addr, conf;
1093
1094 addr.s_addr = conf.s_addr = 0;
1095
1096 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1097 addr = option_addr(opt);
1098
1099 if (have_config(config, CONFIG_ADDR))
1100 {
1101 inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
1102
1103 if ((ltmp = lease_find_by_addr(config->addr)) &&
1104 ltmp != lease &&
1105 !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1106 {
1107 int len;
1108 unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
1109 ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
1110 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
1111 daemon->addrbuff, print_mac(daemon->namebuff, mac, len));
1112 }
1113 else
1114 {
1115 struct dhcp_context *tmp;
1116 for (tmp = context; tmp; tmp = tmp->current)
1117 if (context->router.s_addr == config->addr.s_addr)
1118 break;
1119 if (tmp)
1120 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), daemon->addrbuff);
1121 else if (have_config(config, CONFIG_DECLINED) &&
1122 difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
1123 my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), daemon->addrbuff);
1124 else
1125 conf = config->addr;
1126 }
1127 }
1128
1129 if (conf.s_addr)
1130 mess->yiaddr = conf;
1131 else if (lease &&
1132 address_available(context, lease->addr, tagif_netid) &&
1133 !config_find_by_address(daemon->dhcp_conf, lease->addr))
1134 mess->yiaddr = lease->addr;
1135 else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) &&
1136 !config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
1137 mess->yiaddr = addr;
1138 else if (emac_len == 0)
1139 message = _("no unique-id");
1140 else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
1141 message = _("no address available");
1142 }
1143
1144 daemon->metrics[METRIC_DHCPDISCOVER]++;
1145 log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid);
1146
1147 if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1148 return 0;
1149
1150 if (context->netid.net)
1151 {
1152 context->netid.next = netid;
1153 tagif_netid = run_tag_if(&context->netid);
1154 }
1155
1156 log_tags(tagif_netid, ntohl(mess->xid));
1157 apply_delay(mess->xid, recvtime, tagif_netid);
1158
1159 if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
1160 {
1161 rapid_commit = 1;
1162 goto rapid_commit;
1163 }
1164
1165 daemon->metrics[METRIC_DHCPOFFER]++;
1166 log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1167
1168 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1169 clear_packet(mess, end);
1170 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
1171 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1172 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1173 /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1174 do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr),
1175 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
1176
1177 return dhcp_packet_size(mess, agent_id, real_end);
1178
1179
1180 case DHCPREQUEST:
1181 if (ignore || have_config(config, CONFIG_DISABLE))
1182 return 0;
1183 if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1184 {
1185 /* SELECTING or INIT_REBOOT */
1186 mess->yiaddr = option_addr(opt);
1187
1188 /* send vendor and user class info for new or recreated lease */
1189 do_classes = 1;
1190
1191 if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1192 {
1193 /* SELECTING */
1194 selecting = 1;
1195
1196 if (override.s_addr != 0)
1197 {
1198 if (option_addr(opt).s_addr != override.s_addr)
1199 return 0;
1200 }
1201 else
1202 {
1203 for (; context; context = context->current)
1204 if (context->local.s_addr == option_addr(opt).s_addr)
1205 break;
1206
1207 if (!context)
1208 {
1209 /* Handle very strange configs where clients have more than one route to the server.
1210 If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1211 Have to set override to make sure we echo back the correct server-id */
1212 struct irec *intr;
1213
1214 enumerate_interfaces(0);
1215
1216 for (intr = daemon->interfaces; intr; intr = intr->next)
1217 if (intr->addr.sa.sa_family == AF_INET &&
1218 intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
1219 intr->tftp_ok)
1220 break;
1221
1222 if (intr)
1223 override = intr->addr.in.sin_addr;
1224 else
1225 {
1226 /* In auth mode, a REQUEST sent to the wrong server
1227 should be faulted, so that the client establishes
1228 communication with us, otherwise, silently ignore. */
1229 if (!option_bool(OPT_AUTHORITATIVE))
1230 return 0;
1231 message = _("wrong server-ID");
1232 }
1233 }
1234 }
1235
1236 /* If a lease exists for this host and another address, squash it. */
1237 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1238 {
1239 lease_prune(lease, now);
1240 lease = NULL;
1241 }
1242 }
1243 else
1244 {
1245 /* INIT-REBOOT */
1246 if (!lease && !option_bool(OPT_AUTHORITATIVE))
1247 return 0;
1248
1249 if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1250 message = _("wrong address");
1251 }
1252 }
1253 else
1254 {
1255 /* RENEWING or REBINDING */
1256 /* Check existing lease for this address.
1257 We allow it to be missing if dhcp-authoritative mode
1258 as long as we can allocate the lease now - checked below.
1259 This makes for a smooth recovery from a lost lease DB */
1260 if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1261 (!lease && !option_bool(OPT_AUTHORITATIVE)))
1262 {
1263 /* A client rebinding will broadcast the request, so we may see it even
1264 if the lease is held by another server. Just ignore it in that case.
1265 If the request is unicast to us, then somethings wrong, NAK */
1266 if (!unicast_dest)
1267 return 0;
1268 message = _("lease not found");
1269 /* ensure we broadcast NAK */
1270 unicast_dest = 0;
1271 }
1272
1273 /* desynchronise renewals */
1274 fuzz = rand16();
1275 mess->yiaddr = mess->ciaddr;
1276 }
1277
1278 daemon->metrics[METRIC_DHCPREQUEST]++;
1279 log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1280
1281 rapid_commit:
1282 if (!message)
1283 {
1284 struct dhcp_config *addr_config;
1285 struct dhcp_context *tmp = NULL;
1286
1287 if (have_config(config, CONFIG_ADDR))
1288 for (tmp = context; tmp; tmp = tmp->current)
1289 if (context->router.s_addr == config->addr.s_addr)
1290 break;
1291
1292 if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1293 {
1294 /* If a machine moves networks whilst it has a lease, we catch that here. */
1295 message = _("wrong network");
1296 /* ensure we broadcast NAK */
1297 unicast_dest = 0;
1298 }
1299
1300 /* Check for renewal of a lease which is outside the allowed range. */
1301 else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1302 (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1303 message = _("address not available");
1304
1305 /* Check if a new static address has been configured. Be very sure that
1306 when the client does DISCOVER, it will get the static address, otherwise
1307 an endless protocol loop will ensue. */
1308 else if (!tmp && !selecting &&
1309 have_config(config, CONFIG_ADDR) &&
1310 (!have_config(config, CONFIG_DECLINED) ||
1311 difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1312 config->addr.s_addr != mess->yiaddr.s_addr &&
1313 (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1314 message = _("static lease available");
1315
1316 /* Check to see if the address is reserved as a static address for another host */
1317 else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1318 message = _("address reserved");
1319
1320 else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1321 {
1322 /* If a host is configured with more than one MAC address, it's OK to 'nix
1323 a lease from one of it's MACs to give the address to another. */
1324 if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1325 {
1326 inet_ntop(AF_INET, &ltmp->addr, daemon->addrbuff, ADDRSTRLEN);
1327 my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1328 print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len),
1329 daemon->addrbuff);
1330 lease = ltmp;
1331 }
1332 else
1333 message = _("address in use");
1334 }
1335
1336 if (!message)
1337 {
1338 if (emac_len == 0)
1339 message = _("no unique-id");
1340
1341 else if (!lease)
1342 {
1343 if ((lease = lease4_allocate(mess->yiaddr)))
1344 do_classes = 1;
1345 else
1346 message = _("no leases left");
1347 }
1348 }
1349 }
1350
1351 if (message)
1352 {
1353 daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
1354 log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1355
1356 /* rapid commit case: lease allocate failed but don't send DHCPNAK */
1357 if (rapid_commit)
1358 return 0;
1359
1360 mess->yiaddr.s_addr = 0;
1361 clear_packet(mess, end);
1362 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1363 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1364 option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1365 /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on
1366 a distant subnet which unicast a REQ to us won't work. */
1367 if (!unicast_dest || mess->giaddr.s_addr != 0 ||
1368 mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1369 {
1370 mess->flags |= htons(0x8000); /* broadcast */
1371 mess->ciaddr.s_addr = 0;
1372 }
1373 }
1374 else
1375 {
1376 if (context->netid.net)
1377 {
1378 context->netid.next = netid;
1379 tagif_netid = run_tag_if( &context->netid);
1380 }
1381
1382 log_tags(tagif_netid, ntohl(mess->xid));
1383
1384 if (do_classes)
1385 {
1386 /* pick up INIT-REBOOT events. */
1387 lease->flags |= LEASE_CHANGED;
1388
1389#ifdef HAVE_SCRIPT
1390 if (daemon->lease_change_command)
1391 {
1392 struct dhcp_netid *n;
1393
1394 if (mess->giaddr.s_addr)
1395 lease->giaddr = mess->giaddr;
1396
1397 free(lease->extradata);
1398 lease->extradata = NULL;
1399 lease->extradata_size = lease->extradata_len = 0;
1400
1401 add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1402 add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1403 add_extradata_opt(lease, oui);
1404 add_extradata_opt(lease, serial);
1405 add_extradata_opt(lease, class);
1406
1407 if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
1408 {
1409 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
1410 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
1411 add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
1412 }
1413 else
1414 {
1415 add_extradata_opt(lease, NULL);
1416 add_extradata_opt(lease, NULL);
1417 add_extradata_opt(lease, NULL);
1418 }
1419
1420 /* DNSMASQ_REQUESTED_OPTIONS */
1421 if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
1422 {
1423 int len = option_len(opt);
1424 unsigned char *rop = option_ptr(opt, 0);
1425 char *q = daemon->namebuff;
1426 int i;
1427 for (i = 0; i < len; i++)
1428 {
1429 q += snprintf(q, MAXDNAME - (q - daemon->namebuff), "%d%s", rop[i], i + 1 == len ? "" : ",");
1430 }
1431 lease_add_extradata(lease, (unsigned char *)daemon->namebuff, (q - daemon->namebuff), 0);
1432 }
1433 else
1434 {
1435 add_extradata_opt(lease, NULL);
1436 }
1437
1438 /* space-concat tag set */
1439 if (!tagif_netid)
1440 add_extradata_opt(lease, NULL);
1441 else
1442 for (n = tagif_netid; n; n = n->next)
1443 {
1444 struct dhcp_netid *n1;
1445 /* kill dupes */
1446 for (n1 = n->next; n1; n1 = n1->next)
1447 if (strcmp(n->net, n1->net) == 0)
1448 break;
1449 if (!n1)
1450 lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0);
1451 }
1452
1453 if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1454 {
1455 int len = option_len(opt);
1456 unsigned char *ucp = option_ptr(opt, 0);
1457 /* If the user-class option started as counted strings, the first byte will be zero. */
1458 if (len != 0 && ucp[0] == 0)
1459 ucp++, len--;
1460 lease_add_extradata(lease, ucp, len, -1);
1461 }
1462 }
1463#endif
1464 }
1465
1466 if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1467 {
1468 domain = get_domain(mess->yiaddr);
1469 hostname = client_hostname;
1470 hostname_auth = 1;
1471 }
1472
1473 time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1474 lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
1475
1476 /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1477 if (!hostname_auth)
1478 {
1479 for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1480 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1481 break;
1482 if (id_list)
1483 hostname = NULL;
1484 }
1485
1486 /* Last ditch, if configured, generate hostname from mac address */
1487 if (!hostname && emac_len != 0)
1488 {
1489 for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1490 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1491 break;
1492 if (id_list)
1493 {
1494 int i;
1495
1496 hostname = daemon->dhcp_buff;
1497 /* buffer is 256 bytes, 3 bytes per octet */
1498 for (i = 0; (i < emac_len) && (i < 80); i++)
1499 hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1500 hostname = daemon->dhcp_buff;
1501 }
1502 }
1503
1504 if (hostname)
1505 lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
1506
1507 lease_set_expires(lease, time, now);
1508 lease_set_interface(lease, int_index, now);
1509
1510 if (override.s_addr != 0)
1511 lease->override = override;
1512 else
1513 override = lease->override;
1514
1515 daemon->metrics[METRIC_DHCPACK]++;
1516 log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1517
1518 clear_packet(mess, end);
1519 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1520 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1521 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1522 if (rapid_commit)
1523 option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
1524 do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr),
1525 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
1526 }
1527
1528 return dhcp_packet_size(mess, agent_id, real_end);
1529
1530 case DHCPINFORM:
1531 if (ignore || have_config(config, CONFIG_DISABLE))
1532 message = _("ignored");
1533
1534 daemon->metrics[METRIC_DHCPINFORM]++;
1535 log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
1536
1537 if (message || mess->ciaddr.s_addr == 0)
1538 return 0;
1539
1540 /* For DHCPINFORM only, cope without a valid context */
1541 context = narrow_context(context, mess->ciaddr, tagif_netid);
1542
1543 /* Find a least based on IP address if we didn't
1544 get one from MAC address/client-d */
1545 if (!lease &&
1546 (lease = lease_find_by_addr(mess->ciaddr)) &&
1547 lease->hostname)
1548 hostname = lease->hostname;
1549
1550 if (!hostname)
1551 hostname = host_from_dns(mess->ciaddr);
1552
1553 if (context && context->netid.net)
1554 {
1555 context->netid.next = netid;
1556 tagif_netid = run_tag_if(&context->netid);
1557 }
1558
1559 log_tags(tagif_netid, ntohl(mess->xid));
1560
1561 daemon->metrics[METRIC_DHCPACK]++;
1562 log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1563
1564 if (lease)
1565 {
1566 lease_set_interface(lease, int_index, now);
1567 if (override.s_addr != 0)
1568 lease->override = override;
1569 else
1570 override = lease->override;
1571 }
1572
1573 clear_packet(mess, end);
1574 option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1575 option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1576
1577 /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but
1578 we supply a utility which makes DHCPINFORM requests to get this information.
1579 Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1580 which won't be true for ordinary clients, but will be true for the
1581 dhcp_lease_time utility. */
1582 if (lease && in_list(req_options, OPTION_LEASE_TIME))
1583 {
1584 if (lease->expires == 0)
1585 time = 0xffffffff;
1586 else
1587 time = (unsigned int)difftime(lease->expires, now);
1588 option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1589 }
1590
1591 do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1592 netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0, pxevendor);
1593
1594 *is_inform = 1; /* handle reply differently */
1595 return dhcp_packet_size(mess, agent_id, real_end);
1596 }
1597
1598 return 0;
1599}
1600
1601/* find a good value to use as MAC address for logging and address-allocation hashing.
1602 This is normally just the chaddr field from the DHCP packet,
1603 but eg Firewire will have hlen == 0 and use the client-id instead.
1604 This could be anything, but will normally be EUI64 for Firewire.
1605 We assume that if the first byte of the client-id equals the htype byte
1606 then the client-id is using the usual encoding and use the rest of the
1607 client-id: if not we can use the whole client-id. This should give
1608 sane MAC address logs. */
1609unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr,
1610 int clid_len, unsigned char *clid, int *len_out)
1611{
1612 if (hwlen == 0 && clid && clid_len > 3)
1613 {
1614 if (clid[0] == hwtype)
1615 {
1616 *len_out = clid_len - 1 ;
1617 return clid + 1;
1618 }
1619
1620#if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1621 if (clid[0] == ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1622 {
1623 *len_out = clid_len - 1 ;
1624 return clid + 1;
1625 }
1626#endif
1627
1628 *len_out = clid_len;
1629 return clid;
1630 }
1631
1632 *len_out = hwlen;
1633 return hwaddr;
1634}
1635
1636static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1637{
1638 unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1639
1640 if (opt)
1641 {
1642 unsigned int req_time = option_uint(opt, 0, 4);
1643 if (req_time < 120 )
1644 req_time = 120; /* sanity */
1645 if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1646 time = req_time;
1647 }
1648
1649 return time;
1650}
1651
1652static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1653{
1654 if (override.s_addr != 0)
1655 return override;
1656 else if (context && context->local.s_addr != 0)
1657 return context->local;
1658 else
1659 return fallback;
1660}
1661
1662static int sanitise(unsigned char *opt, char *buf)
1663{
1664 char *p;
1665 int i;
1666
1667 *buf = 0;
1668
1669 if (!opt)
1670 return 0;
1671
1672 p = option_ptr(opt, 0);
1673
1674 for (i = option_len(opt); i > 0; i--)
1675 {
1676 char c = *p++;
1677 if (isprint((int)c))
1678 *buf++ = c;
1679 }
1680 *buf = 0; /* add terminator */
1681
1682 return 1;
1683}
1684
1685#ifdef HAVE_SCRIPT
1686static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1687{
1688 if (!opt)
1689 lease_add_extradata(lease, NULL, 0, 0);
1690 else
1691 lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0);
1692}
1693#endif
1694
1695static void log_packet(char *type, void *addr, unsigned char *ext_mac,
1696 int mac_len, char *interface, char *string, char *err, u32 xid)
1697{
1698 if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
1699 return;
1700
1701 daemon->addrbuff[0] = 0;
1702 if (addr)
1703 inet_ntop(AF_INET, addr, daemon->addrbuff, ADDRSTRLEN);
1704
1705 print_mac(daemon->namebuff, ext_mac, mac_len);
1706
1707 if (option_bool(OPT_LOG_OPTS))
1708 my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
1709 ntohl(xid),
1710 type,
1711 interface,
1712 daemon->addrbuff,
1713 addr ? " " : "",
1714 daemon->namebuff,
1715 string ? string : "",
1716 err ? err : "");
1717 else
1718 my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
1719 type,
1720 interface,
1721 daemon->addrbuff,
1722 addr ? " " : "",
1723 daemon->namebuff,
1724 string ? string : "",
1725 err ? err : "");
1726
1727#ifdef HAVE_UBUS
1728 if (!strcmp(type, "DHCPACK"))
1729 ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
1730 else if (!strcmp(type, "DHCPRELEASE"))
1731 ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
1732#endif
1733}
1734
1735static void log_options(unsigned char *start, u32 xid)
1736{
1737 while (*start != OPTION_END)
1738 {
1739 char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
1740
1741 my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s %s",
1742 ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
1743 start += start[1] + 2;
1744 }
1745}
1746
1747static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1748{
1749 while (1)
1750 {
1751 if (p >= end)
1752 return NULL;
1753 else if (*p == OPTION_END)
1754 return opt == OPTION_END ? p : NULL;
1755 else if (*p == OPTION_PAD)
1756 p++;
1757 else
1758 {
1759 int opt_len;
1760 if (p > end - 2)
1761 return NULL; /* malformed packet */
1762 opt_len = option_len(p);
1763 if (p > end - (2 + opt_len))
1764 return NULL; /* malformed packet */
1765 if (*p == opt && opt_len >= minsize)
1766 return p;
1767 p += opt_len + 2;
1768 }
1769 }
1770}
1771
1772static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1773{
1774 unsigned char *ret, *overload;
1775
1776 /* skip over DHCP cookie; */
1777 if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1778 return ret;
1779
1780 /* look for overload option. */
1781 if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1782 return NULL;
1783
1784 /* Can we look in filename area ? */
1785 if ((overload[2] & 1) &&
1786 (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1787 return ret;
1788
1789 /* finally try sname area */
1790 if ((overload[2] & 2) &&
1791 (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1792 return ret;
1793
1794 return NULL;
1795}
1796
1797static struct in_addr option_addr(unsigned char *opt)
1798{
1799 /* this worries about unaligned data in the option. */
1800 /* struct in_addr is network byte order */
1801 struct in_addr ret;
1802
1803 memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
1804
1805 return ret;
1806}
1807
1808static unsigned int option_uint(unsigned char *opt, int offset, int size)
1809{
1810 /* this worries about unaligned data and byte order */
1811 unsigned int ret = 0;
1812 int i;
1813 unsigned char *p = option_ptr(opt, offset);
1814
1815 for (i = 0; i < size; i++)
1816 ret = (ret << 8) | *p++;
1817
1818 return ret;
1819}
1820
1821static unsigned char *dhcp_skip_opts(unsigned char *start)
1822{
1823 while (*start != 0)
1824 start += start[1] + 2;
1825 return start;
1826}
1827
1828/* only for use when building packet: doesn't check for bad data. */
1829static unsigned char *find_overload(struct dhcp_packet *mess)
1830{
1831 unsigned char *p = &mess->options[0] + sizeof(u32);
1832
1833 while (*p != 0)
1834 {
1835 if (*p == OPTION_OVERLOAD)
1836 return p;
1837 p += p[1] + 2;
1838 }
1839 return NULL;
1840}
1841
1842static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
1843{
1844 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1845 unsigned char *overload;
1846 size_t ret;
1847
1848 /* move agent_id back down to the end of the packet */
1849 if (agent_id)
1850 {
1851 memmove(p, agent_id, real_end - agent_id);
1852 p += real_end - agent_id;
1853 memset(p, 0, real_end - p); /* in case of overlap */
1854 }
1855
1856 /* add END options to the regions. */
1857 overload = find_overload(mess);
1858
1859 if (overload && (option_uint(overload, 0, 1) & 1))
1860 {
1861 *dhcp_skip_opts(mess->file) = OPTION_END;
1862 if (option_bool(OPT_LOG_OPTS))
1863 log_options(mess->file, mess->xid);
1864 }
1865 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1866 my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1867
1868 if (overload && (option_uint(overload, 0, 1) & 2))
1869 {
1870 *dhcp_skip_opts(mess->sname) = OPTION_END;
1871 if (option_bool(OPT_LOG_OPTS))
1872 log_options(mess->sname, mess->xid);
1873 }
1874 else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1875 my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1876
1877
1878 *p++ = OPTION_END;
1879
1880 if (option_bool(OPT_LOG_OPTS))
1881 {
1882 if (mess->siaddr.s_addr != 0)
1883 {
1884 inet_ntop(AF_INET, &mess->siaddr, daemon->addrbuff, ADDRSTRLEN);
1885 my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), daemon->addrbuff);
1886 }
1887
1888 if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1889 my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1890
1891 log_options(&mess->options[0] + sizeof(u32), mess->xid);
1892 }
1893
1894 ret = (size_t)(p - (unsigned char *)mess);
1895
1896 if (ret < MIN_PACKETSZ)
1897 ret = MIN_PACKETSZ;
1898
1899 return ret;
1900}
1901
1902static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1903{
1904 unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1905
1906 if (p + len + 3 >= end)
1907 /* not enough space in options area, try and use overload, if poss */
1908 {
1909 unsigned char *overload;
1910
1911 if (!(overload = find_overload(mess)) &&
1912 (mess->file[0] == 0 || mess->sname[0] == 0))
1913 {
1914 /* attempt to overload fname and sname areas, we've reserved space for the
1915 overflow option previuously. */
1916 overload = p;
1917 *(p++) = OPTION_OVERLOAD;
1918 *(p++) = 1;
1919 }
1920
1921 p = NULL;
1922
1923 /* using filename field ? */
1924 if (overload)
1925 {
1926 if (mess->file[0] == 0)
1927 overload[2] |= 1;
1928
1929 if (overload[2] & 1)
1930 {
1931 p = dhcp_skip_opts(mess->file);
1932 if (p + len + 3 >= mess->file + sizeof(mess->file))
1933 p = NULL;
1934 }
1935
1936 if (!p)
1937 {
1938 /* try to bring sname into play (it may be already) */
1939 if (mess->sname[0] == 0)
1940 overload[2] |= 2;
1941
1942 if (overload[2] & 2)
1943 {
1944 p = dhcp_skip_opts(mess->sname);
1945 if (p + len + 3 >= mess->sname + sizeof(mess->sname))
1946 p = NULL;
1947 }
1948 }
1949 }
1950
1951 if (!p)
1952 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1953 }
1954
1955 if (p)
1956 {
1957 *(p++) = opt;
1958 *(p++) = len;
1959 }
1960
1961 return p;
1962}
1963
1964static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1965{
1966 int i;
1967 unsigned char *p = free_space(mess, end, opt, len);
1968
1969 if (p)
1970 for (i = 0; i < len; i++)
1971 *(p++) = val >> (8 * (len - (i + 1)));
1972}
1973
1974static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt,
1975 const char *string, int null_term)
1976{
1977 unsigned char *p;
1978 size_t len = strlen(string);
1979
1980 if (null_term && len != 255)
1981 len++;
1982
1983 if ((p = free_space(mess, end, opt, len)))
1984 memcpy(p, string, len);
1985}
1986
1987/* return length, note this only does the data part */
1988static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1989{
1990 int len = opt->len;
1991
1992 if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1993 len++;
1994
1995 if (p && len != 0)
1996 {
1997 if (context && (opt->flags & DHOPT_ADDR))
1998 {
1999 int j;
2000 struct in_addr *a = (struct in_addr *)opt->val;
2001 for (j = 0; j < opt->len; j+=INADDRSZ, a++)
2002 {
2003 /* zero means "self" (but not in vendorclass options.) */
2004 if (a->s_addr == 0)
2005 memcpy(p, &context->local, INADDRSZ);
2006 else
2007 memcpy(p, a, INADDRSZ);
2008 p += INADDRSZ;
2009 }
2010 }
2011 else
2012 /* empty string may be extended to "\0" by null_term */
2013 memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
2014 }
2015 return len;
2016}
2017
2018static int in_list(unsigned char *list, int opt)
2019{
2020 int i;
2021
2022 /* If no requested options, send everything, not nothing. */
2023 if (!list)
2024 return 1;
2025
2026 for (i = 0; list[i] != OPTION_END; i++)
2027 if (opt == list[i])
2028 return 1;
2029
2030 return 0;
2031}
2032
2033static struct dhcp_opt *option_find2(int opt)
2034{
2035 struct dhcp_opt *opts;
2036
2037 for (opts = daemon->dhcp_opts; opts; opts = opts->next)
2038 if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
2039 return opts;
2040
2041 return NULL;
2042}
2043
2044/* mark vendor-encapsulated options which match the client-supplied or
2045 config-supplied vendor class */
2046static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
2047{
2048 for (; dopt; dopt = dopt->next)
2049 {
2050 dopt->flags &= ~DHOPT_VENDOR_MATCH;
2051 if (opt && (dopt->flags & DHOPT_VENDOR))
2052 {
2053 const struct dhcp_pxe_vendor *pv;
2054 struct dhcp_pxe_vendor dummy_vendor = {
2055 .data = (char *)dopt->u.vendor_class,
2056 .next = NULL,
2057 };
2058 if (dopt->flags & DHOPT_VENDOR_PXE)
2059 pv = daemon->dhcp_pxe_vendors;
2060 else
2061 pv = &dummy_vendor;
2062 for (; pv; pv = pv->next)
2063 {
2064 int i, len = 0, matched = 0;
2065 if (pv->data)
2066 len = strlen(pv->data);
2067 for (i = 0; i <= (option_len(opt) - len); i++)
2068 if (len == 0 || memcmp(pv->data, option_ptr(opt, i), len) == 0)
2069 {
2070 matched = 1;
2071 break;
2072 }
2073 if (matched)
2074 {
2075 dopt->flags |= DHOPT_VENDOR_MATCH;
2076 break;
2077 }
2078 }
2079 }
2080 }
2081}
2082
2083static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,
2084 struct dhcp_packet *mess, unsigned char *end, int null_term)
2085{
2086 int len, enc_len, ret = 0;
2087 struct dhcp_opt *start;
2088 unsigned char *p;
2089
2090 /* find size in advance */
2091 for (enc_len = 0, start = opt; opt; opt = opt->next)
2092 if (opt->flags & flag)
2093 {
2094 int new = do_opt(opt, NULL, NULL, null_term) + 2;
2095 ret = 1;
2096 if (enc_len + new <= 255)
2097 enc_len += new;
2098 else
2099 {
2100 p = free_space(mess, end, encap, enc_len);
2101 for (; start && start != opt; start = start->next)
2102 if (p && (start->flags & flag))
2103 {
2104 len = do_opt(start, p + 2, NULL, null_term);
2105 *(p++) = start->opt;
2106 *(p++) = len;
2107 p += len;
2108 }
2109 enc_len = new;
2110 start = opt;
2111 }
2112 }
2113
2114 if (enc_len != 0 &&
2115 (p = free_space(mess, end, encap, enc_len + 1)))
2116 {
2117 for (; start; start = start->next)
2118 if (start->flags & flag)
2119 {
2120 len = do_opt(start, p + 2, NULL, null_term);
2121 *(p++) = start->opt;
2122 *(p++) = len;
2123 p += len;
2124 }
2125 *p = OPTION_END;
2126 }
2127
2128 return ret;
2129}
2130
2131static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor)
2132{
2133 unsigned char *p;
2134
2135 if (!pxevendor)
2136 pxevendor="PXEClient";
2137 option_put_string(mess, end, OPTION_VENDOR_ID, pxevendor, 0);
2138 if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
2139 memcpy(p, uuid, 17);
2140}
2141
2142static int prune_vendor_opts(struct dhcp_netid *netid)
2143{
2144 int force = 0;
2145 struct dhcp_opt *opt;
2146
2147 /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
2148 for (opt = daemon->dhcp_opts; opt; opt = opt->next)
2149 if (opt->flags & DHOPT_VENDOR_MATCH)
2150 {
2151 if (!match_netid(opt->netid, netid, 1))
2152 opt->flags &= ~DHOPT_VENDOR_MATCH;
2153 else if (opt->flags & DHOPT_FORCE)
2154 force = 1;
2155 }
2156 return force;
2157}
2158
2159
2160/* Many UEFI PXE implementations have badly broken menu code.
2161 If there's exactly one relevant menu item, we abandon the menu system,
2162 and jamb the data direct into the DHCP file, siaddr and sname fields.
2163 Note that in this case, we have to assume that layer zero would be requested
2164 by the client PXE stack. */
2165static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
2166{
2167 struct pxe_service *service, *found;
2168
2169 /* Only workaround UEFI archs. */
2170 if (pxe_arch < 6)
2171 return 0;
2172
2173 for (found = NULL, service = daemon->pxe_services; service; service = service->next)
2174 if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
2175 {
2176 if (found)
2177 return 0; /* More than one relevant menu item */
2178
2179 found = service;
2180 }
2181
2182 if (!found)
2183 return 0; /* No relevant menu items. */
2184
2185 if (!pxe)
2186 return 1;
2187
2188 if (found->sname)
2189 {
2190 mess->siaddr = a_record_from_hosts(found->sname, now);
2191 snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
2192 }
2193 else
2194 {
2195 if (found->server.s_addr != 0)
2196 mess->siaddr = found->server;
2197 else
2198 mess->siaddr = local;
2199
2200 inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
2201 }
2202
2203 snprintf((char *)mess->file, sizeof(mess->file),
2204 strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
2205
2206 return 1;
2207}
2208
2209static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
2210{
2211#define NUM_OPTS 4
2212
2213 unsigned char *p, *q;
2214 struct pxe_service *service;
2215 static struct dhcp_opt *o, *ret;
2216 int i, j = NUM_OPTS - 1;
2217 struct in_addr boot_server;
2218
2219 /* We pass back references to these, hence they are declared static */
2220 static unsigned char discovery_control;
2221 static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' };
2222 static struct dhcp_opt *fake_opts = NULL;
2223
2224 /* Disable multicast, since we don't support it, and broadcast
2225 unless we need it */
2226 discovery_control = 3;
2227
2228 ret = daemon->dhcp_opts;
2229
2230 if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2231 return ret;
2232
2233 for (i = 0; i < NUM_OPTS; i++)
2234 {
2235 fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2236 fake_opts[i].netid = NULL;
2237 fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2238 }
2239
2240 /* create the data for the PXE_MENU and PXE_SERVERS options. */
2241 p = (unsigned char *)daemon->dhcp_buff;
2242 q = (unsigned char *)daemon->dhcp_buff3;
2243
2244 for (i = 0, service = daemon->pxe_services; service; service = service->next)
2245 if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2246 {
2247 size_t len = strlen(service->menu);
2248 /* opt 43 max size is 255. encapsulated option has type and length
2249 bytes, so its max size is 253. */
2250 if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2251 {
2252 *(p++) = service->type >> 8;
2253 *(p++) = service->type;
2254 *(p++) = len;
2255 memcpy(p, service->menu, len);
2256 p += len;
2257 i++;
2258 }
2259 else
2260 {
2261 toobig:
2262 my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2263 return daemon->dhcp_opts;
2264 }
2265
2266 boot_server = service->basename ? local :
2267 (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
2268
2269 if (boot_server.s_addr != 0)
2270 {
2271 if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2272 goto toobig;
2273
2274 /* Boot service with known address - give it */
2275 *(q++) = service->type >> 8;
2276 *(q++) = service->type;
2277 *(q++) = 1;
2278 /* dest misaligned */
2279 memcpy(q, &boot_server.s_addr, INADDRSZ);
2280 q += INADDRSZ;
2281 }
2282 else if (service->type != 0)
2283 /* We don't know the server for a service type, so we'll
2284 allow the client to broadcast for it */
2285 discovery_control = 2;
2286 }
2287
2288 /* if no prompt, wait forever if there's a choice */
2289 fake_prompt[0] = (i > 1) ? 255 : 0;
2290
2291 if (i == 0)
2292 discovery_control = 8; /* no menu - just use use mess->filename */
2293 else
2294 {
2295 ret = &fake_opts[j--];
2296 ret->len = p - (unsigned char *)daemon->dhcp_buff;
2297 ret->val = (unsigned char *)daemon->dhcp_buff;
2298 ret->opt = SUBOPT_PXE_MENU;
2299
2300 if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2301 {
2302 ret = &fake_opts[j--];
2303 ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2304 ret->val = (unsigned char *)daemon->dhcp_buff3;
2305 ret->opt = SUBOPT_PXE_SERVERS;
2306 }
2307 }
2308
2309 for (o = daemon->dhcp_opts; o; o = o->next)
2310 if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2311 break;
2312
2313 if (!o)
2314 {
2315 ret = &fake_opts[j--];
2316 ret->len = sizeof(fake_prompt);
2317 ret->val = fake_prompt;
2318 ret->opt = SUBOPT_PXE_MENU_PROMPT;
2319 }
2320
2321 ret = &fake_opts[j--];
2322 ret->len = 1;
2323 ret->opt = SUBOPT_PXE_DISCOVERY;
2324 ret->val= &discovery_control;
2325
2326 return ret;
2327}
2328
2329static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2330{
2331 memset(mess->sname, 0, sizeof(mess->sname));
2332 memset(mess->file, 0, sizeof(mess->file));
2333 memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2334 mess->siaddr.s_addr = 0;
2335}
2336
2337struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2338{
2339 struct dhcp_boot *boot;
2340
2341 /* decide which dhcp-boot option we're using */
2342 for (boot = daemon->boot_config; boot; boot = boot->next)
2343 if (match_netid(boot->netid, netid, 0))
2344 break;
2345 if (!boot)
2346 /* No match, look for one without a netid */
2347 for (boot = daemon->boot_config; boot; boot = boot->next)
2348 if (match_netid(boot->netid, netid, 1))
2349 break;
2350
2351 return boot;
2352}
2353
2354static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor)
2355{
2356 const unsigned char *opt = NULL;
2357 ssize_t conf_len = 0;
2358 const struct dhcp_pxe_vendor *conf = daemon->dhcp_pxe_vendors;
2359 opt = option_find(mess, sz, OPTION_VENDOR_ID, 0);
2360 if (!opt)
2361 return 0;
2362 for (; conf; conf = conf->next)
2363 {
2364 conf_len = strlen(conf->data);
2365 if (option_len(opt) < conf_len)
2366 continue;
2367 if (strncmp(option_ptr(opt, 0), conf->data, conf_len) == 0)
2368 {
2369 if (pxe_vendor)
2370 *pxe_vendor = conf->data;
2371 return 1;
2372 }
2373 }
2374 return 0;
2375}
2376
2377static void do_options(struct dhcp_context *context,
2378 struct dhcp_packet *mess,
2379 unsigned char *end,
2380 unsigned char *req_options,
2381 char *hostname,
2382 char *domain,
2383 struct dhcp_netid *netid,
2384 struct in_addr subnet_addr,
2385 unsigned char fqdn_flags,
2386 int null_term, int pxe_arch,
2387 unsigned char *uuid,
2388 int vendor_class_len,
2389 time_t now,
2390 unsigned int lease_time,
2391 unsigned short fuzz,
2392 const char *pxevendor)
2393{
2394 struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2395 struct dhcp_boot *boot;
2396 unsigned char *p;
2397 int i, len, force_encap = 0;
2398 unsigned char f0 = 0, s0 = 0;
2399 int done_file = 0, done_server = 0;
2400 int done_vendor_class = 0;
2401 struct dhcp_netid *tagif;
2402 struct dhcp_netid_list *id_list;
2403
2404 /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2405 if (context)
2406 context->netid.next = NULL;
2407 tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
2408
2409 /* logging */
2410 if (option_bool(OPT_LOG_OPTS) && req_options)
2411 {
2412 char *q = daemon->namebuff;
2413 for (i = 0; req_options[i] != OPTION_END; i++)
2414 {
2415 char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
2416 q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2417 "%d%s%s%s",
2418 req_options[i],
2419 strlen(s) != 0 ? ":" : "",
2420 s,
2421 req_options[i+1] == OPTION_END ? "" : ", ");
2422 if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2423 {
2424 q = daemon->namebuff;
2425 my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2426 }
2427 }
2428 }
2429
2430 for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
2431 if ((!id_list->list) || match_netid(id_list->list, netid, 0))
2432 break;
2433 if (id_list)
2434 mess->flags |= htons(0x8000); /* force broadcast */
2435
2436 if (context)
2437 mess->siaddr = context->local;
2438
2439 /* See if we can send the boot stuff as options.
2440 To do this we need a requested option list, BOOTP
2441 and very old DHCP clients won't have this, we also
2442 provide a manual option to disable it.
2443 Some PXE ROMs have bugs (surprise!) and need zero-terminated
2444 names, so we always send those. */
2445 if ((boot = find_boot(tagif)))
2446 {
2447 if (boot->sname)
2448 {
2449 if (!option_bool(OPT_NO_OVERRIDE) &&
2450 req_options &&
2451 in_list(req_options, OPTION_SNAME))
2452 option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2453 else
2454 safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
2455 }
2456
2457 if (boot->file)
2458 {
2459 if (!option_bool(OPT_NO_OVERRIDE) &&
2460 req_options &&
2461 in_list(req_options, OPTION_FILENAME))
2462 option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2463 else
2464 safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
2465 }
2466
2467 if (boot->next_server.s_addr)
2468 mess->siaddr = boot->next_server;
2469 else if (boot->tftp_sname)
2470 mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
2471 }
2472 else
2473 /* Use the values of the relevant options if no dhcp-boot given and
2474 they're not explicitly asked for as options. OPTION_END is used
2475 as an internal way to specify siaddr without using dhcp-boot, for use in
2476 dhcp-optsfile. */
2477 {
2478 if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2479 (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2480 {
2481 safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
2482 done_file = 1;
2483 }
2484
2485 if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2486 (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2487 {
2488 safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
2489 done_server = 1;
2490 }
2491
2492 if ((opt = option_find2(OPTION_END)))
2493 mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;
2494 }
2495
2496 /* We don't want to do option-overload for BOOTP, so make the file and sname
2497 fields look like they are in use, even when they aren't. This gets restored
2498 at the end of this function. */
2499
2500 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2501 {
2502 f0 = mess->file[0];
2503 mess->file[0] = 1;
2504 s0 = mess->sname[0];
2505 mess->sname[0] = 1;
2506 }
2507
2508 /* At this point, if mess->sname or mess->file are zeroed, they are available
2509 for option overload, reserve space for the overload option. */
2510 if (mess->file[0] == 0 || mess->sname[0] == 0)
2511 end -= 3;
2512
2513 /* rfc3011 says this doesn't need to be in the requested options list. */
2514 if (subnet_addr.s_addr)
2515 option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2516
2517 if (lease_time != 0xffffffff)
2518 {
2519 unsigned int t1val = lease_time/2;
2520 unsigned int t2val = (lease_time*7)/8;
2521 unsigned int hval;
2522
2523 /* If set by user, sanity check, so not longer than lease. */
2524 if ((opt = option_find2(OPTION_T1)))
2525 {
2526 hval = ntohl(*((unsigned int *)opt->val));
2527 if (hval < lease_time && hval > 2)
2528 t1val = hval;
2529 }
2530
2531 if ((opt = option_find2(OPTION_T2)))
2532 {
2533 hval = ntohl(*((unsigned int *)opt->val));
2534 if (hval < lease_time && hval > 2)
2535 t2val = hval;
2536 }
2537
2538 /* ensure T1 is still < T2 */
2539 if (t2val <= t1val)
2540 t1val = t2val - 1;
2541
2542 while (fuzz > (t1val/8))
2543 fuzz = fuzz/2;
2544
2545 t1val -= fuzz;
2546 t2val -= fuzz;
2547
2548 option_put(mess, end, OPTION_T1, 4, t1val);
2549 option_put(mess, end, OPTION_T2, 4, t2val);
2550 }
2551
2552 /* replies to DHCPINFORM may not have a valid context */
2553 if (context)
2554 {
2555 if (!option_find2(OPTION_NETMASK))
2556 option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2557
2558 /* May not have a "guessed" broadcast address if we got no packets via a relay
2559 from this net yet (ie just unicast renewals after a restart */
2560 if (context->broadcast.s_addr &&
2561 !option_find2(OPTION_BROADCAST))
2562 option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2563
2564 /* Same comments as broadcast apply, and also may not be able to get a sensible
2565 default when using subnet select. User must configure by steam in that case. */
2566 if (context->router.s_addr &&
2567 in_list(req_options, OPTION_ROUTER) &&
2568 !option_find2(OPTION_ROUTER))
2569 option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2570
2571 if (daemon->port == NAMESERVER_PORT &&
2572 in_list(req_options, OPTION_DNSSERVER) &&
2573 !option_find2(OPTION_DNSSERVER))
2574 option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2575 }
2576
2577 if (domain && in_list(req_options, OPTION_DOMAINNAME) &&
2578 !option_find2(OPTION_DOMAINNAME))
2579 option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2580
2581 /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2582 if (hostname)
2583 {
2584 if (in_list(req_options, OPTION_HOSTNAME) &&
2585 !option_find2(OPTION_HOSTNAME))
2586 option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2587
2588 if (fqdn_flags != 0)
2589 {
2590 len = strlen(hostname) + 3;
2591
2592 if (fqdn_flags & 0x04)
2593 len += 2;
2594 else if (null_term)
2595 len++;
2596
2597 if (domain)
2598 len += strlen(domain) + 1;
2599 else if (fqdn_flags & 0x04)
2600 len--;
2601
2602 if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2603 {
2604 *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */
2605 *(p++) = 255;
2606 *(p++) = 255;
2607
2608 if (fqdn_flags & 0x04)
2609 {
2610 p = do_rfc1035_name(p, hostname, NULL);
2611 if (domain)
2612 {
2613 p = do_rfc1035_name(p, domain, NULL);
2614 *p++ = 0;
2615 }
2616 }
2617 else
2618 {
2619 memcpy(p, hostname, strlen(hostname));
2620 p += strlen(hostname);
2621 if (domain)
2622 {
2623 *(p++) = '.';
2624 memcpy(p, domain, strlen(domain));
2625 p += strlen(domain);
2626 }
2627 if (null_term)
2628 *(p++) = 0;
2629 }
2630 }
2631 }
2632 }
2633
2634 for (opt = config_opts; opt; opt = opt->next)
2635 {
2636 int optno = opt->opt;
2637
2638 /* netids match and not encapsulated? */
2639 if (!(opt->flags & DHOPT_TAGOK))
2640 continue;
2641
2642 /* was it asked for, or are we sending it anyway? */
2643 if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2644 continue;
2645
2646 /* prohibit some used-internally options. T1 and T2 already handled. */
2647 if (optno == OPTION_CLIENT_FQDN ||
2648 optno == OPTION_MAXMESSAGE ||
2649 optno == OPTION_OVERLOAD ||
2650 optno == OPTION_PAD ||
2651 optno == OPTION_END ||
2652 optno == OPTION_T1 ||
2653 optno == OPTION_T2)
2654 continue;
2655
2656 if (optno == OPTION_SNAME && done_server)
2657 continue;
2658
2659 if (optno == OPTION_FILENAME && done_file)
2660 continue;
2661
2662 /* For the options we have default values on
2663 dhc-option=<optionno> means "don't include this option"
2664 not "include a zero-length option" */
2665 if (opt->len == 0 &&
2666 (optno == OPTION_NETMASK ||
2667 optno == OPTION_BROADCAST ||
2668 optno == OPTION_ROUTER ||
2669 optno == OPTION_DNSSERVER ||
2670 optno == OPTION_DOMAINNAME ||
2671 optno == OPTION_HOSTNAME))
2672 continue;
2673
2674 /* vendor-class comes from elsewhere for PXE */
2675 if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2676 continue;
2677
2678 /* always force null-term for filename and servername - buggy PXE again. */
2679 len = do_opt(opt, NULL, context,
2680 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2681
2682 if ((p = free_space(mess, end, optno, len)))
2683 {
2684 do_opt(opt, p, context,
2685 (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2686
2687 /* If we send a vendor-id, revisit which vendor-ops we consider
2688 it appropriate to send. */
2689 if (optno == OPTION_VENDOR_ID)
2690 {
2691 match_vendor_opts(p - 2, config_opts);
2692 done_vendor_class = 1;
2693 }
2694 }
2695 }
2696
2697 /* Now send options to be encapsulated in arbitrary options,
2698 eg dhcp-option=encap:172,17,.......
2699 Also handle vendor-identifying vendor-encapsulated options,
2700 dhcp-option = vi-encap:13,17,.......
2701 The may be more that one "outer" to do, so group
2702 all the options which match each outer in turn. */
2703 for (opt = config_opts; opt; opt = opt->next)
2704 opt->flags &= ~DHOPT_ENCAP_DONE;
2705
2706 for (opt = config_opts; opt; opt = opt->next)
2707 {
2708 int flags;
2709
2710 if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2711 {
2712 int found = 0;
2713 struct dhcp_opt *o;
2714
2715 if (opt->flags & DHOPT_ENCAP_DONE)
2716 continue;
2717
2718 for (len = 0, o = config_opts; o; o = o->next)
2719 {
2720 int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2721
2722 o->flags &= ~DHOPT_ENCAP_MATCH;
2723
2724 if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2725 continue;
2726
2727 o->flags |= DHOPT_ENCAP_DONE;
2728 if (match_netid(o->netid, tagif, 1) &&
2729 ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2730 {
2731 o->flags |= DHOPT_ENCAP_MATCH;
2732 found = 1;
2733 len += do_opt(o, NULL, NULL, 0) + 2;
2734 }
2735 }
2736
2737 if (found)
2738 {
2739 if (flags & DHOPT_ENCAPSULATE)
2740 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2741 else if (len > 250)
2742 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2743 else if ((p = free_space(mess, end, OPTION_VENDOR_IDENT_OPT, len + 5)))
2744 {
2745 int swap_ent = htonl(opt->u.encap);
2746 memcpy(p, &swap_ent, 4);
2747 p += 4;
2748 *(p++) = len;
2749 for (o = config_opts; o; o = o->next)
2750 if (o->flags & DHOPT_ENCAP_MATCH)
2751 {
2752 len = do_opt(o, p + 2, NULL, 0);
2753 *(p++) = o->opt;
2754 *(p++) = len;
2755 p += len;
2756 }
2757 }
2758 }
2759 }
2760 }
2761
2762 force_encap = prune_vendor_opts(tagif);
2763
2764 if (context && pxe_arch != -1)
2765 {
2766 pxe_misc(mess, end, uuid, pxevendor);
2767 if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
2768 config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
2769 }
2770
2771 if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2772 do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) &&
2773 pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2774 (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2775 /* If we send vendor encapsulated options, and haven't already sent option 60,
2776 echo back the value we got from the client. */
2777 memcpy(p, daemon->dhcp_buff3, vendor_class_len);
2778
2779 /* restore BOOTP anti-overload hack */
2780 if (!req_options || option_bool(OPT_NO_OVERRIDE))
2781 {
2782 mess->file[0] = f0;
2783 mess->sname[0] = s0;
2784 }
2785}
2786
2787static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
2788{
2789 struct delay_config *delay_conf;
2790
2791 /* Decide which delay_config option we're using */
2792 for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
2793 if (match_netid(delay_conf->netid, netid, 0))
2794 break;
2795
2796 if (!delay_conf)
2797 /* No match, look for one without a netid */
2798 for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
2799 if (match_netid(delay_conf->netid, netid, 1))
2800 break;
2801
2802 if (delay_conf)
2803 {
2804 if (!option_bool(OPT_QUIET_DHCP))
2805 my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
2806 delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
2807 }
2808}
2809
2810#endif /* HAVE_DHCP */