1 /* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */ 2 3 /* 4 * Copyright 2004 Henning Brauer <henning@openbsd.org> 5 * Copyright (c) 1995, 1996, 1997, 1998, 1999 6 * The Internet Software Consortium. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. Neither the name of The Internet Software Consortium nor the names 18 * of its contributors may be used to endorse or promote products derived 19 * from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 22 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * This software has been written for the Internet Software Consortium 36 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie 37 * Enterprises. To learn more about the Internet Software Consortium, 38 * see ``http://www.vix.com/isc''. To learn more about Vixie 39 * Enterprises, see ``http://www.vix.com''. 40 * 41 * This client was substantially modified and enhanced by Elliot Poger 42 * for use on Linux while he was working on the MosquitoNet project at 43 * Stanford. 44 * 45 * The current version owes much to Elliot's Linux enhancements, but 46 * was substantially reorganized and partially rewritten by Ted Lemon 47 * so as to use the same networking framework that the Internet Software 48 * Consortium DHCP server uses. Much system-specific configuration code 49 * was moved into a shell script so that as support for more operating 50 * systems is added, it will not be necessary to port and maintain 51 * system-specific configuration code to these operating systems - instead, 52 * the shell script can invoke the native tools to accomplish the same 53 * purpose. 54 */ 55 56 #include <sys/cdefs.h> 57 __FBSDID("$FreeBSD$"); 58 59 #include "dhcpd.h" 60 #include "privsep.h" 61 62 #include <net80211/ieee80211_freebsd.h> 63 64 #ifndef _PATH_VAREMPTY 65 #define _PATH_VAREMPTY "/var/empty" 66 #endif 67 68 #define PERIOD 0x2e 69 #define hyphenchar(c) ((c) == 0x2d) 70 #define bslashchar(c) ((c) == 0x5c) 71 #define periodchar(c) ((c) == PERIOD) 72 #define asterchar(c) ((c) == 0x2a) 73 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \ 74 ((c) >= 0x61 && (c) <= 0x7a)) 75 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) 76 #define whitechar(c) ((c) == ' ' || (c) == '\t') 77 78 #define borderchar(c) (alphachar(c) || digitchar(c)) 79 #define middlechar(c) (borderchar(c) || hyphenchar(c)) 80 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) 81 82 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin" 83 84 time_t cur_time; 85 time_t default_lease_time = 43200; /* 12 hours... */ 86 87 char *path_dhclient_conf = _PATH_DHCLIENT_CONF; 88 char *path_dhclient_db = NULL; 89 90 int log_perror = 1; 91 int privfd; 92 int nullfd = -1; 93 94 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; 95 struct in_addr inaddr_any; 96 struct sockaddr_in sockaddr_broadcast; 97 98 /* 99 * ASSERT_STATE() does nothing now; it used to be 100 * assert (state_is == state_shouldbe). 101 */ 102 #define ASSERT_STATE(state_is, state_shouldbe) {} 103 104 #define TIME_MAX 2147483647 105 106 int log_priority; 107 int no_daemon; 108 int unknown_ok = 1; 109 int routefd; 110 111 struct interface_info *ifi; 112 113 int findproto(char *, int); 114 struct sockaddr *get_ifa(char *, int); 115 void routehandler(struct protocol *); 116 void usage(void); 117 int check_option(struct client_lease *l, int option); 118 int check_classless_option(unsigned char *data, int len); 119 int ipv4addrs(char * buf); 120 int res_hnok(const char *dn); 121 int check_search(const char *srch); 122 char *option_as_string(unsigned int code, unsigned char *data, int len); 123 int fork_privchld(int, int); 124 125 #define ROUNDUP(a) \ 126 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long)) 127 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 128 129 static time_t scripttime; 130 131 int 132 findproto(char *cp, int n) 133 { 134 struct sockaddr *sa; 135 int i; 136 137 if (n == 0) 138 return -1; 139 for (i = 1; i; i <<= 1) { 140 if (i & n) { 141 sa = (struct sockaddr *)cp; 142 switch (i) { 143 case RTA_IFA: 144 case RTA_DST: 145 case RTA_GATEWAY: 146 case RTA_NETMASK: 147 if (sa->sa_family == AF_INET) 148 return AF_INET; 149 if (sa->sa_family == AF_INET6) 150 return AF_INET6; 151 break; 152 case RTA_IFP: 153 break; 154 } 155 ADVANCE(cp, sa); 156 } 157 } 158 return (-1); 159 } 160 161 struct sockaddr * 162 get_ifa(char *cp, int n) 163 { 164 struct sockaddr *sa; 165 int i; 166 167 if (n == 0) 168 return (NULL); 169 for (i = 1; i; i <<= 1) 170 if (i & n) { 171 sa = (struct sockaddr *)cp; 172 if (i == RTA_IFA) 173 return (sa); 174 ADVANCE(cp, sa); 175 } 176 177 return (NULL); 178 } 179 180 struct iaddr defaddr = { 4 }; 181 uint8_t curbssid[6]; 182 183 static void 184 disassoc(void *arg) 185 { 186 struct interface_info *ifi = arg; 187 188 /* 189 * Clear existing state. 190 */ 191 if (ifi->client->active != NULL) { 192 script_init("EXPIRE", NULL); 193 script_write_params("old_", 194 ifi->client->active); 195 if (ifi->client->alias) 196 script_write_params("alias_", 197 ifi->client->alias); 198 script_go(); 199 } 200 ifi->client->state = S_INIT; 201 } 202 203 /* ARGSUSED */ 204 void 205 routehandler(struct protocol *p) 206 { 207 char msg[2048], *addr; 208 struct rt_msghdr *rtm; 209 struct if_msghdr *ifm; 210 struct ifa_msghdr *ifam; 211 struct if_announcemsghdr *ifan; 212 struct ieee80211_join_event *jev; 213 struct client_lease *l; 214 time_t t = time(NULL); 215 struct sockaddr *sa; 216 struct iaddr a; 217 ssize_t n; 218 219 n = read(routefd, &msg, sizeof(msg)); 220 rtm = (struct rt_msghdr *)msg; 221 if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen || 222 rtm->rtm_version != RTM_VERSION) 223 return; 224 225 switch (rtm->rtm_type) { 226 case RTM_NEWADDR: 227 case RTM_DELADDR: 228 ifam = (struct ifa_msghdr *)rtm; 229 230 if (ifam->ifam_index != ifi->index) 231 break; 232 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET) 233 break; 234 if (scripttime == 0 || t < scripttime + 10) 235 break; 236 237 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs); 238 if (sa == NULL) 239 break; 240 241 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf)) 242 error("king bula sez: len mismatch"); 243 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len); 244 if (addr_eq(a, defaddr)) 245 break; 246 247 for (l = ifi->client->active; l != NULL; l = l->next) 248 if (addr_eq(a, l->address)) 249 break; 250 251 if (l == NULL) /* added/deleted addr is not the one we set */ 252 break; 253 254 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr); 255 if (rtm->rtm_type == RTM_NEWADDR) { 256 /* 257 * XXX: If someone other than us adds our address, 258 * should we assume they are taking over from us, 259 * delete the lease record, and exit without modifying 260 * the interface? 261 */ 262 warning("My address (%s) was re-added", addr); 263 } else { 264 warning("My address (%s) was deleted, dhclient exiting", 265 addr); 266 goto die; 267 } 268 break; 269 case RTM_IFINFO: 270 ifm = (struct if_msghdr *)rtm; 271 if (ifm->ifm_index != ifi->index) 272 break; 273 if ((rtm->rtm_flags & RTF_UP) == 0) { 274 warning("Interface %s is down, dhclient exiting", 275 ifi->name); 276 goto die; 277 } 278 break; 279 case RTM_IFANNOUNCE: 280 ifan = (struct if_announcemsghdr *)rtm; 281 if (ifan->ifan_what == IFAN_DEPARTURE && 282 ifan->ifan_index == ifi->index) { 283 warning("Interface %s is gone, dhclient exiting", 284 ifi->name); 285 goto die; 286 } 287 break; 288 case RTM_IEEE80211: 289 ifan = (struct if_announcemsghdr *)rtm; 290 if (ifan->ifan_index != ifi->index) 291 break; 292 switch (ifan->ifan_what) { 293 case RTM_IEEE80211_ASSOC: 294 case RTM_IEEE80211_REASSOC: 295 /* 296 * Use assoc/reassoc event to kick state machine 297 * in case we roam. Otherwise fall back to the 298 * normal state machine just like a wired network. 299 */ 300 jev = (struct ieee80211_join_event *) &ifan[1]; 301 if (memcmp(curbssid, jev->iev_addr, 6)) { 302 disassoc(ifi); 303 state_reboot(ifi); 304 } 305 memcpy(curbssid, jev->iev_addr, 6); 306 break; 307 } 308 break; 309 default: 310 break; 311 } 312 return; 313 314 die: 315 script_init("FAIL", NULL); 316 if (ifi->client->alias) 317 script_write_params("alias_", ifi->client->alias); 318 script_go(); 319 exit(1); 320 } 321 322 int 323 main(int argc, char *argv[]) 324 { 325 extern char *__progname; 326 int ch, fd, quiet = 0, i = 0; 327 int pipe_fd[2]; 328 int immediate_daemon = 0; 329 struct passwd *pw; 330 331 /* Initially, log errors to stderr as well as to syslogd. */ 332 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY); 333 setlogmask(LOG_UPTO(LOG_DEBUG)); 334 335 while ((ch = getopt(argc, argv, "bc:dl:qu")) != -1) 336 switch (ch) { 337 case 'b': 338 immediate_daemon = 1; 339 break; 340 case 'c': 341 path_dhclient_conf = optarg; 342 break; 343 case 'd': 344 no_daemon = 1; 345 break; 346 case 'l': 347 path_dhclient_db = optarg; 348 break; 349 case 'q': 350 quiet = 1; 351 break; 352 case 'u': 353 unknown_ok = 0; 354 break; 355 default: 356 usage(); 357 } 358 359 argc -= optind; 360 argv += optind; 361 362 if (argc != 1) 363 usage(); 364 365 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL) 366 error("calloc"); 367 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ) 368 error("Interface name too long"); 369 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s", 370 _PATH_DHCLIENT_DB, ifi->name) == -1) 371 error("asprintf"); 372 373 if (quiet) 374 log_perror = 0; 375 376 tzset(); 377 time(&cur_time); 378 379 memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast)); 380 sockaddr_broadcast.sin_family = AF_INET; 381 sockaddr_broadcast.sin_port = htons(REMOTE_PORT); 382 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; 383 sockaddr_broadcast.sin_len = sizeof(sockaddr_broadcast); 384 inaddr_any.s_addr = INADDR_ANY; 385 386 read_client_conf(); 387 388 if (!interface_link_status(ifi->name)) { 389 fprintf(stderr, "%s: no link ...", ifi->name); 390 fflush(stderr); 391 sleep(1); 392 while (!interface_link_status(ifi->name)) { 393 fprintf(stderr, "."); 394 fflush(stderr); 395 if (++i > 10) { 396 fprintf(stderr, " giving up\n"); 397 exit(1); 398 } 399 sleep(1); 400 } 401 fprintf(stderr, " got link\n"); 402 } 403 404 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1) 405 error("cannot open %s: %m", _PATH_DEVNULL); 406 407 if ((pw = getpwnam("_dhcp")) == NULL) { 408 warning("no such user: _dhcp, falling back to \"nobody\""); 409 if ((pw = getpwnam("nobody")) == NULL) 410 error("no such user: nobody"); 411 } 412 413 if (pipe(pipe_fd) == -1) 414 error("pipe"); 415 416 fork_privchld(pipe_fd[0], pipe_fd[1]); 417 418 close(pipe_fd[0]); 419 privfd = pipe_fd[1]; 420 421 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1) 422 error("can't open and lock %s: %m", path_dhclient_db); 423 read_client_leases(); 424 rewrite_client_leases(); 425 close(fd); 426 427 priv_script_init("PREINIT", NULL); 428 if (ifi->client->alias) 429 priv_script_write_params("alias_", ifi->client->alias); 430 priv_script_go(); 431 432 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1) 433 add_protocol("AF_ROUTE", routefd, routehandler, ifi); 434 435 /* set up the interface */ 436 discover_interfaces(ifi); 437 438 if (chroot(_PATH_VAREMPTY) == -1) 439 error("chroot"); 440 if (chdir("/") == -1) 441 error("chdir(\"/\")"); 442 443 if (setgroups(1, &pw->pw_gid) || 444 setegid(pw->pw_gid) || setgid(pw->pw_gid) || 445 seteuid(pw->pw_uid) || setuid(pw->pw_uid)) 446 error("can't drop privileges: %m"); 447 448 endpwent(); 449 450 setproctitle("%s", ifi->name); 451 452 if (immediate_daemon) 453 go_daemon(); 454 455 ifi->client->state = S_INIT; 456 state_reboot(ifi); 457 458 bootp_packet_handler = do_packet; 459 460 dispatch(); 461 462 /* not reached */ 463 return (0); 464 } 465 466 void 467 usage(void) 468 { 469 extern char *__progname; 470 471 fprintf(stderr, "usage: %s [-bdqu] ", __progname); 472 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n"); 473 exit(1); 474 } 475 476 /* 477 * Individual States: 478 * 479 * Each routine is called from the dhclient_state_machine() in one of 480 * these conditions: 481 * -> entering INIT state 482 * -> recvpacket_flag == 0: timeout in this state 483 * -> otherwise: received a packet in this state 484 * 485 * Return conditions as handled by dhclient_state_machine(): 486 * Returns 1, sendpacket_flag = 1: send packet, reset timer. 487 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). 488 * Returns 0: finish the nap which was interrupted for no good reason. 489 * 490 * Several per-interface variables are used to keep track of the process: 491 * active_lease: the lease that is being used on the interface 492 * (null pointer if not configured yet). 493 * offered_leases: leases corresponding to DHCPOFFER messages that have 494 * been sent to us by DHCP servers. 495 * acked_leases: leases corresponding to DHCPACK messages that have been 496 * sent to us by DHCP servers. 497 * sendpacket: DHCP packet we're trying to send. 498 * destination: IP address to send sendpacket to 499 * In addition, there are several relevant per-lease variables. 500 * T1_expiry, T2_expiry, lease_expiry: lease milestones 501 * In the active lease, these control the process of renewing the lease; 502 * In leases on the acked_leases list, this simply determines when we 503 * can no longer legitimately use the lease. 504 */ 505 506 void 507 state_reboot(void *ipp) 508 { 509 struct interface_info *ip = ipp; 510 511 /* If we don't remember an active lease, go straight to INIT. */ 512 if (!ip->client->active || ip->client->active->is_bootp) { 513 state_init(ip); 514 return; 515 } 516 517 /* We are in the rebooting state. */ 518 ip->client->state = S_REBOOTING; 519 520 /* make_request doesn't initialize xid because it normally comes 521 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER, 522 so pick an xid now. */ 523 ip->client->xid = arc4random(); 524 525 /* Make a DHCPREQUEST packet, and set appropriate per-interface 526 flags. */ 527 make_request(ip, ip->client->active); 528 ip->client->destination = iaddr_broadcast; 529 ip->client->first_sending = cur_time; 530 ip->client->interval = ip->client->config->initial_interval; 531 532 /* Zap the medium list... */ 533 ip->client->medium = NULL; 534 535 /* Send out the first DHCPREQUEST packet. */ 536 send_request(ip); 537 } 538 539 /* 540 * Called when a lease has completely expired and we've 541 * been unable to renew it. 542 */ 543 void 544 state_init(void *ipp) 545 { 546 struct interface_info *ip = ipp; 547 548 ASSERT_STATE(state, S_INIT); 549 550 /* Make a DHCPDISCOVER packet, and set appropriate per-interface 551 flags. */ 552 make_discover(ip, ip->client->active); 553 ip->client->xid = ip->client->packet.xid; 554 ip->client->destination = iaddr_broadcast; 555 ip->client->state = S_SELECTING; 556 ip->client->first_sending = cur_time; 557 ip->client->interval = ip->client->config->initial_interval; 558 559 /* Add an immediate timeout to cause the first DHCPDISCOVER packet 560 to go out. */ 561 send_discover(ip); 562 } 563 564 /* 565 * state_selecting is called when one or more DHCPOFFER packets 566 * have been received and a configurable period of time has passed. 567 */ 568 void 569 state_selecting(void *ipp) 570 { 571 struct interface_info *ip = ipp; 572 struct client_lease *lp, *next, *picked; 573 574 ASSERT_STATE(state, S_SELECTING); 575 576 /* Cancel state_selecting and send_discover timeouts, since either 577 one could have got us here. */ 578 cancel_timeout(state_selecting, ip); 579 cancel_timeout(send_discover, ip); 580 581 /* We have received one or more DHCPOFFER packets. Currently, 582 the only criterion by which we judge leases is whether or 583 not we get a response when we arp for them. */ 584 picked = NULL; 585 for (lp = ip->client->offered_leases; lp; lp = next) { 586 next = lp->next; 587 588 /* Check to see if we got an ARPREPLY for the address 589 in this particular lease. */ 590 if (!picked) { 591 script_init("ARPCHECK", lp->medium); 592 script_write_params("check_", lp); 593 594 /* If the ARPCHECK code detects another 595 machine using the offered address, it exits 596 nonzero. We need to send a DHCPDECLINE and 597 toss the lease. */ 598 if (script_go()) { 599 make_decline(ip, lp); 600 send_decline(ip); 601 goto freeit; 602 } 603 picked = lp; 604 picked->next = NULL; 605 } else { 606 freeit: 607 free_client_lease(lp); 608 } 609 } 610 ip->client->offered_leases = NULL; 611 612 /* If we just tossed all the leases we were offered, go back 613 to square one. */ 614 if (!picked) { 615 ip->client->state = S_INIT; 616 state_init(ip); 617 return; 618 } 619 620 /* If it was a BOOTREPLY, we can just take the address right now. */ 621 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) { 622 ip->client->new = picked; 623 624 /* Make up some lease expiry times 625 XXX these should be configurable. */ 626 ip->client->new->expiry = cur_time + 12000; 627 ip->client->new->renewal += cur_time + 8000; 628 ip->client->new->rebind += cur_time + 10000; 629 630 ip->client->state = S_REQUESTING; 631 632 /* Bind to the address we received. */ 633 bind_lease(ip); 634 return; 635 } 636 637 /* Go to the REQUESTING state. */ 638 ip->client->destination = iaddr_broadcast; 639 ip->client->state = S_REQUESTING; 640 ip->client->first_sending = cur_time; 641 ip->client->interval = ip->client->config->initial_interval; 642 643 /* Make a DHCPREQUEST packet from the lease we picked. */ 644 make_request(ip, picked); 645 ip->client->xid = ip->client->packet.xid; 646 647 /* Toss the lease we picked - we'll get it back in a DHCPACK. */ 648 free_client_lease(picked); 649 650 /* Add an immediate timeout to send the first DHCPREQUEST packet. */ 651 send_request(ip); 652 } 653 654 /* state_requesting is called when we receive a DHCPACK message after 655 having sent out one or more DHCPREQUEST packets. */ 656 657 void 658 dhcpack(struct packet *packet) 659 { 660 struct interface_info *ip = packet->interface; 661 struct client_lease *lease; 662 663 /* If we're not receptive to an offer right now, or if the offer 664 has an unrecognizable transaction id, then just drop it. */ 665 if (packet->interface->client->xid != packet->raw->xid || 666 (packet->interface->hw_address.hlen != packet->raw->hlen) || 667 (memcmp(packet->interface->hw_address.haddr, 668 packet->raw->chaddr, packet->raw->hlen))) 669 return; 670 671 if (ip->client->state != S_REBOOTING && 672 ip->client->state != S_REQUESTING && 673 ip->client->state != S_RENEWING && 674 ip->client->state != S_REBINDING) 675 return; 676 677 note("DHCPACK from %s", piaddr(packet->client_addr)); 678 679 lease = packet_to_lease(packet); 680 if (!lease) { 681 note("packet_to_lease failed."); 682 return; 683 } 684 685 ip->client->new = lease; 686 687 /* Stop resending DHCPREQUEST. */ 688 cancel_timeout(send_request, ip); 689 690 /* Figure out the lease time. */ 691 if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data) 692 ip->client->new->expiry = getULong( 693 ip->client->new->options[DHO_DHCP_LEASE_TIME].data); 694 else 695 ip->client->new->expiry = default_lease_time; 696 /* A number that looks negative here is really just very large, 697 because the lease expiry offset is unsigned. */ 698 if (ip->client->new->expiry < 0) 699 ip->client->new->expiry = TIME_MAX; 700 /* XXX should be fixed by resetting the client state */ 701 if (ip->client->new->expiry < 60) 702 ip->client->new->expiry = 60; 703 704 /* Take the server-provided renewal time if there is one; 705 otherwise figure it out according to the spec. */ 706 if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len) 707 ip->client->new->renewal = getULong( 708 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data); 709 else 710 ip->client->new->renewal = ip->client->new->expiry / 2; 711 712 /* Same deal with the rebind time. */ 713 if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len) 714 ip->client->new->rebind = getULong( 715 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data); 716 else 717 ip->client->new->rebind = ip->client->new->renewal + 718 ip->client->new->renewal / 2 + ip->client->new->renewal / 4; 719 720 ip->client->new->expiry += cur_time; 721 /* Lease lengths can never be negative. */ 722 if (ip->client->new->expiry < cur_time) 723 ip->client->new->expiry = TIME_MAX; 724 ip->client->new->renewal += cur_time; 725 if (ip->client->new->renewal < cur_time) 726 ip->client->new->renewal = TIME_MAX; 727 ip->client->new->rebind += cur_time; 728 if (ip->client->new->rebind < cur_time) 729 ip->client->new->rebind = TIME_MAX; 730 731 bind_lease(ip); 732 } 733 734 void 735 bind_lease(struct interface_info *ip) 736 { 737 /* Remember the medium. */ 738 ip->client->new->medium = ip->client->medium; 739 740 /* Write out the new lease. */ 741 write_client_lease(ip, ip->client->new, 0); 742 743 /* Run the client script with the new parameters. */ 744 script_init((ip->client->state == S_REQUESTING ? "BOUND" : 745 (ip->client->state == S_RENEWING ? "RENEW" : 746 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))), 747 ip->client->new->medium); 748 if (ip->client->active && ip->client->state != S_REBOOTING) 749 script_write_params("old_", ip->client->active); 750 script_write_params("new_", ip->client->new); 751 if (ip->client->alias) 752 script_write_params("alias_", ip->client->alias); 753 script_go(); 754 755 /* Replace the old active lease with the new one. */ 756 if (ip->client->active) 757 free_client_lease(ip->client->active); 758 ip->client->active = ip->client->new; 759 ip->client->new = NULL; 760 761 /* Set up a timeout to start the renewal process. */ 762 add_timeout(ip->client->active->renewal, state_bound, ip); 763 764 note("bound to %s -- renewal in %d seconds.", 765 piaddr(ip->client->active->address), 766 (int)(ip->client->active->renewal - cur_time)); 767 ip->client->state = S_BOUND; 768 reinitialize_interfaces(); 769 go_daemon(); 770 } 771 772 /* 773 * state_bound is called when we've successfully bound to a particular 774 * lease, but the renewal time on that lease has expired. We are 775 * expected to unicast a DHCPREQUEST to the server that gave us our 776 * original lease. 777 */ 778 void 779 state_bound(void *ipp) 780 { 781 struct interface_info *ip = ipp; 782 783 ASSERT_STATE(state, S_BOUND); 784 785 /* T1 has expired. */ 786 make_request(ip, ip->client->active); 787 ip->client->xid = ip->client->packet.xid; 788 789 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) { 790 memcpy(ip->client->destination.iabuf, ip->client->active-> 791 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4); 792 ip->client->destination.len = 4; 793 } else 794 ip->client->destination = iaddr_broadcast; 795 796 ip->client->first_sending = cur_time; 797 ip->client->interval = ip->client->config->initial_interval; 798 ip->client->state = S_RENEWING; 799 800 /* Send the first packet immediately. */ 801 send_request(ip); 802 } 803 804 void 805 bootp(struct packet *packet) 806 { 807 struct iaddrlist *ap; 808 809 if (packet->raw->op != BOOTREPLY) 810 return; 811 812 /* If there's a reject list, make sure this packet's sender isn't 813 on it. */ 814 for (ap = packet->interface->client->config->reject_list; 815 ap; ap = ap->next) { 816 if (addr_eq(packet->client_addr, ap->addr)) { 817 note("BOOTREPLY from %s rejected.", piaddr(ap->addr)); 818 return; 819 } 820 } 821 dhcpoffer(packet); 822 } 823 824 void 825 dhcp(struct packet *packet) 826 { 827 struct iaddrlist *ap; 828 void (*handler)(struct packet *); 829 char *type; 830 831 switch (packet->packet_type) { 832 case DHCPOFFER: 833 handler = dhcpoffer; 834 type = "DHCPOFFER"; 835 break; 836 case DHCPNAK: 837 handler = dhcpnak; 838 type = "DHCPNACK"; 839 break; 840 case DHCPACK: 841 handler = dhcpack; 842 type = "DHCPACK"; 843 break; 844 default: 845 return; 846 } 847 848 /* If there's a reject list, make sure this packet's sender isn't 849 on it. */ 850 for (ap = packet->interface->client->config->reject_list; 851 ap; ap = ap->next) { 852 if (addr_eq(packet->client_addr, ap->addr)) { 853 note("%s from %s rejected.", type, piaddr(ap->addr)); 854 return; 855 } 856 } 857 (*handler)(packet); 858 } 859 860 void 861 dhcpoffer(struct packet *packet) 862 { 863 struct interface_info *ip = packet->interface; 864 struct client_lease *lease, *lp; 865 int i; 866 int arp_timeout_needed, stop_selecting; 867 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? 868 "DHCPOFFER" : "BOOTREPLY"; 869 870 /* If we're not receptive to an offer right now, or if the offer 871 has an unrecognizable transaction id, then just drop it. */ 872 if (ip->client->state != S_SELECTING || 873 packet->interface->client->xid != packet->raw->xid || 874 (packet->interface->hw_address.hlen != packet->raw->hlen) || 875 (memcmp(packet->interface->hw_address.haddr, 876 packet->raw->chaddr, packet->raw->hlen))) 877 return; 878 879 note("%s from %s", name, piaddr(packet->client_addr)); 880 881 882 /* If this lease doesn't supply the minimum required parameters, 883 blow it off. */ 884 for (i = 0; ip->client->config->required_options[i]; i++) { 885 if (!packet->options[ip->client->config-> 886 required_options[i]].len) { 887 note("%s isn't satisfactory.", name); 888 return; 889 } 890 } 891 892 /* If we've already seen this lease, don't record it again. */ 893 for (lease = ip->client->offered_leases; 894 lease; lease = lease->next) { 895 if (lease->address.len == sizeof(packet->raw->yiaddr) && 896 !memcmp(lease->address.iabuf, 897 &packet->raw->yiaddr, lease->address.len)) { 898 debug("%s already seen.", name); 899 return; 900 } 901 } 902 903 lease = packet_to_lease(packet); 904 if (!lease) { 905 note("packet_to_lease failed."); 906 return; 907 } 908 909 /* If this lease was acquired through a BOOTREPLY, record that 910 fact. */ 911 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len) 912 lease->is_bootp = 1; 913 914 /* Record the medium under which this lease was offered. */ 915 lease->medium = ip->client->medium; 916 917 /* Send out an ARP Request for the offered IP address. */ 918 script_init("ARPSEND", lease->medium); 919 script_write_params("check_", lease); 920 /* If the script can't send an ARP request without waiting, 921 we'll be waiting when we do the ARPCHECK, so don't wait now. */ 922 if (script_go()) 923 arp_timeout_needed = 0; 924 else 925 arp_timeout_needed = 2; 926 927 /* Figure out when we're supposed to stop selecting. */ 928 stop_selecting = 929 ip->client->first_sending + ip->client->config->select_interval; 930 931 /* If this is the lease we asked for, put it at the head of the 932 list, and don't mess with the arp request timeout. */ 933 if (lease->address.len == ip->client->requested_address.len && 934 !memcmp(lease->address.iabuf, 935 ip->client->requested_address.iabuf, 936 ip->client->requested_address.len)) { 937 lease->next = ip->client->offered_leases; 938 ip->client->offered_leases = lease; 939 } else { 940 /* If we already have an offer, and arping for this 941 offer would take us past the selection timeout, 942 then don't extend the timeout - just hope for the 943 best. */ 944 if (ip->client->offered_leases && 945 (cur_time + arp_timeout_needed) > stop_selecting) 946 arp_timeout_needed = 0; 947 948 /* Put the lease at the end of the list. */ 949 lease->next = NULL; 950 if (!ip->client->offered_leases) 951 ip->client->offered_leases = lease; 952 else { 953 for (lp = ip->client->offered_leases; lp->next; 954 lp = lp->next) 955 ; /* nothing */ 956 lp->next = lease; 957 } 958 } 959 960 /* If we're supposed to stop selecting before we've had time 961 to wait for the ARPREPLY, add some delay to wait for 962 the ARPREPLY. */ 963 if (stop_selecting - cur_time < arp_timeout_needed) 964 stop_selecting = cur_time + arp_timeout_needed; 965 966 /* If the selecting interval has expired, go immediately to 967 state_selecting(). Otherwise, time out into 968 state_selecting at the select interval. */ 969 if (stop_selecting <= 0) 970 state_selecting(ip); 971 else { 972 add_timeout(stop_selecting, state_selecting, ip); 973 cancel_timeout(send_discover, ip); 974 } 975 } 976 977 /* Allocate a client_lease structure and initialize it from the parameters 978 in the specified packet. */ 979 980 struct client_lease * 981 packet_to_lease(struct packet *packet) 982 { 983 struct client_lease *lease; 984 int i; 985 986 lease = malloc(sizeof(struct client_lease)); 987 988 if (!lease) { 989 warning("dhcpoffer: no memory to record lease."); 990 return (NULL); 991 } 992 993 memset(lease, 0, sizeof(*lease)); 994 995 /* Copy the lease options. */ 996 for (i = 0; i < 256; i++) { 997 if (packet->options[i].len) { 998 lease->options[i].data = 999 malloc(packet->options[i].len + 1); 1000 if (!lease->options[i].data) { 1001 warning("dhcpoffer: no memory for option %d", i); 1002 free_client_lease(lease); 1003 return (NULL); 1004 } else { 1005 memcpy(lease->options[i].data, 1006 packet->options[i].data, 1007 packet->options[i].len); 1008 lease->options[i].len = 1009 packet->options[i].len; 1010 lease->options[i].data[lease->options[i].len] = 1011 0; 1012 } 1013 if (!check_option(lease,i)) { 1014 /* ignore a bogus lease offer */ 1015 warning("Invalid lease option - ignoring offer"); 1016 free_client_lease(lease); 1017 return (NULL); 1018 } 1019 } 1020 } 1021 1022 lease->address.len = sizeof(packet->raw->yiaddr); 1023 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len); 1024 1025 /* If the server name was filled out, copy it. 1026 Do not attempt to validate the server name as a host name. 1027 RFC 2131 merely states that sname is NUL-terminated (which do 1028 do not assume) and that it is the server's host name. Since 1029 the ISC client and server allow arbitrary characters, we do 1030 as well. */ 1031 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 1032 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) && 1033 packet->raw->sname[0]) { 1034 lease->server_name = malloc(DHCP_SNAME_LEN + 1); 1035 if (!lease->server_name) { 1036 warning("dhcpoffer: no memory for server name."); 1037 free_client_lease(lease); 1038 return (NULL); 1039 } 1040 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); 1041 lease->server_name[DHCP_SNAME_LEN]='\0'; 1042 } 1043 1044 /* Ditto for the filename. */ 1045 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 1046 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) && 1047 packet->raw->file[0]) { 1048 /* Don't count on the NUL terminator. */ 1049 lease->filename = malloc(DHCP_FILE_LEN + 1); 1050 if (!lease->filename) { 1051 warning("dhcpoffer: no memory for filename."); 1052 free_client_lease(lease); 1053 return (NULL); 1054 } 1055 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN); 1056 lease->filename[DHCP_FILE_LEN]='\0'; 1057 } 1058 return lease; 1059 } 1060 1061 void 1062 dhcpnak(struct packet *packet) 1063 { 1064 struct interface_info *ip = packet->interface; 1065 1066 /* If we're not receptive to an offer right now, or if the offer 1067 has an unrecognizable transaction id, then just drop it. */ 1068 if (packet->interface->client->xid != packet->raw->xid || 1069 (packet->interface->hw_address.hlen != packet->raw->hlen) || 1070 (memcmp(packet->interface->hw_address.haddr, 1071 packet->raw->chaddr, packet->raw->hlen))) 1072 return; 1073 1074 if (ip->client->state != S_REBOOTING && 1075 ip->client->state != S_REQUESTING && 1076 ip->client->state != S_RENEWING && 1077 ip->client->state != S_REBINDING) 1078 return; 1079 1080 note("DHCPNAK from %s", piaddr(packet->client_addr)); 1081 1082 if (!ip->client->active) { 1083 note("DHCPNAK with no active lease.\n"); 1084 return; 1085 } 1086 1087 free_client_lease(ip->client->active); 1088 ip->client->active = NULL; 1089 1090 /* Stop sending DHCPREQUEST packets... */ 1091 cancel_timeout(send_request, ip); 1092 1093 ip->client->state = S_INIT; 1094 state_init(ip); 1095 } 1096 1097 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another 1098 one after the right interval has expired. If we don't get an offer by 1099 the time we reach the panic interval, call the panic function. */ 1100 1101 void 1102 send_discover(void *ipp) 1103 { 1104 struct interface_info *ip = ipp; 1105 int interval, increase = 1; 1106 1107 /* Figure out how long it's been since we started transmitting. */ 1108 interval = cur_time - ip->client->first_sending; 1109 1110 /* If we're past the panic timeout, call the script and tell it 1111 we haven't found anything for this interface yet. */ 1112 if (interval > ip->client->config->timeout) { 1113 state_panic(ip); 1114 return; 1115 } 1116 1117 /* If we're selecting media, try the whole list before doing 1118 the exponential backoff, but if we've already received an 1119 offer, stop looping, because we obviously have it right. */ 1120 if (!ip->client->offered_leases && 1121 ip->client->config->media) { 1122 int fail = 0; 1123 again: 1124 if (ip->client->medium) { 1125 ip->client->medium = ip->client->medium->next; 1126 increase = 0; 1127 } 1128 if (!ip->client->medium) { 1129 if (fail) 1130 error("No valid media types for %s!", ip->name); 1131 ip->client->medium = ip->client->config->media; 1132 increase = 1; 1133 } 1134 1135 note("Trying medium \"%s\" %d", ip->client->medium->string, 1136 increase); 1137 script_init("MEDIUM", ip->client->medium); 1138 if (script_go()) 1139 goto again; 1140 } 1141 1142 /* 1143 * If we're supposed to increase the interval, do so. If it's 1144 * currently zero (i.e., we haven't sent any packets yet), set 1145 * it to one; otherwise, add to it a random number between zero 1146 * and two times itself. On average, this means that it will 1147 * double with every transmission. 1148 */ 1149 if (increase) { 1150 if (!ip->client->interval) 1151 ip->client->interval = 1152 ip->client->config->initial_interval; 1153 else { 1154 ip->client->interval += (arc4random() >> 2) % 1155 (2 * ip->client->interval); 1156 } 1157 1158 /* Don't backoff past cutoff. */ 1159 if (ip->client->interval > 1160 ip->client->config->backoff_cutoff) 1161 ip->client->interval = 1162 ((ip->client->config->backoff_cutoff / 2) 1163 + ((arc4random() >> 2) % 1164 ip->client->config->backoff_cutoff)); 1165 } else if (!ip->client->interval) 1166 ip->client->interval = 1167 ip->client->config->initial_interval; 1168 1169 /* If the backoff would take us to the panic timeout, just use that 1170 as the interval. */ 1171 if (cur_time + ip->client->interval > 1172 ip->client->first_sending + ip->client->config->timeout) 1173 ip->client->interval = 1174 (ip->client->first_sending + 1175 ip->client->config->timeout) - cur_time + 1; 1176 1177 /* Record the number of seconds since we started sending. */ 1178 if (interval < 65536) 1179 ip->client->packet.secs = htons(interval); 1180 else 1181 ip->client->packet.secs = htons(65535); 1182 ip->client->secs = ip->client->packet.secs; 1183 1184 note("DHCPDISCOVER on %s to %s port %d interval %d", 1185 ip->name, inet_ntoa(sockaddr_broadcast.sin_addr), 1186 ntohs(sockaddr_broadcast.sin_port), 1187 (int)ip->client->interval); 1188 1189 /* Send out a packet. */ 1190 (void)send_packet(ip, &ip->client->packet, ip->client->packet_length, 1191 inaddr_any, &sockaddr_broadcast, NULL); 1192 1193 add_timeout(cur_time + ip->client->interval, send_discover, ip); 1194 } 1195 1196 /* 1197 * state_panic gets called if we haven't received any offers in a preset 1198 * amount of time. When this happens, we try to use existing leases 1199 * that haven't yet expired, and failing that, we call the client script 1200 * and hope it can do something. 1201 */ 1202 void 1203 state_panic(void *ipp) 1204 { 1205 struct interface_info *ip = ipp; 1206 struct client_lease *loop = ip->client->active; 1207 struct client_lease *lp; 1208 1209 note("No DHCPOFFERS received."); 1210 1211 /* We may not have an active lease, but we may have some 1212 predefined leases that we can try. */ 1213 if (!ip->client->active && ip->client->leases) 1214 goto activate_next; 1215 1216 /* Run through the list of leases and see if one can be used. */ 1217 while (ip->client->active) { 1218 if (ip->client->active->expiry > cur_time) { 1219 note("Trying recorded lease %s", 1220 piaddr(ip->client->active->address)); 1221 /* Run the client script with the existing 1222 parameters. */ 1223 script_init("TIMEOUT", 1224 ip->client->active->medium); 1225 script_write_params("new_", ip->client->active); 1226 if (ip->client->alias) 1227 script_write_params("alias_", 1228 ip->client->alias); 1229 1230 /* If the old lease is still good and doesn't 1231 yet need renewal, go into BOUND state and 1232 timeout at the renewal time. */ 1233 if (!script_go()) { 1234 if (cur_time < 1235 ip->client->active->renewal) { 1236 ip->client->state = S_BOUND; 1237 note("bound: renewal in %d seconds.", 1238 (int)(ip->client->active->renewal - 1239 cur_time)); 1240 add_timeout( 1241 ip->client->active->renewal, 1242 state_bound, ip); 1243 } else { 1244 ip->client->state = S_BOUND; 1245 note("bound: immediate renewal."); 1246 state_bound(ip); 1247 } 1248 reinitialize_interfaces(); 1249 go_daemon(); 1250 return; 1251 } 1252 } 1253 1254 /* If there are no other leases, give up. */ 1255 if (!ip->client->leases) { 1256 ip->client->leases = ip->client->active; 1257 ip->client->active = NULL; 1258 break; 1259 } 1260 1261 activate_next: 1262 /* Otherwise, put the active lease at the end of the 1263 lease list, and try another lease.. */ 1264 for (lp = ip->client->leases; lp->next; lp = lp->next) 1265 ; 1266 lp->next = ip->client->active; 1267 if (lp->next) 1268 lp->next->next = NULL; 1269 ip->client->active = ip->client->leases; 1270 ip->client->leases = ip->client->leases->next; 1271 1272 /* If we already tried this lease, we've exhausted the 1273 set of leases, so we might as well give up for 1274 now. */ 1275 if (ip->client->active == loop) 1276 break; 1277 else if (!loop) 1278 loop = ip->client->active; 1279 } 1280 1281 /* No leases were available, or what was available didn't work, so 1282 tell the shell script that we failed to allocate an address, 1283 and try again later. */ 1284 note("No working leases in persistent database - sleeping.\n"); 1285 script_init("FAIL", NULL); 1286 if (ip->client->alias) 1287 script_write_params("alias_", ip->client->alias); 1288 script_go(); 1289 ip->client->state = S_INIT; 1290 add_timeout(cur_time + ip->client->config->retry_interval, state_init, 1291 ip); 1292 go_daemon(); 1293 } 1294 1295 void 1296 send_request(void *ipp) 1297 { 1298 struct interface_info *ip = ipp; 1299 struct sockaddr_in destination; 1300 struct in_addr from; 1301 int interval; 1302 1303 /* Figure out how long it's been since we started transmitting. */ 1304 interval = cur_time - ip->client->first_sending; 1305 1306 /* If we're in the INIT-REBOOT or REQUESTING state and we're 1307 past the reboot timeout, go to INIT and see if we can 1308 DISCOVER an address... */ 1309 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it 1310 means either that we're on a network with no DHCP server, 1311 or that our server is down. In the latter case, assuming 1312 that there is a backup DHCP server, DHCPDISCOVER will get 1313 us a new address, but we could also have successfully 1314 reused our old address. In the former case, we're hosed 1315 anyway. This is not a win-prone situation. */ 1316 if ((ip->client->state == S_REBOOTING || 1317 ip->client->state == S_REQUESTING) && 1318 interval > ip->client->config->reboot_timeout) { 1319 cancel: 1320 ip->client->state = S_INIT; 1321 cancel_timeout(send_request, ip); 1322 state_init(ip); 1323 return; 1324 } 1325 1326 /* If we're in the reboot state, make sure the media is set up 1327 correctly. */ 1328 if (ip->client->state == S_REBOOTING && 1329 !ip->client->medium && 1330 ip->client->active->medium ) { 1331 script_init("MEDIUM", ip->client->active->medium); 1332 1333 /* If the medium we chose won't fly, go to INIT state. */ 1334 if (script_go()) 1335 goto cancel; 1336 1337 /* Record the medium. */ 1338 ip->client->medium = ip->client->active->medium; 1339 } 1340 1341 /* If the lease has expired, relinquish the address and go back 1342 to the INIT state. */ 1343 if (ip->client->state != S_REQUESTING && 1344 cur_time > ip->client->active->expiry) { 1345 /* Run the client script with the new parameters. */ 1346 script_init("EXPIRE", NULL); 1347 script_write_params("old_", ip->client->active); 1348 if (ip->client->alias) 1349 script_write_params("alias_", ip->client->alias); 1350 script_go(); 1351 1352 /* Now do a preinit on the interface so that we can 1353 discover a new address. */ 1354 script_init("PREINIT", NULL); 1355 if (ip->client->alias) 1356 script_write_params("alias_", ip->client->alias); 1357 script_go(); 1358 1359 ip->client->state = S_INIT; 1360 state_init(ip); 1361 return; 1362 } 1363 1364 /* Do the exponential backoff... */ 1365 if (!ip->client->interval) 1366 ip->client->interval = ip->client->config->initial_interval; 1367 else 1368 ip->client->interval += ((arc4random() >> 2) % 1369 (2 * ip->client->interval)); 1370 1371 /* Don't backoff past cutoff. */ 1372 if (ip->client->interval > 1373 ip->client->config->backoff_cutoff) 1374 ip->client->interval = 1375 ((ip->client->config->backoff_cutoff / 2) + 1376 ((arc4random() >> 2) % ip->client->interval)); 1377 1378 /* If the backoff would take us to the expiry time, just set the 1379 timeout to the expiry time. */ 1380 if (ip->client->state != S_REQUESTING && 1381 cur_time + ip->client->interval > 1382 ip->client->active->expiry) 1383 ip->client->interval = 1384 ip->client->active->expiry - cur_time + 1; 1385 1386 /* If the lease T2 time has elapsed, or if we're not yet bound, 1387 broadcast the DHCPREQUEST rather than unicasting. */ 1388 memset(&destination, 0, sizeof(destination)); 1389 if (ip->client->state == S_REQUESTING || 1390 ip->client->state == S_REBOOTING || 1391 cur_time > ip->client->active->rebind) 1392 destination.sin_addr.s_addr = INADDR_BROADCAST; 1393 else 1394 memcpy(&destination.sin_addr.s_addr, 1395 ip->client->destination.iabuf, 1396 sizeof(destination.sin_addr.s_addr)); 1397 destination.sin_port = htons(REMOTE_PORT); 1398 destination.sin_family = AF_INET; 1399 destination.sin_len = sizeof(destination); 1400 1401 if (ip->client->state != S_REQUESTING) 1402 memcpy(&from, ip->client->active->address.iabuf, 1403 sizeof(from)); 1404 else 1405 from.s_addr = INADDR_ANY; 1406 1407 /* Record the number of seconds since we started sending. */ 1408 if (ip->client->state == S_REQUESTING) 1409 ip->client->packet.secs = ip->client->secs; 1410 else { 1411 if (interval < 65536) 1412 ip->client->packet.secs = htons(interval); 1413 else 1414 ip->client->packet.secs = htons(65535); 1415 } 1416 1417 note("DHCPREQUEST on %s to %s port %d", ip->name, 1418 inet_ntoa(destination.sin_addr), ntohs(destination.sin_port)); 1419 1420 /* Send out a packet. */ 1421 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, 1422 from, &destination, NULL); 1423 1424 add_timeout(cur_time + ip->client->interval, send_request, ip); 1425 } 1426 1427 void 1428 send_decline(void *ipp) 1429 { 1430 struct interface_info *ip = ipp; 1431 1432 note("DHCPDECLINE on %s to %s port %d", ip->name, 1433 inet_ntoa(sockaddr_broadcast.sin_addr), 1434 ntohs(sockaddr_broadcast.sin_port)); 1435 1436 /* Send out a packet. */ 1437 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, 1438 inaddr_any, &sockaddr_broadcast, NULL); 1439 } 1440 1441 void 1442 make_discover(struct interface_info *ip, struct client_lease *lease) 1443 { 1444 unsigned char discover = DHCPDISCOVER; 1445 struct tree_cache *options[256]; 1446 struct tree_cache option_elements[256]; 1447 int i; 1448 1449 memset(option_elements, 0, sizeof(option_elements)); 1450 memset(options, 0, sizeof(options)); 1451 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1452 1453 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ 1454 i = DHO_DHCP_MESSAGE_TYPE; 1455 options[i] = &option_elements[i]; 1456 options[i]->value = &discover; 1457 options[i]->len = sizeof(discover); 1458 options[i]->buf_size = sizeof(discover); 1459 options[i]->timeout = 0xFFFFFFFF; 1460 1461 /* Request the options we want */ 1462 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1463 options[i] = &option_elements[i]; 1464 options[i]->value = ip->client->config->requested_options; 1465 options[i]->len = ip->client->config->requested_option_count; 1466 options[i]->buf_size = 1467 ip->client->config->requested_option_count; 1468 options[i]->timeout = 0xFFFFFFFF; 1469 1470 /* If we had an address, try to get it again. */ 1471 if (lease) { 1472 ip->client->requested_address = lease->address; 1473 i = DHO_DHCP_REQUESTED_ADDRESS; 1474 options[i] = &option_elements[i]; 1475 options[i]->value = lease->address.iabuf; 1476 options[i]->len = lease->address.len; 1477 options[i]->buf_size = lease->address.len; 1478 options[i]->timeout = 0xFFFFFFFF; 1479 } else 1480 ip->client->requested_address.len = 0; 1481 1482 /* Send any options requested in the config file. */ 1483 for (i = 0; i < 256; i++) 1484 if (!options[i] && 1485 ip->client->config->send_options[i].data) { 1486 options[i] = &option_elements[i]; 1487 options[i]->value = 1488 ip->client->config->send_options[i].data; 1489 options[i]->len = 1490 ip->client->config->send_options[i].len; 1491 options[i]->buf_size = 1492 ip->client->config->send_options[i].len; 1493 options[i]->timeout = 0xFFFFFFFF; 1494 } 1495 1496 /* send host name if not set via config file. */ 1497 char hostname[_POSIX_HOST_NAME_MAX+1]; 1498 if (!options[DHO_HOST_NAME]) { 1499 if (gethostname(hostname, sizeof(hostname)) == 0) { 1500 size_t len; 1501 char* posDot = strchr(hostname, '.'); 1502 if (posDot != NULL) 1503 len = posDot - hostname; 1504 else 1505 len = strlen(hostname); 1506 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1507 options[DHO_HOST_NAME]->value = hostname; 1508 options[DHO_HOST_NAME]->len = len; 1509 options[DHO_HOST_NAME]->buf_size = len; 1510 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1511 } 1512 } 1513 1514 /* set unique client identifier */ 1515 char client_ident[sizeof(struct hardware)]; 1516 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1517 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1518 ip->hw_address.hlen : sizeof(client_ident)-1; 1519 client_ident[0] = ip->hw_address.htype; 1520 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1521 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1522 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1523 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1524 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1525 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1526 } 1527 1528 /* Set up the option buffer... */ 1529 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1530 options, 0, 0, 0, NULL, 0); 1531 if (ip->client->packet_length < BOOTP_MIN_LEN) 1532 ip->client->packet_length = BOOTP_MIN_LEN; 1533 1534 ip->client->packet.op = BOOTREQUEST; 1535 ip->client->packet.htype = ip->hw_address.htype; 1536 ip->client->packet.hlen = ip->hw_address.hlen; 1537 ip->client->packet.hops = 0; 1538 ip->client->packet.xid = arc4random(); 1539 ip->client->packet.secs = 0; /* filled in by send_discover. */ 1540 ip->client->packet.flags = 0; 1541 1542 memset(&(ip->client->packet.ciaddr), 1543 0, sizeof(ip->client->packet.ciaddr)); 1544 memset(&(ip->client->packet.yiaddr), 1545 0, sizeof(ip->client->packet.yiaddr)); 1546 memset(&(ip->client->packet.siaddr), 1547 0, sizeof(ip->client->packet.siaddr)); 1548 memset(&(ip->client->packet.giaddr), 1549 0, sizeof(ip->client->packet.giaddr)); 1550 memcpy(ip->client->packet.chaddr, 1551 ip->hw_address.haddr, ip->hw_address.hlen); 1552 } 1553 1554 1555 void 1556 make_request(struct interface_info *ip, struct client_lease * lease) 1557 { 1558 unsigned char request = DHCPREQUEST; 1559 struct tree_cache *options[256]; 1560 struct tree_cache option_elements[256]; 1561 int i; 1562 1563 memset(options, 0, sizeof(options)); 1564 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1565 1566 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ 1567 i = DHO_DHCP_MESSAGE_TYPE; 1568 options[i] = &option_elements[i]; 1569 options[i]->value = &request; 1570 options[i]->len = sizeof(request); 1571 options[i]->buf_size = sizeof(request); 1572 options[i]->timeout = 0xFFFFFFFF; 1573 1574 /* Request the options we want */ 1575 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1576 options[i] = &option_elements[i]; 1577 options[i]->value = ip->client->config->requested_options; 1578 options[i]->len = ip->client->config->requested_option_count; 1579 options[i]->buf_size = 1580 ip->client->config->requested_option_count; 1581 options[i]->timeout = 0xFFFFFFFF; 1582 1583 /* If we are requesting an address that hasn't yet been assigned 1584 to us, use the DHCP Requested Address option. */ 1585 if (ip->client->state == S_REQUESTING) { 1586 /* Send back the server identifier... */ 1587 i = DHO_DHCP_SERVER_IDENTIFIER; 1588 options[i] = &option_elements[i]; 1589 options[i]->value = lease->options[i].data; 1590 options[i]->len = lease->options[i].len; 1591 options[i]->buf_size = lease->options[i].len; 1592 options[i]->timeout = 0xFFFFFFFF; 1593 } 1594 if (ip->client->state == S_REQUESTING || 1595 ip->client->state == S_REBOOTING) { 1596 ip->client->requested_address = lease->address; 1597 i = DHO_DHCP_REQUESTED_ADDRESS; 1598 options[i] = &option_elements[i]; 1599 options[i]->value = lease->address.iabuf; 1600 options[i]->len = lease->address.len; 1601 options[i]->buf_size = lease->address.len; 1602 options[i]->timeout = 0xFFFFFFFF; 1603 } else 1604 ip->client->requested_address.len = 0; 1605 1606 /* Send any options requested in the config file. */ 1607 for (i = 0; i < 256; i++) 1608 if (!options[i] && 1609 ip->client->config->send_options[i].data) { 1610 options[i] = &option_elements[i]; 1611 options[i]->value = 1612 ip->client->config->send_options[i].data; 1613 options[i]->len = 1614 ip->client->config->send_options[i].len; 1615 options[i]->buf_size = 1616 ip->client->config->send_options[i].len; 1617 options[i]->timeout = 0xFFFFFFFF; 1618 } 1619 1620 /* send host name if not set via config file. */ 1621 char hostname[_POSIX_HOST_NAME_MAX+1]; 1622 if (!options[DHO_HOST_NAME]) { 1623 if (gethostname(hostname, sizeof(hostname)) == 0) { 1624 size_t len; 1625 char* posDot = strchr(hostname, '.'); 1626 if (posDot != NULL) 1627 len = posDot - hostname; 1628 else 1629 len = strlen(hostname); 1630 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1631 options[DHO_HOST_NAME]->value = hostname; 1632 options[DHO_HOST_NAME]->len = len; 1633 options[DHO_HOST_NAME]->buf_size = len; 1634 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1635 } 1636 } 1637 1638 /* set unique client identifier */ 1639 char client_ident[sizeof(struct hardware)]; 1640 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1641 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1642 ip->hw_address.hlen : sizeof(client_ident)-1; 1643 client_ident[0] = ip->hw_address.htype; 1644 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1645 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1646 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1647 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1648 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1649 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1650 } 1651 1652 /* Set up the option buffer... */ 1653 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1654 options, 0, 0, 0, NULL, 0); 1655 if (ip->client->packet_length < BOOTP_MIN_LEN) 1656 ip->client->packet_length = BOOTP_MIN_LEN; 1657 1658 ip->client->packet.op = BOOTREQUEST; 1659 ip->client->packet.htype = ip->hw_address.htype; 1660 ip->client->packet.hlen = ip->hw_address.hlen; 1661 ip->client->packet.hops = 0; 1662 ip->client->packet.xid = ip->client->xid; 1663 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1664 1665 /* If we own the address we're requesting, put it in ciaddr; 1666 otherwise set ciaddr to zero. */ 1667 if (ip->client->state == S_BOUND || 1668 ip->client->state == S_RENEWING || 1669 ip->client->state == S_REBINDING) { 1670 memcpy(&ip->client->packet.ciaddr, 1671 lease->address.iabuf, lease->address.len); 1672 ip->client->packet.flags = 0; 1673 } else { 1674 memset(&ip->client->packet.ciaddr, 0, 1675 sizeof(ip->client->packet.ciaddr)); 1676 ip->client->packet.flags = 0; 1677 } 1678 1679 memset(&ip->client->packet.yiaddr, 0, 1680 sizeof(ip->client->packet.yiaddr)); 1681 memset(&ip->client->packet.siaddr, 0, 1682 sizeof(ip->client->packet.siaddr)); 1683 memset(&ip->client->packet.giaddr, 0, 1684 sizeof(ip->client->packet.giaddr)); 1685 memcpy(ip->client->packet.chaddr, 1686 ip->hw_address.haddr, ip->hw_address.hlen); 1687 } 1688 1689 void 1690 make_decline(struct interface_info *ip, struct client_lease *lease) 1691 { 1692 struct tree_cache *options[256], message_type_tree; 1693 struct tree_cache requested_address_tree; 1694 struct tree_cache server_id_tree, client_id_tree; 1695 unsigned char decline = DHCPDECLINE; 1696 int i; 1697 1698 memset(options, 0, sizeof(options)); 1699 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1700 1701 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ 1702 i = DHO_DHCP_MESSAGE_TYPE; 1703 options[i] = &message_type_tree; 1704 options[i]->value = &decline; 1705 options[i]->len = sizeof(decline); 1706 options[i]->buf_size = sizeof(decline); 1707 options[i]->timeout = 0xFFFFFFFF; 1708 1709 /* Send back the server identifier... */ 1710 i = DHO_DHCP_SERVER_IDENTIFIER; 1711 options[i] = &server_id_tree; 1712 options[i]->value = lease->options[i].data; 1713 options[i]->len = lease->options[i].len; 1714 options[i]->buf_size = lease->options[i].len; 1715 options[i]->timeout = 0xFFFFFFFF; 1716 1717 /* Send back the address we're declining. */ 1718 i = DHO_DHCP_REQUESTED_ADDRESS; 1719 options[i] = &requested_address_tree; 1720 options[i]->value = lease->address.iabuf; 1721 options[i]->len = lease->address.len; 1722 options[i]->buf_size = lease->address.len; 1723 options[i]->timeout = 0xFFFFFFFF; 1724 1725 /* Send the uid if the user supplied one. */ 1726 i = DHO_DHCP_CLIENT_IDENTIFIER; 1727 if (ip->client->config->send_options[i].len) { 1728 options[i] = &client_id_tree; 1729 options[i]->value = ip->client->config->send_options[i].data; 1730 options[i]->len = ip->client->config->send_options[i].len; 1731 options[i]->buf_size = ip->client->config->send_options[i].len; 1732 options[i]->timeout = 0xFFFFFFFF; 1733 } 1734 1735 1736 /* Set up the option buffer... */ 1737 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1738 options, 0, 0, 0, NULL, 0); 1739 if (ip->client->packet_length < BOOTP_MIN_LEN) 1740 ip->client->packet_length = BOOTP_MIN_LEN; 1741 1742 ip->client->packet.op = BOOTREQUEST; 1743 ip->client->packet.htype = ip->hw_address.htype; 1744 ip->client->packet.hlen = ip->hw_address.hlen; 1745 ip->client->packet.hops = 0; 1746 ip->client->packet.xid = ip->client->xid; 1747 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1748 ip->client->packet.flags = 0; 1749 1750 /* ciaddr must always be zero. */ 1751 memset(&ip->client->packet.ciaddr, 0, 1752 sizeof(ip->client->packet.ciaddr)); 1753 memset(&ip->client->packet.yiaddr, 0, 1754 sizeof(ip->client->packet.yiaddr)); 1755 memset(&ip->client->packet.siaddr, 0, 1756 sizeof(ip->client->packet.siaddr)); 1757 memset(&ip->client->packet.giaddr, 0, 1758 sizeof(ip->client->packet.giaddr)); 1759 memcpy(ip->client->packet.chaddr, 1760 ip->hw_address.haddr, ip->hw_address.hlen); 1761 } 1762 1763 void 1764 free_client_lease(struct client_lease *lease) 1765 { 1766 int i; 1767 1768 if (lease->server_name) 1769 free(lease->server_name); 1770 if (lease->filename) 1771 free(lease->filename); 1772 for (i = 0; i < 256; i++) { 1773 if (lease->options[i].len) 1774 free(lease->options[i].data); 1775 } 1776 free(lease); 1777 } 1778 1779 FILE *leaseFile; 1780 1781 void 1782 rewrite_client_leases(void) 1783 { 1784 struct client_lease *lp; 1785 1786 if (!leaseFile) { 1787 leaseFile = fopen(path_dhclient_db, "w"); 1788 if (!leaseFile) 1789 error("can't create %s: %m", path_dhclient_db); 1790 } else { 1791 fflush(leaseFile); 1792 rewind(leaseFile); 1793 } 1794 1795 for (lp = ifi->client->leases; lp; lp = lp->next) 1796 write_client_lease(ifi, lp, 1); 1797 if (ifi->client->active) 1798 write_client_lease(ifi, ifi->client->active, 1); 1799 1800 fflush(leaseFile); 1801 ftruncate(fileno(leaseFile), ftello(leaseFile)); 1802 fsync(fileno(leaseFile)); 1803 } 1804 1805 void 1806 write_client_lease(struct interface_info *ip, struct client_lease *lease, 1807 int rewrite) 1808 { 1809 static int leases_written; 1810 struct tm *t; 1811 int i; 1812 1813 if (!rewrite) { 1814 if (leases_written++ > 20) { 1815 rewrite_client_leases(); 1816 leases_written = 0; 1817 } 1818 } 1819 1820 /* If the lease came from the config file, we don't need to stash 1821 a copy in the lease database. */ 1822 if (lease->is_static) 1823 return; 1824 1825 if (!leaseFile) { /* XXX */ 1826 leaseFile = fopen(path_dhclient_db, "w"); 1827 if (!leaseFile) 1828 error("can't create %s: %m", path_dhclient_db); 1829 } 1830 1831 fprintf(leaseFile, "lease {\n"); 1832 if (lease->is_bootp) 1833 fprintf(leaseFile, " bootp;\n"); 1834 fprintf(leaseFile, " interface \"%s\";\n", ip->name); 1835 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address)); 1836 if (lease->filename) 1837 fprintf(leaseFile, " filename \"%s\";\n", lease->filename); 1838 if (lease->server_name) 1839 fprintf(leaseFile, " server-name \"%s\";\n", 1840 lease->server_name); 1841 if (lease->medium) 1842 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string); 1843 for (i = 0; i < 256; i++) 1844 if (lease->options[i].len) 1845 fprintf(leaseFile, " option %s %s;\n", 1846 dhcp_options[i].name, 1847 pretty_print_option(i, lease->options[i].data, 1848 lease->options[i].len, 1, 1)); 1849 1850 t = gmtime(&lease->renewal); 1851 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", 1852 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1853 t->tm_hour, t->tm_min, t->tm_sec); 1854 t = gmtime(&lease->rebind); 1855 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n", 1856 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1857 t->tm_hour, t->tm_min, t->tm_sec); 1858 t = gmtime(&lease->expiry); 1859 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", 1860 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1861 t->tm_hour, t->tm_min, t->tm_sec); 1862 fprintf(leaseFile, "}\n"); 1863 fflush(leaseFile); 1864 } 1865 1866 void 1867 script_init(char *reason, struct string_list *medium) 1868 { 1869 size_t len, mediumlen = 0; 1870 struct imsg_hdr hdr; 1871 struct buf *buf; 1872 int errs; 1873 1874 if (medium != NULL && medium->string != NULL) 1875 mediumlen = strlen(medium->string); 1876 1877 hdr.code = IMSG_SCRIPT_INIT; 1878 hdr.len = sizeof(struct imsg_hdr) + 1879 sizeof(size_t) + mediumlen + 1880 sizeof(size_t) + strlen(reason); 1881 1882 if ((buf = buf_open(hdr.len)) == NULL) 1883 error("buf_open: %m"); 1884 1885 errs = 0; 1886 errs += buf_add(buf, &hdr, sizeof(hdr)); 1887 errs += buf_add(buf, &mediumlen, sizeof(mediumlen)); 1888 if (mediumlen > 0) 1889 errs += buf_add(buf, medium->string, mediumlen); 1890 len = strlen(reason); 1891 errs += buf_add(buf, &len, sizeof(len)); 1892 errs += buf_add(buf, reason, len); 1893 1894 if (errs) 1895 error("buf_add: %m"); 1896 1897 if (buf_close(privfd, buf) == -1) 1898 error("buf_close: %m"); 1899 } 1900 1901 void 1902 priv_script_init(char *reason, char *medium) 1903 { 1904 struct interface_info *ip = ifi; 1905 1906 if (ip) { 1907 ip->client->scriptEnvsize = 100; 1908 if (ip->client->scriptEnv == NULL) 1909 ip->client->scriptEnv = 1910 malloc(ip->client->scriptEnvsize * sizeof(char *)); 1911 if (ip->client->scriptEnv == NULL) 1912 error("script_init: no memory for environment"); 1913 1914 ip->client->scriptEnv[0] = strdup(CLIENT_PATH); 1915 if (ip->client->scriptEnv[0] == NULL) 1916 error("script_init: no memory for environment"); 1917 1918 ip->client->scriptEnv[1] = NULL; 1919 1920 script_set_env(ip->client, "", "interface", ip->name); 1921 1922 if (medium) 1923 script_set_env(ip->client, "", "medium", medium); 1924 1925 script_set_env(ip->client, "", "reason", reason); 1926 } 1927 } 1928 1929 void 1930 priv_script_write_params(char *prefix, struct client_lease *lease) 1931 { 1932 struct interface_info *ip = ifi; 1933 u_int8_t dbuf[1500], *dp = NULL; 1934 int i, len; 1935 char tbuf[128]; 1936 1937 script_set_env(ip->client, prefix, "ip_address", 1938 piaddr(lease->address)); 1939 1940 if (ip->client->config->default_actions[DHO_SUBNET_MASK] == 1941 ACTION_SUPERSEDE) { 1942 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data; 1943 len = ip->client->config->defaults[DHO_SUBNET_MASK].len; 1944 } else { 1945 dp = lease->options[DHO_SUBNET_MASK].data; 1946 len = lease->options[DHO_SUBNET_MASK].len; 1947 } 1948 if (len && (len < sizeof(lease->address.iabuf))) { 1949 struct iaddr netmask, subnet, broadcast; 1950 1951 memcpy(netmask.iabuf, dp, len); 1952 netmask.len = len; 1953 subnet = subnet_number(lease->address, netmask); 1954 if (subnet.len) { 1955 script_set_env(ip->client, prefix, "network_number", 1956 piaddr(subnet)); 1957 if (!lease->options[DHO_BROADCAST_ADDRESS].len) { 1958 broadcast = broadcast_addr(subnet, netmask); 1959 if (broadcast.len) 1960 script_set_env(ip->client, prefix, 1961 "broadcast_address", 1962 piaddr(broadcast)); 1963 } 1964 } 1965 } 1966 1967 if (lease->filename) 1968 script_set_env(ip->client, prefix, "filename", lease->filename); 1969 if (lease->server_name) 1970 script_set_env(ip->client, prefix, "server_name", 1971 lease->server_name); 1972 for (i = 0; i < 256; i++) { 1973 len = 0; 1974 1975 if (ip->client->config->defaults[i].len) { 1976 if (lease->options[i].len) { 1977 switch ( 1978 ip->client->config->default_actions[i]) { 1979 case ACTION_DEFAULT: 1980 dp = lease->options[i].data; 1981 len = lease->options[i].len; 1982 break; 1983 case ACTION_SUPERSEDE: 1984 supersede: 1985 dp = ip->client-> 1986 config->defaults[i].data; 1987 len = ip->client-> 1988 config->defaults[i].len; 1989 break; 1990 case ACTION_PREPEND: 1991 len = ip->client-> 1992 config->defaults[i].len + 1993 lease->options[i].len; 1994 if (len >= sizeof(dbuf)) { 1995 warning("no space to %s %s", 1996 "prepend option", 1997 dhcp_options[i].name); 1998 goto supersede; 1999 } 2000 dp = dbuf; 2001 memcpy(dp, 2002 ip->client-> 2003 config->defaults[i].data, 2004 ip->client-> 2005 config->defaults[i].len); 2006 memcpy(dp + ip->client-> 2007 config->defaults[i].len, 2008 lease->options[i].data, 2009 lease->options[i].len); 2010 dp[len] = '\0'; 2011 break; 2012 case ACTION_APPEND: 2013 /* 2014 * When we append, we assume that we're 2015 * appending to text. Some MS servers 2016 * include a NUL byte at the end of 2017 * the search string provided. 2018 */ 2019 len = ip->client-> 2020 config->defaults[i].len + 2021 lease->options[i].len; 2022 if (len >= sizeof(dbuf)) { 2023 warning("no space to %s %s", 2024 "append option", 2025 dhcp_options[i].name); 2026 goto supersede; 2027 } 2028 memcpy(dbuf, 2029 lease->options[i].data, 2030 lease->options[i].len); 2031 for (dp = dbuf + lease->options[i].len; 2032 dp > dbuf; dp--, len--) 2033 if (dp[-1] != '\0') 2034 break; 2035 memcpy(dp, 2036 ip->client-> 2037 config->defaults[i].data, 2038 ip->client-> 2039 config->defaults[i].len); 2040 dp = dbuf; 2041 dp[len] = '\0'; 2042 } 2043 } else { 2044 dp = ip->client-> 2045 config->defaults[i].data; 2046 len = ip->client-> 2047 config->defaults[i].len; 2048 } 2049 } else if (lease->options[i].len) { 2050 len = lease->options[i].len; 2051 dp = lease->options[i].data; 2052 } else { 2053 len = 0; 2054 } 2055 if (len) { 2056 char name[256]; 2057 2058 if (dhcp_option_ev_name(name, sizeof(name), 2059 &dhcp_options[i])) 2060 script_set_env(ip->client, prefix, name, 2061 pretty_print_option(i, dp, len, 0, 0)); 2062 } 2063 } 2064 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); 2065 script_set_env(ip->client, prefix, "expiry", tbuf); 2066 } 2067 2068 void 2069 script_write_params(char *prefix, struct client_lease *lease) 2070 { 2071 size_t fn_len = 0, sn_len = 0, pr_len = 0; 2072 struct imsg_hdr hdr; 2073 struct buf *buf; 2074 int errs, i; 2075 2076 if (lease->filename != NULL) 2077 fn_len = strlen(lease->filename); 2078 if (lease->server_name != NULL) 2079 sn_len = strlen(lease->server_name); 2080 if (prefix != NULL) 2081 pr_len = strlen(prefix); 2082 2083 hdr.code = IMSG_SCRIPT_WRITE_PARAMS; 2084 hdr.len = sizeof(hdr) + sizeof(struct client_lease) + 2085 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len + 2086 sizeof(size_t) + pr_len; 2087 2088 for (i = 0; i < 256; i++) 2089 hdr.len += sizeof(int) + lease->options[i].len; 2090 2091 scripttime = time(NULL); 2092 2093 if ((buf = buf_open(hdr.len)) == NULL) 2094 error("buf_open: %m"); 2095 2096 errs = 0; 2097 errs += buf_add(buf, &hdr, sizeof(hdr)); 2098 errs += buf_add(buf, lease, sizeof(struct client_lease)); 2099 errs += buf_add(buf, &fn_len, sizeof(fn_len)); 2100 errs += buf_add(buf, lease->filename, fn_len); 2101 errs += buf_add(buf, &sn_len, sizeof(sn_len)); 2102 errs += buf_add(buf, lease->server_name, sn_len); 2103 errs += buf_add(buf, &pr_len, sizeof(pr_len)); 2104 errs += buf_add(buf, prefix, pr_len); 2105 2106 for (i = 0; i < 256; i++) { 2107 errs += buf_add(buf, &lease->options[i].len, 2108 sizeof(lease->options[i].len)); 2109 errs += buf_add(buf, lease->options[i].data, 2110 lease->options[i].len); 2111 } 2112 2113 if (errs) 2114 error("buf_add: %m"); 2115 2116 if (buf_close(privfd, buf) == -1) 2117 error("buf_close: %m"); 2118 } 2119 2120 int 2121 script_go(void) 2122 { 2123 struct imsg_hdr hdr; 2124 struct buf *buf; 2125 int ret; 2126 2127 hdr.code = IMSG_SCRIPT_GO; 2128 hdr.len = sizeof(struct imsg_hdr); 2129 2130 if ((buf = buf_open(hdr.len)) == NULL) 2131 error("buf_open: %m"); 2132 2133 if (buf_add(buf, &hdr, sizeof(hdr))) 2134 error("buf_add: %m"); 2135 2136 if (buf_close(privfd, buf) == -1) 2137 error("buf_close: %m"); 2138 2139 bzero(&hdr, sizeof(hdr)); 2140 buf_read(privfd, &hdr, sizeof(hdr)); 2141 if (hdr.code != IMSG_SCRIPT_GO_RET) 2142 error("unexpected msg type %u", hdr.code); 2143 if (hdr.len != sizeof(hdr) + sizeof(int)) 2144 error("received corrupted message"); 2145 buf_read(privfd, &ret, sizeof(ret)); 2146 2147 scripttime = time(NULL); 2148 2149 return (ret); 2150 } 2151 2152 int 2153 priv_script_go(void) 2154 { 2155 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI"; 2156 static char client_path[] = CLIENT_PATH; 2157 struct interface_info *ip = ifi; 2158 int pid, wpid, wstatus; 2159 2160 scripttime = time(NULL); 2161 2162 if (ip) { 2163 scriptName = ip->client->config->script_name; 2164 envp = ip->client->scriptEnv; 2165 } else { 2166 scriptName = top_level_config.script_name; 2167 epp[0] = reason; 2168 epp[1] = client_path; 2169 epp[2] = NULL; 2170 envp = epp; 2171 } 2172 2173 argv[0] = scriptName; 2174 argv[1] = NULL; 2175 2176 pid = fork(); 2177 if (pid < 0) { 2178 error("fork: %m"); 2179 wstatus = 0; 2180 } else if (pid) { 2181 do { 2182 wpid = wait(&wstatus); 2183 } while (wpid != pid && wpid > 0); 2184 if (wpid < 0) { 2185 error("wait: %m"); 2186 wstatus = 0; 2187 } 2188 } else { 2189 execve(scriptName, argv, envp); 2190 error("execve (%s, ...): %m", scriptName); 2191 } 2192 2193 if (ip) 2194 script_flush_env(ip->client); 2195 2196 return (wstatus & 0xff); 2197 } 2198 2199 void 2200 script_set_env(struct client_state *client, const char *prefix, 2201 const char *name, const char *value) 2202 { 2203 int i, j, namelen; 2204 2205 namelen = strlen(name); 2206 2207 for (i = 0; client->scriptEnv[i]; i++) 2208 if (strncmp(client->scriptEnv[i], name, namelen) == 0 && 2209 client->scriptEnv[i][namelen] == '=') 2210 break; 2211 2212 if (client->scriptEnv[i]) 2213 /* Reuse the slot. */ 2214 free(client->scriptEnv[i]); 2215 else { 2216 /* New variable. Expand if necessary. */ 2217 if (i >= client->scriptEnvsize - 1) { 2218 char **newscriptEnv; 2219 int newscriptEnvsize = client->scriptEnvsize + 50; 2220 2221 newscriptEnv = realloc(client->scriptEnv, 2222 newscriptEnvsize); 2223 if (newscriptEnv == NULL) { 2224 free(client->scriptEnv); 2225 client->scriptEnv = NULL; 2226 client->scriptEnvsize = 0; 2227 error("script_set_env: no memory for variable"); 2228 } 2229 client->scriptEnv = newscriptEnv; 2230 client->scriptEnvsize = newscriptEnvsize; 2231 } 2232 /* need to set the NULL pointer at end of array beyond 2233 the new slot. */ 2234 client->scriptEnv[i + 1] = NULL; 2235 } 2236 /* Allocate space and format the variable in the appropriate slot. */ 2237 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 + 2238 strlen(value) + 1); 2239 if (client->scriptEnv[i] == NULL) 2240 error("script_set_env: no memory for variable assignment"); 2241 2242 /* No `` or $() command substitution allowed in environment values! */ 2243 for (j=0; j < strlen(value); j++) 2244 switch (value[j]) { 2245 case '`': 2246 case '$': 2247 error("illegal character (%c) in value '%s'", value[j], 2248 value); 2249 /* not reached */ 2250 } 2251 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + 2252 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); 2253 } 2254 2255 void 2256 script_flush_env(struct client_state *client) 2257 { 2258 int i; 2259 2260 for (i = 0; client->scriptEnv[i]; i++) { 2261 free(client->scriptEnv[i]); 2262 client->scriptEnv[i] = NULL; 2263 } 2264 client->scriptEnvsize = 0; 2265 } 2266 2267 int 2268 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option) 2269 { 2270 int i; 2271 2272 for (i = 0; option->name[i]; i++) { 2273 if (i + 1 == buflen) 2274 return 0; 2275 if (option->name[i] == '-') 2276 buf[i] = '_'; 2277 else 2278 buf[i] = option->name[i]; 2279 } 2280 2281 buf[i] = 0; 2282 return 1; 2283 } 2284 2285 void 2286 go_daemon(void) 2287 { 2288 static int state = 0; 2289 2290 if (no_daemon || state) 2291 return; 2292 2293 state = 1; 2294 2295 /* Stop logging to stderr... */ 2296 log_perror = 0; 2297 2298 if (daemon(1, 0) == -1) 2299 error("daemon"); 2300 2301 /* we are chrooted, daemon(3) fails to open /dev/null */ 2302 if (nullfd != -1) { 2303 dup2(nullfd, STDIN_FILENO); 2304 dup2(nullfd, STDOUT_FILENO); 2305 dup2(nullfd, STDERR_FILENO); 2306 close(nullfd); 2307 nullfd = -1; 2308 } 2309 } 2310 2311 int 2312 check_option(struct client_lease *l, int option) 2313 { 2314 char *opbuf; 2315 char *sbuf; 2316 2317 /* we use this, since this is what gets passed to dhclient-script */ 2318 2319 opbuf = pretty_print_option(option, l->options[option].data, 2320 l->options[option].len, 0, 0); 2321 2322 sbuf = option_as_string(option, l->options[option].data, 2323 l->options[option].len); 2324 2325 switch (option) { 2326 case DHO_SUBNET_MASK: 2327 case DHO_TIME_SERVERS: 2328 case DHO_NAME_SERVERS: 2329 case DHO_ROUTERS: 2330 case DHO_DOMAIN_NAME_SERVERS: 2331 case DHO_LOG_SERVERS: 2332 case DHO_COOKIE_SERVERS: 2333 case DHO_LPR_SERVERS: 2334 case DHO_IMPRESS_SERVERS: 2335 case DHO_RESOURCE_LOCATION_SERVERS: 2336 case DHO_SWAP_SERVER: 2337 case DHO_BROADCAST_ADDRESS: 2338 case DHO_NIS_SERVERS: 2339 case DHO_NTP_SERVERS: 2340 case DHO_NETBIOS_NAME_SERVERS: 2341 case DHO_NETBIOS_DD_SERVER: 2342 case DHO_FONT_SERVERS: 2343 case DHO_DHCP_SERVER_IDENTIFIER: 2344 case DHO_NISPLUS_SERVERS: 2345 case DHO_MOBILE_IP_HOME_AGENT: 2346 case DHO_SMTP_SERVER: 2347 case DHO_POP_SERVER: 2348 case DHO_NNTP_SERVER: 2349 case DHO_WWW_SERVER: 2350 case DHO_FINGER_SERVER: 2351 case DHO_IRC_SERVER: 2352 case DHO_STREETTALK_SERVER: 2353 case DHO_STREETTALK_DA_SERVER: 2354 if (!ipv4addrs(opbuf)) { 2355 warning("Invalid IP address in option: %s", opbuf); 2356 return (0); 2357 } 2358 return (1) ; 2359 case DHO_HOST_NAME: 2360 case DHO_NIS_DOMAIN: 2361 case DHO_NISPLUS_DOMAIN: 2362 case DHO_TFTP_SERVER_NAME: 2363 if (!res_hnok(sbuf)) { 2364 warning("Bogus Host Name option %d: %s (%s)", option, 2365 sbuf, opbuf); 2366 l->options[option].len = 0; 2367 free(l->options[option].data); 2368 } 2369 return (1); 2370 case DHO_DOMAIN_NAME: 2371 if (!res_hnok(sbuf)) { 2372 if (!check_search(sbuf)) { 2373 warning("Bogus domain search list %d: %s (%s)", 2374 option, sbuf, opbuf); 2375 l->options[option].len = 0; 2376 free(l->options[option].data); 2377 } 2378 } 2379 return (1); 2380 case DHO_PAD: 2381 case DHO_TIME_OFFSET: 2382 case DHO_BOOT_SIZE: 2383 case DHO_MERIT_DUMP: 2384 case DHO_ROOT_PATH: 2385 case DHO_EXTENSIONS_PATH: 2386 case DHO_IP_FORWARDING: 2387 case DHO_NON_LOCAL_SOURCE_ROUTING: 2388 case DHO_POLICY_FILTER: 2389 case DHO_MAX_DGRAM_REASSEMBLY: 2390 case DHO_DEFAULT_IP_TTL: 2391 case DHO_PATH_MTU_AGING_TIMEOUT: 2392 case DHO_PATH_MTU_PLATEAU_TABLE: 2393 case DHO_INTERFACE_MTU: 2394 case DHO_ALL_SUBNETS_LOCAL: 2395 case DHO_PERFORM_MASK_DISCOVERY: 2396 case DHO_MASK_SUPPLIER: 2397 case DHO_ROUTER_DISCOVERY: 2398 case DHO_ROUTER_SOLICITATION_ADDRESS: 2399 case DHO_STATIC_ROUTES: 2400 case DHO_TRAILER_ENCAPSULATION: 2401 case DHO_ARP_CACHE_TIMEOUT: 2402 case DHO_IEEE802_3_ENCAPSULATION: 2403 case DHO_DEFAULT_TCP_TTL: 2404 case DHO_TCP_KEEPALIVE_INTERVAL: 2405 case DHO_TCP_KEEPALIVE_GARBAGE: 2406 case DHO_VENDOR_ENCAPSULATED_OPTIONS: 2407 case DHO_NETBIOS_NODE_TYPE: 2408 case DHO_NETBIOS_SCOPE: 2409 case DHO_X_DISPLAY_MANAGER: 2410 case DHO_DHCP_REQUESTED_ADDRESS: 2411 case DHO_DHCP_LEASE_TIME: 2412 case DHO_DHCP_OPTION_OVERLOAD: 2413 case DHO_DHCP_MESSAGE_TYPE: 2414 case DHO_DHCP_PARAMETER_REQUEST_LIST: 2415 case DHO_DHCP_MESSAGE: 2416 case DHO_DHCP_MAX_MESSAGE_SIZE: 2417 case DHO_DHCP_RENEWAL_TIME: 2418 case DHO_DHCP_REBINDING_TIME: 2419 case DHO_DHCP_CLASS_IDENTIFIER: 2420 case DHO_DHCP_CLIENT_IDENTIFIER: 2421 case DHO_BOOTFILE_NAME: 2422 case DHO_DHCP_USER_CLASS_ID: 2423 case DHO_END: 2424 return (1); 2425 case DHO_CLASSLESS_ROUTES: 2426 return (check_classless_option(l->options[option].data, 2427 l->options[option].len)); 2428 default: 2429 warning("unknown dhcp option value 0x%x", option); 2430 return (unknown_ok); 2431 } 2432 } 2433 2434 /* RFC 3442 The Classless Static Routes option checks */ 2435 int 2436 check_classless_option(unsigned char *data, int len) 2437 { 2438 int i = 0; 2439 unsigned char width; 2440 in_addr_t addr, mask; 2441 2442 if (len < 5) { 2443 warning("Too small length: %d", len); 2444 return (0); 2445 } 2446 while(i < len) { 2447 width = data[i++]; 2448 if (width == 0) { 2449 i += 4; 2450 continue; 2451 } else if (width < 9) { 2452 addr = (in_addr_t)(data[i] << 24); 2453 i += 1; 2454 } else if (width < 17) { 2455 addr = (in_addr_t)(data[i] << 24) + 2456 (in_addr_t)(data[i + 1] << 16); 2457 i += 2; 2458 } else if (width < 25) { 2459 addr = (in_addr_t)(data[i] << 24) + 2460 (in_addr_t)(data[i + 1] << 16) + 2461 (in_addr_t)(data[i + 2] << 8); 2462 i += 3; 2463 } else if (width < 33) { 2464 addr = (in_addr_t)(data[i] << 24) + 2465 (in_addr_t)(data[i + 1] << 16) + 2466 (in_addr_t)(data[i + 2] << 8) + 2467 data[i + 3]; 2468 i += 4; 2469 } else { 2470 warning("Incorrect subnet width: %d", width); 2471 return (0); 2472 } 2473 mask = (in_addr_t)(~0) << (32 - width); 2474 addr = ntohl(addr); 2475 mask = ntohl(mask); 2476 2477 /* 2478 * From RFC 3442: 2479 * ... After deriving a subnet number and subnet mask 2480 * from each destination descriptor, the DHCP client 2481 * MUST zero any bits in the subnet number where the 2482 * corresponding bit in the mask is zero... 2483 */ 2484 if ((addr & mask) != addr) { 2485 addr &= mask; 2486 data[i - 1] = (unsigned char)( 2487 (addr >> (((32 - width)/8)*8)) & 0xFF); 2488 } 2489 i += 4; 2490 } 2491 if (i > len) { 2492 warning("Incorrect data length: %d (must be %d)", len, i); 2493 return (0); 2494 } 2495 return (1); 2496 } 2497 2498 int 2499 res_hnok(const char *dn) 2500 { 2501 int pch = PERIOD, ch = *dn++; 2502 2503 while (ch != '\0') { 2504 int nch = *dn++; 2505 2506 if (periodchar(ch)) { 2507 ; 2508 } else if (periodchar(pch)) { 2509 if (!borderchar(ch)) 2510 return (0); 2511 } else if (periodchar(nch) || nch == '\0') { 2512 if (!borderchar(ch)) 2513 return (0); 2514 } else { 2515 if (!middlechar(ch)) 2516 return (0); 2517 } 2518 pch = ch, ch = nch; 2519 } 2520 return (1); 2521 } 2522 2523 int 2524 check_search(const char *srch) 2525 { 2526 int pch = PERIOD, ch = *srch++; 2527 int domains = 1; 2528 2529 /* 256 char limit re resolv.conf(5) */ 2530 if (strlen(srch) > 256) 2531 return (0); 2532 2533 while (whitechar(ch)) 2534 ch = *srch++; 2535 2536 while (ch != '\0') { 2537 int nch = *srch++; 2538 2539 if (periodchar(ch) || whitechar(ch)) { 2540 ; 2541 } else if (periodchar(pch)) { 2542 if (!borderchar(ch)) 2543 return (0); 2544 } else if (periodchar(nch) || nch == '\0') { 2545 if (!borderchar(ch)) 2546 return (0); 2547 } else { 2548 if (!middlechar(ch)) 2549 return (0); 2550 } 2551 if (!whitechar(ch)) { 2552 pch = ch; 2553 } else { 2554 while (whitechar(nch)) { 2555 nch = *srch++; 2556 } 2557 if (nch != '\0') 2558 domains++; 2559 pch = PERIOD; 2560 } 2561 ch = nch; 2562 } 2563 /* 6 domain limit re resolv.conf(5) */ 2564 if (domains > 6) 2565 return (0); 2566 return (1); 2567 } 2568 2569 /* Does buf consist only of dotted decimal ipv4 addrs? 2570 * return how many if so, 2571 * otherwise, return 0 2572 */ 2573 int 2574 ipv4addrs(char * buf) 2575 { 2576 struct in_addr jnk; 2577 int count = 0; 2578 2579 while (inet_aton(buf, &jnk) == 1){ 2580 count++; 2581 while (periodchar(*buf) || digitchar(*buf)) 2582 buf++; 2583 if (*buf == '\0') 2584 return (count); 2585 while (*buf == ' ') 2586 buf++; 2587 } 2588 return (0); 2589 } 2590 2591 2592 char * 2593 option_as_string(unsigned int code, unsigned char *data, int len) 2594 { 2595 static char optbuf[32768]; /* XXX */ 2596 char *op = optbuf; 2597 int opleft = sizeof(optbuf); 2598 unsigned char *dp = data; 2599 2600 if (code > 255) 2601 error("option_as_string: bad code %d", code); 2602 2603 for (; dp < data + len; dp++) { 2604 if (!isascii(*dp) || !isprint(*dp)) { 2605 if (dp + 1 != data + len || *dp != 0) { 2606 snprintf(op, opleft, "\\%03o", *dp); 2607 op += 4; 2608 opleft -= 4; 2609 } 2610 } else if (*dp == '"' || *dp == '\'' || *dp == '$' || 2611 *dp == '`' || *dp == '\\') { 2612 *op++ = '\\'; 2613 *op++ = *dp; 2614 opleft -= 2; 2615 } else { 2616 *op++ = *dp; 2617 opleft--; 2618 } 2619 } 2620 if (opleft < 1) 2621 goto toobig; 2622 *op = 0; 2623 return optbuf; 2624 toobig: 2625 warning("dhcp option too large"); 2626 return "<error>"; 2627 } 2628 2629 int 2630 fork_privchld(int fd, int fd2) 2631 { 2632 struct pollfd pfd[1]; 2633 int nfds; 2634 2635 switch (fork()) { 2636 case -1: 2637 error("cannot fork"); 2638 case 0: 2639 break; 2640 default: 2641 return (0); 2642 } 2643 2644 setproctitle("%s [priv]", ifi->name); 2645 2646 setsid(); 2647 dup2(nullfd, STDIN_FILENO); 2648 dup2(nullfd, STDOUT_FILENO); 2649 dup2(nullfd, STDERR_FILENO); 2650 close(nullfd); 2651 close(fd2); 2652 2653 for (;;) { 2654 pfd[0].fd = fd; 2655 pfd[0].events = POLLIN; 2656 if ((nfds = poll(pfd, 1, INFTIM)) == -1) 2657 if (errno != EINTR) 2658 error("poll error"); 2659 2660 if (nfds == 0 || !(pfd[0].revents & POLLIN)) 2661 continue; 2662 2663 dispatch_imsg(fd); 2664 } 2665 } 2666