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