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