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