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