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