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