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