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