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