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"
87 cap_channel_t *capsyslog;
90 time_t default_lease_time = 43200; /* 12 hours... */
92 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
93 char *path_dhclient_db = NULL;
99 char hostname[_POSIX_HOST_NAME_MAX + 1];
101 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
102 struct in_addr inaddr_any, inaddr_broadcast;
104 char *path_dhclient_pidfile;
105 struct pidfh *pidfile;
108 * ASSERT_STATE() does nothing now; it used to be
109 * assert (state_is == state_shouldbe).
111 #define ASSERT_STATE(state_is, state_shouldbe) {}
114 * We need to check that the expiry, renewal and rebind times are not beyond
115 * the end of time (~2038 when a 32-bit time_t is being used).
117 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
124 struct interface_info *ifi;
126 int findproto(char *, int);
127 struct sockaddr *get_ifa(char *, int);
128 void routehandler(struct protocol *);
130 int check_option(struct client_lease *l, int option);
131 int check_classless_option(unsigned char *data, int len);
132 int ipv4addrs(char * buf);
133 int res_hnok(const char *dn);
134 int check_search(const char *srch);
135 char *option_as_string(unsigned int code, unsigned char *data, int len);
136 int fork_privchld(int, int);
139 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
140 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
142 /* Minimum MTU is 68 as per RFC791, p. 24 */
145 static time_t scripttime;
148 findproto(char *cp, int n)
155 for (i = 1; i; i <<= 1) {
157 sa = (struct sockaddr *)cp;
163 if (sa->sa_family == AF_INET)
165 if (sa->sa_family == AF_INET6)
178 get_ifa(char *cp, int n)
185 for (i = 1; i; i <<= 1)
187 sa = (struct sockaddr *)cp;
196 struct iaddr defaddr = { 4 };
202 struct interface_info *ifi = arg;
205 * Clear existing state.
207 if (ifi->client->active != NULL) {
208 script_init("EXPIRE", NULL);
209 script_write_params("old_",
210 ifi->client->active);
211 if (ifi->client->alias)
212 script_write_params("alias_",
216 ifi->client->state = S_INIT;
221 routehandler(struct protocol *p)
223 char msg[2048], *addr;
224 struct rt_msghdr *rtm;
225 struct if_msghdr *ifm;
226 struct ifa_msghdr *ifam;
227 struct if_announcemsghdr *ifan;
228 struct ieee80211_join_event *jev;
229 struct client_lease *l;
230 time_t t = time(NULL);
236 n = read(routefd, &msg, sizeof(msg));
237 rtm = (struct rt_msghdr *)msg;
238 if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
239 rtm->rtm_version != RTM_VERSION)
242 switch (rtm->rtm_type) {
245 ifam = (struct ifa_msghdr *)rtm;
247 if (ifam->ifam_index != ifi->index)
249 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
251 if (scripttime == 0 || t < scripttime + 10)
254 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
258 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
259 error("king bula sez: len mismatch");
260 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
261 if (addr_eq(a, defaddr))
264 for (l = ifi->client->active; l != NULL; l = l->next)
265 if (addr_eq(a, l->address))
268 if (l == NULL) /* added/deleted addr is not the one we set */
271 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
272 if (rtm->rtm_type == RTM_NEWADDR) {
274 * XXX: If someone other than us adds our address,
275 * should we assume they are taking over from us,
276 * delete the lease record, and exit without modifying
279 warning("My address (%s) was re-added", addr);
281 warning("My address (%s) was deleted, dhclient exiting",
287 ifm = (struct if_msghdr *)rtm;
288 if (ifm->ifm_index != ifi->index)
290 if ((rtm->rtm_flags & RTF_UP) == 0) {
291 warning("Interface %s is down, dhclient exiting",
295 linkstat = interface_link_status(ifi->name);
296 if (linkstat != ifi->linkstat) {
297 debug("%s link state %s -> %s", ifi->name,
298 ifi->linkstat ? "up" : "down",
299 linkstat ? "up" : "down");
300 ifi->linkstat = linkstat;
306 ifan = (struct if_announcemsghdr *)rtm;
307 if (ifan->ifan_what == IFAN_DEPARTURE &&
308 ifan->ifan_index == ifi->index) {
309 warning("Interface %s is gone, dhclient exiting",
315 ifan = (struct if_announcemsghdr *)rtm;
316 if (ifan->ifan_index != ifi->index)
318 switch (ifan->ifan_what) {
319 case RTM_IEEE80211_ASSOC:
320 case RTM_IEEE80211_REASSOC:
322 * Use assoc/reassoc event to kick state machine
323 * in case we roam. Otherwise fall back to the
324 * normal state machine just like a wired network.
326 jev = (struct ieee80211_join_event *) &ifan[1];
327 if (memcmp(curbssid, jev->iev_addr, 6)) {
331 memcpy(curbssid, jev->iev_addr, 6);
341 script_init("FAIL", NULL);
342 if (ifi->client->alias)
343 script_write_params("alias_", ifi->client->alias);
346 pidfile_remove(pidfile);
353 cap_channel_t *casper;
357 error("unable to start casper");
359 capsyslog = cap_service_open(casper, "system.syslog");
361 if (capsyslog == NULL)
362 error("unable to open system.syslog service");
366 main(int argc, char *argv[])
368 extern char *__progname;
369 int ch, fd, quiet = 0, i = 0;
371 int immediate_daemon = 0;
378 /* Initially, log errors to stderr as well as to syslogd. */
379 cap_openlog(capsyslog, __progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
380 cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
382 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
385 immediate_daemon = 1;
388 path_dhclient_conf = optarg;
394 path_dhclient_db = optarg;
397 path_dhclient_pidfile = optarg;
415 if (path_dhclient_pidfile == NULL) {
416 asprintf(&path_dhclient_pidfile,
417 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
418 if (path_dhclient_pidfile == NULL)
421 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
422 if (pidfile == NULL) {
424 error("dhclient already running, pid: %d.", otherpid);
426 error("dhclient already running.");
427 warning("Cannot open or create pidfile: %m");
430 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
432 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
433 error("Interface name too long");
434 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
435 _PATH_DHCLIENT_DB, ifi->name) == -1)
444 inaddr_broadcast.s_addr = INADDR_BROADCAST;
445 inaddr_any.s_addr = INADDR_ANY;
449 /* The next bit is potentially very time-consuming, so write out
450 the pidfile right away. We will write it out again with the
451 correct pid after daemonizing. */
453 pidfile_write(pidfile);
455 if (!interface_link_status(ifi->name)) {
456 fprintf(stderr, "%s: no link ...", ifi->name);
459 while (!interface_link_status(ifi->name)) {
460 fprintf(stderr, ".");
463 fprintf(stderr, " giving up\n");
468 fprintf(stderr, " got link\n");
472 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
473 error("cannot open %s: %m", _PATH_DEVNULL);
475 if ((pw = getpwnam("_dhcp")) == NULL) {
476 warning("no such user: _dhcp, falling back to \"nobody\"");
477 if ((pw = getpwnam("nobody")) == NULL)
478 error("no such user: nobody");
482 * Obtain hostname before entering capability mode - it won't be
483 * possible then, as reading kern.hostname is not permitted.
485 if (gethostname(hostname, sizeof(hostname)) < 0)
488 priv_script_init("PREINIT", NULL);
489 if (ifi->client->alias)
490 priv_script_write_params("alias_", ifi->client->alias);
493 /* set up the interface */
494 discover_interfaces(ifi);
496 if (pipe(pipe_fd) == -1)
499 fork_privchld(pipe_fd[0], pipe_fd[1]);
508 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
509 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
510 error("can't limit private descriptor: %m");
512 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
513 error("can't open and lock %s: %m", path_dhclient_db);
514 read_client_leases();
515 rewrite_client_leases();
518 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
519 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
520 if (shutdown(routefd, SHUT_WR) < 0)
521 error("can't shutdown route socket: %m");
522 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
523 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
524 error("can't limit route socket: %m");
526 if (chroot(_PATH_VAREMPTY) == -1)
528 if (chdir("/") == -1)
529 error("chdir(\"/\")");
531 if (setgroups(1, &pw->pw_gid) ||
532 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
533 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
534 error("can't drop privileges: %m");
538 setproctitle("%s", ifi->name);
540 if (CASPER_SUPPORT && cap_enter() < 0 && errno != ENOSYS)
541 error("can't enter capability mode: %m");
543 if (immediate_daemon)
546 ifi->client->state = S_INIT;
549 bootp_packet_handler = do_packet;
560 extern char *__progname;
562 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
563 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
570 * Each routine is called from the dhclient_state_machine() in one of
572 * -> entering INIT state
573 * -> recvpacket_flag == 0: timeout in this state
574 * -> otherwise: received a packet in this state
576 * Return conditions as handled by dhclient_state_machine():
577 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
578 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
579 * Returns 0: finish the nap which was interrupted for no good reason.
581 * Several per-interface variables are used to keep track of the process:
582 * active_lease: the lease that is being used on the interface
583 * (null pointer if not configured yet).
584 * offered_leases: leases corresponding to DHCPOFFER messages that have
585 * been sent to us by DHCP servers.
586 * acked_leases: leases corresponding to DHCPACK messages that have been
587 * sent to us by DHCP servers.
588 * sendpacket: DHCP packet we're trying to send.
589 * destination: IP address to send sendpacket to
590 * In addition, there are several relevant per-lease variables.
591 * T1_expiry, T2_expiry, lease_expiry: lease milestones
592 * In the active lease, these control the process of renewing the lease;
593 * In leases on the acked_leases list, this simply determines when we
594 * can no longer legitimately use the lease.
598 state_reboot(void *ipp)
600 struct interface_info *ip = ipp;
602 /* If we don't remember an active lease, go straight to INIT. */
603 if (!ip->client->active || ip->client->active->is_bootp) {
608 /* We are in the rebooting state. */
609 ip->client->state = S_REBOOTING;
611 /* make_request doesn't initialize xid because it normally comes
612 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
613 so pick an xid now. */
614 ip->client->xid = arc4random();
616 /* Make a DHCPREQUEST packet, and set appropriate per-interface
618 make_request(ip, ip->client->active);
619 ip->client->destination = iaddr_broadcast;
620 ip->client->first_sending = cur_time;
621 ip->client->interval = ip->client->config->initial_interval;
623 /* Zap the medium list... */
624 ip->client->medium = NULL;
626 /* Send out the first DHCPREQUEST packet. */
631 * Called when a lease has completely expired and we've
632 * been unable to renew it.
635 state_init(void *ipp)
637 struct interface_info *ip = ipp;
639 ASSERT_STATE(state, S_INIT);
641 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
643 make_discover(ip, ip->client->active);
644 ip->client->xid = ip->client->packet.xid;
645 ip->client->destination = iaddr_broadcast;
646 ip->client->state = S_SELECTING;
647 ip->client->first_sending = cur_time;
648 ip->client->interval = ip->client->config->initial_interval;
650 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
656 * state_selecting is called when one or more DHCPOFFER packets
657 * have been received and a configurable period of time has passed.
660 state_selecting(void *ipp)
662 struct interface_info *ip = ipp;
663 struct client_lease *lp, *next, *picked;
665 ASSERT_STATE(state, S_SELECTING);
667 /* Cancel state_selecting and send_discover timeouts, since either
668 one could have got us here. */
669 cancel_timeout(state_selecting, ip);
670 cancel_timeout(send_discover, ip);
672 /* We have received one or more DHCPOFFER packets. Currently,
673 the only criterion by which we judge leases is whether or
674 not we get a response when we arp for them. */
676 for (lp = ip->client->offered_leases; lp; lp = next) {
679 /* Check to see if we got an ARPREPLY for the address
680 in this particular lease. */
682 script_init("ARPCHECK", lp->medium);
683 script_write_params("check_", lp);
685 /* If the ARPCHECK code detects another
686 machine using the offered address, it exits
687 nonzero. We need to send a DHCPDECLINE and
690 make_decline(ip, lp);
698 free_client_lease(lp);
701 ip->client->offered_leases = NULL;
703 /* If we just tossed all the leases we were offered, go back
706 ip->client->state = S_INIT;
711 /* If it was a BOOTREPLY, we can just take the address right now. */
712 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
713 ip->client->new = picked;
715 /* Make up some lease expiry times
716 XXX these should be configurable. */
717 ip->client->new->expiry = cur_time + 12000;
718 ip->client->new->renewal += cur_time + 8000;
719 ip->client->new->rebind += cur_time + 10000;
721 ip->client->state = S_REQUESTING;
723 /* Bind to the address we received. */
728 /* Go to the REQUESTING state. */
729 ip->client->destination = iaddr_broadcast;
730 ip->client->state = S_REQUESTING;
731 ip->client->first_sending = cur_time;
732 ip->client->interval = ip->client->config->initial_interval;
734 /* Make a DHCPREQUEST packet from the lease we picked. */
735 make_request(ip, picked);
736 ip->client->xid = ip->client->packet.xid;
738 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
739 free_client_lease(picked);
741 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
745 /* state_requesting is called when we receive a DHCPACK message after
746 having sent out one or more DHCPREQUEST packets. */
749 dhcpack(struct packet *packet)
751 struct interface_info *ip = packet->interface;
752 struct client_lease *lease;
754 /* If we're not receptive to an offer right now, or if the offer
755 has an unrecognizable transaction id, then just drop it. */
756 if (packet->interface->client->xid != packet->raw->xid ||
757 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
758 (memcmp(packet->interface->hw_address.haddr,
759 packet->raw->chaddr, packet->raw->hlen)))
762 if (ip->client->state != S_REBOOTING &&
763 ip->client->state != S_REQUESTING &&
764 ip->client->state != S_RENEWING &&
765 ip->client->state != S_REBINDING)
768 note("DHCPACK from %s", piaddr(packet->client_addr));
770 lease = packet_to_lease(packet);
772 note("packet_to_lease failed.");
776 ip->client->new = lease;
778 /* Stop resending DHCPREQUEST. */
779 cancel_timeout(send_request, ip);
781 /* Figure out the lease time. */
782 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
784 ip->client->new->expiry = getULong(
785 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
786 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
787 ip->client->new->expiry = getULong(
788 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
790 ip->client->new->expiry = default_lease_time;
791 /* A number that looks negative here is really just very large,
792 because the lease expiry offset is unsigned. Also make sure that
793 the addition of cur_time below does not overflow (a 32 bit) time_t. */
794 if (ip->client->new->expiry < 0 ||
795 ip->client->new->expiry > TIME_MAX - cur_time)
796 ip->client->new->expiry = TIME_MAX - cur_time;
797 /* XXX should be fixed by resetting the client state */
798 if (ip->client->new->expiry < 60)
799 ip->client->new->expiry = 60;
801 /* Unless overridden in the config, take the server-provided renewal
802 * time if there is one. Otherwise figure it out according to the spec.
803 * Also make sure the renewal time does not exceed the expiry time.
805 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
807 ip->client->new->renewal = getULong(
808 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
809 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
810 ip->client->new->renewal = getULong(
811 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
813 ip->client->new->renewal = ip->client->new->expiry / 2;
814 if (ip->client->new->renewal < 0 ||
815 ip->client->new->renewal > ip->client->new->expiry / 2)
816 ip->client->new->renewal = ip->client->new->expiry / 2;
818 /* Same deal with the rebind time. */
819 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
821 ip->client->new->rebind = getULong(
822 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
823 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
824 ip->client->new->rebind = getULong(
825 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
827 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
828 if (ip->client->new->rebind < 0 ||
829 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
830 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
832 /* Convert the time offsets into seconds-since-the-epoch */
833 ip->client->new->expiry += cur_time;
834 ip->client->new->renewal += cur_time;
835 ip->client->new->rebind += cur_time;
841 bind_lease(struct interface_info *ip)
843 struct option_data *opt;
845 /* Remember the medium. */
846 ip->client->new->medium = ip->client->medium;
848 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
849 if (opt->len == sizeof(u_int16_t)) {
850 u_int16_t mtu = be16dec(opt->data);
852 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
854 interface_set_mtu_unpriv(privfd, mtu);
857 /* Write out the new lease. */
858 write_client_lease(ip, ip->client->new, 0);
860 /* Run the client script with the new parameters. */
861 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
862 (ip->client->state == S_RENEWING ? "RENEW" :
863 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
864 ip->client->new->medium);
865 if (ip->client->active && ip->client->state != S_REBOOTING)
866 script_write_params("old_", ip->client->active);
867 script_write_params("new_", ip->client->new);
868 if (ip->client->alias)
869 script_write_params("alias_", ip->client->alias);
872 /* Replace the old active lease with the new one. */
873 if (ip->client->active)
874 free_client_lease(ip->client->active);
875 ip->client->active = ip->client->new;
876 ip->client->new = NULL;
878 /* Set up a timeout to start the renewal process. */
879 add_timeout(ip->client->active->renewal, state_bound, ip);
881 note("bound to %s -- renewal in %d seconds.",
882 piaddr(ip->client->active->address),
883 (int)(ip->client->active->renewal - cur_time));
884 ip->client->state = S_BOUND;
885 reinitialize_interfaces();
890 * state_bound is called when we've successfully bound to a particular
891 * lease, but the renewal time on that lease has expired. We are
892 * expected to unicast a DHCPREQUEST to the server that gave us our
896 state_bound(void *ipp)
898 struct interface_info *ip = ipp;
900 ASSERT_STATE(state, S_BOUND);
902 /* T1 has expired. */
903 make_request(ip, ip->client->active);
904 ip->client->xid = ip->client->packet.xid;
906 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
907 memcpy(ip->client->destination.iabuf, ip->client->active->
908 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
909 ip->client->destination.len = 4;
911 ip->client->destination = iaddr_broadcast;
913 ip->client->first_sending = cur_time;
914 ip->client->interval = ip->client->config->initial_interval;
915 ip->client->state = S_RENEWING;
917 /* Send the first packet immediately. */
922 bootp(struct packet *packet)
924 struct iaddrlist *ap;
926 if (packet->raw->op != BOOTREPLY)
929 /* If there's a reject list, make sure this packet's sender isn't
931 for (ap = packet->interface->client->config->reject_list;
933 if (addr_eq(packet->client_addr, ap->addr)) {
934 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
942 dhcp(struct packet *packet)
944 struct iaddrlist *ap;
945 void (*handler)(struct packet *);
948 switch (packet->packet_type) {
965 /* If there's a reject list, make sure this packet's sender isn't
967 for (ap = packet->interface->client->config->reject_list;
969 if (addr_eq(packet->client_addr, ap->addr)) {
970 note("%s from %s rejected.", type, piaddr(ap->addr));
978 dhcpoffer(struct packet *packet)
980 struct interface_info *ip = packet->interface;
981 struct client_lease *lease, *lp;
983 int arp_timeout_needed, stop_selecting;
984 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
985 "DHCPOFFER" : "BOOTREPLY";
987 /* If we're not receptive to an offer right now, or if the offer
988 has an unrecognizable transaction id, then just drop it. */
989 if (ip->client->state != S_SELECTING ||
990 packet->interface->client->xid != packet->raw->xid ||
991 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
992 (memcmp(packet->interface->hw_address.haddr,
993 packet->raw->chaddr, packet->raw->hlen)))
996 note("%s from %s", name, piaddr(packet->client_addr));
999 /* If this lease doesn't supply the minimum required parameters,
1001 for (i = 0; ip->client->config->required_options[i]; i++) {
1002 if (!packet->options[ip->client->config->
1003 required_options[i]].len) {
1004 note("%s isn't satisfactory.", name);
1009 /* If we've already seen this lease, don't record it again. */
1010 for (lease = ip->client->offered_leases;
1011 lease; lease = lease->next) {
1012 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1013 !memcmp(lease->address.iabuf,
1014 &packet->raw->yiaddr, lease->address.len)) {
1015 debug("%s already seen.", name);
1020 lease = packet_to_lease(packet);
1022 note("packet_to_lease failed.");
1026 /* If this lease was acquired through a BOOTREPLY, record that
1028 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1029 lease->is_bootp = 1;
1031 /* Record the medium under which this lease was offered. */
1032 lease->medium = ip->client->medium;
1034 /* Send out an ARP Request for the offered IP address. */
1035 script_init("ARPSEND", lease->medium);
1036 script_write_params("check_", lease);
1037 /* If the script can't send an ARP request without waiting,
1038 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1040 arp_timeout_needed = 0;
1042 arp_timeout_needed = 2;
1044 /* Figure out when we're supposed to stop selecting. */
1046 ip->client->first_sending + ip->client->config->select_interval;
1048 /* If this is the lease we asked for, put it at the head of the
1049 list, and don't mess with the arp request timeout. */
1050 if (lease->address.len == ip->client->requested_address.len &&
1051 !memcmp(lease->address.iabuf,
1052 ip->client->requested_address.iabuf,
1053 ip->client->requested_address.len)) {
1054 lease->next = ip->client->offered_leases;
1055 ip->client->offered_leases = lease;
1057 /* If we already have an offer, and arping for this
1058 offer would take us past the selection timeout,
1059 then don't extend the timeout - just hope for the
1061 if (ip->client->offered_leases &&
1062 (cur_time + arp_timeout_needed) > stop_selecting)
1063 arp_timeout_needed = 0;
1065 /* Put the lease at the end of the list. */
1067 if (!ip->client->offered_leases)
1068 ip->client->offered_leases = lease;
1070 for (lp = ip->client->offered_leases; lp->next;
1077 /* If we're supposed to stop selecting before we've had time
1078 to wait for the ARPREPLY, add some delay to wait for
1080 if (stop_selecting - cur_time < arp_timeout_needed)
1081 stop_selecting = cur_time + arp_timeout_needed;
1083 /* If the selecting interval has expired, go immediately to
1084 state_selecting(). Otherwise, time out into
1085 state_selecting at the select interval. */
1086 if (stop_selecting <= 0)
1087 state_selecting(ip);
1089 add_timeout(stop_selecting, state_selecting, ip);
1090 cancel_timeout(send_discover, ip);
1094 /* Allocate a client_lease structure and initialize it from the parameters
1095 in the specified packet. */
1097 struct client_lease *
1098 packet_to_lease(struct packet *packet)
1100 struct client_lease *lease;
1103 lease = malloc(sizeof(struct client_lease));
1106 warning("dhcpoffer: no memory to record lease.");
1110 memset(lease, 0, sizeof(*lease));
1112 /* Copy the lease options. */
1113 for (i = 0; i < 256; i++) {
1114 if (packet->options[i].len) {
1115 lease->options[i].data =
1116 malloc(packet->options[i].len + 1);
1117 if (!lease->options[i].data) {
1118 warning("dhcpoffer: no memory for option %d", i);
1119 free_client_lease(lease);
1122 memcpy(lease->options[i].data,
1123 packet->options[i].data,
1124 packet->options[i].len);
1125 lease->options[i].len =
1126 packet->options[i].len;
1127 lease->options[i].data[lease->options[i].len] =
1130 if (!check_option(lease,i)) {
1131 /* ignore a bogus lease offer */
1132 warning("Invalid lease option - ignoring offer");
1133 free_client_lease(lease);
1139 lease->address.len = sizeof(packet->raw->yiaddr);
1140 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1142 lease->nextserver.len = sizeof(packet->raw->siaddr);
1143 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1145 /* If the server name was filled out, copy it.
1146 Do not attempt to validate the server name as a host name.
1147 RFC 2131 merely states that sname is NUL-terminated (which do
1148 do not assume) and that it is the server's host name. Since
1149 the ISC client and server allow arbitrary characters, we do
1151 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1152 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1153 packet->raw->sname[0]) {
1154 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1155 if (!lease->server_name) {
1156 warning("dhcpoffer: no memory for server name.");
1157 free_client_lease(lease);
1160 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1161 lease->server_name[DHCP_SNAME_LEN]='\0';
1164 /* Ditto for the filename. */
1165 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1166 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1167 packet->raw->file[0]) {
1168 /* Don't count on the NUL terminator. */
1169 lease->filename = malloc(DHCP_FILE_LEN + 1);
1170 if (!lease->filename) {
1171 warning("dhcpoffer: no memory for filename.");
1172 free_client_lease(lease);
1175 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1176 lease->filename[DHCP_FILE_LEN]='\0';
1182 dhcpnak(struct packet *packet)
1184 struct interface_info *ip = packet->interface;
1186 /* If we're not receptive to an offer right now, or if the offer
1187 has an unrecognizable transaction id, then just drop it. */
1188 if (packet->interface->client->xid != packet->raw->xid ||
1189 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1190 (memcmp(packet->interface->hw_address.haddr,
1191 packet->raw->chaddr, packet->raw->hlen)))
1194 if (ip->client->state != S_REBOOTING &&
1195 ip->client->state != S_REQUESTING &&
1196 ip->client->state != S_RENEWING &&
1197 ip->client->state != S_REBINDING)
1200 note("DHCPNAK from %s", piaddr(packet->client_addr));
1202 if (!ip->client->active) {
1203 note("DHCPNAK with no active lease.\n");
1207 free_client_lease(ip->client->active);
1208 ip->client->active = NULL;
1210 /* Stop sending DHCPREQUEST packets... */
1211 cancel_timeout(send_request, ip);
1213 ip->client->state = S_INIT;
1217 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1218 one after the right interval has expired. If we don't get an offer by
1219 the time we reach the panic interval, call the panic function. */
1222 send_discover(void *ipp)
1224 struct interface_info *ip = ipp;
1225 int interval, increase = 1;
1227 /* Figure out how long it's been since we started transmitting. */
1228 interval = cur_time - ip->client->first_sending;
1230 /* If we're past the panic timeout, call the script and tell it
1231 we haven't found anything for this interface yet. */
1232 if (interval > ip->client->config->timeout) {
1237 /* If we're selecting media, try the whole list before doing
1238 the exponential backoff, but if we've already received an
1239 offer, stop looping, because we obviously have it right. */
1240 if (!ip->client->offered_leases &&
1241 ip->client->config->media) {
1244 if (ip->client->medium) {
1245 ip->client->medium = ip->client->medium->next;
1248 if (!ip->client->medium) {
1250 error("No valid media types for %s!", ip->name);
1251 ip->client->medium = ip->client->config->media;
1255 note("Trying medium \"%s\" %d", ip->client->medium->string,
1257 script_init("MEDIUM", ip->client->medium);
1263 * If we're supposed to increase the interval, do so. If it's
1264 * currently zero (i.e., we haven't sent any packets yet), set
1265 * it to one; otherwise, add to it a random number between zero
1266 * and two times itself. On average, this means that it will
1267 * double with every transmission.
1270 if (!ip->client->interval)
1271 ip->client->interval =
1272 ip->client->config->initial_interval;
1274 ip->client->interval += (arc4random() >> 2) %
1275 (2 * ip->client->interval);
1278 /* Don't backoff past cutoff. */
1279 if (ip->client->interval >
1280 ip->client->config->backoff_cutoff)
1281 ip->client->interval =
1282 ((ip->client->config->backoff_cutoff / 2)
1283 + ((arc4random() >> 2) %
1284 ip->client->config->backoff_cutoff));
1285 } else if (!ip->client->interval)
1286 ip->client->interval =
1287 ip->client->config->initial_interval;
1289 /* If the backoff would take us to the panic timeout, just use that
1291 if (cur_time + ip->client->interval >
1292 ip->client->first_sending + ip->client->config->timeout)
1293 ip->client->interval =
1294 (ip->client->first_sending +
1295 ip->client->config->timeout) - cur_time + 1;
1297 /* Record the number of seconds since we started sending. */
1298 if (interval < 65536)
1299 ip->client->packet.secs = htons(interval);
1301 ip->client->packet.secs = htons(65535);
1302 ip->client->secs = ip->client->packet.secs;
1304 note("DHCPDISCOVER on %s to %s port %d interval %d",
1305 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1306 (int)ip->client->interval);
1308 /* Send out a packet. */
1309 send_packet_unpriv(privfd, &ip->client->packet,
1310 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1312 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1316 * state_panic gets called if we haven't received any offers in a preset
1317 * amount of time. When this happens, we try to use existing leases
1318 * that haven't yet expired, and failing that, we call the client script
1319 * and hope it can do something.
1322 state_panic(void *ipp)
1324 struct interface_info *ip = ipp;
1325 struct client_lease *loop = ip->client->active;
1326 struct client_lease *lp;
1328 note("No DHCPOFFERS received.");
1330 /* We may not have an active lease, but we may have some
1331 predefined leases that we can try. */
1332 if (!ip->client->active && ip->client->leases)
1335 /* Run through the list of leases and see if one can be used. */
1336 while (ip->client->active) {
1337 if (ip->client->active->expiry > cur_time) {
1338 note("Trying recorded lease %s",
1339 piaddr(ip->client->active->address));
1340 /* Run the client script with the existing
1342 script_init("TIMEOUT",
1343 ip->client->active->medium);
1344 script_write_params("new_", ip->client->active);
1345 if (ip->client->alias)
1346 script_write_params("alias_",
1349 /* If the old lease is still good and doesn't
1350 yet need renewal, go into BOUND state and
1351 timeout at the renewal time. */
1354 ip->client->active->renewal) {
1355 ip->client->state = S_BOUND;
1356 note("bound: renewal in %d seconds.",
1357 (int)(ip->client->active->renewal -
1360 ip->client->active->renewal,
1363 ip->client->state = S_BOUND;
1364 note("bound: immediate renewal.");
1367 reinitialize_interfaces();
1373 /* If there are no other leases, give up. */
1374 if (!ip->client->leases) {
1375 ip->client->leases = ip->client->active;
1376 ip->client->active = NULL;
1381 /* Otherwise, put the active lease at the end of the
1382 lease list, and try another lease.. */
1383 for (lp = ip->client->leases; lp->next; lp = lp->next)
1385 lp->next = ip->client->active;
1387 lp->next->next = NULL;
1388 ip->client->active = ip->client->leases;
1389 ip->client->leases = ip->client->leases->next;
1391 /* If we already tried this lease, we've exhausted the
1392 set of leases, so we might as well give up for
1394 if (ip->client->active == loop)
1397 loop = ip->client->active;
1400 /* No leases were available, or what was available didn't work, so
1401 tell the shell script that we failed to allocate an address,
1402 and try again later. */
1403 note("No working leases in persistent database - sleeping.\n");
1404 script_init("FAIL", NULL);
1405 if (ip->client->alias)
1406 script_write_params("alias_", ip->client->alias);
1408 ip->client->state = S_INIT;
1409 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1415 send_request(void *ipp)
1417 struct interface_info *ip = ipp;
1418 struct in_addr from, to;
1421 /* Figure out how long it's been since we started transmitting. */
1422 interval = cur_time - ip->client->first_sending;
1424 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1425 past the reboot timeout, go to INIT and see if we can
1426 DISCOVER an address... */
1427 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1428 means either that we're on a network with no DHCP server,
1429 or that our server is down. In the latter case, assuming
1430 that there is a backup DHCP server, DHCPDISCOVER will get
1431 us a new address, but we could also have successfully
1432 reused our old address. In the former case, we're hosed
1433 anyway. This is not a win-prone situation. */
1434 if ((ip->client->state == S_REBOOTING ||
1435 ip->client->state == S_REQUESTING) &&
1436 interval > ip->client->config->reboot_timeout) {
1438 ip->client->state = S_INIT;
1439 cancel_timeout(send_request, ip);
1444 /* If we're in the reboot state, make sure the media is set up
1446 if (ip->client->state == S_REBOOTING &&
1447 !ip->client->medium &&
1448 ip->client->active->medium ) {
1449 script_init("MEDIUM", ip->client->active->medium);
1451 /* If the medium we chose won't fly, go to INIT state. */
1455 /* Record the medium. */
1456 ip->client->medium = ip->client->active->medium;
1459 /* If the lease has expired, relinquish the address and go back
1460 to the INIT state. */
1461 if (ip->client->state != S_REQUESTING &&
1462 cur_time > ip->client->active->expiry) {
1463 /* Run the client script with the new parameters. */
1464 script_init("EXPIRE", NULL);
1465 script_write_params("old_", ip->client->active);
1466 if (ip->client->alias)
1467 script_write_params("alias_", ip->client->alias);
1470 /* Now do a preinit on the interface so that we can
1471 discover a new address. */
1472 script_init("PREINIT", NULL);
1473 if (ip->client->alias)
1474 script_write_params("alias_", ip->client->alias);
1477 ip->client->state = S_INIT;
1482 /* Do the exponential backoff... */
1483 if (!ip->client->interval)
1484 ip->client->interval = ip->client->config->initial_interval;
1486 ip->client->interval += ((arc4random() >> 2) %
1487 (2 * ip->client->interval));
1489 /* Don't backoff past cutoff. */
1490 if (ip->client->interval >
1491 ip->client->config->backoff_cutoff)
1492 ip->client->interval =
1493 ((ip->client->config->backoff_cutoff / 2) +
1494 ((arc4random() >> 2) % ip->client->interval));
1496 /* If the backoff would take us to the expiry time, just set the
1497 timeout to the expiry time. */
1498 if (ip->client->state != S_REQUESTING &&
1499 cur_time + ip->client->interval >
1500 ip->client->active->expiry)
1501 ip->client->interval =
1502 ip->client->active->expiry - cur_time + 1;
1504 /* If the lease T2 time has elapsed, or if we're not yet bound,
1505 broadcast the DHCPREQUEST rather than unicasting. */
1506 if (ip->client->state == S_REQUESTING ||
1507 ip->client->state == S_REBOOTING ||
1508 cur_time > ip->client->active->rebind)
1509 to.s_addr = INADDR_BROADCAST;
1511 memcpy(&to.s_addr, ip->client->destination.iabuf,
1514 if (ip->client->state != S_REQUESTING)
1515 memcpy(&from, ip->client->active->address.iabuf,
1518 from.s_addr = INADDR_ANY;
1520 /* Record the number of seconds since we started sending. */
1521 if (ip->client->state == S_REQUESTING)
1522 ip->client->packet.secs = ip->client->secs;
1524 if (interval < 65536)
1525 ip->client->packet.secs = htons(interval);
1527 ip->client->packet.secs = htons(65535);
1530 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1533 /* Send out a packet. */
1534 send_packet_unpriv(privfd, &ip->client->packet,
1535 ip->client->packet_length, from, to);
1537 add_timeout(cur_time + ip->client->interval, send_request, ip);
1541 send_decline(void *ipp)
1543 struct interface_info *ip = ipp;
1545 note("DHCPDECLINE on %s to %s port %d", ip->name,
1546 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1548 /* Send out a packet. */
1549 send_packet_unpriv(privfd, &ip->client->packet,
1550 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1554 make_discover(struct interface_info *ip, struct client_lease *lease)
1556 unsigned char discover = DHCPDISCOVER;
1557 struct tree_cache *options[256];
1558 struct tree_cache option_elements[256];
1561 memset(option_elements, 0, sizeof(option_elements));
1562 memset(options, 0, sizeof(options));
1563 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1565 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1566 i = DHO_DHCP_MESSAGE_TYPE;
1567 options[i] = &option_elements[i];
1568 options[i]->value = &discover;
1569 options[i]->len = sizeof(discover);
1570 options[i]->buf_size = sizeof(discover);
1571 options[i]->timeout = 0xFFFFFFFF;
1573 /* Request the options we want */
1574 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1575 options[i] = &option_elements[i];
1576 options[i]->value = ip->client->config->requested_options;
1577 options[i]->len = ip->client->config->requested_option_count;
1578 options[i]->buf_size =
1579 ip->client->config->requested_option_count;
1580 options[i]->timeout = 0xFFFFFFFF;
1582 /* If we had an address, try to get it again. */
1584 ip->client->requested_address = lease->address;
1585 i = DHO_DHCP_REQUESTED_ADDRESS;
1586 options[i] = &option_elements[i];
1587 options[i]->value = lease->address.iabuf;
1588 options[i]->len = lease->address.len;
1589 options[i]->buf_size = lease->address.len;
1590 options[i]->timeout = 0xFFFFFFFF;
1592 ip->client->requested_address.len = 0;
1594 /* Send any options requested in the config file. */
1595 for (i = 0; i < 256; i++)
1597 ip->client->config->send_options[i].data) {
1598 options[i] = &option_elements[i];
1600 ip->client->config->send_options[i].data;
1602 ip->client->config->send_options[i].len;
1603 options[i]->buf_size =
1604 ip->client->config->send_options[i].len;
1605 options[i]->timeout = 0xFFFFFFFF;
1608 /* send host name if not set via config file. */
1609 if (!options[DHO_HOST_NAME]) {
1610 if (hostname[0] != '\0') {
1612 char* posDot = strchr(hostname, '.');
1614 len = posDot - hostname;
1616 len = strlen(hostname);
1617 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1618 options[DHO_HOST_NAME]->value = hostname;
1619 options[DHO_HOST_NAME]->len = len;
1620 options[DHO_HOST_NAME]->buf_size = len;
1621 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1625 /* set unique client identifier */
1626 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1627 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1628 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1629 ip->hw_address.hlen : sizeof(client_ident)-1;
1630 client_ident[0] = ip->hw_address.htype;
1631 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1632 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1633 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1634 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1635 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1636 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1639 /* Set up the option buffer... */
1640 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1641 options, 0, 0, 0, NULL, 0);
1642 if (ip->client->packet_length < BOOTP_MIN_LEN)
1643 ip->client->packet_length = BOOTP_MIN_LEN;
1645 ip->client->packet.op = BOOTREQUEST;
1646 ip->client->packet.htype = ip->hw_address.htype;
1647 ip->client->packet.hlen = ip->hw_address.hlen;
1648 ip->client->packet.hops = 0;
1649 ip->client->packet.xid = arc4random();
1650 ip->client->packet.secs = 0; /* filled in by send_discover. */
1651 ip->client->packet.flags = 0;
1653 memset(&(ip->client->packet.ciaddr),
1654 0, sizeof(ip->client->packet.ciaddr));
1655 memset(&(ip->client->packet.yiaddr),
1656 0, sizeof(ip->client->packet.yiaddr));
1657 memset(&(ip->client->packet.siaddr),
1658 0, sizeof(ip->client->packet.siaddr));
1659 memset(&(ip->client->packet.giaddr),
1660 0, sizeof(ip->client->packet.giaddr));
1661 memcpy(ip->client->packet.chaddr,
1662 ip->hw_address.haddr, ip->hw_address.hlen);
1667 make_request(struct interface_info *ip, struct client_lease * lease)
1669 unsigned char request = DHCPREQUEST;
1670 struct tree_cache *options[256];
1671 struct tree_cache option_elements[256];
1674 memset(options, 0, sizeof(options));
1675 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1677 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1678 i = DHO_DHCP_MESSAGE_TYPE;
1679 options[i] = &option_elements[i];
1680 options[i]->value = &request;
1681 options[i]->len = sizeof(request);
1682 options[i]->buf_size = sizeof(request);
1683 options[i]->timeout = 0xFFFFFFFF;
1685 /* Request the options we want */
1686 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1687 options[i] = &option_elements[i];
1688 options[i]->value = ip->client->config->requested_options;
1689 options[i]->len = ip->client->config->requested_option_count;
1690 options[i]->buf_size =
1691 ip->client->config->requested_option_count;
1692 options[i]->timeout = 0xFFFFFFFF;
1694 /* If we are requesting an address that hasn't yet been assigned
1695 to us, use the DHCP Requested Address option. */
1696 if (ip->client->state == S_REQUESTING) {
1697 /* Send back the server identifier... */
1698 i = DHO_DHCP_SERVER_IDENTIFIER;
1699 options[i] = &option_elements[i];
1700 options[i]->value = lease->options[i].data;
1701 options[i]->len = lease->options[i].len;
1702 options[i]->buf_size = lease->options[i].len;
1703 options[i]->timeout = 0xFFFFFFFF;
1705 if (ip->client->state == S_REQUESTING ||
1706 ip->client->state == S_REBOOTING) {
1707 ip->client->requested_address = lease->address;
1708 i = DHO_DHCP_REQUESTED_ADDRESS;
1709 options[i] = &option_elements[i];
1710 options[i]->value = lease->address.iabuf;
1711 options[i]->len = lease->address.len;
1712 options[i]->buf_size = lease->address.len;
1713 options[i]->timeout = 0xFFFFFFFF;
1715 ip->client->requested_address.len = 0;
1717 /* Send any options requested in the config file. */
1718 for (i = 0; i < 256; i++)
1720 ip->client->config->send_options[i].data) {
1721 options[i] = &option_elements[i];
1723 ip->client->config->send_options[i].data;
1725 ip->client->config->send_options[i].len;
1726 options[i]->buf_size =
1727 ip->client->config->send_options[i].len;
1728 options[i]->timeout = 0xFFFFFFFF;
1731 /* send host name if not set via config file. */
1732 if (!options[DHO_HOST_NAME]) {
1733 if (hostname[0] != '\0') {
1735 char* posDot = strchr(hostname, '.');
1737 len = posDot - hostname;
1739 len = strlen(hostname);
1740 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1741 options[DHO_HOST_NAME]->value = hostname;
1742 options[DHO_HOST_NAME]->len = len;
1743 options[DHO_HOST_NAME]->buf_size = len;
1744 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1748 /* set unique client identifier */
1749 char client_ident[sizeof(struct hardware)];
1750 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1751 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1752 ip->hw_address.hlen : sizeof(client_ident)-1;
1753 client_ident[0] = ip->hw_address.htype;
1754 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1755 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1756 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1757 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1758 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1759 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1762 /* Set up the option buffer... */
1763 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1764 options, 0, 0, 0, NULL, 0);
1765 if (ip->client->packet_length < BOOTP_MIN_LEN)
1766 ip->client->packet_length = BOOTP_MIN_LEN;
1768 ip->client->packet.op = BOOTREQUEST;
1769 ip->client->packet.htype = ip->hw_address.htype;
1770 ip->client->packet.hlen = ip->hw_address.hlen;
1771 ip->client->packet.hops = 0;
1772 ip->client->packet.xid = ip->client->xid;
1773 ip->client->packet.secs = 0; /* Filled in by send_request. */
1775 /* If we own the address we're requesting, put it in ciaddr;
1776 otherwise set ciaddr to zero. */
1777 if (ip->client->state == S_BOUND ||
1778 ip->client->state == S_RENEWING ||
1779 ip->client->state == S_REBINDING) {
1780 memcpy(&ip->client->packet.ciaddr,
1781 lease->address.iabuf, lease->address.len);
1782 ip->client->packet.flags = 0;
1784 memset(&ip->client->packet.ciaddr, 0,
1785 sizeof(ip->client->packet.ciaddr));
1786 ip->client->packet.flags = 0;
1789 memset(&ip->client->packet.yiaddr, 0,
1790 sizeof(ip->client->packet.yiaddr));
1791 memset(&ip->client->packet.siaddr, 0,
1792 sizeof(ip->client->packet.siaddr));
1793 memset(&ip->client->packet.giaddr, 0,
1794 sizeof(ip->client->packet.giaddr));
1795 memcpy(ip->client->packet.chaddr,
1796 ip->hw_address.haddr, ip->hw_address.hlen);
1800 make_decline(struct interface_info *ip, struct client_lease *lease)
1802 struct tree_cache *options[256], message_type_tree;
1803 struct tree_cache requested_address_tree;
1804 struct tree_cache server_id_tree, client_id_tree;
1805 unsigned char decline = DHCPDECLINE;
1808 memset(options, 0, sizeof(options));
1809 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1811 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1812 i = DHO_DHCP_MESSAGE_TYPE;
1813 options[i] = &message_type_tree;
1814 options[i]->value = &decline;
1815 options[i]->len = sizeof(decline);
1816 options[i]->buf_size = sizeof(decline);
1817 options[i]->timeout = 0xFFFFFFFF;
1819 /* Send back the server identifier... */
1820 i = DHO_DHCP_SERVER_IDENTIFIER;
1821 options[i] = &server_id_tree;
1822 options[i]->value = lease->options[i].data;
1823 options[i]->len = lease->options[i].len;
1824 options[i]->buf_size = lease->options[i].len;
1825 options[i]->timeout = 0xFFFFFFFF;
1827 /* Send back the address we're declining. */
1828 i = DHO_DHCP_REQUESTED_ADDRESS;
1829 options[i] = &requested_address_tree;
1830 options[i]->value = lease->address.iabuf;
1831 options[i]->len = lease->address.len;
1832 options[i]->buf_size = lease->address.len;
1833 options[i]->timeout = 0xFFFFFFFF;
1835 /* Send the uid if the user supplied one. */
1836 i = DHO_DHCP_CLIENT_IDENTIFIER;
1837 if (ip->client->config->send_options[i].len) {
1838 options[i] = &client_id_tree;
1839 options[i]->value = ip->client->config->send_options[i].data;
1840 options[i]->len = ip->client->config->send_options[i].len;
1841 options[i]->buf_size = ip->client->config->send_options[i].len;
1842 options[i]->timeout = 0xFFFFFFFF;
1846 /* Set up the option buffer... */
1847 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1848 options, 0, 0, 0, NULL, 0);
1849 if (ip->client->packet_length < BOOTP_MIN_LEN)
1850 ip->client->packet_length = BOOTP_MIN_LEN;
1852 ip->client->packet.op = BOOTREQUEST;
1853 ip->client->packet.htype = ip->hw_address.htype;
1854 ip->client->packet.hlen = ip->hw_address.hlen;
1855 ip->client->packet.hops = 0;
1856 ip->client->packet.xid = ip->client->xid;
1857 ip->client->packet.secs = 0; /* Filled in by send_request. */
1858 ip->client->packet.flags = 0;
1860 /* ciaddr must always be zero. */
1861 memset(&ip->client->packet.ciaddr, 0,
1862 sizeof(ip->client->packet.ciaddr));
1863 memset(&ip->client->packet.yiaddr, 0,
1864 sizeof(ip->client->packet.yiaddr));
1865 memset(&ip->client->packet.siaddr, 0,
1866 sizeof(ip->client->packet.siaddr));
1867 memset(&ip->client->packet.giaddr, 0,
1868 sizeof(ip->client->packet.giaddr));
1869 memcpy(ip->client->packet.chaddr,
1870 ip->hw_address.haddr, ip->hw_address.hlen);
1874 free_client_lease(struct client_lease *lease)
1878 if (lease->server_name)
1879 free(lease->server_name);
1880 if (lease->filename)
1881 free(lease->filename);
1882 for (i = 0; i < 256; i++) {
1883 if (lease->options[i].len)
1884 free(lease->options[i].data);
1892 rewrite_client_leases(void)
1894 struct client_lease *lp;
1895 cap_rights_t rights;
1898 leaseFile = fopen(path_dhclient_db, "w");
1900 error("can't create %s: %m", path_dhclient_db);
1901 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1902 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1903 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1905 error("can't limit lease descriptor: %m");
1907 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1909 error("can't limit lease descriptor fcntls: %m");
1916 for (lp = ifi->client->leases; lp; lp = lp->next)
1917 write_client_lease(ifi, lp, 1);
1918 if (ifi->client->active)
1919 write_client_lease(ifi, ifi->client->active, 1);
1922 ftruncate(fileno(leaseFile), ftello(leaseFile));
1923 fsync(fileno(leaseFile));
1927 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1930 static int leases_written;
1935 if (leases_written++ > 20) {
1936 rewrite_client_leases();
1941 /* If the lease came from the config file, we don't need to stash
1942 a copy in the lease database. */
1943 if (lease->is_static)
1946 if (!leaseFile) { /* XXX */
1947 leaseFile = fopen(path_dhclient_db, "w");
1949 error("can't create %s: %m", path_dhclient_db);
1952 fprintf(leaseFile, "lease {\n");
1953 if (lease->is_bootp)
1954 fprintf(leaseFile, " bootp;\n");
1955 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1956 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1957 if (lease->nextserver.len == sizeof(inaddr_any) &&
1958 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1959 sizeof(inaddr_any)))
1960 fprintf(leaseFile, " next-server %s;\n",
1961 piaddr(lease->nextserver));
1962 if (lease->filename)
1963 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1964 if (lease->server_name)
1965 fprintf(leaseFile, " server-name \"%s\";\n",
1966 lease->server_name);
1968 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1969 for (i = 0; i < 256; i++)
1970 if (lease->options[i].len)
1971 fprintf(leaseFile, " option %s %s;\n",
1972 dhcp_options[i].name,
1973 pretty_print_option(i, lease->options[i].data,
1974 lease->options[i].len, 1, 1));
1976 t = gmtime(&lease->renewal);
1977 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1978 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1979 t->tm_hour, t->tm_min, t->tm_sec);
1980 t = gmtime(&lease->rebind);
1981 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1982 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1983 t->tm_hour, t->tm_min, t->tm_sec);
1984 t = gmtime(&lease->expiry);
1985 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1986 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1987 t->tm_hour, t->tm_min, t->tm_sec);
1988 fprintf(leaseFile, "}\n");
1993 script_init(char *reason, struct string_list *medium)
1995 size_t len, mediumlen = 0;
1996 struct imsg_hdr hdr;
2000 if (medium != NULL && medium->string != NULL)
2001 mediumlen = strlen(medium->string);
2003 hdr.code = IMSG_SCRIPT_INIT;
2004 hdr.len = sizeof(struct imsg_hdr) +
2005 sizeof(size_t) + mediumlen +
2006 sizeof(size_t) + strlen(reason);
2008 if ((buf = buf_open(hdr.len)) == NULL)
2009 error("buf_open: %m");
2012 errs += buf_add(buf, &hdr, sizeof(hdr));
2013 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2015 errs += buf_add(buf, medium->string, mediumlen);
2016 len = strlen(reason);
2017 errs += buf_add(buf, &len, sizeof(len));
2018 errs += buf_add(buf, reason, len);
2021 error("buf_add: %m");
2023 if (buf_close(privfd, buf) == -1)
2024 error("buf_close: %m");
2028 priv_script_init(char *reason, char *medium)
2030 struct interface_info *ip = ifi;
2033 ip->client->scriptEnvsize = 100;
2034 if (ip->client->scriptEnv == NULL)
2035 ip->client->scriptEnv =
2036 malloc(ip->client->scriptEnvsize * sizeof(char *));
2037 if (ip->client->scriptEnv == NULL)
2038 error("script_init: no memory for environment");
2040 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2041 if (ip->client->scriptEnv[0] == NULL)
2042 error("script_init: no memory for environment");
2044 ip->client->scriptEnv[1] = NULL;
2046 script_set_env(ip->client, "", "interface", ip->name);
2049 script_set_env(ip->client, "", "medium", medium);
2051 script_set_env(ip->client, "", "reason", reason);
2056 priv_script_write_params(char *prefix, struct client_lease *lease)
2058 struct interface_info *ip = ifi;
2059 u_int8_t dbuf[1500], *dp = NULL;
2063 script_set_env(ip->client, prefix, "ip_address",
2064 piaddr(lease->address));
2066 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2068 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2069 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2071 dp = lease->options[DHO_SUBNET_MASK].data;
2072 len = lease->options[DHO_SUBNET_MASK].len;
2074 if (len && (len < sizeof(lease->address.iabuf))) {
2075 struct iaddr netmask, subnet, broadcast;
2077 memcpy(netmask.iabuf, dp, len);
2079 subnet = subnet_number(lease->address, netmask);
2081 script_set_env(ip->client, prefix, "network_number",
2083 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2084 broadcast = broadcast_addr(subnet, netmask);
2086 script_set_env(ip->client, prefix,
2087 "broadcast_address",
2093 if (lease->filename)
2094 script_set_env(ip->client, prefix, "filename", lease->filename);
2095 if (lease->server_name)
2096 script_set_env(ip->client, prefix, "server_name",
2097 lease->server_name);
2098 for (i = 0; i < 256; i++) {
2101 if (ip->client->config->defaults[i].len) {
2102 if (lease->options[i].len) {
2104 ip->client->config->default_actions[i]) {
2105 case ACTION_DEFAULT:
2106 dp = lease->options[i].data;
2107 len = lease->options[i].len;
2109 case ACTION_SUPERSEDE:
2112 config->defaults[i].data;
2114 config->defaults[i].len;
2116 case ACTION_PREPEND:
2118 config->defaults[i].len +
2119 lease->options[i].len;
2120 if (len >= sizeof(dbuf)) {
2121 warning("no space to %s %s",
2123 dhcp_options[i].name);
2129 config->defaults[i].data,
2131 config->defaults[i].len);
2132 memcpy(dp + ip->client->
2133 config->defaults[i].len,
2134 lease->options[i].data,
2135 lease->options[i].len);
2140 * When we append, we assume that we're
2141 * appending to text. Some MS servers
2142 * include a NUL byte at the end of
2143 * the search string provided.
2146 config->defaults[i].len +
2147 lease->options[i].len;
2148 if (len >= sizeof(dbuf)) {
2149 warning("no space to %s %s",
2151 dhcp_options[i].name);
2155 lease->options[i].data,
2156 lease->options[i].len);
2157 for (dp = dbuf + lease->options[i].len;
2158 dp > dbuf; dp--, len--)
2163 config->defaults[i].data,
2165 config->defaults[i].len);
2171 config->defaults[i].data;
2173 config->defaults[i].len;
2175 } else if (lease->options[i].len) {
2176 len = lease->options[i].len;
2177 dp = lease->options[i].data;
2184 if (dhcp_option_ev_name(name, sizeof(name),
2186 script_set_env(ip->client, prefix, name,
2187 pretty_print_option(i, dp, len, 0, 0));
2190 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2191 script_set_env(ip->client, prefix, "expiry", tbuf);
2195 script_write_params(char *prefix, struct client_lease *lease)
2197 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2198 struct imsg_hdr hdr;
2202 if (lease->filename != NULL)
2203 fn_len = strlen(lease->filename);
2204 if (lease->server_name != NULL)
2205 sn_len = strlen(lease->server_name);
2207 pr_len = strlen(prefix);
2209 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2210 hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2211 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2212 sizeof(size_t) + pr_len;
2214 for (i = 0; i < 256; i++)
2215 hdr.len += sizeof(int) + lease->options[i].len;
2217 scripttime = time(NULL);
2219 if ((buf = buf_open(hdr.len)) == NULL)
2220 error("buf_open: %m");
2223 errs += buf_add(buf, &hdr, sizeof(hdr));
2224 errs += buf_add(buf, lease, sizeof(struct client_lease));
2225 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2226 errs += buf_add(buf, lease->filename, fn_len);
2227 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2228 errs += buf_add(buf, lease->server_name, sn_len);
2229 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2230 errs += buf_add(buf, prefix, pr_len);
2232 for (i = 0; i < 256; i++) {
2233 errs += buf_add(buf, &lease->options[i].len,
2234 sizeof(lease->options[i].len));
2235 errs += buf_add(buf, lease->options[i].data,
2236 lease->options[i].len);
2240 error("buf_add: %m");
2242 if (buf_close(privfd, buf) == -1)
2243 error("buf_close: %m");
2249 struct imsg_hdr hdr;
2253 hdr.code = IMSG_SCRIPT_GO;
2254 hdr.len = sizeof(struct imsg_hdr);
2256 if ((buf = buf_open(hdr.len)) == NULL)
2257 error("buf_open: %m");
2259 if (buf_add(buf, &hdr, sizeof(hdr)))
2260 error("buf_add: %m");
2262 if (buf_close(privfd, buf) == -1)
2263 error("buf_close: %m");
2265 bzero(&hdr, sizeof(hdr));
2266 buf_read(privfd, &hdr, sizeof(hdr));
2267 if (hdr.code != IMSG_SCRIPT_GO_RET)
2268 error("unexpected msg type %u", hdr.code);
2269 if (hdr.len != sizeof(hdr) + sizeof(int))
2270 error("received corrupted message");
2271 buf_read(privfd, &ret, sizeof(ret));
2273 scripttime = time(NULL);
2279 priv_script_go(void)
2281 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2282 static char client_path[] = CLIENT_PATH;
2283 struct interface_info *ip = ifi;
2284 int pid, wpid, wstatus;
2286 scripttime = time(NULL);
2289 scriptName = ip->client->config->script_name;
2290 envp = ip->client->scriptEnv;
2292 scriptName = top_level_config.script_name;
2294 epp[1] = client_path;
2299 argv[0] = scriptName;
2308 wpid = wait(&wstatus);
2309 } while (wpid != pid && wpid > 0);
2315 execve(scriptName, argv, envp);
2316 error("execve (%s, ...): %m", scriptName);
2320 script_flush_env(ip->client);
2322 return (wstatus & 0xff);
2326 script_set_env(struct client_state *client, const char *prefix,
2327 const char *name, const char *value)
2331 /* No `` or $() command substitution allowed in environment values! */
2332 for (j=0; j < strlen(value); j++)
2336 warning("illegal character (%c) in value '%s'",
2338 /* Ignore this option */
2342 namelen = strlen(name);
2344 for (i = 0; client->scriptEnv[i]; i++)
2345 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2346 client->scriptEnv[i][namelen] == '=')
2349 if (client->scriptEnv[i])
2350 /* Reuse the slot. */
2351 free(client->scriptEnv[i]);
2353 /* New variable. Expand if necessary. */
2354 if (i >= client->scriptEnvsize - 1) {
2355 char **newscriptEnv;
2356 int newscriptEnvsize = client->scriptEnvsize + 50;
2358 newscriptEnv = realloc(client->scriptEnv,
2360 if (newscriptEnv == NULL) {
2361 free(client->scriptEnv);
2362 client->scriptEnv = NULL;
2363 client->scriptEnvsize = 0;
2364 error("script_set_env: no memory for variable");
2366 client->scriptEnv = newscriptEnv;
2367 client->scriptEnvsize = newscriptEnvsize;
2369 /* need to set the NULL pointer at end of array beyond
2371 client->scriptEnv[i + 1] = NULL;
2373 /* Allocate space and format the variable in the appropriate slot. */
2374 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2376 if (client->scriptEnv[i] == NULL)
2377 error("script_set_env: no memory for variable assignment");
2378 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2379 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2383 script_flush_env(struct client_state *client)
2387 for (i = 0; client->scriptEnv[i]; i++) {
2388 free(client->scriptEnv[i]);
2389 client->scriptEnv[i] = NULL;
2391 client->scriptEnvsize = 0;
2395 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2399 for (i = 0; option->name[i]; i++) {
2400 if (i + 1 == buflen)
2402 if (option->name[i] == '-')
2405 buf[i] = option->name[i];
2415 static int state = 0;
2416 cap_rights_t rights;
2418 if (no_daemon || state)
2423 /* Stop logging to stderr... */
2426 if (daemon(1, 1) == -1)
2429 cap_rights_init(&rights);
2431 if (pidfile != NULL) {
2432 pidfile_write(pidfile);
2433 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2435 error("can't limit pidfile descriptor: %m");
2439 /* we are chrooted, daemon(3) fails to open /dev/null */
2441 dup2(nullfd, STDIN_FILENO);
2442 dup2(nullfd, STDOUT_FILENO);
2443 dup2(nullfd, STDERR_FILENO);
2448 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2449 error("can't limit stdin: %m");
2450 cap_rights_init(&rights, CAP_WRITE);
2451 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2452 error("can't limit stdout: %m");
2453 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2454 error("can't limit stderr: %m");
2458 check_option(struct client_lease *l, int option)
2463 /* we use this, since this is what gets passed to dhclient-script */
2465 opbuf = pretty_print_option(option, l->options[option].data,
2466 l->options[option].len, 0, 0);
2468 sbuf = option_as_string(option, l->options[option].data,
2469 l->options[option].len);
2472 case DHO_SUBNET_MASK:
2473 case DHO_TIME_SERVERS:
2474 case DHO_NAME_SERVERS:
2476 case DHO_DOMAIN_NAME_SERVERS:
2477 case DHO_LOG_SERVERS:
2478 case DHO_COOKIE_SERVERS:
2479 case DHO_LPR_SERVERS:
2480 case DHO_IMPRESS_SERVERS:
2481 case DHO_RESOURCE_LOCATION_SERVERS:
2482 case DHO_SWAP_SERVER:
2483 case DHO_BROADCAST_ADDRESS:
2484 case DHO_NIS_SERVERS:
2485 case DHO_NTP_SERVERS:
2486 case DHO_NETBIOS_NAME_SERVERS:
2487 case DHO_NETBIOS_DD_SERVER:
2488 case DHO_FONT_SERVERS:
2489 case DHO_DHCP_SERVER_IDENTIFIER:
2490 case DHO_NISPLUS_SERVERS:
2491 case DHO_MOBILE_IP_HOME_AGENT:
2492 case DHO_SMTP_SERVER:
2493 case DHO_POP_SERVER:
2494 case DHO_NNTP_SERVER:
2495 case DHO_WWW_SERVER:
2496 case DHO_FINGER_SERVER:
2497 case DHO_IRC_SERVER:
2498 case DHO_STREETTALK_SERVER:
2499 case DHO_STREETTALK_DA_SERVER:
2500 if (!ipv4addrs(opbuf)) {
2501 warning("Invalid IP address in option: %s", opbuf);
2506 case DHO_NIS_DOMAIN:
2507 case DHO_NISPLUS_DOMAIN:
2508 case DHO_TFTP_SERVER_NAME:
2509 if (!res_hnok(sbuf)) {
2510 warning("Bogus Host Name option %d: %s (%s)", option,
2512 l->options[option].len = 0;
2513 free(l->options[option].data);
2516 case DHO_DOMAIN_NAME:
2517 case DHO_DOMAIN_SEARCH:
2518 if (!res_hnok(sbuf)) {
2519 if (!check_search(sbuf)) {
2520 warning("Bogus domain search list %d: %s (%s)",
2521 option, sbuf, opbuf);
2522 l->options[option].len = 0;
2523 free(l->options[option].data);
2528 case DHO_TIME_OFFSET:
2530 case DHO_MERIT_DUMP:
2532 case DHO_EXTENSIONS_PATH:
2533 case DHO_IP_FORWARDING:
2534 case DHO_NON_LOCAL_SOURCE_ROUTING:
2535 case DHO_POLICY_FILTER:
2536 case DHO_MAX_DGRAM_REASSEMBLY:
2537 case DHO_DEFAULT_IP_TTL:
2538 case DHO_PATH_MTU_AGING_TIMEOUT:
2539 case DHO_PATH_MTU_PLATEAU_TABLE:
2540 case DHO_INTERFACE_MTU:
2541 case DHO_ALL_SUBNETS_LOCAL:
2542 case DHO_PERFORM_MASK_DISCOVERY:
2543 case DHO_MASK_SUPPLIER:
2544 case DHO_ROUTER_DISCOVERY:
2545 case DHO_ROUTER_SOLICITATION_ADDRESS:
2546 case DHO_STATIC_ROUTES:
2547 case DHO_TRAILER_ENCAPSULATION:
2548 case DHO_ARP_CACHE_TIMEOUT:
2549 case DHO_IEEE802_3_ENCAPSULATION:
2550 case DHO_DEFAULT_TCP_TTL:
2551 case DHO_TCP_KEEPALIVE_INTERVAL:
2552 case DHO_TCP_KEEPALIVE_GARBAGE:
2553 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2554 case DHO_NETBIOS_NODE_TYPE:
2555 case DHO_NETBIOS_SCOPE:
2556 case DHO_X_DISPLAY_MANAGER:
2557 case DHO_DHCP_REQUESTED_ADDRESS:
2558 case DHO_DHCP_LEASE_TIME:
2559 case DHO_DHCP_OPTION_OVERLOAD:
2560 case DHO_DHCP_MESSAGE_TYPE:
2561 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2562 case DHO_DHCP_MESSAGE:
2563 case DHO_DHCP_MAX_MESSAGE_SIZE:
2564 case DHO_DHCP_RENEWAL_TIME:
2565 case DHO_DHCP_REBINDING_TIME:
2566 case DHO_DHCP_CLASS_IDENTIFIER:
2567 case DHO_DHCP_CLIENT_IDENTIFIER:
2568 case DHO_BOOTFILE_NAME:
2569 case DHO_DHCP_USER_CLASS_ID:
2572 case DHO_CLASSLESS_ROUTES:
2573 return (check_classless_option(l->options[option].data,
2574 l->options[option].len));
2576 warning("unknown dhcp option value 0x%x", option);
2577 return (unknown_ok);
2581 /* RFC 3442 The Classless Static Routes option checks */
2583 check_classless_option(unsigned char *data, int len)
2586 unsigned char width;
2587 in_addr_t addr, mask;
2590 warning("Too small length: %d", len);
2598 } else if (width < 9) {
2599 addr = (in_addr_t)(data[i] << 24);
2601 } else if (width < 17) {
2602 addr = (in_addr_t)(data[i] << 24) +
2603 (in_addr_t)(data[i + 1] << 16);
2605 } else if (width < 25) {
2606 addr = (in_addr_t)(data[i] << 24) +
2607 (in_addr_t)(data[i + 1] << 16) +
2608 (in_addr_t)(data[i + 2] << 8);
2610 } else if (width < 33) {
2611 addr = (in_addr_t)(data[i] << 24) +
2612 (in_addr_t)(data[i + 1] << 16) +
2613 (in_addr_t)(data[i + 2] << 8) +
2617 warning("Incorrect subnet width: %d", width);
2620 mask = (in_addr_t)(~0) << (32 - width);
2626 * ... After deriving a subnet number and subnet mask
2627 * from each destination descriptor, the DHCP client
2628 * MUST zero any bits in the subnet number where the
2629 * corresponding bit in the mask is zero...
2631 if ((addr & mask) != addr) {
2633 data[i - 1] = (unsigned char)(
2634 (addr >> (((32 - width)/8)*8)) & 0xFF);
2639 warning("Incorrect data length: %d (must be %d)", len, i);
2646 res_hnok(const char *dn)
2648 int pch = PERIOD, ch = *dn++;
2650 while (ch != '\0') {
2653 if (periodchar(ch)) {
2655 } else if (periodchar(pch)) {
2656 if (!borderchar(ch))
2658 } else if (periodchar(nch) || nch == '\0') {
2659 if (!borderchar(ch))
2662 if (!middlechar(ch))
2671 check_search(const char *srch)
2673 int pch = PERIOD, ch = *srch++;
2676 /* 256 char limit re resolv.conf(5) */
2677 if (strlen(srch) > 256)
2680 while (whitechar(ch))
2683 while (ch != '\0') {
2686 if (periodchar(ch) || whitechar(ch)) {
2688 } else if (periodchar(pch)) {
2689 if (!borderchar(ch))
2691 } else if (periodchar(nch) || nch == '\0') {
2692 if (!borderchar(ch))
2695 if (!middlechar(ch))
2698 if (!whitechar(ch)) {
2701 while (whitechar(nch)) {
2710 /* 6 domain limit re resolv.conf(5) */
2716 /* Does buf consist only of dotted decimal ipv4 addrs?
2717 * return how many if so,
2718 * otherwise, return 0
2721 ipv4addrs(char * buf)
2726 while (inet_aton(buf, &jnk) == 1){
2728 while (periodchar(*buf) || digitchar(*buf))
2740 option_as_string(unsigned int code, unsigned char *data, int len)
2742 static char optbuf[32768]; /* XXX */
2744 int opleft = sizeof(optbuf);
2745 unsigned char *dp = data;
2748 error("option_as_string: bad code %d", code);
2750 for (; dp < data + len; dp++) {
2751 if (!isascii(*dp) || !isprint(*dp)) {
2752 if (dp + 1 != data + len || *dp != 0) {
2753 snprintf(op, opleft, "\\%03o", *dp);
2757 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2758 *dp == '`' || *dp == '\\') {
2772 warning("dhcp option too large");
2777 fork_privchld(int fd, int fd2)
2779 struct pollfd pfd[1];
2784 error("cannot fork");
2791 setproctitle("%s [priv]", ifi->name);
2794 dup2(nullfd, STDIN_FILENO);
2795 dup2(nullfd, STDOUT_FILENO);
2796 dup2(nullfd, STDERR_FILENO);
2804 pfd[0].events = POLLIN;
2805 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2807 error("poll error");
2809 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2812 dispatch_imsg(ifi, fd);