1 /* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
4 * Copyright 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 1995, 1996, 1997, 1998, 1999
6 * The Internet Software Consortium. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
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.
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
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''.
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
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
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
62 #include <sys/capsicum.h>
63 #include <sys/endian.h>
65 #include <net80211/ieee80211_freebsd.h>
67 #ifndef _PATH_VAREMPTY
68 #define _PATH_VAREMPTY "/var/empty"
72 #define hyphenchar(c) ((c) == 0x2d)
73 #define bslashchar(c) ((c) == 0x5c)
74 #define periodchar(c) ((c) == PERIOD)
75 #define asterchar(c) ((c) == 0x2a)
76 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
77 ((c) >= 0x61 && (c) <= 0x7a))
78 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
79 #define whitechar(c) ((c) == ' ' || (c) == '\t')
81 #define borderchar(c) (alphachar(c) || digitchar(c))
82 #define middlechar(c) (borderchar(c) || hyphenchar(c))
83 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
85 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
88 time_t default_lease_time = 43200; /* 12 hours... */
90 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
91 char *path_dhclient_db = NULL;
97 char hostname[_POSIX_HOST_NAME_MAX + 1];
99 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
100 struct in_addr inaddr_any, inaddr_broadcast;
102 char *path_dhclient_pidfile;
103 struct pidfh *pidfile;
106 * ASSERT_STATE() does nothing now; it used to be
107 * assert (state_is == state_shouldbe).
109 #define ASSERT_STATE(state_is, state_shouldbe) {}
112 * We need to check that the expiry, renewal and rebind times are not beyond
113 * the end of time (~2038 when a 32-bit time_t is being used).
115 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
122 struct interface_info *ifi;
124 int findproto(char *, int);
125 struct sockaddr *get_ifa(char *, int);
126 void routehandler(struct protocol *);
128 int check_option(struct client_lease *l, int option);
129 int check_classless_option(unsigned char *data, int len);
130 int ipv4addrs(char * buf);
131 int res_hnok(const char *dn);
132 int check_search(const char *srch);
133 char *option_as_string(unsigned int code, unsigned char *data, int len);
134 int fork_privchld(int, int);
137 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
138 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
140 /* Minimum MTU is 68 as per RFC791, p. 24 */
143 static time_t scripttime;
146 findproto(char *cp, int n)
153 for (i = 1; i; i <<= 1) {
155 sa = (struct sockaddr *)cp;
161 if (sa->sa_family == AF_INET)
163 if (sa->sa_family == AF_INET6)
176 get_ifa(char *cp, int n)
183 for (i = 1; i; i <<= 1)
185 sa = (struct sockaddr *)cp;
194 struct iaddr defaddr = { 4 };
200 struct interface_info *ifi = arg;
203 * Clear existing state.
205 if (ifi->client->active != NULL) {
206 script_init("EXPIRE", NULL);
207 script_write_params("old_",
208 ifi->client->active);
209 if (ifi->client->alias)
210 script_write_params("alias_",
214 ifi->client->state = S_INIT;
219 routehandler(struct protocol *p)
221 char msg[2048], *addr;
222 struct rt_msghdr *rtm;
223 struct if_msghdr *ifm;
224 struct ifa_msghdr *ifam;
225 struct if_announcemsghdr *ifan;
226 struct ieee80211_join_event *jev;
227 struct client_lease *l;
228 time_t t = time(NULL);
234 n = read(routefd, &msg, sizeof(msg));
235 rtm = (struct rt_msghdr *)msg;
236 if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
237 rtm->rtm_version != RTM_VERSION)
240 switch (rtm->rtm_type) {
243 ifam = (struct ifa_msghdr *)rtm;
245 if (ifam->ifam_index != ifi->index)
247 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
249 if (scripttime == 0 || t < scripttime + 10)
252 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
256 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
257 error("king bula sez: len mismatch");
258 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
259 if (addr_eq(a, defaddr))
262 for (l = ifi->client->active; l != NULL; l = l->next)
263 if (addr_eq(a, l->address))
266 if (l == NULL) /* added/deleted addr is not the one we set */
269 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
270 if (rtm->rtm_type == RTM_NEWADDR) {
272 * XXX: If someone other than us adds our address,
273 * should we assume they are taking over from us,
274 * delete the lease record, and exit without modifying
277 warning("My address (%s) was re-added", addr);
279 warning("My address (%s) was deleted, dhclient exiting",
285 ifm = (struct if_msghdr *)rtm;
286 if (ifm->ifm_index != ifi->index)
288 if ((rtm->rtm_flags & RTF_UP) == 0) {
289 warning("Interface %s is down, dhclient exiting",
293 linkstat = interface_link_status(ifi->name);
294 if (linkstat != ifi->linkstat) {
295 debug("%s link state %s -> %s", ifi->name,
296 ifi->linkstat ? "up" : "down",
297 linkstat ? "up" : "down");
298 ifi->linkstat = linkstat;
304 ifan = (struct if_announcemsghdr *)rtm;
305 if (ifan->ifan_what == IFAN_DEPARTURE &&
306 ifan->ifan_index == ifi->index) {
307 warning("Interface %s is gone, dhclient exiting",
313 ifan = (struct if_announcemsghdr *)rtm;
314 if (ifan->ifan_index != ifi->index)
316 switch (ifan->ifan_what) {
317 case RTM_IEEE80211_ASSOC:
318 case RTM_IEEE80211_REASSOC:
320 * Use assoc/reassoc event to kick state machine
321 * in case we roam. Otherwise fall back to the
322 * normal state machine just like a wired network.
324 jev = (struct ieee80211_join_event *) &ifan[1];
325 if (memcmp(curbssid, jev->iev_addr, 6)) {
329 memcpy(curbssid, jev->iev_addr, 6);
339 script_init("FAIL", NULL);
340 if (ifi->client->alias)
341 script_write_params("alias_", ifi->client->alias);
344 pidfile_remove(pidfile);
349 main(int argc, char *argv[])
351 extern char *__progname;
352 int ch, fd, quiet = 0, i = 0;
354 int immediate_daemon = 0;
359 /* Initially, log errors to stderr as well as to syslogd. */
360 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
361 setlogmask(LOG_UPTO(LOG_DEBUG));
363 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
366 immediate_daemon = 1;
369 path_dhclient_conf = optarg;
375 path_dhclient_db = optarg;
378 path_dhclient_pidfile = optarg;
396 if (path_dhclient_pidfile == NULL) {
397 asprintf(&path_dhclient_pidfile,
398 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
399 if (path_dhclient_pidfile == NULL)
402 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
403 if (pidfile == NULL) {
405 error("dhclient already running, pid: %d.", otherpid);
407 error("dhclient already running.");
408 warning("Cannot open or create pidfile: %m");
411 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
413 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
414 error("Interface name too long");
415 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
416 _PATH_DHCLIENT_DB, ifi->name) == -1)
425 inaddr_broadcast.s_addr = INADDR_BROADCAST;
426 inaddr_any.s_addr = INADDR_ANY;
430 /* The next bit is potentially very time-consuming, so write out
431 the pidfile right away. We will write it out again with the
432 correct pid after daemonizing. */
434 pidfile_write(pidfile);
436 if (!interface_link_status(ifi->name)) {
437 fprintf(stderr, "%s: no link ...", ifi->name);
440 while (!interface_link_status(ifi->name)) {
441 fprintf(stderr, ".");
444 fprintf(stderr, " giving up\n");
449 fprintf(stderr, " got link\n");
453 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
454 error("cannot open %s: %m", _PATH_DEVNULL);
456 if ((pw = getpwnam("_dhcp")) == NULL) {
457 warning("no such user: _dhcp, falling back to \"nobody\"");
458 if ((pw = getpwnam("nobody")) == NULL)
459 error("no such user: nobody");
463 * Obtain hostname before entering capability mode - it won't be
464 * possible then, as reading kern.hostname is not permitted.
466 if (gethostname(hostname, sizeof(hostname)) < 0)
469 priv_script_init("PREINIT", NULL);
470 if (ifi->client->alias)
471 priv_script_write_params("alias_", ifi->client->alias);
474 /* set up the interface */
475 discover_interfaces(ifi);
477 if (pipe(pipe_fd) == -1)
480 fork_privchld(pipe_fd[0], pipe_fd[1]);
489 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
490 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
491 error("can't limit private descriptor: %m");
493 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
494 error("can't open and lock %s: %m", path_dhclient_db);
495 read_client_leases();
496 rewrite_client_leases();
499 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
500 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
501 if (shutdown(routefd, SHUT_WR) < 0)
502 error("can't shutdown route socket: %m");
503 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
504 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
505 error("can't limit route socket: %m");
507 if (chroot(_PATH_VAREMPTY) == -1)
509 if (chdir("/") == -1)
510 error("chdir(\"/\")");
512 if (setgroups(1, &pw->pw_gid) ||
513 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
514 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
515 error("can't drop privileges: %m");
519 setproctitle("%s", ifi->name);
521 if (cap_enter() < 0 && errno != ENOSYS)
522 error("can't enter capability mode: %m");
524 if (immediate_daemon)
527 ifi->client->state = S_INIT;
530 bootp_packet_handler = do_packet;
541 extern char *__progname;
543 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
544 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
551 * Each routine is called from the dhclient_state_machine() in one of
553 * -> entering INIT state
554 * -> recvpacket_flag == 0: timeout in this state
555 * -> otherwise: received a packet in this state
557 * Return conditions as handled by dhclient_state_machine():
558 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
559 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
560 * Returns 0: finish the nap which was interrupted for no good reason.
562 * Several per-interface variables are used to keep track of the process:
563 * active_lease: the lease that is being used on the interface
564 * (null pointer if not configured yet).
565 * offered_leases: leases corresponding to DHCPOFFER messages that have
566 * been sent to us by DHCP servers.
567 * acked_leases: leases corresponding to DHCPACK messages that have been
568 * sent to us by DHCP servers.
569 * sendpacket: DHCP packet we're trying to send.
570 * destination: IP address to send sendpacket to
571 * In addition, there are several relevant per-lease variables.
572 * T1_expiry, T2_expiry, lease_expiry: lease milestones
573 * In the active lease, these control the process of renewing the lease;
574 * In leases on the acked_leases list, this simply determines when we
575 * can no longer legitimately use the lease.
579 state_reboot(void *ipp)
581 struct interface_info *ip = ipp;
583 /* If we don't remember an active lease, go straight to INIT. */
584 if (!ip->client->active || ip->client->active->is_bootp) {
589 /* We are in the rebooting state. */
590 ip->client->state = S_REBOOTING;
592 /* make_request doesn't initialize xid because it normally comes
593 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
594 so pick an xid now. */
595 ip->client->xid = arc4random();
597 /* Make a DHCPREQUEST packet, and set appropriate per-interface
599 make_request(ip, ip->client->active);
600 ip->client->destination = iaddr_broadcast;
601 ip->client->first_sending = cur_time;
602 ip->client->interval = ip->client->config->initial_interval;
604 /* Zap the medium list... */
605 ip->client->medium = NULL;
607 /* Send out the first DHCPREQUEST packet. */
612 * Called when a lease has completely expired and we've
613 * been unable to renew it.
616 state_init(void *ipp)
618 struct interface_info *ip = ipp;
620 ASSERT_STATE(state, S_INIT);
622 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
624 make_discover(ip, ip->client->active);
625 ip->client->xid = ip->client->packet.xid;
626 ip->client->destination = iaddr_broadcast;
627 ip->client->state = S_SELECTING;
628 ip->client->first_sending = cur_time;
629 ip->client->interval = ip->client->config->initial_interval;
631 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
637 * state_selecting is called when one or more DHCPOFFER packets
638 * have been received and a configurable period of time has passed.
641 state_selecting(void *ipp)
643 struct interface_info *ip = ipp;
644 struct client_lease *lp, *next, *picked;
646 ASSERT_STATE(state, S_SELECTING);
648 /* Cancel state_selecting and send_discover timeouts, since either
649 one could have got us here. */
650 cancel_timeout(state_selecting, ip);
651 cancel_timeout(send_discover, ip);
653 /* We have received one or more DHCPOFFER packets. Currently,
654 the only criterion by which we judge leases is whether or
655 not we get a response when we arp for them. */
657 for (lp = ip->client->offered_leases; lp; lp = next) {
660 /* Check to see if we got an ARPREPLY for the address
661 in this particular lease. */
663 script_init("ARPCHECK", lp->medium);
664 script_write_params("check_", lp);
666 /* If the ARPCHECK code detects another
667 machine using the offered address, it exits
668 nonzero. We need to send a DHCPDECLINE and
671 make_decline(ip, lp);
679 free_client_lease(lp);
682 ip->client->offered_leases = NULL;
684 /* If we just tossed all the leases we were offered, go back
687 ip->client->state = S_INIT;
692 /* If it was a BOOTREPLY, we can just take the address right now. */
693 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
694 ip->client->new = picked;
696 /* Make up some lease expiry times
697 XXX these should be configurable. */
698 ip->client->new->expiry = cur_time + 12000;
699 ip->client->new->renewal += cur_time + 8000;
700 ip->client->new->rebind += cur_time + 10000;
702 ip->client->state = S_REQUESTING;
704 /* Bind to the address we received. */
709 /* Go to the REQUESTING state. */
710 ip->client->destination = iaddr_broadcast;
711 ip->client->state = S_REQUESTING;
712 ip->client->first_sending = cur_time;
713 ip->client->interval = ip->client->config->initial_interval;
715 /* Make a DHCPREQUEST packet from the lease we picked. */
716 make_request(ip, picked);
717 ip->client->xid = ip->client->packet.xid;
719 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
720 free_client_lease(picked);
722 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
726 /* state_requesting is called when we receive a DHCPACK message after
727 having sent out one or more DHCPREQUEST packets. */
730 dhcpack(struct packet *packet)
732 struct interface_info *ip = packet->interface;
733 struct client_lease *lease;
735 /* If we're not receptive to an offer right now, or if the offer
736 has an unrecognizable transaction id, then just drop it. */
737 if (packet->interface->client->xid != packet->raw->xid ||
738 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
739 (memcmp(packet->interface->hw_address.haddr,
740 packet->raw->chaddr, packet->raw->hlen)))
743 if (ip->client->state != S_REBOOTING &&
744 ip->client->state != S_REQUESTING &&
745 ip->client->state != S_RENEWING &&
746 ip->client->state != S_REBINDING)
749 note("DHCPACK from %s", piaddr(packet->client_addr));
751 lease = packet_to_lease(packet);
753 note("packet_to_lease failed.");
757 ip->client->new = lease;
759 /* Stop resending DHCPREQUEST. */
760 cancel_timeout(send_request, ip);
762 /* Figure out the lease time. */
763 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
765 ip->client->new->expiry = getULong(
766 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
767 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
768 ip->client->new->expiry = getULong(
769 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
771 ip->client->new->expiry = default_lease_time;
772 /* A number that looks negative here is really just very large,
773 because the lease expiry offset is unsigned. Also make sure that
774 the addition of cur_time below does not overflow (a 32 bit) time_t. */
775 if (ip->client->new->expiry < 0 ||
776 ip->client->new->expiry > TIME_MAX - cur_time)
777 ip->client->new->expiry = TIME_MAX - cur_time;
778 /* XXX should be fixed by resetting the client state */
779 if (ip->client->new->expiry < 60)
780 ip->client->new->expiry = 60;
782 /* Unless overridden in the config, take the server-provided renewal
783 * time if there is one. Otherwise figure it out according to the spec.
784 * Also make sure the renewal time does not exceed the expiry time.
786 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
788 ip->client->new->renewal = getULong(
789 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
790 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
791 ip->client->new->renewal = getULong(
792 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
794 ip->client->new->renewal = ip->client->new->expiry / 2;
795 if (ip->client->new->renewal < 0 ||
796 ip->client->new->renewal > ip->client->new->expiry / 2)
797 ip->client->new->renewal = ip->client->new->expiry / 2;
799 /* Same deal with the rebind time. */
800 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
802 ip->client->new->rebind = getULong(
803 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
804 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
805 ip->client->new->rebind = getULong(
806 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
808 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
809 if (ip->client->new->rebind < 0 ||
810 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
811 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
813 /* Convert the time offsets into seconds-since-the-epoch */
814 ip->client->new->expiry += cur_time;
815 ip->client->new->renewal += cur_time;
816 ip->client->new->rebind += cur_time;
822 bind_lease(struct interface_info *ip)
824 struct option_data *opt;
826 /* Remember the medium. */
827 ip->client->new->medium = ip->client->medium;
829 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
830 if (opt->len == sizeof(u_int16_t)) {
831 u_int16_t mtu = be16dec(opt->data);
833 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
835 interface_set_mtu_unpriv(privfd, mtu);
838 /* Write out the new lease. */
839 write_client_lease(ip, ip->client->new, 0);
841 /* Run the client script with the new parameters. */
842 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
843 (ip->client->state == S_RENEWING ? "RENEW" :
844 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
845 ip->client->new->medium);
846 if (ip->client->active && ip->client->state != S_REBOOTING)
847 script_write_params("old_", ip->client->active);
848 script_write_params("new_", ip->client->new);
849 if (ip->client->alias)
850 script_write_params("alias_", ip->client->alias);
853 /* Replace the old active lease with the new one. */
854 if (ip->client->active)
855 free_client_lease(ip->client->active);
856 ip->client->active = ip->client->new;
857 ip->client->new = NULL;
859 /* Set up a timeout to start the renewal process. */
860 add_timeout(ip->client->active->renewal, state_bound, ip);
862 note("bound to %s -- renewal in %d seconds.",
863 piaddr(ip->client->active->address),
864 (int)(ip->client->active->renewal - cur_time));
865 ip->client->state = S_BOUND;
866 reinitialize_interfaces();
871 * state_bound is called when we've successfully bound to a particular
872 * lease, but the renewal time on that lease has expired. We are
873 * expected to unicast a DHCPREQUEST to the server that gave us our
877 state_bound(void *ipp)
879 struct interface_info *ip = ipp;
881 ASSERT_STATE(state, S_BOUND);
883 /* T1 has expired. */
884 make_request(ip, ip->client->active);
885 ip->client->xid = ip->client->packet.xid;
887 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
888 memcpy(ip->client->destination.iabuf, ip->client->active->
889 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
890 ip->client->destination.len = 4;
892 ip->client->destination = iaddr_broadcast;
894 ip->client->first_sending = cur_time;
895 ip->client->interval = ip->client->config->initial_interval;
896 ip->client->state = S_RENEWING;
898 /* Send the first packet immediately. */
903 bootp(struct packet *packet)
905 struct iaddrlist *ap;
907 if (packet->raw->op != BOOTREPLY)
910 /* If there's a reject list, make sure this packet's sender isn't
912 for (ap = packet->interface->client->config->reject_list;
914 if (addr_eq(packet->client_addr, ap->addr)) {
915 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
923 dhcp(struct packet *packet)
925 struct iaddrlist *ap;
926 void (*handler)(struct packet *);
929 switch (packet->packet_type) {
946 /* If there's a reject list, make sure this packet's sender isn't
948 for (ap = packet->interface->client->config->reject_list;
950 if (addr_eq(packet->client_addr, ap->addr)) {
951 note("%s from %s rejected.", type, piaddr(ap->addr));
959 dhcpoffer(struct packet *packet)
961 struct interface_info *ip = packet->interface;
962 struct client_lease *lease, *lp;
964 int arp_timeout_needed, stop_selecting;
965 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
966 "DHCPOFFER" : "BOOTREPLY";
968 /* If we're not receptive to an offer right now, or if the offer
969 has an unrecognizable transaction id, then just drop it. */
970 if (ip->client->state != S_SELECTING ||
971 packet->interface->client->xid != packet->raw->xid ||
972 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
973 (memcmp(packet->interface->hw_address.haddr,
974 packet->raw->chaddr, packet->raw->hlen)))
977 note("%s from %s", name, piaddr(packet->client_addr));
980 /* If this lease doesn't supply the minimum required parameters,
982 for (i = 0; ip->client->config->required_options[i]; i++) {
983 if (!packet->options[ip->client->config->
984 required_options[i]].len) {
985 note("%s isn't satisfactory.", name);
990 /* If we've already seen this lease, don't record it again. */
991 for (lease = ip->client->offered_leases;
992 lease; lease = lease->next) {
993 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
994 !memcmp(lease->address.iabuf,
995 &packet->raw->yiaddr, lease->address.len)) {
996 debug("%s already seen.", name);
1001 lease = packet_to_lease(packet);
1003 note("packet_to_lease failed.");
1007 /* If this lease was acquired through a BOOTREPLY, record that
1009 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1010 lease->is_bootp = 1;
1012 /* Record the medium under which this lease was offered. */
1013 lease->medium = ip->client->medium;
1015 /* Send out an ARP Request for the offered IP address. */
1016 script_init("ARPSEND", lease->medium);
1017 script_write_params("check_", lease);
1018 /* If the script can't send an ARP request without waiting,
1019 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1021 arp_timeout_needed = 0;
1023 arp_timeout_needed = 2;
1025 /* Figure out when we're supposed to stop selecting. */
1027 ip->client->first_sending + ip->client->config->select_interval;
1029 /* If this is the lease we asked for, put it at the head of the
1030 list, and don't mess with the arp request timeout. */
1031 if (lease->address.len == ip->client->requested_address.len &&
1032 !memcmp(lease->address.iabuf,
1033 ip->client->requested_address.iabuf,
1034 ip->client->requested_address.len)) {
1035 lease->next = ip->client->offered_leases;
1036 ip->client->offered_leases = lease;
1038 /* If we already have an offer, and arping for this
1039 offer would take us past the selection timeout,
1040 then don't extend the timeout - just hope for the
1042 if (ip->client->offered_leases &&
1043 (cur_time + arp_timeout_needed) > stop_selecting)
1044 arp_timeout_needed = 0;
1046 /* Put the lease at the end of the list. */
1048 if (!ip->client->offered_leases)
1049 ip->client->offered_leases = lease;
1051 for (lp = ip->client->offered_leases; lp->next;
1058 /* If we're supposed to stop selecting before we've had time
1059 to wait for the ARPREPLY, add some delay to wait for
1061 if (stop_selecting - cur_time < arp_timeout_needed)
1062 stop_selecting = cur_time + arp_timeout_needed;
1064 /* If the selecting interval has expired, go immediately to
1065 state_selecting(). Otherwise, time out into
1066 state_selecting at the select interval. */
1067 if (stop_selecting <= 0)
1068 state_selecting(ip);
1070 add_timeout(stop_selecting, state_selecting, ip);
1071 cancel_timeout(send_discover, ip);
1075 /* Allocate a client_lease structure and initialize it from the parameters
1076 in the specified packet. */
1078 struct client_lease *
1079 packet_to_lease(struct packet *packet)
1081 struct client_lease *lease;
1084 lease = malloc(sizeof(struct client_lease));
1087 warning("dhcpoffer: no memory to record lease.");
1091 memset(lease, 0, sizeof(*lease));
1093 /* Copy the lease options. */
1094 for (i = 0; i < 256; i++) {
1095 if (packet->options[i].len) {
1096 lease->options[i].data =
1097 malloc(packet->options[i].len + 1);
1098 if (!lease->options[i].data) {
1099 warning("dhcpoffer: no memory for option %d", i);
1100 free_client_lease(lease);
1103 memcpy(lease->options[i].data,
1104 packet->options[i].data,
1105 packet->options[i].len);
1106 lease->options[i].len =
1107 packet->options[i].len;
1108 lease->options[i].data[lease->options[i].len] =
1111 if (!check_option(lease,i)) {
1112 /* ignore a bogus lease offer */
1113 warning("Invalid lease option - ignoring offer");
1114 free_client_lease(lease);
1120 lease->address.len = sizeof(packet->raw->yiaddr);
1121 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1123 lease->nextserver.len = sizeof(packet->raw->siaddr);
1124 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1126 /* If the server name was filled out, copy it.
1127 Do not attempt to validate the server name as a host name.
1128 RFC 2131 merely states that sname is NUL-terminated (which do
1129 do not assume) and that it is the server's host name. Since
1130 the ISC client and server allow arbitrary characters, we do
1132 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1133 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1134 packet->raw->sname[0]) {
1135 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1136 if (!lease->server_name) {
1137 warning("dhcpoffer: no memory for server name.");
1138 free_client_lease(lease);
1141 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1142 lease->server_name[DHCP_SNAME_LEN]='\0';
1145 /* Ditto for the filename. */
1146 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1147 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1148 packet->raw->file[0]) {
1149 /* Don't count on the NUL terminator. */
1150 lease->filename = malloc(DHCP_FILE_LEN + 1);
1151 if (!lease->filename) {
1152 warning("dhcpoffer: no memory for filename.");
1153 free_client_lease(lease);
1156 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1157 lease->filename[DHCP_FILE_LEN]='\0';
1163 dhcpnak(struct packet *packet)
1165 struct interface_info *ip = packet->interface;
1167 /* If we're not receptive to an offer right now, or if the offer
1168 has an unrecognizable transaction id, then just drop it. */
1169 if (packet->interface->client->xid != packet->raw->xid ||
1170 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1171 (memcmp(packet->interface->hw_address.haddr,
1172 packet->raw->chaddr, packet->raw->hlen)))
1175 if (ip->client->state != S_REBOOTING &&
1176 ip->client->state != S_REQUESTING &&
1177 ip->client->state != S_RENEWING &&
1178 ip->client->state != S_REBINDING)
1181 note("DHCPNAK from %s", piaddr(packet->client_addr));
1183 if (!ip->client->active) {
1184 note("DHCPNAK with no active lease.\n");
1188 free_client_lease(ip->client->active);
1189 ip->client->active = NULL;
1191 /* Stop sending DHCPREQUEST packets... */
1192 cancel_timeout(send_request, ip);
1194 ip->client->state = S_INIT;
1198 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1199 one after the right interval has expired. If we don't get an offer by
1200 the time we reach the panic interval, call the panic function. */
1203 send_discover(void *ipp)
1205 struct interface_info *ip = ipp;
1206 int interval, increase = 1;
1208 /* Figure out how long it's been since we started transmitting. */
1209 interval = cur_time - ip->client->first_sending;
1211 /* If we're past the panic timeout, call the script and tell it
1212 we haven't found anything for this interface yet. */
1213 if (interval > ip->client->config->timeout) {
1218 /* If we're selecting media, try the whole list before doing
1219 the exponential backoff, but if we've already received an
1220 offer, stop looping, because we obviously have it right. */
1221 if (!ip->client->offered_leases &&
1222 ip->client->config->media) {
1225 if (ip->client->medium) {
1226 ip->client->medium = ip->client->medium->next;
1229 if (!ip->client->medium) {
1231 error("No valid media types for %s!", ip->name);
1232 ip->client->medium = ip->client->config->media;
1236 note("Trying medium \"%s\" %d", ip->client->medium->string,
1238 script_init("MEDIUM", ip->client->medium);
1244 * If we're supposed to increase the interval, do so. If it's
1245 * currently zero (i.e., we haven't sent any packets yet), set
1246 * it to one; otherwise, add to it a random number between zero
1247 * and two times itself. On average, this means that it will
1248 * double with every transmission.
1251 if (!ip->client->interval)
1252 ip->client->interval =
1253 ip->client->config->initial_interval;
1255 ip->client->interval += (arc4random() >> 2) %
1256 (2 * ip->client->interval);
1259 /* Don't backoff past cutoff. */
1260 if (ip->client->interval >
1261 ip->client->config->backoff_cutoff)
1262 ip->client->interval =
1263 ((ip->client->config->backoff_cutoff / 2)
1264 + ((arc4random() >> 2) %
1265 ip->client->config->backoff_cutoff));
1266 } else if (!ip->client->interval)
1267 ip->client->interval =
1268 ip->client->config->initial_interval;
1270 /* If the backoff would take us to the panic timeout, just use that
1272 if (cur_time + ip->client->interval >
1273 ip->client->first_sending + ip->client->config->timeout)
1274 ip->client->interval =
1275 (ip->client->first_sending +
1276 ip->client->config->timeout) - cur_time + 1;
1278 /* Record the number of seconds since we started sending. */
1279 if (interval < 65536)
1280 ip->client->packet.secs = htons(interval);
1282 ip->client->packet.secs = htons(65535);
1283 ip->client->secs = ip->client->packet.secs;
1285 note("DHCPDISCOVER on %s to %s port %d interval %d",
1286 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1287 (int)ip->client->interval);
1289 /* Send out a packet. */
1290 send_packet_unpriv(privfd, &ip->client->packet,
1291 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1293 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1297 * state_panic gets called if we haven't received any offers in a preset
1298 * amount of time. When this happens, we try to use existing leases
1299 * that haven't yet expired, and failing that, we call the client script
1300 * and hope it can do something.
1303 state_panic(void *ipp)
1305 struct interface_info *ip = ipp;
1306 struct client_lease *loop = ip->client->active;
1307 struct client_lease *lp;
1309 note("No DHCPOFFERS received.");
1311 /* We may not have an active lease, but we may have some
1312 predefined leases that we can try. */
1313 if (!ip->client->active && ip->client->leases)
1316 /* Run through the list of leases and see if one can be used. */
1317 while (ip->client->active) {
1318 if (ip->client->active->expiry > cur_time) {
1319 note("Trying recorded lease %s",
1320 piaddr(ip->client->active->address));
1321 /* Run the client script with the existing
1323 script_init("TIMEOUT",
1324 ip->client->active->medium);
1325 script_write_params("new_", ip->client->active);
1326 if (ip->client->alias)
1327 script_write_params("alias_",
1330 /* If the old lease is still good and doesn't
1331 yet need renewal, go into BOUND state and
1332 timeout at the renewal time. */
1335 ip->client->active->renewal) {
1336 ip->client->state = S_BOUND;
1337 note("bound: renewal in %d seconds.",
1338 (int)(ip->client->active->renewal -
1341 ip->client->active->renewal,
1344 ip->client->state = S_BOUND;
1345 note("bound: immediate renewal.");
1348 reinitialize_interfaces();
1354 /* If there are no other leases, give up. */
1355 if (!ip->client->leases) {
1356 ip->client->leases = ip->client->active;
1357 ip->client->active = NULL;
1362 /* Otherwise, put the active lease at the end of the
1363 lease list, and try another lease.. */
1364 for (lp = ip->client->leases; lp->next; lp = lp->next)
1366 lp->next = ip->client->active;
1368 lp->next->next = NULL;
1369 ip->client->active = ip->client->leases;
1370 ip->client->leases = ip->client->leases->next;
1372 /* If we already tried this lease, we've exhausted the
1373 set of leases, so we might as well give up for
1375 if (ip->client->active == loop)
1378 loop = ip->client->active;
1381 /* No leases were available, or what was available didn't work, so
1382 tell the shell script that we failed to allocate an address,
1383 and try again later. */
1384 note("No working leases in persistent database - sleeping.\n");
1385 script_init("FAIL", NULL);
1386 if (ip->client->alias)
1387 script_write_params("alias_", ip->client->alias);
1389 ip->client->state = S_INIT;
1390 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1396 send_request(void *ipp)
1398 struct interface_info *ip = ipp;
1399 struct in_addr from, to;
1402 /* Figure out how long it's been since we started transmitting. */
1403 interval = cur_time - ip->client->first_sending;
1405 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1406 past the reboot timeout, go to INIT and see if we can
1407 DISCOVER an address... */
1408 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1409 means either that we're on a network with no DHCP server,
1410 or that our server is down. In the latter case, assuming
1411 that there is a backup DHCP server, DHCPDISCOVER will get
1412 us a new address, but we could also have successfully
1413 reused our old address. In the former case, we're hosed
1414 anyway. This is not a win-prone situation. */
1415 if ((ip->client->state == S_REBOOTING ||
1416 ip->client->state == S_REQUESTING) &&
1417 interval > ip->client->config->reboot_timeout) {
1419 ip->client->state = S_INIT;
1420 cancel_timeout(send_request, ip);
1425 /* If we're in the reboot state, make sure the media is set up
1427 if (ip->client->state == S_REBOOTING &&
1428 !ip->client->medium &&
1429 ip->client->active->medium ) {
1430 script_init("MEDIUM", ip->client->active->medium);
1432 /* If the medium we chose won't fly, go to INIT state. */
1436 /* Record the medium. */
1437 ip->client->medium = ip->client->active->medium;
1440 /* If the lease has expired, relinquish the address and go back
1441 to the INIT state. */
1442 if (ip->client->state != S_REQUESTING &&
1443 cur_time > ip->client->active->expiry) {
1444 /* Run the client script with the new parameters. */
1445 script_init("EXPIRE", NULL);
1446 script_write_params("old_", ip->client->active);
1447 if (ip->client->alias)
1448 script_write_params("alias_", ip->client->alias);
1451 /* Now do a preinit on the interface so that we can
1452 discover a new address. */
1453 script_init("PREINIT", NULL);
1454 if (ip->client->alias)
1455 script_write_params("alias_", ip->client->alias);
1458 ip->client->state = S_INIT;
1463 /* Do the exponential backoff... */
1464 if (!ip->client->interval)
1465 ip->client->interval = ip->client->config->initial_interval;
1467 ip->client->interval += ((arc4random() >> 2) %
1468 (2 * ip->client->interval));
1470 /* Don't backoff past cutoff. */
1471 if (ip->client->interval >
1472 ip->client->config->backoff_cutoff)
1473 ip->client->interval =
1474 ((ip->client->config->backoff_cutoff / 2) +
1475 ((arc4random() >> 2) % ip->client->interval));
1477 /* If the backoff would take us to the expiry time, just set the
1478 timeout to the expiry time. */
1479 if (ip->client->state != S_REQUESTING &&
1480 cur_time + ip->client->interval >
1481 ip->client->active->expiry)
1482 ip->client->interval =
1483 ip->client->active->expiry - cur_time + 1;
1485 /* If the lease T2 time has elapsed, or if we're not yet bound,
1486 broadcast the DHCPREQUEST rather than unicasting. */
1487 if (ip->client->state == S_REQUESTING ||
1488 ip->client->state == S_REBOOTING ||
1489 cur_time > ip->client->active->rebind)
1490 to.s_addr = INADDR_BROADCAST;
1492 memcpy(&to.s_addr, ip->client->destination.iabuf,
1495 if (ip->client->state != S_REQUESTING)
1496 memcpy(&from, ip->client->active->address.iabuf,
1499 from.s_addr = INADDR_ANY;
1501 /* Record the number of seconds since we started sending. */
1502 if (ip->client->state == S_REQUESTING)
1503 ip->client->packet.secs = ip->client->secs;
1505 if (interval < 65536)
1506 ip->client->packet.secs = htons(interval);
1508 ip->client->packet.secs = htons(65535);
1511 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1514 /* Send out a packet. */
1515 send_packet_unpriv(privfd, &ip->client->packet,
1516 ip->client->packet_length, from, to);
1518 add_timeout(cur_time + ip->client->interval, send_request, ip);
1522 send_decline(void *ipp)
1524 struct interface_info *ip = ipp;
1526 note("DHCPDECLINE on %s to %s port %d", ip->name,
1527 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1529 /* Send out a packet. */
1530 send_packet_unpriv(privfd, &ip->client->packet,
1531 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1535 make_discover(struct interface_info *ip, struct client_lease *lease)
1537 unsigned char discover = DHCPDISCOVER;
1538 struct tree_cache *options[256];
1539 struct tree_cache option_elements[256];
1542 memset(option_elements, 0, sizeof(option_elements));
1543 memset(options, 0, sizeof(options));
1544 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1546 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1547 i = DHO_DHCP_MESSAGE_TYPE;
1548 options[i] = &option_elements[i];
1549 options[i]->value = &discover;
1550 options[i]->len = sizeof(discover);
1551 options[i]->buf_size = sizeof(discover);
1552 options[i]->timeout = 0xFFFFFFFF;
1554 /* Request the options we want */
1555 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1556 options[i] = &option_elements[i];
1557 options[i]->value = ip->client->config->requested_options;
1558 options[i]->len = ip->client->config->requested_option_count;
1559 options[i]->buf_size =
1560 ip->client->config->requested_option_count;
1561 options[i]->timeout = 0xFFFFFFFF;
1563 /* If we had an address, try to get it again. */
1565 ip->client->requested_address = lease->address;
1566 i = DHO_DHCP_REQUESTED_ADDRESS;
1567 options[i] = &option_elements[i];
1568 options[i]->value = lease->address.iabuf;
1569 options[i]->len = lease->address.len;
1570 options[i]->buf_size = lease->address.len;
1571 options[i]->timeout = 0xFFFFFFFF;
1573 ip->client->requested_address.len = 0;
1575 /* Send any options requested in the config file. */
1576 for (i = 0; i < 256; i++)
1578 ip->client->config->send_options[i].data) {
1579 options[i] = &option_elements[i];
1581 ip->client->config->send_options[i].data;
1583 ip->client->config->send_options[i].len;
1584 options[i]->buf_size =
1585 ip->client->config->send_options[i].len;
1586 options[i]->timeout = 0xFFFFFFFF;
1589 /* send host name if not set via config file. */
1590 if (!options[DHO_HOST_NAME]) {
1591 if (hostname[0] != '\0') {
1593 char* posDot = strchr(hostname, '.');
1595 len = posDot - hostname;
1597 len = strlen(hostname);
1598 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1599 options[DHO_HOST_NAME]->value = hostname;
1600 options[DHO_HOST_NAME]->len = len;
1601 options[DHO_HOST_NAME]->buf_size = len;
1602 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1606 /* set unique client identifier */
1607 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1608 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1609 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1610 ip->hw_address.hlen : sizeof(client_ident)-1;
1611 client_ident[0] = ip->hw_address.htype;
1612 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1613 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1614 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1615 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1616 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1617 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1620 /* Set up the option buffer... */
1621 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1622 options, 0, 0, 0, NULL, 0);
1623 if (ip->client->packet_length < BOOTP_MIN_LEN)
1624 ip->client->packet_length = BOOTP_MIN_LEN;
1626 ip->client->packet.op = BOOTREQUEST;
1627 ip->client->packet.htype = ip->hw_address.htype;
1628 ip->client->packet.hlen = ip->hw_address.hlen;
1629 ip->client->packet.hops = 0;
1630 ip->client->packet.xid = arc4random();
1631 ip->client->packet.secs = 0; /* filled in by send_discover. */
1632 ip->client->packet.flags = 0;
1634 memset(&(ip->client->packet.ciaddr),
1635 0, sizeof(ip->client->packet.ciaddr));
1636 memset(&(ip->client->packet.yiaddr),
1637 0, sizeof(ip->client->packet.yiaddr));
1638 memset(&(ip->client->packet.siaddr),
1639 0, sizeof(ip->client->packet.siaddr));
1640 memset(&(ip->client->packet.giaddr),
1641 0, sizeof(ip->client->packet.giaddr));
1642 memcpy(ip->client->packet.chaddr,
1643 ip->hw_address.haddr, ip->hw_address.hlen);
1648 make_request(struct interface_info *ip, struct client_lease * lease)
1650 unsigned char request = DHCPREQUEST;
1651 struct tree_cache *options[256];
1652 struct tree_cache option_elements[256];
1655 memset(options, 0, sizeof(options));
1656 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1658 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1659 i = DHO_DHCP_MESSAGE_TYPE;
1660 options[i] = &option_elements[i];
1661 options[i]->value = &request;
1662 options[i]->len = sizeof(request);
1663 options[i]->buf_size = sizeof(request);
1664 options[i]->timeout = 0xFFFFFFFF;
1666 /* Request the options we want */
1667 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1668 options[i] = &option_elements[i];
1669 options[i]->value = ip->client->config->requested_options;
1670 options[i]->len = ip->client->config->requested_option_count;
1671 options[i]->buf_size =
1672 ip->client->config->requested_option_count;
1673 options[i]->timeout = 0xFFFFFFFF;
1675 /* If we are requesting an address that hasn't yet been assigned
1676 to us, use the DHCP Requested Address option. */
1677 if (ip->client->state == S_REQUESTING) {
1678 /* Send back the server identifier... */
1679 i = DHO_DHCP_SERVER_IDENTIFIER;
1680 options[i] = &option_elements[i];
1681 options[i]->value = lease->options[i].data;
1682 options[i]->len = lease->options[i].len;
1683 options[i]->buf_size = lease->options[i].len;
1684 options[i]->timeout = 0xFFFFFFFF;
1686 if (ip->client->state == S_REQUESTING ||
1687 ip->client->state == S_REBOOTING) {
1688 ip->client->requested_address = lease->address;
1689 i = DHO_DHCP_REQUESTED_ADDRESS;
1690 options[i] = &option_elements[i];
1691 options[i]->value = lease->address.iabuf;
1692 options[i]->len = lease->address.len;
1693 options[i]->buf_size = lease->address.len;
1694 options[i]->timeout = 0xFFFFFFFF;
1696 ip->client->requested_address.len = 0;
1698 /* Send any options requested in the config file. */
1699 for (i = 0; i < 256; i++)
1701 ip->client->config->send_options[i].data) {
1702 options[i] = &option_elements[i];
1704 ip->client->config->send_options[i].data;
1706 ip->client->config->send_options[i].len;
1707 options[i]->buf_size =
1708 ip->client->config->send_options[i].len;
1709 options[i]->timeout = 0xFFFFFFFF;
1712 /* send host name if not set via config file. */
1713 if (!options[DHO_HOST_NAME]) {
1714 if (hostname[0] != '\0') {
1716 char* posDot = strchr(hostname, '.');
1718 len = posDot - hostname;
1720 len = strlen(hostname);
1721 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1722 options[DHO_HOST_NAME]->value = hostname;
1723 options[DHO_HOST_NAME]->len = len;
1724 options[DHO_HOST_NAME]->buf_size = len;
1725 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1729 /* set unique client identifier */
1730 char client_ident[sizeof(struct hardware)];
1731 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1732 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1733 ip->hw_address.hlen : sizeof(client_ident)-1;
1734 client_ident[0] = ip->hw_address.htype;
1735 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1736 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1737 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1738 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1739 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1740 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1743 /* Set up the option buffer... */
1744 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1745 options, 0, 0, 0, NULL, 0);
1746 if (ip->client->packet_length < BOOTP_MIN_LEN)
1747 ip->client->packet_length = BOOTP_MIN_LEN;
1749 ip->client->packet.op = BOOTREQUEST;
1750 ip->client->packet.htype = ip->hw_address.htype;
1751 ip->client->packet.hlen = ip->hw_address.hlen;
1752 ip->client->packet.hops = 0;
1753 ip->client->packet.xid = ip->client->xid;
1754 ip->client->packet.secs = 0; /* Filled in by send_request. */
1756 /* If we own the address we're requesting, put it in ciaddr;
1757 otherwise set ciaddr to zero. */
1758 if (ip->client->state == S_BOUND ||
1759 ip->client->state == S_RENEWING ||
1760 ip->client->state == S_REBINDING) {
1761 memcpy(&ip->client->packet.ciaddr,
1762 lease->address.iabuf, lease->address.len);
1763 ip->client->packet.flags = 0;
1765 memset(&ip->client->packet.ciaddr, 0,
1766 sizeof(ip->client->packet.ciaddr));
1767 ip->client->packet.flags = 0;
1770 memset(&ip->client->packet.yiaddr, 0,
1771 sizeof(ip->client->packet.yiaddr));
1772 memset(&ip->client->packet.siaddr, 0,
1773 sizeof(ip->client->packet.siaddr));
1774 memset(&ip->client->packet.giaddr, 0,
1775 sizeof(ip->client->packet.giaddr));
1776 memcpy(ip->client->packet.chaddr,
1777 ip->hw_address.haddr, ip->hw_address.hlen);
1781 make_decline(struct interface_info *ip, struct client_lease *lease)
1783 struct tree_cache *options[256], message_type_tree;
1784 struct tree_cache requested_address_tree;
1785 struct tree_cache server_id_tree, client_id_tree;
1786 unsigned char decline = DHCPDECLINE;
1789 memset(options, 0, sizeof(options));
1790 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1792 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1793 i = DHO_DHCP_MESSAGE_TYPE;
1794 options[i] = &message_type_tree;
1795 options[i]->value = &decline;
1796 options[i]->len = sizeof(decline);
1797 options[i]->buf_size = sizeof(decline);
1798 options[i]->timeout = 0xFFFFFFFF;
1800 /* Send back the server identifier... */
1801 i = DHO_DHCP_SERVER_IDENTIFIER;
1802 options[i] = &server_id_tree;
1803 options[i]->value = lease->options[i].data;
1804 options[i]->len = lease->options[i].len;
1805 options[i]->buf_size = lease->options[i].len;
1806 options[i]->timeout = 0xFFFFFFFF;
1808 /* Send back the address we're declining. */
1809 i = DHO_DHCP_REQUESTED_ADDRESS;
1810 options[i] = &requested_address_tree;
1811 options[i]->value = lease->address.iabuf;
1812 options[i]->len = lease->address.len;
1813 options[i]->buf_size = lease->address.len;
1814 options[i]->timeout = 0xFFFFFFFF;
1816 /* Send the uid if the user supplied one. */
1817 i = DHO_DHCP_CLIENT_IDENTIFIER;
1818 if (ip->client->config->send_options[i].len) {
1819 options[i] = &client_id_tree;
1820 options[i]->value = ip->client->config->send_options[i].data;
1821 options[i]->len = ip->client->config->send_options[i].len;
1822 options[i]->buf_size = ip->client->config->send_options[i].len;
1823 options[i]->timeout = 0xFFFFFFFF;
1827 /* Set up the option buffer... */
1828 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1829 options, 0, 0, 0, NULL, 0);
1830 if (ip->client->packet_length < BOOTP_MIN_LEN)
1831 ip->client->packet_length = BOOTP_MIN_LEN;
1833 ip->client->packet.op = BOOTREQUEST;
1834 ip->client->packet.htype = ip->hw_address.htype;
1835 ip->client->packet.hlen = ip->hw_address.hlen;
1836 ip->client->packet.hops = 0;
1837 ip->client->packet.xid = ip->client->xid;
1838 ip->client->packet.secs = 0; /* Filled in by send_request. */
1839 ip->client->packet.flags = 0;
1841 /* ciaddr must always be zero. */
1842 memset(&ip->client->packet.ciaddr, 0,
1843 sizeof(ip->client->packet.ciaddr));
1844 memset(&ip->client->packet.yiaddr, 0,
1845 sizeof(ip->client->packet.yiaddr));
1846 memset(&ip->client->packet.siaddr, 0,
1847 sizeof(ip->client->packet.siaddr));
1848 memset(&ip->client->packet.giaddr, 0,
1849 sizeof(ip->client->packet.giaddr));
1850 memcpy(ip->client->packet.chaddr,
1851 ip->hw_address.haddr, ip->hw_address.hlen);
1855 free_client_lease(struct client_lease *lease)
1859 if (lease->server_name)
1860 free(lease->server_name);
1861 if (lease->filename)
1862 free(lease->filename);
1863 for (i = 0; i < 256; i++) {
1864 if (lease->options[i].len)
1865 free(lease->options[i].data);
1873 rewrite_client_leases(void)
1875 struct client_lease *lp;
1876 cap_rights_t rights;
1879 leaseFile = fopen(path_dhclient_db, "w");
1881 error("can't create %s: %m", path_dhclient_db);
1882 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1883 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1884 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1886 error("can't limit lease descriptor: %m");
1888 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1890 error("can't limit lease descriptor fcntls: %m");
1897 for (lp = ifi->client->leases; lp; lp = lp->next)
1898 write_client_lease(ifi, lp, 1);
1899 if (ifi->client->active)
1900 write_client_lease(ifi, ifi->client->active, 1);
1903 ftruncate(fileno(leaseFile), ftello(leaseFile));
1904 fsync(fileno(leaseFile));
1908 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1911 static int leases_written;
1916 if (leases_written++ > 20) {
1917 rewrite_client_leases();
1922 /* If the lease came from the config file, we don't need to stash
1923 a copy in the lease database. */
1924 if (lease->is_static)
1927 if (!leaseFile) { /* XXX */
1928 leaseFile = fopen(path_dhclient_db, "w");
1930 error("can't create %s: %m", path_dhclient_db);
1933 fprintf(leaseFile, "lease {\n");
1934 if (lease->is_bootp)
1935 fprintf(leaseFile, " bootp;\n");
1936 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1937 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1938 if (lease->nextserver.len == sizeof(inaddr_any) &&
1939 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1940 sizeof(inaddr_any)))
1941 fprintf(leaseFile, " next-server %s;\n",
1942 piaddr(lease->nextserver));
1943 if (lease->filename)
1944 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1945 if (lease->server_name)
1946 fprintf(leaseFile, " server-name \"%s\";\n",
1947 lease->server_name);
1949 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1950 for (i = 0; i < 256; i++)
1951 if (lease->options[i].len)
1952 fprintf(leaseFile, " option %s %s;\n",
1953 dhcp_options[i].name,
1954 pretty_print_option(i, lease->options[i].data,
1955 lease->options[i].len, 1, 1));
1957 t = gmtime(&lease->renewal);
1958 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1959 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1960 t->tm_hour, t->tm_min, t->tm_sec);
1961 t = gmtime(&lease->rebind);
1962 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1963 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1964 t->tm_hour, t->tm_min, t->tm_sec);
1965 t = gmtime(&lease->expiry);
1966 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1967 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1968 t->tm_hour, t->tm_min, t->tm_sec);
1969 fprintf(leaseFile, "}\n");
1974 script_init(char *reason, struct string_list *medium)
1976 size_t len, mediumlen = 0;
1977 struct imsg_hdr hdr;
1981 if (medium != NULL && medium->string != NULL)
1982 mediumlen = strlen(medium->string);
1984 hdr.code = IMSG_SCRIPT_INIT;
1985 hdr.len = sizeof(struct imsg_hdr) +
1986 sizeof(size_t) + mediumlen +
1987 sizeof(size_t) + strlen(reason);
1989 if ((buf = buf_open(hdr.len)) == NULL)
1990 error("buf_open: %m");
1993 errs += buf_add(buf, &hdr, sizeof(hdr));
1994 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1996 errs += buf_add(buf, medium->string, mediumlen);
1997 len = strlen(reason);
1998 errs += buf_add(buf, &len, sizeof(len));
1999 errs += buf_add(buf, reason, len);
2002 error("buf_add: %m");
2004 if (buf_close(privfd, buf) == -1)
2005 error("buf_close: %m");
2009 priv_script_init(char *reason, char *medium)
2011 struct interface_info *ip = ifi;
2014 ip->client->scriptEnvsize = 100;
2015 if (ip->client->scriptEnv == NULL)
2016 ip->client->scriptEnv =
2017 malloc(ip->client->scriptEnvsize * sizeof(char *));
2018 if (ip->client->scriptEnv == NULL)
2019 error("script_init: no memory for environment");
2021 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2022 if (ip->client->scriptEnv[0] == NULL)
2023 error("script_init: no memory for environment");
2025 ip->client->scriptEnv[1] = NULL;
2027 script_set_env(ip->client, "", "interface", ip->name);
2030 script_set_env(ip->client, "", "medium", medium);
2032 script_set_env(ip->client, "", "reason", reason);
2037 priv_script_write_params(char *prefix, struct client_lease *lease)
2039 struct interface_info *ip = ifi;
2040 u_int8_t dbuf[1500], *dp = NULL;
2044 script_set_env(ip->client, prefix, "ip_address",
2045 piaddr(lease->address));
2047 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2049 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2050 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2052 dp = lease->options[DHO_SUBNET_MASK].data;
2053 len = lease->options[DHO_SUBNET_MASK].len;
2055 if (len && (len < sizeof(lease->address.iabuf))) {
2056 struct iaddr netmask, subnet, broadcast;
2058 memcpy(netmask.iabuf, dp, len);
2060 subnet = subnet_number(lease->address, netmask);
2062 script_set_env(ip->client, prefix, "network_number",
2064 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2065 broadcast = broadcast_addr(subnet, netmask);
2067 script_set_env(ip->client, prefix,
2068 "broadcast_address",
2074 if (lease->filename)
2075 script_set_env(ip->client, prefix, "filename", lease->filename);
2076 if (lease->server_name)
2077 script_set_env(ip->client, prefix, "server_name",
2078 lease->server_name);
2079 for (i = 0; i < 256; i++) {
2082 if (ip->client->config->defaults[i].len) {
2083 if (lease->options[i].len) {
2085 ip->client->config->default_actions[i]) {
2086 case ACTION_DEFAULT:
2087 dp = lease->options[i].data;
2088 len = lease->options[i].len;
2090 case ACTION_SUPERSEDE:
2093 config->defaults[i].data;
2095 config->defaults[i].len;
2097 case ACTION_PREPEND:
2099 config->defaults[i].len +
2100 lease->options[i].len;
2101 if (len >= sizeof(dbuf)) {
2102 warning("no space to %s %s",
2104 dhcp_options[i].name);
2110 config->defaults[i].data,
2112 config->defaults[i].len);
2113 memcpy(dp + ip->client->
2114 config->defaults[i].len,
2115 lease->options[i].data,
2116 lease->options[i].len);
2121 * When we append, we assume that we're
2122 * appending to text. Some MS servers
2123 * include a NUL byte at the end of
2124 * the search string provided.
2127 config->defaults[i].len +
2128 lease->options[i].len;
2129 if (len >= sizeof(dbuf)) {
2130 warning("no space to %s %s",
2132 dhcp_options[i].name);
2136 lease->options[i].data,
2137 lease->options[i].len);
2138 for (dp = dbuf + lease->options[i].len;
2139 dp > dbuf; dp--, len--)
2144 config->defaults[i].data,
2146 config->defaults[i].len);
2152 config->defaults[i].data;
2154 config->defaults[i].len;
2156 } else if (lease->options[i].len) {
2157 len = lease->options[i].len;
2158 dp = lease->options[i].data;
2165 if (dhcp_option_ev_name(name, sizeof(name),
2167 script_set_env(ip->client, prefix, name,
2168 pretty_print_option(i, dp, len, 0, 0));
2171 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2172 script_set_env(ip->client, prefix, "expiry", tbuf);
2176 script_write_params(char *prefix, struct client_lease *lease)
2178 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2179 struct imsg_hdr hdr;
2183 if (lease->filename != NULL)
2184 fn_len = strlen(lease->filename);
2185 if (lease->server_name != NULL)
2186 sn_len = strlen(lease->server_name);
2188 pr_len = strlen(prefix);
2190 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2191 hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2192 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2193 sizeof(size_t) + pr_len;
2195 for (i = 0; i < 256; i++)
2196 hdr.len += sizeof(int) + lease->options[i].len;
2198 scripttime = time(NULL);
2200 if ((buf = buf_open(hdr.len)) == NULL)
2201 error("buf_open: %m");
2204 errs += buf_add(buf, &hdr, sizeof(hdr));
2205 errs += buf_add(buf, lease, sizeof(struct client_lease));
2206 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2207 errs += buf_add(buf, lease->filename, fn_len);
2208 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2209 errs += buf_add(buf, lease->server_name, sn_len);
2210 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2211 errs += buf_add(buf, prefix, pr_len);
2213 for (i = 0; i < 256; i++) {
2214 errs += buf_add(buf, &lease->options[i].len,
2215 sizeof(lease->options[i].len));
2216 errs += buf_add(buf, lease->options[i].data,
2217 lease->options[i].len);
2221 error("buf_add: %m");
2223 if (buf_close(privfd, buf) == -1)
2224 error("buf_close: %m");
2230 struct imsg_hdr hdr;
2234 hdr.code = IMSG_SCRIPT_GO;
2235 hdr.len = sizeof(struct imsg_hdr);
2237 if ((buf = buf_open(hdr.len)) == NULL)
2238 error("buf_open: %m");
2240 if (buf_add(buf, &hdr, sizeof(hdr)))
2241 error("buf_add: %m");
2243 if (buf_close(privfd, buf) == -1)
2244 error("buf_close: %m");
2246 bzero(&hdr, sizeof(hdr));
2247 buf_read(privfd, &hdr, sizeof(hdr));
2248 if (hdr.code != IMSG_SCRIPT_GO_RET)
2249 error("unexpected msg type %u", hdr.code);
2250 if (hdr.len != sizeof(hdr) + sizeof(int))
2251 error("received corrupted message");
2252 buf_read(privfd, &ret, sizeof(ret));
2254 scripttime = time(NULL);
2260 priv_script_go(void)
2262 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2263 static char client_path[] = CLIENT_PATH;
2264 struct interface_info *ip = ifi;
2265 int pid, wpid, wstatus;
2267 scripttime = time(NULL);
2270 scriptName = ip->client->config->script_name;
2271 envp = ip->client->scriptEnv;
2273 scriptName = top_level_config.script_name;
2275 epp[1] = client_path;
2280 argv[0] = scriptName;
2289 wpid = wait(&wstatus);
2290 } while (wpid != pid && wpid > 0);
2296 execve(scriptName, argv, envp);
2297 error("execve (%s, ...): %m", scriptName);
2301 script_flush_env(ip->client);
2303 return (wstatus & 0xff);
2307 script_set_env(struct client_state *client, const char *prefix,
2308 const char *name, const char *value)
2312 /* No `` or $() command substitution allowed in environment values! */
2313 for (j=0; j < strlen(value); j++)
2317 warning("illegal character (%c) in value '%s'",
2319 /* Ignore this option */
2323 namelen = strlen(name);
2325 for (i = 0; client->scriptEnv[i]; i++)
2326 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2327 client->scriptEnv[i][namelen] == '=')
2330 if (client->scriptEnv[i])
2331 /* Reuse the slot. */
2332 free(client->scriptEnv[i]);
2334 /* New variable. Expand if necessary. */
2335 if (i >= client->scriptEnvsize - 1) {
2336 char **newscriptEnv;
2337 int newscriptEnvsize = client->scriptEnvsize + 50;
2339 newscriptEnv = realloc(client->scriptEnv,
2341 if (newscriptEnv == NULL) {
2342 free(client->scriptEnv);
2343 client->scriptEnv = NULL;
2344 client->scriptEnvsize = 0;
2345 error("script_set_env: no memory for variable");
2347 client->scriptEnv = newscriptEnv;
2348 client->scriptEnvsize = newscriptEnvsize;
2350 /* need to set the NULL pointer at end of array beyond
2352 client->scriptEnv[i + 1] = NULL;
2354 /* Allocate space and format the variable in the appropriate slot. */
2355 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2357 if (client->scriptEnv[i] == NULL)
2358 error("script_set_env: no memory for variable assignment");
2359 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2360 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2364 script_flush_env(struct client_state *client)
2368 for (i = 0; client->scriptEnv[i]; i++) {
2369 free(client->scriptEnv[i]);
2370 client->scriptEnv[i] = NULL;
2372 client->scriptEnvsize = 0;
2376 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2380 for (i = 0; option->name[i]; i++) {
2381 if (i + 1 == buflen)
2383 if (option->name[i] == '-')
2386 buf[i] = option->name[i];
2396 static int state = 0;
2397 cap_rights_t rights;
2399 if (no_daemon || state)
2404 /* Stop logging to stderr... */
2407 if (daemon(1, 0) == -1)
2410 cap_rights_init(&rights);
2412 if (pidfile != NULL) {
2413 pidfile_write(pidfile);
2414 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2416 error("can't limit pidfile descriptor: %m");
2420 /* we are chrooted, daemon(3) fails to open /dev/null */
2422 dup2(nullfd, STDIN_FILENO);
2423 dup2(nullfd, STDOUT_FILENO);
2424 dup2(nullfd, STDERR_FILENO);
2429 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2430 error("can't limit stdin: %m");
2431 cap_rights_init(&rights, CAP_WRITE);
2432 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2433 error("can't limit stdout: %m");
2434 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2435 error("can't limit stderr: %m");
2439 check_option(struct client_lease *l, int option)
2444 /* we use this, since this is what gets passed to dhclient-script */
2446 opbuf = pretty_print_option(option, l->options[option].data,
2447 l->options[option].len, 0, 0);
2449 sbuf = option_as_string(option, l->options[option].data,
2450 l->options[option].len);
2453 case DHO_SUBNET_MASK:
2454 case DHO_TIME_SERVERS:
2455 case DHO_NAME_SERVERS:
2457 case DHO_DOMAIN_NAME_SERVERS:
2458 case DHO_LOG_SERVERS:
2459 case DHO_COOKIE_SERVERS:
2460 case DHO_LPR_SERVERS:
2461 case DHO_IMPRESS_SERVERS:
2462 case DHO_RESOURCE_LOCATION_SERVERS:
2463 case DHO_SWAP_SERVER:
2464 case DHO_BROADCAST_ADDRESS:
2465 case DHO_NIS_SERVERS:
2466 case DHO_NTP_SERVERS:
2467 case DHO_NETBIOS_NAME_SERVERS:
2468 case DHO_NETBIOS_DD_SERVER:
2469 case DHO_FONT_SERVERS:
2470 case DHO_DHCP_SERVER_IDENTIFIER:
2471 case DHO_NISPLUS_SERVERS:
2472 case DHO_MOBILE_IP_HOME_AGENT:
2473 case DHO_SMTP_SERVER:
2474 case DHO_POP_SERVER:
2475 case DHO_NNTP_SERVER:
2476 case DHO_WWW_SERVER:
2477 case DHO_FINGER_SERVER:
2478 case DHO_IRC_SERVER:
2479 case DHO_STREETTALK_SERVER:
2480 case DHO_STREETTALK_DA_SERVER:
2481 if (!ipv4addrs(opbuf)) {
2482 warning("Invalid IP address in option: %s", opbuf);
2487 case DHO_NIS_DOMAIN:
2488 case DHO_NISPLUS_DOMAIN:
2489 case DHO_TFTP_SERVER_NAME:
2490 if (!res_hnok(sbuf)) {
2491 warning("Bogus Host Name option %d: %s (%s)", option,
2493 l->options[option].len = 0;
2494 free(l->options[option].data);
2497 case DHO_DOMAIN_NAME:
2498 case DHO_DOMAIN_SEARCH:
2499 if (!res_hnok(sbuf)) {
2500 if (!check_search(sbuf)) {
2501 warning("Bogus domain search list %d: %s (%s)",
2502 option, sbuf, opbuf);
2503 l->options[option].len = 0;
2504 free(l->options[option].data);
2509 case DHO_TIME_OFFSET:
2511 case DHO_MERIT_DUMP:
2513 case DHO_EXTENSIONS_PATH:
2514 case DHO_IP_FORWARDING:
2515 case DHO_NON_LOCAL_SOURCE_ROUTING:
2516 case DHO_POLICY_FILTER:
2517 case DHO_MAX_DGRAM_REASSEMBLY:
2518 case DHO_DEFAULT_IP_TTL:
2519 case DHO_PATH_MTU_AGING_TIMEOUT:
2520 case DHO_PATH_MTU_PLATEAU_TABLE:
2521 case DHO_INTERFACE_MTU:
2522 case DHO_ALL_SUBNETS_LOCAL:
2523 case DHO_PERFORM_MASK_DISCOVERY:
2524 case DHO_MASK_SUPPLIER:
2525 case DHO_ROUTER_DISCOVERY:
2526 case DHO_ROUTER_SOLICITATION_ADDRESS:
2527 case DHO_STATIC_ROUTES:
2528 case DHO_TRAILER_ENCAPSULATION:
2529 case DHO_ARP_CACHE_TIMEOUT:
2530 case DHO_IEEE802_3_ENCAPSULATION:
2531 case DHO_DEFAULT_TCP_TTL:
2532 case DHO_TCP_KEEPALIVE_INTERVAL:
2533 case DHO_TCP_KEEPALIVE_GARBAGE:
2534 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2535 case DHO_NETBIOS_NODE_TYPE:
2536 case DHO_NETBIOS_SCOPE:
2537 case DHO_X_DISPLAY_MANAGER:
2538 case DHO_DHCP_REQUESTED_ADDRESS:
2539 case DHO_DHCP_LEASE_TIME:
2540 case DHO_DHCP_OPTION_OVERLOAD:
2541 case DHO_DHCP_MESSAGE_TYPE:
2542 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2543 case DHO_DHCP_MESSAGE:
2544 case DHO_DHCP_MAX_MESSAGE_SIZE:
2545 case DHO_DHCP_RENEWAL_TIME:
2546 case DHO_DHCP_REBINDING_TIME:
2547 case DHO_DHCP_CLASS_IDENTIFIER:
2548 case DHO_DHCP_CLIENT_IDENTIFIER:
2549 case DHO_BOOTFILE_NAME:
2550 case DHO_DHCP_USER_CLASS_ID:
2553 case DHO_CLASSLESS_ROUTES:
2554 return (check_classless_option(l->options[option].data,
2555 l->options[option].len));
2557 warning("unknown dhcp option value 0x%x", option);
2558 return (unknown_ok);
2562 /* RFC 3442 The Classless Static Routes option checks */
2564 check_classless_option(unsigned char *data, int len)
2567 unsigned char width;
2568 in_addr_t addr, mask;
2571 warning("Too small length: %d", len);
2579 } else if (width < 9) {
2580 addr = (in_addr_t)(data[i] << 24);
2582 } else if (width < 17) {
2583 addr = (in_addr_t)(data[i] << 24) +
2584 (in_addr_t)(data[i + 1] << 16);
2586 } else if (width < 25) {
2587 addr = (in_addr_t)(data[i] << 24) +
2588 (in_addr_t)(data[i + 1] << 16) +
2589 (in_addr_t)(data[i + 2] << 8);
2591 } else if (width < 33) {
2592 addr = (in_addr_t)(data[i] << 24) +
2593 (in_addr_t)(data[i + 1] << 16) +
2594 (in_addr_t)(data[i + 2] << 8) +
2598 warning("Incorrect subnet width: %d", width);
2601 mask = (in_addr_t)(~0) << (32 - width);
2607 * ... After deriving a subnet number and subnet mask
2608 * from each destination descriptor, the DHCP client
2609 * MUST zero any bits in the subnet number where the
2610 * corresponding bit in the mask is zero...
2612 if ((addr & mask) != addr) {
2614 data[i - 1] = (unsigned char)(
2615 (addr >> (((32 - width)/8)*8)) & 0xFF);
2620 warning("Incorrect data length: %d (must be %d)", len, i);
2627 res_hnok(const char *dn)
2629 int pch = PERIOD, ch = *dn++;
2631 while (ch != '\0') {
2634 if (periodchar(ch)) {
2636 } else if (periodchar(pch)) {
2637 if (!borderchar(ch))
2639 } else if (periodchar(nch) || nch == '\0') {
2640 if (!borderchar(ch))
2643 if (!middlechar(ch))
2652 check_search(const char *srch)
2654 int pch = PERIOD, ch = *srch++;
2657 /* 256 char limit re resolv.conf(5) */
2658 if (strlen(srch) > 256)
2661 while (whitechar(ch))
2664 while (ch != '\0') {
2667 if (periodchar(ch) || whitechar(ch)) {
2669 } else if (periodchar(pch)) {
2670 if (!borderchar(ch))
2672 } else if (periodchar(nch) || nch == '\0') {
2673 if (!borderchar(ch))
2676 if (!middlechar(ch))
2679 if (!whitechar(ch)) {
2682 while (whitechar(nch)) {
2691 /* 6 domain limit re resolv.conf(5) */
2697 /* Does buf consist only of dotted decimal ipv4 addrs?
2698 * return how many if so,
2699 * otherwise, return 0
2702 ipv4addrs(char * buf)
2707 while (inet_aton(buf, &jnk) == 1){
2709 while (periodchar(*buf) || digitchar(*buf))
2721 option_as_string(unsigned int code, unsigned char *data, int len)
2723 static char optbuf[32768]; /* XXX */
2725 int opleft = sizeof(optbuf);
2726 unsigned char *dp = data;
2729 error("option_as_string: bad code %d", code);
2731 for (; dp < data + len; dp++) {
2732 if (!isascii(*dp) || !isprint(*dp)) {
2733 if (dp + 1 != data + len || *dp != 0) {
2734 snprintf(op, opleft, "\\%03o", *dp);
2738 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2739 *dp == '`' || *dp == '\\') {
2753 warning("dhcp option too large");
2758 fork_privchld(int fd, int fd2)
2760 struct pollfd pfd[1];
2765 error("cannot fork");
2772 setproctitle("%s [priv]", ifi->name);
2775 dup2(nullfd, STDIN_FILENO);
2776 dup2(nullfd, STDOUT_FILENO);
2777 dup2(nullfd, STDERR_FILENO);
2785 pfd[0].events = POLLIN;
2786 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2788 error("poll error");
2790 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2793 dispatch_imsg(ifi, fd);