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