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