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