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