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->new->options[DHO_DHCP_LEASE_TIME].data) 760 ip->client->new->expiry = getULong( 761 ip->client->new->options[DHO_DHCP_LEASE_TIME].data); 762 else 763 ip->client->new->expiry = default_lease_time; 764 /* A number that looks negative here is really just very large, 765 because the lease expiry offset is unsigned. */ 766 if (ip->client->new->expiry < 0) 767 ip->client->new->expiry = TIME_MAX; 768 /* XXX should be fixed by resetting the client state */ 769 if (ip->client->new->expiry < 60) 770 ip->client->new->expiry = 60; 771 772 /* Unless overridden in the config, take the server-provided renewal 773 * time if there is one; otherwise figure it out according to the spec. 774 * Also make sure the renewal time does not exceed the expiry time. 775 */ 776 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] == 777 ACTION_SUPERSEDE) 778 ip->client->new->renewal = getULong( 779 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data); 780 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len) 781 ip->client->new->renewal = getULong( 782 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data); 783 else 784 ip->client->new->renewal = ip->client->new->expiry / 2; 785 if (ip->client->new->renewal > ip->client->new->expiry / 2) 786 ip->client->new->renewal = ip->client->new->expiry / 2; 787 788 /* Same deal with the rebind time. */ 789 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] == 790 ACTION_SUPERSEDE) 791 ip->client->new->rebind = getULong( 792 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data); 793 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len) 794 ip->client->new->rebind = getULong( 795 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data); 796 else 797 ip->client->new->rebind = ip->client->new->renewal * 7 / 4; 798 if (ip->client->new->rebind > ip->client->new->renewal * 7 / 4) 799 ip->client->new->rebind = ip->client->new->renewal * 7 / 4; 800 801 ip->client->new->expiry += cur_time; 802 /* Lease lengths can never be negative. */ 803 if (ip->client->new->expiry < cur_time) 804 ip->client->new->expiry = TIME_MAX; 805 ip->client->new->renewal += cur_time; 806 if (ip->client->new->renewal < cur_time) 807 ip->client->new->renewal = TIME_MAX; 808 ip->client->new->rebind += cur_time; 809 if (ip->client->new->rebind < cur_time) 810 ip->client->new->rebind = TIME_MAX; 811 812 bind_lease(ip); 813 } 814 815 void 816 bind_lease(struct interface_info *ip) 817 { 818 struct option_data *opt; 819 820 /* Remember the medium. */ 821 ip->client->new->medium = ip->client->medium; 822 823 opt = &ip->client->new->options[DHO_INTERFACE_MTU]; 824 if (opt->len == sizeof(u_int16_t)) { 825 u_int16_t mtu = be16dec(opt->data); 826 if (mtu < MIN_MTU) 827 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU); 828 else 829 interface_set_mtu_unpriv(privfd, mtu); 830 } 831 832 /* Write out the new lease. */ 833 write_client_lease(ip, ip->client->new, 0); 834 835 /* Run the client script with the new parameters. */ 836 script_init((ip->client->state == S_REQUESTING ? "BOUND" : 837 (ip->client->state == S_RENEWING ? "RENEW" : 838 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))), 839 ip->client->new->medium); 840 if (ip->client->active && ip->client->state != S_REBOOTING) 841 script_write_params("old_", ip->client->active); 842 script_write_params("new_", ip->client->new); 843 if (ip->client->alias) 844 script_write_params("alias_", ip->client->alias); 845 script_go(); 846 847 /* Replace the old active lease with the new one. */ 848 if (ip->client->active) 849 free_client_lease(ip->client->active); 850 ip->client->active = ip->client->new; 851 ip->client->new = NULL; 852 853 /* Set up a timeout to start the renewal process. */ 854 add_timeout(ip->client->active->renewal, state_bound, ip); 855 856 note("bound to %s -- renewal in %d seconds.", 857 piaddr(ip->client->active->address), 858 (int)(ip->client->active->renewal - cur_time)); 859 ip->client->state = S_BOUND; 860 reinitialize_interfaces(); 861 go_daemon(); 862 } 863 864 /* 865 * state_bound is called when we've successfully bound to a particular 866 * lease, but the renewal time on that lease has expired. We are 867 * expected to unicast a DHCPREQUEST to the server that gave us our 868 * original lease. 869 */ 870 void 871 state_bound(void *ipp) 872 { 873 struct interface_info *ip = ipp; 874 875 ASSERT_STATE(state, S_BOUND); 876 877 /* T1 has expired. */ 878 make_request(ip, ip->client->active); 879 ip->client->xid = ip->client->packet.xid; 880 881 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) { 882 memcpy(ip->client->destination.iabuf, ip->client->active-> 883 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4); 884 ip->client->destination.len = 4; 885 } else 886 ip->client->destination = iaddr_broadcast; 887 888 ip->client->first_sending = cur_time; 889 ip->client->interval = ip->client->config->initial_interval; 890 ip->client->state = S_RENEWING; 891 892 /* Send the first packet immediately. */ 893 send_request(ip); 894 } 895 896 void 897 bootp(struct packet *packet) 898 { 899 struct iaddrlist *ap; 900 901 if (packet->raw->op != BOOTREPLY) 902 return; 903 904 /* If there's a reject list, make sure this packet's sender isn't 905 on it. */ 906 for (ap = packet->interface->client->config->reject_list; 907 ap; ap = ap->next) { 908 if (addr_eq(packet->client_addr, ap->addr)) { 909 note("BOOTREPLY from %s rejected.", piaddr(ap->addr)); 910 return; 911 } 912 } 913 dhcpoffer(packet); 914 } 915 916 void 917 dhcp(struct packet *packet) 918 { 919 struct iaddrlist *ap; 920 void (*handler)(struct packet *); 921 char *type; 922 923 switch (packet->packet_type) { 924 case DHCPOFFER: 925 handler = dhcpoffer; 926 type = "DHCPOFFER"; 927 break; 928 case DHCPNAK: 929 handler = dhcpnak; 930 type = "DHCPNACK"; 931 break; 932 case DHCPACK: 933 handler = dhcpack; 934 type = "DHCPACK"; 935 break; 936 default: 937 return; 938 } 939 940 /* If there's a reject list, make sure this packet's sender isn't 941 on it. */ 942 for (ap = packet->interface->client->config->reject_list; 943 ap; ap = ap->next) { 944 if (addr_eq(packet->client_addr, ap->addr)) { 945 note("%s from %s rejected.", type, piaddr(ap->addr)); 946 return; 947 } 948 } 949 (*handler)(packet); 950 } 951 952 void 953 dhcpoffer(struct packet *packet) 954 { 955 struct interface_info *ip = packet->interface; 956 struct client_lease *lease, *lp; 957 int i; 958 int arp_timeout_needed, stop_selecting; 959 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? 960 "DHCPOFFER" : "BOOTREPLY"; 961 962 /* If we're not receptive to an offer right now, or if the offer 963 has an unrecognizable transaction id, then just drop it. */ 964 if (ip->client->state != S_SELECTING || 965 packet->interface->client->xid != packet->raw->xid || 966 (packet->interface->hw_address.hlen != packet->raw->hlen) || 967 (memcmp(packet->interface->hw_address.haddr, 968 packet->raw->chaddr, packet->raw->hlen))) 969 return; 970 971 note("%s from %s", name, piaddr(packet->client_addr)); 972 973 974 /* If this lease doesn't supply the minimum required parameters, 975 blow it off. */ 976 for (i = 0; ip->client->config->required_options[i]; i++) { 977 if (!packet->options[ip->client->config-> 978 required_options[i]].len) { 979 note("%s isn't satisfactory.", name); 980 return; 981 } 982 } 983 984 /* If we've already seen this lease, don't record it again. */ 985 for (lease = ip->client->offered_leases; 986 lease; lease = lease->next) { 987 if (lease->address.len == sizeof(packet->raw->yiaddr) && 988 !memcmp(lease->address.iabuf, 989 &packet->raw->yiaddr, lease->address.len)) { 990 debug("%s already seen.", name); 991 return; 992 } 993 } 994 995 lease = packet_to_lease(packet); 996 if (!lease) { 997 note("packet_to_lease failed."); 998 return; 999 } 1000 1001 /* If this lease was acquired through a BOOTREPLY, record that 1002 fact. */ 1003 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len) 1004 lease->is_bootp = 1; 1005 1006 /* Record the medium under which this lease was offered. */ 1007 lease->medium = ip->client->medium; 1008 1009 /* Send out an ARP Request for the offered IP address. */ 1010 script_init("ARPSEND", lease->medium); 1011 script_write_params("check_", lease); 1012 /* If the script can't send an ARP request without waiting, 1013 we'll be waiting when we do the ARPCHECK, so don't wait now. */ 1014 if (script_go()) 1015 arp_timeout_needed = 0; 1016 else 1017 arp_timeout_needed = 2; 1018 1019 /* Figure out when we're supposed to stop selecting. */ 1020 stop_selecting = 1021 ip->client->first_sending + ip->client->config->select_interval; 1022 1023 /* If this is the lease we asked for, put it at the head of the 1024 list, and don't mess with the arp request timeout. */ 1025 if (lease->address.len == ip->client->requested_address.len && 1026 !memcmp(lease->address.iabuf, 1027 ip->client->requested_address.iabuf, 1028 ip->client->requested_address.len)) { 1029 lease->next = ip->client->offered_leases; 1030 ip->client->offered_leases = lease; 1031 } else { 1032 /* If we already have an offer, and arping for this 1033 offer would take us past the selection timeout, 1034 then don't extend the timeout - just hope for the 1035 best. */ 1036 if (ip->client->offered_leases && 1037 (cur_time + arp_timeout_needed) > stop_selecting) 1038 arp_timeout_needed = 0; 1039 1040 /* Put the lease at the end of the list. */ 1041 lease->next = NULL; 1042 if (!ip->client->offered_leases) 1043 ip->client->offered_leases = lease; 1044 else { 1045 for (lp = ip->client->offered_leases; lp->next; 1046 lp = lp->next) 1047 ; /* nothing */ 1048 lp->next = lease; 1049 } 1050 } 1051 1052 /* If we're supposed to stop selecting before we've had time 1053 to wait for the ARPREPLY, add some delay to wait for 1054 the ARPREPLY. */ 1055 if (stop_selecting - cur_time < arp_timeout_needed) 1056 stop_selecting = cur_time + arp_timeout_needed; 1057 1058 /* If the selecting interval has expired, go immediately to 1059 state_selecting(). Otherwise, time out into 1060 state_selecting at the select interval. */ 1061 if (stop_selecting <= 0) 1062 state_selecting(ip); 1063 else { 1064 add_timeout(stop_selecting, state_selecting, ip); 1065 cancel_timeout(send_discover, ip); 1066 } 1067 } 1068 1069 /* Allocate a client_lease structure and initialize it from the parameters 1070 in the specified packet. */ 1071 1072 struct client_lease * 1073 packet_to_lease(struct packet *packet) 1074 { 1075 struct client_lease *lease; 1076 int i; 1077 1078 lease = malloc(sizeof(struct client_lease)); 1079 1080 if (!lease) { 1081 warning("dhcpoffer: no memory to record lease."); 1082 return (NULL); 1083 } 1084 1085 memset(lease, 0, sizeof(*lease)); 1086 1087 /* Copy the lease options. */ 1088 for (i = 0; i < 256; i++) { 1089 if (packet->options[i].len) { 1090 lease->options[i].data = 1091 malloc(packet->options[i].len + 1); 1092 if (!lease->options[i].data) { 1093 warning("dhcpoffer: no memory for option %d", i); 1094 free_client_lease(lease); 1095 return (NULL); 1096 } else { 1097 memcpy(lease->options[i].data, 1098 packet->options[i].data, 1099 packet->options[i].len); 1100 lease->options[i].len = 1101 packet->options[i].len; 1102 lease->options[i].data[lease->options[i].len] = 1103 0; 1104 } 1105 if (!check_option(lease,i)) { 1106 /* ignore a bogus lease offer */ 1107 warning("Invalid lease option - ignoring offer"); 1108 free_client_lease(lease); 1109 return (NULL); 1110 } 1111 } 1112 } 1113 1114 lease->address.len = sizeof(packet->raw->yiaddr); 1115 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len); 1116 1117 lease->nextserver.len = sizeof(packet->raw->siaddr); 1118 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len); 1119 1120 /* If the server name was filled out, copy it. 1121 Do not attempt to validate the server name as a host name. 1122 RFC 2131 merely states that sname is NUL-terminated (which do 1123 do not assume) and that it is the server's host name. Since 1124 the ISC client and server allow arbitrary characters, we do 1125 as well. */ 1126 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 1127 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) && 1128 packet->raw->sname[0]) { 1129 lease->server_name = malloc(DHCP_SNAME_LEN + 1); 1130 if (!lease->server_name) { 1131 warning("dhcpoffer: no memory for server name."); 1132 free_client_lease(lease); 1133 return (NULL); 1134 } 1135 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); 1136 lease->server_name[DHCP_SNAME_LEN]='\0'; 1137 } 1138 1139 /* Ditto for the filename. */ 1140 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 1141 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) && 1142 packet->raw->file[0]) { 1143 /* Don't count on the NUL terminator. */ 1144 lease->filename = malloc(DHCP_FILE_LEN + 1); 1145 if (!lease->filename) { 1146 warning("dhcpoffer: no memory for filename."); 1147 free_client_lease(lease); 1148 return (NULL); 1149 } 1150 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN); 1151 lease->filename[DHCP_FILE_LEN]='\0'; 1152 } 1153 return lease; 1154 } 1155 1156 void 1157 dhcpnak(struct packet *packet) 1158 { 1159 struct interface_info *ip = packet->interface; 1160 1161 /* If we're not receptive to an offer right now, or if the offer 1162 has an unrecognizable transaction id, then just drop it. */ 1163 if (packet->interface->client->xid != packet->raw->xid || 1164 (packet->interface->hw_address.hlen != packet->raw->hlen) || 1165 (memcmp(packet->interface->hw_address.haddr, 1166 packet->raw->chaddr, packet->raw->hlen))) 1167 return; 1168 1169 if (ip->client->state != S_REBOOTING && 1170 ip->client->state != S_REQUESTING && 1171 ip->client->state != S_RENEWING && 1172 ip->client->state != S_REBINDING) 1173 return; 1174 1175 note("DHCPNAK from %s", piaddr(packet->client_addr)); 1176 1177 if (!ip->client->active) { 1178 note("DHCPNAK with no active lease.\n"); 1179 return; 1180 } 1181 1182 free_client_lease(ip->client->active); 1183 ip->client->active = NULL; 1184 1185 /* Stop sending DHCPREQUEST packets... */ 1186 cancel_timeout(send_request, ip); 1187 1188 ip->client->state = S_INIT; 1189 state_init(ip); 1190 } 1191 1192 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another 1193 one after the right interval has expired. If we don't get an offer by 1194 the time we reach the panic interval, call the panic function. */ 1195 1196 void 1197 send_discover(void *ipp) 1198 { 1199 struct interface_info *ip = ipp; 1200 int interval, increase = 1; 1201 1202 /* Figure out how long it's been since we started transmitting. */ 1203 interval = cur_time - ip->client->first_sending; 1204 1205 /* If we're past the panic timeout, call the script and tell it 1206 we haven't found anything for this interface yet. */ 1207 if (interval > ip->client->config->timeout) { 1208 state_panic(ip); 1209 return; 1210 } 1211 1212 /* If we're selecting media, try the whole list before doing 1213 the exponential backoff, but if we've already received an 1214 offer, stop looping, because we obviously have it right. */ 1215 if (!ip->client->offered_leases && 1216 ip->client->config->media) { 1217 int fail = 0; 1218 again: 1219 if (ip->client->medium) { 1220 ip->client->medium = ip->client->medium->next; 1221 increase = 0; 1222 } 1223 if (!ip->client->medium) { 1224 if (fail) 1225 error("No valid media types for %s!", ip->name); 1226 ip->client->medium = ip->client->config->media; 1227 increase = 1; 1228 } 1229 1230 note("Trying medium \"%s\" %d", ip->client->medium->string, 1231 increase); 1232 script_init("MEDIUM", ip->client->medium); 1233 if (script_go()) 1234 goto again; 1235 } 1236 1237 /* 1238 * If we're supposed to increase the interval, do so. If it's 1239 * currently zero (i.e., we haven't sent any packets yet), set 1240 * it to one; otherwise, add to it a random number between zero 1241 * and two times itself. On average, this means that it will 1242 * double with every transmission. 1243 */ 1244 if (increase) { 1245 if (!ip->client->interval) 1246 ip->client->interval = 1247 ip->client->config->initial_interval; 1248 else { 1249 ip->client->interval += (arc4random() >> 2) % 1250 (2 * ip->client->interval); 1251 } 1252 1253 /* Don't backoff past cutoff. */ 1254 if (ip->client->interval > 1255 ip->client->config->backoff_cutoff) 1256 ip->client->interval = 1257 ((ip->client->config->backoff_cutoff / 2) 1258 + ((arc4random() >> 2) % 1259 ip->client->config->backoff_cutoff)); 1260 } else if (!ip->client->interval) 1261 ip->client->interval = 1262 ip->client->config->initial_interval; 1263 1264 /* If the backoff would take us to the panic timeout, just use that 1265 as the interval. */ 1266 if (cur_time + ip->client->interval > 1267 ip->client->first_sending + ip->client->config->timeout) 1268 ip->client->interval = 1269 (ip->client->first_sending + 1270 ip->client->config->timeout) - cur_time + 1; 1271 1272 /* Record the number of seconds since we started sending. */ 1273 if (interval < 65536) 1274 ip->client->packet.secs = htons(interval); 1275 else 1276 ip->client->packet.secs = htons(65535); 1277 ip->client->secs = ip->client->packet.secs; 1278 1279 note("DHCPDISCOVER on %s to %s port %d interval %d", 1280 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT, 1281 (int)ip->client->interval); 1282 1283 /* Send out a packet. */ 1284 send_packet_unpriv(privfd, &ip->client->packet, 1285 ip->client->packet_length, inaddr_any, inaddr_broadcast); 1286 1287 add_timeout(cur_time + ip->client->interval, send_discover, ip); 1288 } 1289 1290 /* 1291 * state_panic gets called if we haven't received any offers in a preset 1292 * amount of time. When this happens, we try to use existing leases 1293 * that haven't yet expired, and failing that, we call the client script 1294 * and hope it can do something. 1295 */ 1296 void 1297 state_panic(void *ipp) 1298 { 1299 struct interface_info *ip = ipp; 1300 struct client_lease *loop = ip->client->active; 1301 struct client_lease *lp; 1302 1303 note("No DHCPOFFERS received."); 1304 1305 /* We may not have an active lease, but we may have some 1306 predefined leases that we can try. */ 1307 if (!ip->client->active && ip->client->leases) 1308 goto activate_next; 1309 1310 /* Run through the list of leases and see if one can be used. */ 1311 while (ip->client->active) { 1312 if (ip->client->active->expiry > cur_time) { 1313 note("Trying recorded lease %s", 1314 piaddr(ip->client->active->address)); 1315 /* Run the client script with the existing 1316 parameters. */ 1317 script_init("TIMEOUT", 1318 ip->client->active->medium); 1319 script_write_params("new_", ip->client->active); 1320 if (ip->client->alias) 1321 script_write_params("alias_", 1322 ip->client->alias); 1323 1324 /* If the old lease is still good and doesn't 1325 yet need renewal, go into BOUND state and 1326 timeout at the renewal time. */ 1327 if (!script_go()) { 1328 if (cur_time < 1329 ip->client->active->renewal) { 1330 ip->client->state = S_BOUND; 1331 note("bound: renewal in %d seconds.", 1332 (int)(ip->client->active->renewal - 1333 cur_time)); 1334 add_timeout( 1335 ip->client->active->renewal, 1336 state_bound, ip); 1337 } else { 1338 ip->client->state = S_BOUND; 1339 note("bound: immediate renewal."); 1340 state_bound(ip); 1341 } 1342 reinitialize_interfaces(); 1343 go_daemon(); 1344 return; 1345 } 1346 } 1347 1348 /* If there are no other leases, give up. */ 1349 if (!ip->client->leases) { 1350 ip->client->leases = ip->client->active; 1351 ip->client->active = NULL; 1352 break; 1353 } 1354 1355 activate_next: 1356 /* Otherwise, put the active lease at the end of the 1357 lease list, and try another lease.. */ 1358 for (lp = ip->client->leases; lp->next; lp = lp->next) 1359 ; 1360 lp->next = ip->client->active; 1361 if (lp->next) 1362 lp->next->next = NULL; 1363 ip->client->active = ip->client->leases; 1364 ip->client->leases = ip->client->leases->next; 1365 1366 /* If we already tried this lease, we've exhausted the 1367 set of leases, so we might as well give up for 1368 now. */ 1369 if (ip->client->active == loop) 1370 break; 1371 else if (!loop) 1372 loop = ip->client->active; 1373 } 1374 1375 /* No leases were available, or what was available didn't work, so 1376 tell the shell script that we failed to allocate an address, 1377 and try again later. */ 1378 note("No working leases in persistent database - sleeping.\n"); 1379 script_init("FAIL", NULL); 1380 if (ip->client->alias) 1381 script_write_params("alias_", ip->client->alias); 1382 script_go(); 1383 ip->client->state = S_INIT; 1384 add_timeout(cur_time + ip->client->config->retry_interval, state_init, 1385 ip); 1386 go_daemon(); 1387 } 1388 1389 void 1390 send_request(void *ipp) 1391 { 1392 struct interface_info *ip = ipp; 1393 struct in_addr from, to; 1394 int interval; 1395 1396 /* Figure out how long it's been since we started transmitting. */ 1397 interval = cur_time - ip->client->first_sending; 1398 1399 /* If we're in the INIT-REBOOT or REQUESTING state and we're 1400 past the reboot timeout, go to INIT and see if we can 1401 DISCOVER an address... */ 1402 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it 1403 means either that we're on a network with no DHCP server, 1404 or that our server is down. In the latter case, assuming 1405 that there is a backup DHCP server, DHCPDISCOVER will get 1406 us a new address, but we could also have successfully 1407 reused our old address. In the former case, we're hosed 1408 anyway. This is not a win-prone situation. */ 1409 if ((ip->client->state == S_REBOOTING || 1410 ip->client->state == S_REQUESTING) && 1411 interval > ip->client->config->reboot_timeout) { 1412 cancel: 1413 ip->client->state = S_INIT; 1414 cancel_timeout(send_request, ip); 1415 state_init(ip); 1416 return; 1417 } 1418 1419 /* If we're in the reboot state, make sure the media is set up 1420 correctly. */ 1421 if (ip->client->state == S_REBOOTING && 1422 !ip->client->medium && 1423 ip->client->active->medium ) { 1424 script_init("MEDIUM", ip->client->active->medium); 1425 1426 /* If the medium we chose won't fly, go to INIT state. */ 1427 if (script_go()) 1428 goto cancel; 1429 1430 /* Record the medium. */ 1431 ip->client->medium = ip->client->active->medium; 1432 } 1433 1434 /* If the lease has expired, relinquish the address and go back 1435 to the INIT state. */ 1436 if (ip->client->state != S_REQUESTING && 1437 cur_time > ip->client->active->expiry) { 1438 /* Run the client script with the new parameters. */ 1439 script_init("EXPIRE", NULL); 1440 script_write_params("old_", ip->client->active); 1441 if (ip->client->alias) 1442 script_write_params("alias_", ip->client->alias); 1443 script_go(); 1444 1445 /* Now do a preinit on the interface so that we can 1446 discover a new address. */ 1447 script_init("PREINIT", NULL); 1448 if (ip->client->alias) 1449 script_write_params("alias_", ip->client->alias); 1450 script_go(); 1451 1452 ip->client->state = S_INIT; 1453 state_init(ip); 1454 return; 1455 } 1456 1457 /* Do the exponential backoff... */ 1458 if (!ip->client->interval) 1459 ip->client->interval = ip->client->config->initial_interval; 1460 else 1461 ip->client->interval += ((arc4random() >> 2) % 1462 (2 * ip->client->interval)); 1463 1464 /* Don't backoff past cutoff. */ 1465 if (ip->client->interval > 1466 ip->client->config->backoff_cutoff) 1467 ip->client->interval = 1468 ((ip->client->config->backoff_cutoff / 2) + 1469 ((arc4random() >> 2) % ip->client->interval)); 1470 1471 /* If the backoff would take us to the expiry time, just set the 1472 timeout to the expiry time. */ 1473 if (ip->client->state != S_REQUESTING && 1474 cur_time + ip->client->interval > 1475 ip->client->active->expiry) 1476 ip->client->interval = 1477 ip->client->active->expiry - cur_time + 1; 1478 1479 /* If the lease T2 time has elapsed, or if we're not yet bound, 1480 broadcast the DHCPREQUEST rather than unicasting. */ 1481 if (ip->client->state == S_REQUESTING || 1482 ip->client->state == S_REBOOTING || 1483 cur_time > ip->client->active->rebind) 1484 to.s_addr = INADDR_BROADCAST; 1485 else 1486 memcpy(&to.s_addr, ip->client->destination.iabuf, 1487 sizeof(to.s_addr)); 1488 1489 if (ip->client->state != S_REQUESTING) 1490 memcpy(&from, ip->client->active->address.iabuf, 1491 sizeof(from)); 1492 else 1493 from.s_addr = INADDR_ANY; 1494 1495 /* Record the number of seconds since we started sending. */ 1496 if (ip->client->state == S_REQUESTING) 1497 ip->client->packet.secs = ip->client->secs; 1498 else { 1499 if (interval < 65536) 1500 ip->client->packet.secs = htons(interval); 1501 else 1502 ip->client->packet.secs = htons(65535); 1503 } 1504 1505 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to), 1506 REMOTE_PORT); 1507 1508 /* Send out a packet. */ 1509 send_packet_unpriv(privfd, &ip->client->packet, 1510 ip->client->packet_length, from, to); 1511 1512 add_timeout(cur_time + ip->client->interval, send_request, ip); 1513 } 1514 1515 void 1516 send_decline(void *ipp) 1517 { 1518 struct interface_info *ip = ipp; 1519 1520 note("DHCPDECLINE on %s to %s port %d", ip->name, 1521 inet_ntoa(inaddr_broadcast), REMOTE_PORT); 1522 1523 /* Send out a packet. */ 1524 send_packet_unpriv(privfd, &ip->client->packet, 1525 ip->client->packet_length, inaddr_any, inaddr_broadcast); 1526 } 1527 1528 void 1529 make_discover(struct interface_info *ip, struct client_lease *lease) 1530 { 1531 unsigned char discover = DHCPDISCOVER; 1532 struct tree_cache *options[256]; 1533 struct tree_cache option_elements[256]; 1534 int i; 1535 1536 memset(option_elements, 0, sizeof(option_elements)); 1537 memset(options, 0, sizeof(options)); 1538 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1539 1540 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ 1541 i = DHO_DHCP_MESSAGE_TYPE; 1542 options[i] = &option_elements[i]; 1543 options[i]->value = &discover; 1544 options[i]->len = sizeof(discover); 1545 options[i]->buf_size = sizeof(discover); 1546 options[i]->timeout = 0xFFFFFFFF; 1547 1548 /* Request the options we want */ 1549 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1550 options[i] = &option_elements[i]; 1551 options[i]->value = ip->client->config->requested_options; 1552 options[i]->len = ip->client->config->requested_option_count; 1553 options[i]->buf_size = 1554 ip->client->config->requested_option_count; 1555 options[i]->timeout = 0xFFFFFFFF; 1556 1557 /* If we had an address, try to get it again. */ 1558 if (lease) { 1559 ip->client->requested_address = lease->address; 1560 i = DHO_DHCP_REQUESTED_ADDRESS; 1561 options[i] = &option_elements[i]; 1562 options[i]->value = lease->address.iabuf; 1563 options[i]->len = lease->address.len; 1564 options[i]->buf_size = lease->address.len; 1565 options[i]->timeout = 0xFFFFFFFF; 1566 } else 1567 ip->client->requested_address.len = 0; 1568 1569 /* Send any options requested in the config file. */ 1570 for (i = 0; i < 256; i++) 1571 if (!options[i] && 1572 ip->client->config->send_options[i].data) { 1573 options[i] = &option_elements[i]; 1574 options[i]->value = 1575 ip->client->config->send_options[i].data; 1576 options[i]->len = 1577 ip->client->config->send_options[i].len; 1578 options[i]->buf_size = 1579 ip->client->config->send_options[i].len; 1580 options[i]->timeout = 0xFFFFFFFF; 1581 } 1582 1583 /* send host name if not set via config file. */ 1584 if (!options[DHO_HOST_NAME]) { 1585 if (hostname[0] != '\0') { 1586 size_t len; 1587 char* posDot = strchr(hostname, '.'); 1588 if (posDot != NULL) 1589 len = posDot - hostname; 1590 else 1591 len = strlen(hostname); 1592 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1593 options[DHO_HOST_NAME]->value = hostname; 1594 options[DHO_HOST_NAME]->len = len; 1595 options[DHO_HOST_NAME]->buf_size = len; 1596 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1597 } 1598 } 1599 1600 /* set unique client identifier */ 1601 char client_ident[sizeof(ip->hw_address.haddr) + 1]; 1602 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1603 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1604 ip->hw_address.hlen : sizeof(client_ident)-1; 1605 client_ident[0] = ip->hw_address.htype; 1606 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1607 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1608 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1609 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1610 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1611 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1612 } 1613 1614 /* Set up the option buffer... */ 1615 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1616 options, 0, 0, 0, NULL, 0); 1617 if (ip->client->packet_length < BOOTP_MIN_LEN) 1618 ip->client->packet_length = BOOTP_MIN_LEN; 1619 1620 ip->client->packet.op = BOOTREQUEST; 1621 ip->client->packet.htype = ip->hw_address.htype; 1622 ip->client->packet.hlen = ip->hw_address.hlen; 1623 ip->client->packet.hops = 0; 1624 ip->client->packet.xid = arc4random(); 1625 ip->client->packet.secs = 0; /* filled in by send_discover. */ 1626 ip->client->packet.flags = 0; 1627 1628 memset(&(ip->client->packet.ciaddr), 1629 0, sizeof(ip->client->packet.ciaddr)); 1630 memset(&(ip->client->packet.yiaddr), 1631 0, sizeof(ip->client->packet.yiaddr)); 1632 memset(&(ip->client->packet.siaddr), 1633 0, sizeof(ip->client->packet.siaddr)); 1634 memset(&(ip->client->packet.giaddr), 1635 0, sizeof(ip->client->packet.giaddr)); 1636 memcpy(ip->client->packet.chaddr, 1637 ip->hw_address.haddr, ip->hw_address.hlen); 1638 } 1639 1640 1641 void 1642 make_request(struct interface_info *ip, struct client_lease * lease) 1643 { 1644 unsigned char request = DHCPREQUEST; 1645 struct tree_cache *options[256]; 1646 struct tree_cache option_elements[256]; 1647 int i; 1648 1649 memset(options, 0, sizeof(options)); 1650 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1651 1652 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ 1653 i = DHO_DHCP_MESSAGE_TYPE; 1654 options[i] = &option_elements[i]; 1655 options[i]->value = &request; 1656 options[i]->len = sizeof(request); 1657 options[i]->buf_size = sizeof(request); 1658 options[i]->timeout = 0xFFFFFFFF; 1659 1660 /* Request the options we want */ 1661 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 1662 options[i] = &option_elements[i]; 1663 options[i]->value = ip->client->config->requested_options; 1664 options[i]->len = ip->client->config->requested_option_count; 1665 options[i]->buf_size = 1666 ip->client->config->requested_option_count; 1667 options[i]->timeout = 0xFFFFFFFF; 1668 1669 /* If we are requesting an address that hasn't yet been assigned 1670 to us, use the DHCP Requested Address option. */ 1671 if (ip->client->state == S_REQUESTING) { 1672 /* Send back the server identifier... */ 1673 i = DHO_DHCP_SERVER_IDENTIFIER; 1674 options[i] = &option_elements[i]; 1675 options[i]->value = lease->options[i].data; 1676 options[i]->len = lease->options[i].len; 1677 options[i]->buf_size = lease->options[i].len; 1678 options[i]->timeout = 0xFFFFFFFF; 1679 } 1680 if (ip->client->state == S_REQUESTING || 1681 ip->client->state == S_REBOOTING) { 1682 ip->client->requested_address = lease->address; 1683 i = DHO_DHCP_REQUESTED_ADDRESS; 1684 options[i] = &option_elements[i]; 1685 options[i]->value = lease->address.iabuf; 1686 options[i]->len = lease->address.len; 1687 options[i]->buf_size = lease->address.len; 1688 options[i]->timeout = 0xFFFFFFFF; 1689 } else 1690 ip->client->requested_address.len = 0; 1691 1692 /* Send any options requested in the config file. */ 1693 for (i = 0; i < 256; i++) 1694 if (!options[i] && 1695 ip->client->config->send_options[i].data) { 1696 options[i] = &option_elements[i]; 1697 options[i]->value = 1698 ip->client->config->send_options[i].data; 1699 options[i]->len = 1700 ip->client->config->send_options[i].len; 1701 options[i]->buf_size = 1702 ip->client->config->send_options[i].len; 1703 options[i]->timeout = 0xFFFFFFFF; 1704 } 1705 1706 /* send host name if not set via config file. */ 1707 if (!options[DHO_HOST_NAME]) { 1708 if (hostname[0] != '\0') { 1709 size_t len; 1710 char* posDot = strchr(hostname, '.'); 1711 if (posDot != NULL) 1712 len = posDot - hostname; 1713 else 1714 len = strlen(hostname); 1715 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME]; 1716 options[DHO_HOST_NAME]->value = hostname; 1717 options[DHO_HOST_NAME]->len = len; 1718 options[DHO_HOST_NAME]->buf_size = len; 1719 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF; 1720 } 1721 } 1722 1723 /* set unique client identifier */ 1724 char client_ident[sizeof(struct hardware)]; 1725 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) { 1726 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ? 1727 ip->hw_address.hlen : sizeof(client_ident)-1; 1728 client_ident[0] = ip->hw_address.htype; 1729 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen); 1730 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER]; 1731 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident; 1732 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1; 1733 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1; 1734 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF; 1735 } 1736 1737 /* Set up the option buffer... */ 1738 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1739 options, 0, 0, 0, NULL, 0); 1740 if (ip->client->packet_length < BOOTP_MIN_LEN) 1741 ip->client->packet_length = BOOTP_MIN_LEN; 1742 1743 ip->client->packet.op = BOOTREQUEST; 1744 ip->client->packet.htype = ip->hw_address.htype; 1745 ip->client->packet.hlen = ip->hw_address.hlen; 1746 ip->client->packet.hops = 0; 1747 ip->client->packet.xid = ip->client->xid; 1748 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1749 1750 /* If we own the address we're requesting, put it in ciaddr; 1751 otherwise set ciaddr to zero. */ 1752 if (ip->client->state == S_BOUND || 1753 ip->client->state == S_RENEWING || 1754 ip->client->state == S_REBINDING) { 1755 memcpy(&ip->client->packet.ciaddr, 1756 lease->address.iabuf, lease->address.len); 1757 ip->client->packet.flags = 0; 1758 } else { 1759 memset(&ip->client->packet.ciaddr, 0, 1760 sizeof(ip->client->packet.ciaddr)); 1761 ip->client->packet.flags = 0; 1762 } 1763 1764 memset(&ip->client->packet.yiaddr, 0, 1765 sizeof(ip->client->packet.yiaddr)); 1766 memset(&ip->client->packet.siaddr, 0, 1767 sizeof(ip->client->packet.siaddr)); 1768 memset(&ip->client->packet.giaddr, 0, 1769 sizeof(ip->client->packet.giaddr)); 1770 memcpy(ip->client->packet.chaddr, 1771 ip->hw_address.haddr, ip->hw_address.hlen); 1772 } 1773 1774 void 1775 make_decline(struct interface_info *ip, struct client_lease *lease) 1776 { 1777 struct tree_cache *options[256], message_type_tree; 1778 struct tree_cache requested_address_tree; 1779 struct tree_cache server_id_tree, client_id_tree; 1780 unsigned char decline = DHCPDECLINE; 1781 int i; 1782 1783 memset(options, 0, sizeof(options)); 1784 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 1785 1786 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ 1787 i = DHO_DHCP_MESSAGE_TYPE; 1788 options[i] = &message_type_tree; 1789 options[i]->value = &decline; 1790 options[i]->len = sizeof(decline); 1791 options[i]->buf_size = sizeof(decline); 1792 options[i]->timeout = 0xFFFFFFFF; 1793 1794 /* Send back the server identifier... */ 1795 i = DHO_DHCP_SERVER_IDENTIFIER; 1796 options[i] = &server_id_tree; 1797 options[i]->value = lease->options[i].data; 1798 options[i]->len = lease->options[i].len; 1799 options[i]->buf_size = lease->options[i].len; 1800 options[i]->timeout = 0xFFFFFFFF; 1801 1802 /* Send back the address we're declining. */ 1803 i = DHO_DHCP_REQUESTED_ADDRESS; 1804 options[i] = &requested_address_tree; 1805 options[i]->value = lease->address.iabuf; 1806 options[i]->len = lease->address.len; 1807 options[i]->buf_size = lease->address.len; 1808 options[i]->timeout = 0xFFFFFFFF; 1809 1810 /* Send the uid if the user supplied one. */ 1811 i = DHO_DHCP_CLIENT_IDENTIFIER; 1812 if (ip->client->config->send_options[i].len) { 1813 options[i] = &client_id_tree; 1814 options[i]->value = ip->client->config->send_options[i].data; 1815 options[i]->len = ip->client->config->send_options[i].len; 1816 options[i]->buf_size = ip->client->config->send_options[i].len; 1817 options[i]->timeout = 0xFFFFFFFF; 1818 } 1819 1820 1821 /* Set up the option buffer... */ 1822 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 1823 options, 0, 0, 0, NULL, 0); 1824 if (ip->client->packet_length < BOOTP_MIN_LEN) 1825 ip->client->packet_length = BOOTP_MIN_LEN; 1826 1827 ip->client->packet.op = BOOTREQUEST; 1828 ip->client->packet.htype = ip->hw_address.htype; 1829 ip->client->packet.hlen = ip->hw_address.hlen; 1830 ip->client->packet.hops = 0; 1831 ip->client->packet.xid = ip->client->xid; 1832 ip->client->packet.secs = 0; /* Filled in by send_request. */ 1833 ip->client->packet.flags = 0; 1834 1835 /* ciaddr must always be zero. */ 1836 memset(&ip->client->packet.ciaddr, 0, 1837 sizeof(ip->client->packet.ciaddr)); 1838 memset(&ip->client->packet.yiaddr, 0, 1839 sizeof(ip->client->packet.yiaddr)); 1840 memset(&ip->client->packet.siaddr, 0, 1841 sizeof(ip->client->packet.siaddr)); 1842 memset(&ip->client->packet.giaddr, 0, 1843 sizeof(ip->client->packet.giaddr)); 1844 memcpy(ip->client->packet.chaddr, 1845 ip->hw_address.haddr, ip->hw_address.hlen); 1846 } 1847 1848 void 1849 free_client_lease(struct client_lease *lease) 1850 { 1851 int i; 1852 1853 if (lease->server_name) 1854 free(lease->server_name); 1855 if (lease->filename) 1856 free(lease->filename); 1857 for (i = 0; i < 256; i++) { 1858 if (lease->options[i].len) 1859 free(lease->options[i].data); 1860 } 1861 free(lease); 1862 } 1863 1864 FILE *leaseFile; 1865 1866 void 1867 rewrite_client_leases(void) 1868 { 1869 struct client_lease *lp; 1870 cap_rights_t rights; 1871 1872 if (!leaseFile) { 1873 leaseFile = fopen(path_dhclient_db, "w"); 1874 if (!leaseFile) 1875 error("can't create %s: %m", path_dhclient_db); 1876 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC, 1877 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE); 1878 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 && 1879 errno != ENOSYS) { 1880 error("can't limit lease descriptor: %m"); 1881 } 1882 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 && 1883 errno != ENOSYS) { 1884 error("can't limit lease descriptor fcntls: %m"); 1885 } 1886 } else { 1887 fflush(leaseFile); 1888 rewind(leaseFile); 1889 } 1890 1891 for (lp = ifi->client->leases; lp; lp = lp->next) 1892 write_client_lease(ifi, lp, 1); 1893 if (ifi->client->active) 1894 write_client_lease(ifi, ifi->client->active, 1); 1895 1896 fflush(leaseFile); 1897 ftruncate(fileno(leaseFile), ftello(leaseFile)); 1898 fsync(fileno(leaseFile)); 1899 } 1900 1901 void 1902 write_client_lease(struct interface_info *ip, struct client_lease *lease, 1903 int rewrite) 1904 { 1905 static int leases_written; 1906 struct tm *t; 1907 int i; 1908 1909 if (!rewrite) { 1910 if (leases_written++ > 20) { 1911 rewrite_client_leases(); 1912 leases_written = 0; 1913 } 1914 } 1915 1916 /* If the lease came from the config file, we don't need to stash 1917 a copy in the lease database. */ 1918 if (lease->is_static) 1919 return; 1920 1921 if (!leaseFile) { /* XXX */ 1922 leaseFile = fopen(path_dhclient_db, "w"); 1923 if (!leaseFile) 1924 error("can't create %s: %m", path_dhclient_db); 1925 } 1926 1927 fprintf(leaseFile, "lease {\n"); 1928 if (lease->is_bootp) 1929 fprintf(leaseFile, " bootp;\n"); 1930 fprintf(leaseFile, " interface \"%s\";\n", ip->name); 1931 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address)); 1932 if (lease->nextserver.len == sizeof(inaddr_any) && 1933 0 != memcmp(lease->nextserver.iabuf, &inaddr_any, 1934 sizeof(inaddr_any))) 1935 fprintf(leaseFile, " next-server %s;\n", 1936 piaddr(lease->nextserver)); 1937 if (lease->filename) 1938 fprintf(leaseFile, " filename \"%s\";\n", lease->filename); 1939 if (lease->server_name) 1940 fprintf(leaseFile, " server-name \"%s\";\n", 1941 lease->server_name); 1942 if (lease->medium) 1943 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string); 1944 for (i = 0; i < 256; i++) 1945 if (lease->options[i].len) 1946 fprintf(leaseFile, " option %s %s;\n", 1947 dhcp_options[i].name, 1948 pretty_print_option(i, lease->options[i].data, 1949 lease->options[i].len, 1, 1)); 1950 1951 t = gmtime(&lease->renewal); 1952 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", 1953 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 1954 t->tm_hour, t->tm_min, t->tm_sec); 1955 t = gmtime(&lease->rebind); 1956 fprintf(leaseFile, " rebind %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->expiry); 1960 fprintf(leaseFile, " expire %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 fprintf(leaseFile, "}\n"); 1964 fflush(leaseFile); 1965 } 1966 1967 void 1968 script_init(char *reason, struct string_list *medium) 1969 { 1970 size_t len, mediumlen = 0; 1971 struct imsg_hdr hdr; 1972 struct buf *buf; 1973 int errs; 1974 1975 if (medium != NULL && medium->string != NULL) 1976 mediumlen = strlen(medium->string); 1977 1978 hdr.code = IMSG_SCRIPT_INIT; 1979 hdr.len = sizeof(struct imsg_hdr) + 1980 sizeof(size_t) + mediumlen + 1981 sizeof(size_t) + strlen(reason); 1982 1983 if ((buf = buf_open(hdr.len)) == NULL) 1984 error("buf_open: %m"); 1985 1986 errs = 0; 1987 errs += buf_add(buf, &hdr, sizeof(hdr)); 1988 errs += buf_add(buf, &mediumlen, sizeof(mediumlen)); 1989 if (mediumlen > 0) 1990 errs += buf_add(buf, medium->string, mediumlen); 1991 len = strlen(reason); 1992 errs += buf_add(buf, &len, sizeof(len)); 1993 errs += buf_add(buf, reason, len); 1994 1995 if (errs) 1996 error("buf_add: %m"); 1997 1998 if (buf_close(privfd, buf) == -1) 1999 error("buf_close: %m"); 2000 } 2001 2002 void 2003 priv_script_init(char *reason, char *medium) 2004 { 2005 struct interface_info *ip = ifi; 2006 2007 if (ip) { 2008 ip->client->scriptEnvsize = 100; 2009 if (ip->client->scriptEnv == NULL) 2010 ip->client->scriptEnv = 2011 malloc(ip->client->scriptEnvsize * sizeof(char *)); 2012 if (ip->client->scriptEnv == NULL) 2013 error("script_init: no memory for environment"); 2014 2015 ip->client->scriptEnv[0] = strdup(CLIENT_PATH); 2016 if (ip->client->scriptEnv[0] == NULL) 2017 error("script_init: no memory for environment"); 2018 2019 ip->client->scriptEnv[1] = NULL; 2020 2021 script_set_env(ip->client, "", "interface", ip->name); 2022 2023 if (medium) 2024 script_set_env(ip->client, "", "medium", medium); 2025 2026 script_set_env(ip->client, "", "reason", reason); 2027 } 2028 } 2029 2030 void 2031 priv_script_write_params(char *prefix, struct client_lease *lease) 2032 { 2033 struct interface_info *ip = ifi; 2034 u_int8_t dbuf[1500], *dp = NULL; 2035 int i, len; 2036 char tbuf[128]; 2037 2038 script_set_env(ip->client, prefix, "ip_address", 2039 piaddr(lease->address)); 2040 2041 if (ip->client->config->default_actions[DHO_SUBNET_MASK] == 2042 ACTION_SUPERSEDE) { 2043 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data; 2044 len = ip->client->config->defaults[DHO_SUBNET_MASK].len; 2045 } else { 2046 dp = lease->options[DHO_SUBNET_MASK].data; 2047 len = lease->options[DHO_SUBNET_MASK].len; 2048 } 2049 if (len && (len < sizeof(lease->address.iabuf))) { 2050 struct iaddr netmask, subnet, broadcast; 2051 2052 memcpy(netmask.iabuf, dp, len); 2053 netmask.len = len; 2054 subnet = subnet_number(lease->address, netmask); 2055 if (subnet.len) { 2056 script_set_env(ip->client, prefix, "network_number", 2057 piaddr(subnet)); 2058 if (!lease->options[DHO_BROADCAST_ADDRESS].len) { 2059 broadcast = broadcast_addr(subnet, netmask); 2060 if (broadcast.len) 2061 script_set_env(ip->client, prefix, 2062 "broadcast_address", 2063 piaddr(broadcast)); 2064 } 2065 } 2066 } 2067 2068 if (lease->filename) 2069 script_set_env(ip->client, prefix, "filename", lease->filename); 2070 if (lease->server_name) 2071 script_set_env(ip->client, prefix, "server_name", 2072 lease->server_name); 2073 for (i = 0; i < 256; i++) { 2074 len = 0; 2075 2076 if (ip->client->config->defaults[i].len) { 2077 if (lease->options[i].len) { 2078 switch ( 2079 ip->client->config->default_actions[i]) { 2080 case ACTION_DEFAULT: 2081 dp = lease->options[i].data; 2082 len = lease->options[i].len; 2083 break; 2084 case ACTION_SUPERSEDE: 2085 supersede: 2086 dp = ip->client-> 2087 config->defaults[i].data; 2088 len = ip->client-> 2089 config->defaults[i].len; 2090 break; 2091 case ACTION_PREPEND: 2092 len = ip->client-> 2093 config->defaults[i].len + 2094 lease->options[i].len; 2095 if (len >= sizeof(dbuf)) { 2096 warning("no space to %s %s", 2097 "prepend option", 2098 dhcp_options[i].name); 2099 goto supersede; 2100 } 2101 dp = dbuf; 2102 memcpy(dp, 2103 ip->client-> 2104 config->defaults[i].data, 2105 ip->client-> 2106 config->defaults[i].len); 2107 memcpy(dp + ip->client-> 2108 config->defaults[i].len, 2109 lease->options[i].data, 2110 lease->options[i].len); 2111 dp[len] = '\0'; 2112 break; 2113 case ACTION_APPEND: 2114 /* 2115 * When we append, we assume that we're 2116 * appending to text. Some MS servers 2117 * include a NUL byte at the end of 2118 * the search string provided. 2119 */ 2120 len = ip->client-> 2121 config->defaults[i].len + 2122 lease->options[i].len; 2123 if (len >= sizeof(dbuf)) { 2124 warning("no space to %s %s", 2125 "append option", 2126 dhcp_options[i].name); 2127 goto supersede; 2128 } 2129 memcpy(dbuf, 2130 lease->options[i].data, 2131 lease->options[i].len); 2132 for (dp = dbuf + lease->options[i].len; 2133 dp > dbuf; dp--, len--) 2134 if (dp[-1] != '\0') 2135 break; 2136 memcpy(dp, 2137 ip->client-> 2138 config->defaults[i].data, 2139 ip->client-> 2140 config->defaults[i].len); 2141 dp = dbuf; 2142 dp[len] = '\0'; 2143 } 2144 } else { 2145 dp = ip->client-> 2146 config->defaults[i].data; 2147 len = ip->client-> 2148 config->defaults[i].len; 2149 } 2150 } else if (lease->options[i].len) { 2151 len = lease->options[i].len; 2152 dp = lease->options[i].data; 2153 } else { 2154 len = 0; 2155 } 2156 if (len) { 2157 char name[256]; 2158 2159 if (dhcp_option_ev_name(name, sizeof(name), 2160 &dhcp_options[i])) 2161 script_set_env(ip->client, prefix, name, 2162 pretty_print_option(i, dp, len, 0, 0)); 2163 } 2164 } 2165 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); 2166 script_set_env(ip->client, prefix, "expiry", tbuf); 2167 } 2168 2169 void 2170 script_write_params(char *prefix, struct client_lease *lease) 2171 { 2172 size_t fn_len = 0, sn_len = 0, pr_len = 0; 2173 struct imsg_hdr hdr; 2174 struct buf *buf; 2175 int errs, i; 2176 2177 if (lease->filename != NULL) 2178 fn_len = strlen(lease->filename); 2179 if (lease->server_name != NULL) 2180 sn_len = strlen(lease->server_name); 2181 if (prefix != NULL) 2182 pr_len = strlen(prefix); 2183 2184 hdr.code = IMSG_SCRIPT_WRITE_PARAMS; 2185 hdr.len = sizeof(hdr) + sizeof(struct client_lease) + 2186 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len + 2187 sizeof(size_t) + pr_len; 2188 2189 for (i = 0; i < 256; i++) 2190 hdr.len += sizeof(int) + lease->options[i].len; 2191 2192 scripttime = time(NULL); 2193 2194 if ((buf = buf_open(hdr.len)) == NULL) 2195 error("buf_open: %m"); 2196 2197 errs = 0; 2198 errs += buf_add(buf, &hdr, sizeof(hdr)); 2199 errs += buf_add(buf, lease, sizeof(struct client_lease)); 2200 errs += buf_add(buf, &fn_len, sizeof(fn_len)); 2201 errs += buf_add(buf, lease->filename, fn_len); 2202 errs += buf_add(buf, &sn_len, sizeof(sn_len)); 2203 errs += buf_add(buf, lease->server_name, sn_len); 2204 errs += buf_add(buf, &pr_len, sizeof(pr_len)); 2205 errs += buf_add(buf, prefix, pr_len); 2206 2207 for (i = 0; i < 256; i++) { 2208 errs += buf_add(buf, &lease->options[i].len, 2209 sizeof(lease->options[i].len)); 2210 errs += buf_add(buf, lease->options[i].data, 2211 lease->options[i].len); 2212 } 2213 2214 if (errs) 2215 error("buf_add: %m"); 2216 2217 if (buf_close(privfd, buf) == -1) 2218 error("buf_close: %m"); 2219 } 2220 2221 int 2222 script_go(void) 2223 { 2224 struct imsg_hdr hdr; 2225 struct buf *buf; 2226 int ret; 2227 2228 hdr.code = IMSG_SCRIPT_GO; 2229 hdr.len = sizeof(struct imsg_hdr); 2230 2231 if ((buf = buf_open(hdr.len)) == NULL) 2232 error("buf_open: %m"); 2233 2234 if (buf_add(buf, &hdr, sizeof(hdr))) 2235 error("buf_add: %m"); 2236 2237 if (buf_close(privfd, buf) == -1) 2238 error("buf_close: %m"); 2239 2240 bzero(&hdr, sizeof(hdr)); 2241 buf_read(privfd, &hdr, sizeof(hdr)); 2242 if (hdr.code != IMSG_SCRIPT_GO_RET) 2243 error("unexpected msg type %u", hdr.code); 2244 if (hdr.len != sizeof(hdr) + sizeof(int)) 2245 error("received corrupted message"); 2246 buf_read(privfd, &ret, sizeof(ret)); 2247 2248 scripttime = time(NULL); 2249 2250 return (ret); 2251 } 2252 2253 int 2254 priv_script_go(void) 2255 { 2256 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI"; 2257 static char client_path[] = CLIENT_PATH; 2258 struct interface_info *ip = ifi; 2259 int pid, wpid, wstatus; 2260 2261 scripttime = time(NULL); 2262 2263 if (ip) { 2264 scriptName = ip->client->config->script_name; 2265 envp = ip->client->scriptEnv; 2266 } else { 2267 scriptName = top_level_config.script_name; 2268 epp[0] = reason; 2269 epp[1] = client_path; 2270 epp[2] = NULL; 2271 envp = epp; 2272 } 2273 2274 argv[0] = scriptName; 2275 argv[1] = NULL; 2276 2277 pid = fork(); 2278 if (pid < 0) { 2279 error("fork: %m"); 2280 wstatus = 0; 2281 } else if (pid) { 2282 do { 2283 wpid = wait(&wstatus); 2284 } while (wpid != pid && wpid > 0); 2285 if (wpid < 0) { 2286 error("wait: %m"); 2287 wstatus = 0; 2288 } 2289 } else { 2290 execve(scriptName, argv, envp); 2291 error("execve (%s, ...): %m", scriptName); 2292 } 2293 2294 if (ip) 2295 script_flush_env(ip->client); 2296 2297 return (wstatus & 0xff); 2298 } 2299 2300 void 2301 script_set_env(struct client_state *client, const char *prefix, 2302 const char *name, const char *value) 2303 { 2304 int i, j, namelen; 2305 2306 /* No `` or $() command substitution allowed in environment values! */ 2307 for (j=0; j < strlen(value); j++) 2308 switch (value[j]) { 2309 case '`': 2310 case '$': 2311 warning("illegal character (%c) in value '%s'", 2312 value[j], value); 2313 /* Ignore this option */ 2314 return; 2315 } 2316 2317 namelen = strlen(name); 2318 2319 for (i = 0; client->scriptEnv[i]; i++) 2320 if (strncmp(client->scriptEnv[i], name, namelen) == 0 && 2321 client->scriptEnv[i][namelen] == '=') 2322 break; 2323 2324 if (client->scriptEnv[i]) 2325 /* Reuse the slot. */ 2326 free(client->scriptEnv[i]); 2327 else { 2328 /* New variable. Expand if necessary. */ 2329 if (i >= client->scriptEnvsize - 1) { 2330 char **newscriptEnv; 2331 int newscriptEnvsize = client->scriptEnvsize + 50; 2332 2333 newscriptEnv = realloc(client->scriptEnv, 2334 newscriptEnvsize); 2335 if (newscriptEnv == NULL) { 2336 free(client->scriptEnv); 2337 client->scriptEnv = NULL; 2338 client->scriptEnvsize = 0; 2339 error("script_set_env: no memory for variable"); 2340 } 2341 client->scriptEnv = newscriptEnv; 2342 client->scriptEnvsize = newscriptEnvsize; 2343 } 2344 /* need to set the NULL pointer at end of array beyond 2345 the new slot. */ 2346 client->scriptEnv[i + 1] = NULL; 2347 } 2348 /* Allocate space and format the variable in the appropriate slot. */ 2349 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 + 2350 strlen(value) + 1); 2351 if (client->scriptEnv[i] == NULL) 2352 error("script_set_env: no memory for variable assignment"); 2353 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) + 2354 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value); 2355 } 2356 2357 void 2358 script_flush_env(struct client_state *client) 2359 { 2360 int i; 2361 2362 for (i = 0; client->scriptEnv[i]; i++) { 2363 free(client->scriptEnv[i]); 2364 client->scriptEnv[i] = NULL; 2365 } 2366 client->scriptEnvsize = 0; 2367 } 2368 2369 int 2370 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option) 2371 { 2372 int i; 2373 2374 for (i = 0; option->name[i]; i++) { 2375 if (i + 1 == buflen) 2376 return 0; 2377 if (option->name[i] == '-') 2378 buf[i] = '_'; 2379 else 2380 buf[i] = option->name[i]; 2381 } 2382 2383 buf[i] = 0; 2384 return 1; 2385 } 2386 2387 void 2388 go_daemon(void) 2389 { 2390 static int state = 0; 2391 cap_rights_t rights; 2392 2393 if (no_daemon || state) 2394 return; 2395 2396 state = 1; 2397 2398 /* Stop logging to stderr... */ 2399 log_perror = 0; 2400 2401 if (daemon(1, 0) == -1) 2402 error("daemon"); 2403 2404 cap_rights_init(&rights); 2405 2406 if (pidfile != NULL) { 2407 pidfile_write(pidfile); 2408 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 && 2409 errno != ENOSYS) { 2410 error("can't limit pidfile descriptor: %m"); 2411 } 2412 } 2413 2414 /* we are chrooted, daemon(3) fails to open /dev/null */ 2415 if (nullfd != -1) { 2416 dup2(nullfd, STDIN_FILENO); 2417 dup2(nullfd, STDOUT_FILENO); 2418 dup2(nullfd, STDERR_FILENO); 2419 close(nullfd); 2420 nullfd = -1; 2421 } 2422 2423 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS) 2424 error("can't limit stdin: %m"); 2425 cap_rights_init(&rights, CAP_WRITE); 2426 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS) 2427 error("can't limit stdout: %m"); 2428 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS) 2429 error("can't limit stderr: %m"); 2430 } 2431 2432 int 2433 check_option(struct client_lease *l, int option) 2434 { 2435 char *opbuf; 2436 char *sbuf; 2437 2438 /* we use this, since this is what gets passed to dhclient-script */ 2439 2440 opbuf = pretty_print_option(option, l->options[option].data, 2441 l->options[option].len, 0, 0); 2442 2443 sbuf = option_as_string(option, l->options[option].data, 2444 l->options[option].len); 2445 2446 switch (option) { 2447 case DHO_SUBNET_MASK: 2448 case DHO_TIME_SERVERS: 2449 case DHO_NAME_SERVERS: 2450 case DHO_ROUTERS: 2451 case DHO_DOMAIN_NAME_SERVERS: 2452 case DHO_LOG_SERVERS: 2453 case DHO_COOKIE_SERVERS: 2454 case DHO_LPR_SERVERS: 2455 case DHO_IMPRESS_SERVERS: 2456 case DHO_RESOURCE_LOCATION_SERVERS: 2457 case DHO_SWAP_SERVER: 2458 case DHO_BROADCAST_ADDRESS: 2459 case DHO_NIS_SERVERS: 2460 case DHO_NTP_SERVERS: 2461 case DHO_NETBIOS_NAME_SERVERS: 2462 case DHO_NETBIOS_DD_SERVER: 2463 case DHO_FONT_SERVERS: 2464 case DHO_DHCP_SERVER_IDENTIFIER: 2465 case DHO_NISPLUS_SERVERS: 2466 case DHO_MOBILE_IP_HOME_AGENT: 2467 case DHO_SMTP_SERVER: 2468 case DHO_POP_SERVER: 2469 case DHO_NNTP_SERVER: 2470 case DHO_WWW_SERVER: 2471 case DHO_FINGER_SERVER: 2472 case DHO_IRC_SERVER: 2473 case DHO_STREETTALK_SERVER: 2474 case DHO_STREETTALK_DA_SERVER: 2475 if (!ipv4addrs(opbuf)) { 2476 warning("Invalid IP address in option: %s", opbuf); 2477 return (0); 2478 } 2479 return (1) ; 2480 case DHO_HOST_NAME: 2481 case DHO_NIS_DOMAIN: 2482 case DHO_NISPLUS_DOMAIN: 2483 case DHO_TFTP_SERVER_NAME: 2484 if (!res_hnok(sbuf)) { 2485 warning("Bogus Host Name option %d: %s (%s)", option, 2486 sbuf, opbuf); 2487 l->options[option].len = 0; 2488 free(l->options[option].data); 2489 } 2490 return (1); 2491 case DHO_DOMAIN_NAME: 2492 case DHO_DOMAIN_SEARCH: 2493 if (!res_hnok(sbuf)) { 2494 if (!check_search(sbuf)) { 2495 warning("Bogus domain search list %d: %s (%s)", 2496 option, sbuf, opbuf); 2497 l->options[option].len = 0; 2498 free(l->options[option].data); 2499 } 2500 } 2501 return (1); 2502 case DHO_PAD: 2503 case DHO_TIME_OFFSET: 2504 case DHO_BOOT_SIZE: 2505 case DHO_MERIT_DUMP: 2506 case DHO_ROOT_PATH: 2507 case DHO_EXTENSIONS_PATH: 2508 case DHO_IP_FORWARDING: 2509 case DHO_NON_LOCAL_SOURCE_ROUTING: 2510 case DHO_POLICY_FILTER: 2511 case DHO_MAX_DGRAM_REASSEMBLY: 2512 case DHO_DEFAULT_IP_TTL: 2513 case DHO_PATH_MTU_AGING_TIMEOUT: 2514 case DHO_PATH_MTU_PLATEAU_TABLE: 2515 case DHO_INTERFACE_MTU: 2516 case DHO_ALL_SUBNETS_LOCAL: 2517 case DHO_PERFORM_MASK_DISCOVERY: 2518 case DHO_MASK_SUPPLIER: 2519 case DHO_ROUTER_DISCOVERY: 2520 case DHO_ROUTER_SOLICITATION_ADDRESS: 2521 case DHO_STATIC_ROUTES: 2522 case DHO_TRAILER_ENCAPSULATION: 2523 case DHO_ARP_CACHE_TIMEOUT: 2524 case DHO_IEEE802_3_ENCAPSULATION: 2525 case DHO_DEFAULT_TCP_TTL: 2526 case DHO_TCP_KEEPALIVE_INTERVAL: 2527 case DHO_TCP_KEEPALIVE_GARBAGE: 2528 case DHO_VENDOR_ENCAPSULATED_OPTIONS: 2529 case DHO_NETBIOS_NODE_TYPE: 2530 case DHO_NETBIOS_SCOPE: 2531 case DHO_X_DISPLAY_MANAGER: 2532 case DHO_DHCP_REQUESTED_ADDRESS: 2533 case DHO_DHCP_LEASE_TIME: 2534 case DHO_DHCP_OPTION_OVERLOAD: 2535 case DHO_DHCP_MESSAGE_TYPE: 2536 case DHO_DHCP_PARAMETER_REQUEST_LIST: 2537 case DHO_DHCP_MESSAGE: 2538 case DHO_DHCP_MAX_MESSAGE_SIZE: 2539 case DHO_DHCP_RENEWAL_TIME: 2540 case DHO_DHCP_REBINDING_TIME: 2541 case DHO_DHCP_CLASS_IDENTIFIER: 2542 case DHO_DHCP_CLIENT_IDENTIFIER: 2543 case DHO_BOOTFILE_NAME: 2544 case DHO_DHCP_USER_CLASS_ID: 2545 case DHO_END: 2546 return (1); 2547 case DHO_CLASSLESS_ROUTES: 2548 return (check_classless_option(l->options[option].data, 2549 l->options[option].len)); 2550 default: 2551 warning("unknown dhcp option value 0x%x", option); 2552 return (unknown_ok); 2553 } 2554 } 2555 2556 /* RFC 3442 The Classless Static Routes option checks */ 2557 int 2558 check_classless_option(unsigned char *data, int len) 2559 { 2560 int i = 0; 2561 unsigned char width; 2562 in_addr_t addr, mask; 2563 2564 if (len < 5) { 2565 warning("Too small length: %d", len); 2566 return (0); 2567 } 2568 while(i < len) { 2569 width = data[i++]; 2570 if (width == 0) { 2571 i += 4; 2572 continue; 2573 } else if (width < 9) { 2574 addr = (in_addr_t)(data[i] << 24); 2575 i += 1; 2576 } else if (width < 17) { 2577 addr = (in_addr_t)(data[i] << 24) + 2578 (in_addr_t)(data[i + 1] << 16); 2579 i += 2; 2580 } else if (width < 25) { 2581 addr = (in_addr_t)(data[i] << 24) + 2582 (in_addr_t)(data[i + 1] << 16) + 2583 (in_addr_t)(data[i + 2] << 8); 2584 i += 3; 2585 } else if (width < 33) { 2586 addr = (in_addr_t)(data[i] << 24) + 2587 (in_addr_t)(data[i + 1] << 16) + 2588 (in_addr_t)(data[i + 2] << 8) + 2589 data[i + 3]; 2590 i += 4; 2591 } else { 2592 warning("Incorrect subnet width: %d", width); 2593 return (0); 2594 } 2595 mask = (in_addr_t)(~0) << (32 - width); 2596 addr = ntohl(addr); 2597 mask = ntohl(mask); 2598 2599 /* 2600 * From RFC 3442: 2601 * ... After deriving a subnet number and subnet mask 2602 * from each destination descriptor, the DHCP client 2603 * MUST zero any bits in the subnet number where the 2604 * corresponding bit in the mask is zero... 2605 */ 2606 if ((addr & mask) != addr) { 2607 addr &= mask; 2608 data[i - 1] = (unsigned char)( 2609 (addr >> (((32 - width)/8)*8)) & 0xFF); 2610 } 2611 i += 4; 2612 } 2613 if (i > len) { 2614 warning("Incorrect data length: %d (must be %d)", len, i); 2615 return (0); 2616 } 2617 return (1); 2618 } 2619 2620 int 2621 res_hnok(const char *dn) 2622 { 2623 int pch = PERIOD, ch = *dn++; 2624 2625 while (ch != '\0') { 2626 int nch = *dn++; 2627 2628 if (periodchar(ch)) { 2629 ; 2630 } else if (periodchar(pch)) { 2631 if (!borderchar(ch)) 2632 return (0); 2633 } else if (periodchar(nch) || nch == '\0') { 2634 if (!borderchar(ch)) 2635 return (0); 2636 } else { 2637 if (!middlechar(ch)) 2638 return (0); 2639 } 2640 pch = ch, ch = nch; 2641 } 2642 return (1); 2643 } 2644 2645 int 2646 check_search(const char *srch) 2647 { 2648 int pch = PERIOD, ch = *srch++; 2649 int domains = 1; 2650 2651 /* 256 char limit re resolv.conf(5) */ 2652 if (strlen(srch) > 256) 2653 return (0); 2654 2655 while (whitechar(ch)) 2656 ch = *srch++; 2657 2658 while (ch != '\0') { 2659 int nch = *srch++; 2660 2661 if (periodchar(ch) || whitechar(ch)) { 2662 ; 2663 } else if (periodchar(pch)) { 2664 if (!borderchar(ch)) 2665 return (0); 2666 } else if (periodchar(nch) || nch == '\0') { 2667 if (!borderchar(ch)) 2668 return (0); 2669 } else { 2670 if (!middlechar(ch)) 2671 return (0); 2672 } 2673 if (!whitechar(ch)) { 2674 pch = ch; 2675 } else { 2676 while (whitechar(nch)) { 2677 nch = *srch++; 2678 } 2679 if (nch != '\0') 2680 domains++; 2681 pch = PERIOD; 2682 } 2683 ch = nch; 2684 } 2685 /* 6 domain limit re resolv.conf(5) */ 2686 if (domains > 6) 2687 return (0); 2688 return (1); 2689 } 2690 2691 /* Does buf consist only of dotted decimal ipv4 addrs? 2692 * return how many if so, 2693 * otherwise, return 0 2694 */ 2695 int 2696 ipv4addrs(char * buf) 2697 { 2698 struct in_addr jnk; 2699 int count = 0; 2700 2701 while (inet_aton(buf, &jnk) == 1){ 2702 count++; 2703 while (periodchar(*buf) || digitchar(*buf)) 2704 buf++; 2705 if (*buf == '\0') 2706 return (count); 2707 while (*buf == ' ') 2708 buf++; 2709 } 2710 return (0); 2711 } 2712 2713 2714 char * 2715 option_as_string(unsigned int code, unsigned char *data, int len) 2716 { 2717 static char optbuf[32768]; /* XXX */ 2718 char *op = optbuf; 2719 int opleft = sizeof(optbuf); 2720 unsigned char *dp = data; 2721 2722 if (code > 255) 2723 error("option_as_string: bad code %d", code); 2724 2725 for (; dp < data + len; dp++) { 2726 if (!isascii(*dp) || !isprint(*dp)) { 2727 if (dp + 1 != data + len || *dp != 0) { 2728 snprintf(op, opleft, "\\%03o", *dp); 2729 op += 4; 2730 opleft -= 4; 2731 } 2732 } else if (*dp == '"' || *dp == '\'' || *dp == '$' || 2733 *dp == '`' || *dp == '\\') { 2734 *op++ = '\\'; 2735 *op++ = *dp; 2736 opleft -= 2; 2737 } else { 2738 *op++ = *dp; 2739 opleft--; 2740 } 2741 } 2742 if (opleft < 1) 2743 goto toobig; 2744 *op = 0; 2745 return optbuf; 2746 toobig: 2747 warning("dhcp option too large"); 2748 return "<error>"; 2749 } 2750 2751 int 2752 fork_privchld(int fd, int fd2) 2753 { 2754 struct pollfd pfd[1]; 2755 int nfds; 2756 2757 switch (fork()) { 2758 case -1: 2759 error("cannot fork"); 2760 case 0: 2761 break; 2762 default: 2763 return (0); 2764 } 2765 2766 setproctitle("%s [priv]", ifi->name); 2767 2768 setsid(); 2769 dup2(nullfd, STDIN_FILENO); 2770 dup2(nullfd, STDOUT_FILENO); 2771 dup2(nullfd, STDERR_FILENO); 2772 close(nullfd); 2773 close(fd2); 2774 close(ifi->rfdesc); 2775 ifi->rfdesc = -1; 2776 2777 for (;;) { 2778 pfd[0].fd = fd; 2779 pfd[0].events = POLLIN; 2780 if ((nfds = poll(pfd, 1, INFTIM)) == -1) 2781 if (errno != EINTR) 2782 error("poll error"); 2783 2784 if (nfds == 0 || !(pfd[0].revents & POLLIN)) 2785 continue; 2786 2787 dispatch_imsg(ifi, fd); 2788 } 2789 } 2790