1 /* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
4 * SPDX-License-Identifier: BSD-3-Clause
6 * Copyright 2004 Henning Brauer <henning@openbsd.org>
7 * Copyright (c) 1995, 1996, 1997, 1998, 1999
8 * The Internet Software Consortium. All rights reserved.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of The Internet Software Consortium nor the names
20 * of its contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
24 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
25 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
28 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
29 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
30 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
32 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * This software has been written for the Internet Software Consortium
38 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
39 * Enterprises. To learn more about the Internet Software Consortium,
40 * see ``http://www.vix.com/isc''. To learn more about Vixie
41 * Enterprises, see ``http://www.vix.com''.
43 * This client was substantially modified and enhanced by Elliot Poger
44 * for use on Linux while he was working on the MosquitoNet project at
47 * The current version owes much to Elliot's Linux enhancements, but
48 * was substantially reorganized and partially rewritten by Ted Lemon
49 * so as to use the same networking framework that the Internet Software
50 * Consortium DHCP server uses. Much system-specific configuration code
51 * was moved into a shell script so that as support for more operating
52 * systems is added, it will not be necessary to port and maintain
53 * system-specific configuration code to these operating systems - instead,
54 * the shell script can invoke the native tools to accomplish the same
58 #include <sys/cdefs.h>
59 __FBSDID("$FreeBSD$");
64 #include <sys/capsicum.h>
65 #include <sys/endian.h>
67 #include <capsicum_helpers.h>
70 #include <net80211/ieee80211_freebsd.h>
73 #ifndef _PATH_VAREMPTY
74 #define _PATH_VAREMPTY "/var/empty"
78 #define hyphenchar(c) ((c) == 0x2d)
79 #define bslashchar(c) ((c) == 0x5c)
80 #define periodchar(c) ((c) == PERIOD)
81 #define asterchar(c) ((c) == 0x2a)
82 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
83 ((c) >= 0x61 && (c) <= 0x7a))
84 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
85 #define whitechar(c) ((c) == ' ' || (c) == '\t')
87 #define borderchar(c) (alphachar(c) || digitchar(c))
88 #define middlechar(c) (borderchar(c) || hyphenchar(c))
89 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
91 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
93 cap_channel_t *capsyslog;
96 static time_t default_lease_time = 43200; /* 12 hours... */
98 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
99 char *path_dhclient_db = NULL;
103 static int nullfd = -1;
105 static char hostname[_POSIX_HOST_NAME_MAX + 1];
107 static struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
108 static struct in_addr inaddr_any, inaddr_broadcast;
110 static char *path_dhclient_pidfile;
111 struct pidfh *pidfile;
114 * ASSERT_STATE() does nothing now; it used to be
115 * assert (state_is == state_shouldbe).
117 #define ASSERT_STATE(state_is, state_shouldbe) {}
120 * We need to check that the expiry, renewal and rebind times are not beyond
121 * the end of time (~2038 when a 32-bit time_t is being used).
123 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
126 static int no_daemon;
127 static int unknown_ok = 1;
130 struct interface_info *ifi;
132 int findproto(char *, int);
133 struct sockaddr *get_ifa(char *, int);
134 void routehandler(struct protocol *);
136 int check_option(struct client_lease *l, int option);
137 int check_classless_option(unsigned char *data, int len);
138 int ipv4addrs(const char * buf);
139 int res_hnok(const char *dn);
140 int check_search(const char *srch);
141 const char *option_as_string(unsigned int code, unsigned char *data, int len);
142 int fork_privchld(int, int);
145 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
146 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
148 /* Minimum MTU is 68 as per RFC791, p. 24 */
151 static time_t scripttime;
154 findproto(char *cp, int n)
161 for (i = 1; i; i <<= 1) {
163 sa = (struct sockaddr *)cp;
169 if (sa->sa_family == AF_INET)
171 if (sa->sa_family == AF_INET6)
184 get_ifa(char *cp, int n)
191 for (i = 1; i; i <<= 1)
193 sa = (struct sockaddr *)cp;
202 static struct iaddr defaddr = { .len = 4 };
203 static uint8_t curbssid[6];
208 struct interface_info *_ifi = arg;
211 * Clear existing state.
213 if (_ifi->client->active != NULL) {
214 script_init("EXPIRE", NULL);
215 script_write_params("old_",
216 _ifi->client->active);
217 if (_ifi->client->alias)
218 script_write_params("alias_",
219 _ifi->client->alias);
222 _ifi->client->state = S_INIT;
226 routehandler(struct protocol *p __unused)
228 char msg[2048], *addr;
229 struct rt_msghdr *rtm;
230 struct if_msghdr *ifm;
231 struct ifa_msghdr *ifam;
232 struct if_announcemsghdr *ifan;
233 struct ieee80211_join_event *jev;
234 struct client_lease *l;
235 time_t t = time(NULL);
236 struct sockaddr_in *sa;
241 n = read(routefd, &msg, sizeof(msg));
242 rtm = (struct rt_msghdr *)msg;
243 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
244 n < (ssize_t)rtm->rtm_msglen ||
245 rtm->rtm_version != RTM_VERSION)
248 switch (rtm->rtm_type) {
251 ifam = (struct ifa_msghdr *)rtm;
253 if (ifam->ifam_index != ifi->index)
255 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
257 if (scripttime == 0 || t < scripttime + 10)
260 sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
264 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
265 error("king bula sez: len mismatch");
266 memcpy(a.iabuf, &sa->sin_addr, a.len);
267 if (addr_eq(a, defaddr))
270 for (l = ifi->client->active; l != NULL; l = l->next)
271 if (addr_eq(a, l->address))
274 if (l == NULL) /* added/deleted addr is not the one we set */
277 addr = inet_ntoa(sa->sin_addr);
278 if (rtm->rtm_type == RTM_NEWADDR) {
280 * XXX: If someone other than us adds our address,
281 * should we assume they are taking over from us,
282 * delete the lease record, and exit without modifying
285 warning("My address (%s) was re-added", addr);
287 warning("My address (%s) was deleted, dhclient exiting",
293 ifm = (struct if_msghdr *)rtm;
294 if (ifm->ifm_index != ifi->index)
296 if ((rtm->rtm_flags & RTF_UP) == 0) {
297 warning("Interface %s is down, dhclient exiting",
301 linkstat = interface_link_status(ifi->name);
302 if (linkstat != ifi->linkstat) {
303 debug("%s link state %s -> %s", ifi->name,
304 ifi->linkstat ? "up" : "down",
305 linkstat ? "up" : "down");
306 ifi->linkstat = linkstat;
312 ifan = (struct if_announcemsghdr *)rtm;
313 if (ifan->ifan_what == IFAN_DEPARTURE &&
314 ifan->ifan_index == ifi->index) {
315 warning("Interface %s is gone, dhclient exiting",
321 ifan = (struct if_announcemsghdr *)rtm;
322 if (ifan->ifan_index != ifi->index)
324 switch (ifan->ifan_what) {
325 case RTM_IEEE80211_ASSOC:
326 case RTM_IEEE80211_REASSOC:
328 * Use assoc/reassoc event to kick state machine
329 * in case we roam. Otherwise fall back to the
330 * normal state machine just like a wired network.
332 jev = (struct ieee80211_join_event *) &ifan[1];
333 if (memcmp(curbssid, jev->iev_addr, 6)) {
337 memcpy(curbssid, jev->iev_addr, 6);
347 script_init("FAIL", NULL);
348 if (ifi->client->alias)
349 script_write_params("alias_", ifi->client->alias);
352 pidfile_remove(pidfile);
359 cap_channel_t *casper;
363 error("unable to start casper");
365 capsyslog = cap_service_open(casper, "system.syslog");
367 if (capsyslog == NULL)
368 error("unable to open system.syslog service");
372 main(int argc, char *argv[])
375 int ch, fd, quiet = 0, i = 0;
377 int immediate_daemon = 0;
384 /* Initially, log errors to stderr as well as to syslogd. */
385 cap_openlog(capsyslog, getprogname(), LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
386 cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
388 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
391 immediate_daemon = 1;
394 path_dhclient_conf = optarg;
400 path_dhclient_db = optarg;
403 path_dhclient_pidfile = optarg;
421 if (path_dhclient_pidfile == NULL) {
422 asprintf(&path_dhclient_pidfile,
423 "%s/dhclient/dhclient.%s.pid", _PATH_VARRUN, *argv);
424 if (path_dhclient_pidfile == NULL)
427 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
428 if (pidfile == NULL) {
430 error("dhclient already running, pid: %d.", otherpid);
432 error("dhclient already running.");
433 warning("Cannot open or create pidfile: %m");
436 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
438 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
439 error("Interface name too long");
440 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
441 _PATH_DHCLIENT_DB, ifi->name) == -1)
450 inaddr_broadcast.s_addr = INADDR_BROADCAST;
451 inaddr_any.s_addr = INADDR_ANY;
455 /* The next bit is potentially very time-consuming, so write out
456 the pidfile right away. We will write it out again with the
457 correct pid after daemonizing. */
459 pidfile_write(pidfile);
461 if (!interface_link_status(ifi->name)) {
462 fprintf(stderr, "%s: no link ...", ifi->name);
465 while (!interface_link_status(ifi->name)) {
466 fprintf(stderr, ".");
469 fprintf(stderr, " giving up\n");
474 fprintf(stderr, " got link\n");
478 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
479 error("cannot open %s: %m", _PATH_DEVNULL);
481 if ((pw = getpwnam("_dhcp")) == NULL) {
482 warning("no such user: _dhcp, falling back to \"nobody\"");
483 if ((pw = getpwnam("nobody")) == NULL)
484 error("no such user: nobody");
488 * Obtain hostname before entering capability mode - it won't be
489 * possible then, as reading kern.hostname is not permitted.
491 if (gethostname(hostname, sizeof(hostname)) < 0)
494 priv_script_init("PREINIT", NULL);
495 if (ifi->client->alias)
496 priv_script_write_params("alias_", ifi->client->alias);
499 /* set up the interface */
500 discover_interfaces(ifi);
502 if (pipe(pipe_fd) == -1)
505 fork_privchld(pipe_fd[0], pipe_fd[1]);
514 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
515 if (caph_rights_limit(privfd, &rights) < 0)
516 error("can't limit private descriptor: %m");
518 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
519 error("can't open and lock %s: %m", path_dhclient_db);
520 read_client_leases();
521 rewrite_client_leases();
524 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
525 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
526 if (shutdown(routefd, SHUT_WR) < 0)
527 error("can't shutdown route socket: %m");
528 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
529 if (caph_rights_limit(routefd, &rights) < 0)
530 error("can't limit route socket: %m");
534 setproctitle("%s", ifi->name);
536 /* setgroups(2) is not permitted in capability mode. */
537 if (setgroups(1, &pw->pw_gid) != 0)
538 error("can't restrict groups: %m");
540 if (caph_enter_casper() < 0)
541 error("can't enter capability mode: %m");
544 * If we are not in capability mode (i.e., Capsicum or libcasper is
545 * disabled), try to restrict filesystem access. This will fail if
546 * kern.chroot_allow_open_directories is 0 or the process is jailed.
548 if (cap_getmode(&capmode) < 0 || capmode == 0) {
549 if (chroot(_PATH_VAREMPTY) == -1)
551 if (chdir("/") == -1)
552 error("chdir(\"/\")");
555 if (setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
556 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
557 error("can't drop privileges: %m");
559 if (immediate_daemon)
562 ifi->client->state = S_INIT;
565 bootp_packet_handler = do_packet;
577 fprintf(stderr, "usage: %s [-bdqu] ", getprogname());
578 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
585 * Each routine is called from the dhclient_state_machine() in one of
587 * -> entering INIT state
588 * -> recvpacket_flag == 0: timeout in this state
589 * -> otherwise: received a packet in this state
591 * Return conditions as handled by dhclient_state_machine():
592 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
593 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
594 * Returns 0: finish the nap which was interrupted for no good reason.
596 * Several per-interface variables are used to keep track of the process:
597 * active_lease: the lease that is being used on the interface
598 * (null pointer if not configured yet).
599 * offered_leases: leases corresponding to DHCPOFFER messages that have
600 * been sent to us by DHCP servers.
601 * acked_leases: leases corresponding to DHCPACK messages that have been
602 * sent to us by DHCP servers.
603 * sendpacket: DHCP packet we're trying to send.
604 * destination: IP address to send sendpacket to
605 * In addition, there are several relevant per-lease variables.
606 * T1_expiry, T2_expiry, lease_expiry: lease milestones
607 * In the active lease, these control the process of renewing the lease;
608 * In leases on the acked_leases list, this simply determines when we
609 * can no longer legitimately use the lease.
613 state_reboot(void *ipp)
615 struct interface_info *ip = ipp;
617 /* If we don't remember an active lease, go straight to INIT. */
618 if (!ip->client->active || ip->client->active->is_bootp) {
623 /* We are in the rebooting state. */
624 ip->client->state = S_REBOOTING;
626 /* make_request doesn't initialize xid because it normally comes
627 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
628 so pick an xid now. */
629 ip->client->xid = arc4random();
631 /* Make a DHCPREQUEST packet, and set appropriate per-interface
633 make_request(ip, ip->client->active);
634 ip->client->destination = iaddr_broadcast;
635 ip->client->first_sending = cur_time;
636 ip->client->interval = ip->client->config->initial_interval;
638 /* Zap the medium list... */
639 ip->client->medium = NULL;
641 /* Send out the first DHCPREQUEST packet. */
646 * Called when a lease has completely expired and we've
647 * been unable to renew it.
650 state_init(void *ipp)
652 struct interface_info *ip = ipp;
654 ASSERT_STATE(state, S_INIT);
656 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
658 make_discover(ip, ip->client->active);
659 ip->client->xid = ip->client->packet.xid;
660 ip->client->destination = iaddr_broadcast;
661 ip->client->state = S_SELECTING;
662 ip->client->first_sending = cur_time;
663 ip->client->interval = ip->client->config->initial_interval;
665 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
671 * state_selecting is called when one or more DHCPOFFER packets
672 * have been received and a configurable period of time has passed.
675 state_selecting(void *ipp)
677 struct interface_info *ip = ipp;
678 struct client_lease *lp, *next, *picked;
680 ASSERT_STATE(state, S_SELECTING);
682 /* Cancel state_selecting and send_discover timeouts, since either
683 one could have got us here. */
684 cancel_timeout(state_selecting, ip);
685 cancel_timeout(send_discover, ip);
687 /* We have received one or more DHCPOFFER packets. Currently,
688 the only criterion by which we judge leases is whether or
689 not we get a response when we arp for them. */
691 for (lp = ip->client->offered_leases; lp; lp = next) {
694 /* Check to see if we got an ARPREPLY for the address
695 in this particular lease. */
697 script_init("ARPCHECK", lp->medium);
698 script_write_params("check_", lp);
700 /* If the ARPCHECK code detects another
701 machine using the offered address, it exits
702 nonzero. We need to send a DHCPDECLINE and
705 make_decline(ip, lp);
713 free_client_lease(lp);
716 ip->client->offered_leases = NULL;
718 /* If we just tossed all the leases we were offered, go back
721 ip->client->state = S_INIT;
726 /* If it was a BOOTREPLY, we can just take the address right now. */
727 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
728 ip->client->new = picked;
730 /* Make up some lease expiry times
731 XXX these should be configurable. */
732 ip->client->new->expiry = cur_time + 12000;
733 ip->client->new->renewal += cur_time + 8000;
734 ip->client->new->rebind += cur_time + 10000;
736 ip->client->state = S_REQUESTING;
738 /* Bind to the address we received. */
743 /* Go to the REQUESTING state. */
744 ip->client->destination = iaddr_broadcast;
745 ip->client->state = S_REQUESTING;
746 ip->client->first_sending = cur_time;
747 ip->client->interval = ip->client->config->initial_interval;
749 /* Make a DHCPREQUEST packet from the lease we picked. */
750 make_request(ip, picked);
751 ip->client->xid = ip->client->packet.xid;
753 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
754 free_client_lease(picked);
756 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
760 /* state_requesting is called when we receive a DHCPACK message after
761 having sent out one or more DHCPREQUEST packets. */
764 dhcpack(struct packet *packet)
766 struct interface_info *ip = packet->interface;
767 struct client_lease *lease;
769 /* If we're not receptive to an offer right now, or if the offer
770 has an unrecognizable transaction id, then just drop it. */
771 if (packet->interface->client->xid != packet->raw->xid ||
772 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
773 (memcmp(packet->interface->hw_address.haddr,
774 packet->raw->chaddr, packet->raw->hlen)))
777 if (ip->client->state != S_REBOOTING &&
778 ip->client->state != S_REQUESTING &&
779 ip->client->state != S_RENEWING &&
780 ip->client->state != S_REBINDING)
783 note("DHCPACK from %s", piaddr(packet->client_addr));
785 lease = packet_to_lease(packet);
787 note("packet_to_lease failed.");
791 ip->client->new = lease;
793 /* Stop resending DHCPREQUEST. */
794 cancel_timeout(send_request, ip);
796 /* Figure out the lease time. */
797 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
799 ip->client->new->expiry = getULong(
800 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
801 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
802 ip->client->new->expiry = getULong(
803 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
805 ip->client->new->expiry = default_lease_time;
806 /* A number that looks negative here is really just very large,
807 because the lease expiry offset is unsigned. Also make sure that
808 the addition of cur_time below does not overflow (a 32 bit) time_t. */
809 if (ip->client->new->expiry < 0 ||
810 ip->client->new->expiry > TIME_MAX - cur_time)
811 ip->client->new->expiry = TIME_MAX - cur_time;
812 /* XXX should be fixed by resetting the client state */
813 if (ip->client->new->expiry < 60)
814 ip->client->new->expiry = 60;
816 /* Unless overridden in the config, take the server-provided renewal
817 * time if there is one. Otherwise figure it out according to the spec.
818 * Also make sure the renewal time does not exceed the expiry time.
820 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
822 ip->client->new->renewal = getULong(
823 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
824 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
825 ip->client->new->renewal = getULong(
826 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
828 ip->client->new->renewal = ip->client->new->expiry / 2;
829 if (ip->client->new->renewal < 0 ||
830 ip->client->new->renewal > ip->client->new->expiry / 2)
831 ip->client->new->renewal = ip->client->new->expiry / 2;
833 /* Same deal with the rebind time. */
834 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
836 ip->client->new->rebind = getULong(
837 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
838 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
839 ip->client->new->rebind = getULong(
840 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
842 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
843 if (ip->client->new->rebind < 0 ||
844 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
845 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
847 /* Convert the time offsets into seconds-since-the-epoch */
848 ip->client->new->expiry += cur_time;
849 ip->client->new->renewal += cur_time;
850 ip->client->new->rebind += cur_time;
856 bind_lease(struct interface_info *ip)
858 struct option_data *opt;
860 /* Remember the medium. */
861 ip->client->new->medium = ip->client->medium;
863 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
864 if (opt->len == sizeof(u_int16_t)) {
866 bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
870 mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
872 mtu = be16dec(opt->data);
875 /* Treat 0 like a user intentionally doesn't want to change MTU and,
876 * therefore, warning is not needed */
877 if (!supersede || mtu != 0)
878 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
880 interface_set_mtu_unpriv(privfd, mtu);
884 /* Write out the new lease. */
885 write_client_lease(ip, ip->client->new, 0);
887 /* Run the client script with the new parameters. */
888 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
889 (ip->client->state == S_RENEWING ? "RENEW" :
890 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
891 ip->client->new->medium);
892 if (ip->client->active && ip->client->state != S_REBOOTING)
893 script_write_params("old_", ip->client->active);
894 script_write_params("new_", ip->client->new);
895 if (ip->client->alias)
896 script_write_params("alias_", ip->client->alias);
899 /* Replace the old active lease with the new one. */
900 if (ip->client->active)
901 free_client_lease(ip->client->active);
902 ip->client->active = ip->client->new;
903 ip->client->new = NULL;
905 /* Set up a timeout to start the renewal process. */
906 add_timeout(ip->client->active->renewal, state_bound, ip);
908 note("bound to %s -- renewal in %d seconds.",
909 piaddr(ip->client->active->address),
910 (int)(ip->client->active->renewal - cur_time));
911 ip->client->state = S_BOUND;
912 reinitialize_interfaces();
917 * state_bound is called when we've successfully bound to a particular
918 * lease, but the renewal time on that lease has expired. We are
919 * expected to unicast a DHCPREQUEST to the server that gave us our
923 state_bound(void *ipp)
925 struct interface_info *ip = ipp;
929 ASSERT_STATE(state, S_BOUND);
931 /* T1 has expired. */
932 make_request(ip, ip->client->active);
933 ip->client->xid = ip->client->packet.xid;
935 if (ip->client->config->default_actions[DHO_DHCP_SERVER_IDENTIFIER] ==
937 dp = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].data;
938 len = ip->client->config->defaults[DHO_DHCP_SERVER_IDENTIFIER].len;
940 dp = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].data;
941 len = ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len;
944 memcpy(ip->client->destination.iabuf, dp, len);
945 ip->client->destination.len = len;
947 ip->client->destination = iaddr_broadcast;
949 ip->client->first_sending = cur_time;
950 ip->client->interval = ip->client->config->initial_interval;
951 ip->client->state = S_RENEWING;
953 /* Send the first packet immediately. */
958 bootp(struct packet *packet)
960 struct iaddrlist *ap;
962 if (packet->raw->op != BOOTREPLY)
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("BOOTREPLY from %s rejected.", piaddr(ap->addr));
978 dhcp(struct packet *packet)
980 struct iaddrlist *ap;
981 void (*handler)(struct packet *);
984 switch (packet->packet_type) {
1001 /* If there's a reject list, make sure this packet's sender isn't
1003 for (ap = packet->interface->client->config->reject_list;
1004 ap; ap = ap->next) {
1005 if (addr_eq(packet->client_addr, ap->addr)) {
1006 note("%s from %s rejected.", type, piaddr(ap->addr));
1014 dhcpoffer(struct packet *packet)
1016 struct interface_info *ip = packet->interface;
1017 struct client_lease *lease, *lp;
1019 int arp_timeout_needed, stop_selecting;
1020 const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
1021 "DHCPOFFER" : "BOOTREPLY";
1023 /* If we're not receptive to an offer right now, or if the offer
1024 has an unrecognizable transaction id, then just drop it. */
1025 if (ip->client->state != S_SELECTING ||
1026 packet->interface->client->xid != packet->raw->xid ||
1027 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1028 (memcmp(packet->interface->hw_address.haddr,
1029 packet->raw->chaddr, packet->raw->hlen)))
1032 note("%s from %s", name, piaddr(packet->client_addr));
1035 /* If this lease doesn't supply the minimum required parameters,
1037 for (i = 0; ip->client->config->required_options[i]; i++) {
1038 if (!packet->options[ip->client->config->
1039 required_options[i]].len) {
1040 note("%s isn't satisfactory.", name);
1045 /* If we've already seen this lease, don't record it again. */
1046 for (lease = ip->client->offered_leases;
1047 lease; lease = lease->next) {
1048 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1049 !memcmp(lease->address.iabuf,
1050 &packet->raw->yiaddr, lease->address.len)) {
1051 debug("%s already seen.", name);
1056 lease = packet_to_lease(packet);
1058 note("packet_to_lease failed.");
1062 /* If this lease was acquired through a BOOTREPLY, record that
1064 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1065 lease->is_bootp = 1;
1067 /* Record the medium under which this lease was offered. */
1068 lease->medium = ip->client->medium;
1070 /* Send out an ARP Request for the offered IP address. */
1071 script_init("ARPSEND", lease->medium);
1072 script_write_params("check_", lease);
1073 /* If the script can't send an ARP request without waiting,
1074 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1076 arp_timeout_needed = 0;
1078 arp_timeout_needed = 2;
1080 /* Figure out when we're supposed to stop selecting. */
1082 ip->client->first_sending + ip->client->config->select_interval;
1084 /* If this is the lease we asked for, put it at the head of the
1085 list, and don't mess with the arp request timeout. */
1086 if (lease->address.len == ip->client->requested_address.len &&
1087 !memcmp(lease->address.iabuf,
1088 ip->client->requested_address.iabuf,
1089 ip->client->requested_address.len)) {
1090 lease->next = ip->client->offered_leases;
1091 ip->client->offered_leases = lease;
1093 /* If we already have an offer, and arping for this
1094 offer would take us past the selection timeout,
1095 then don't extend the timeout - just hope for the
1097 if (ip->client->offered_leases &&
1098 (cur_time + arp_timeout_needed) > stop_selecting)
1099 arp_timeout_needed = 0;
1101 /* Put the lease at the end of the list. */
1103 if (!ip->client->offered_leases)
1104 ip->client->offered_leases = lease;
1106 for (lp = ip->client->offered_leases; lp->next;
1113 /* If we're supposed to stop selecting before we've had time
1114 to wait for the ARPREPLY, add some delay to wait for
1116 if (stop_selecting - cur_time < arp_timeout_needed)
1117 stop_selecting = cur_time + arp_timeout_needed;
1119 /* If the selecting interval has expired, go immediately to
1120 state_selecting(). Otherwise, time out into
1121 state_selecting at the select interval. */
1122 if (stop_selecting <= 0)
1123 state_selecting(ip);
1125 add_timeout(stop_selecting, state_selecting, ip);
1126 cancel_timeout(send_discover, ip);
1130 /* Allocate a client_lease structure and initialize it from the parameters
1131 in the specified packet. */
1133 struct client_lease *
1134 packet_to_lease(struct packet *packet)
1136 struct client_lease *lease;
1139 lease = malloc(sizeof(struct client_lease));
1142 warning("dhcpoffer: no memory to record lease.");
1146 memset(lease, 0, sizeof(*lease));
1148 /* Copy the lease options. */
1149 for (i = 0; i < 256; i++) {
1150 if (packet->options[i].len) {
1151 lease->options[i].data =
1152 malloc(packet->options[i].len + 1);
1153 if (!lease->options[i].data) {
1154 warning("dhcpoffer: no memory for option %d", i);
1155 free_client_lease(lease);
1158 memcpy(lease->options[i].data,
1159 packet->options[i].data,
1160 packet->options[i].len);
1161 lease->options[i].len =
1162 packet->options[i].len;
1163 lease->options[i].data[lease->options[i].len] =
1166 if (!check_option(lease,i)) {
1167 /* ignore a bogus lease offer */
1168 warning("Invalid lease option - ignoring offer");
1169 free_client_lease(lease);
1175 lease->address.len = sizeof(packet->raw->yiaddr);
1176 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1178 lease->nextserver.len = sizeof(packet->raw->siaddr);
1179 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1181 /* If the server name was filled out, copy it.
1182 Do not attempt to validate the server name as a host name.
1183 RFC 2131 merely states that sname is NUL-terminated (which do
1184 do not assume) and that it is the server's host name. Since
1185 the ISC client and server allow arbitrary characters, we do
1187 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1188 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1189 packet->raw->sname[0]) {
1190 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1191 if (!lease->server_name) {
1192 warning("dhcpoffer: no memory for server name.");
1193 free_client_lease(lease);
1196 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1197 lease->server_name[DHCP_SNAME_LEN]='\0';
1200 /* Ditto for the filename. */
1201 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1202 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1203 packet->raw->file[0]) {
1204 /* Don't count on the NUL terminator. */
1205 lease->filename = malloc(DHCP_FILE_LEN + 1);
1206 if (!lease->filename) {
1207 warning("dhcpoffer: no memory for filename.");
1208 free_client_lease(lease);
1211 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1212 lease->filename[DHCP_FILE_LEN]='\0';
1218 dhcpnak(struct packet *packet)
1220 struct interface_info *ip = packet->interface;
1222 /* If we're not receptive to an offer right now, or if the offer
1223 has an unrecognizable transaction id, then just drop it. */
1224 if (packet->interface->client->xid != packet->raw->xid ||
1225 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1226 (memcmp(packet->interface->hw_address.haddr,
1227 packet->raw->chaddr, packet->raw->hlen)))
1230 if (ip->client->state != S_REBOOTING &&
1231 ip->client->state != S_REQUESTING &&
1232 ip->client->state != S_RENEWING &&
1233 ip->client->state != S_REBINDING)
1236 note("DHCPNAK from %s", piaddr(packet->client_addr));
1238 if (!ip->client->active) {
1239 note("DHCPNAK with no active lease.\n");
1243 free_client_lease(ip->client->active);
1244 ip->client->active = NULL;
1246 /* Stop sending DHCPREQUEST packets... */
1247 cancel_timeout(send_request, ip);
1249 ip->client->state = S_INIT;
1253 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1254 one after the right interval has expired. If we don't get an offer by
1255 the time we reach the panic interval, call the panic function. */
1258 send_discover(void *ipp)
1260 struct interface_info *ip = ipp;
1261 int interval, increase = 1;
1263 /* Figure out how long it's been since we started transmitting. */
1264 interval = cur_time - ip->client->first_sending;
1266 /* If we're past the panic timeout, call the script and tell it
1267 we haven't found anything for this interface yet. */
1268 if (interval > ip->client->config->timeout) {
1273 /* If we're selecting media, try the whole list before doing
1274 the exponential backoff, but if we've already received an
1275 offer, stop looping, because we obviously have it right. */
1276 if (!ip->client->offered_leases &&
1277 ip->client->config->media) {
1280 if (ip->client->medium) {
1281 ip->client->medium = ip->client->medium->next;
1284 if (!ip->client->medium) {
1286 error("No valid media types for %s!", ip->name);
1287 ip->client->medium = ip->client->config->media;
1291 note("Trying medium \"%s\" %d", ip->client->medium->string,
1293 script_init("MEDIUM", ip->client->medium);
1299 * If we're supposed to increase the interval, do so. If it's
1300 * currently zero (i.e., we haven't sent any packets yet), set
1301 * it to one; otherwise, add to it a random number between zero
1302 * and two times itself. On average, this means that it will
1303 * double with every transmission.
1306 if (!ip->client->interval)
1307 ip->client->interval =
1308 ip->client->config->initial_interval;
1310 ip->client->interval += (arc4random() >> 2) %
1311 (2 * ip->client->interval);
1314 /* Don't backoff past cutoff. */
1315 if (ip->client->interval >
1316 ip->client->config->backoff_cutoff)
1317 ip->client->interval =
1318 ((ip->client->config->backoff_cutoff / 2)
1319 + ((arc4random() >> 2) %
1320 ip->client->config->backoff_cutoff));
1321 } else if (!ip->client->interval)
1322 ip->client->interval =
1323 ip->client->config->initial_interval;
1325 /* If the backoff would take us to the panic timeout, just use that
1327 if (cur_time + ip->client->interval >
1328 ip->client->first_sending + ip->client->config->timeout)
1329 ip->client->interval =
1330 (ip->client->first_sending +
1331 ip->client->config->timeout) - cur_time + 1;
1333 /* Record the number of seconds since we started sending. */
1334 if (interval < 65536)
1335 ip->client->packet.secs = htons(interval);
1337 ip->client->packet.secs = htons(65535);
1338 ip->client->secs = ip->client->packet.secs;
1340 note("DHCPDISCOVER on %s to %s port %d interval %d",
1341 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1342 (int)ip->client->interval);
1344 /* Send out a packet. */
1345 send_packet_unpriv(privfd, &ip->client->packet,
1346 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1348 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1352 * state_panic gets called if we haven't received any offers in a preset
1353 * amount of time. When this happens, we try to use existing leases
1354 * that haven't yet expired, and failing that, we call the client script
1355 * and hope it can do something.
1358 state_panic(void *ipp)
1360 struct interface_info *ip = ipp;
1361 struct client_lease *loop = ip->client->active;
1362 struct client_lease *lp;
1364 note("No DHCPOFFERS received.");
1366 /* We may not have an active lease, but we may have some
1367 predefined leases that we can try. */
1368 if (!ip->client->active && ip->client->leases)
1371 /* Run through the list of leases and see if one can be used. */
1372 while (ip->client->active) {
1373 if (ip->client->active->expiry > cur_time) {
1374 note("Trying recorded lease %s",
1375 piaddr(ip->client->active->address));
1376 /* Run the client script with the existing
1378 script_init("TIMEOUT",
1379 ip->client->active->medium);
1380 script_write_params("new_", ip->client->active);
1381 if (ip->client->alias)
1382 script_write_params("alias_",
1385 /* If the old lease is still good and doesn't
1386 yet need renewal, go into BOUND state and
1387 timeout at the renewal time. */
1390 ip->client->active->renewal) {
1391 ip->client->state = S_BOUND;
1392 note("bound: renewal in %d seconds.",
1393 (int)(ip->client->active->renewal -
1396 ip->client->active->renewal,
1399 ip->client->state = S_BOUND;
1400 note("bound: immediate renewal.");
1403 reinitialize_interfaces();
1409 /* If there are no other leases, give up. */
1410 if (!ip->client->leases) {
1411 ip->client->leases = ip->client->active;
1412 ip->client->active = NULL;
1417 /* Otherwise, put the active lease at the end of the
1418 lease list, and try another lease.. */
1419 for (lp = ip->client->leases; lp->next; lp = lp->next)
1421 lp->next = ip->client->active;
1423 lp->next->next = NULL;
1424 ip->client->active = ip->client->leases;
1425 ip->client->leases = ip->client->leases->next;
1427 /* If we already tried this lease, we've exhausted the
1428 set of leases, so we might as well give up for
1430 if (ip->client->active == loop)
1433 loop = ip->client->active;
1436 /* No leases were available, or what was available didn't work, so
1437 tell the shell script that we failed to allocate an address,
1438 and try again later. */
1439 note("No working leases in persistent database - sleeping.\n");
1440 script_init("FAIL", NULL);
1441 if (ip->client->alias)
1442 script_write_params("alias_", ip->client->alias);
1444 ip->client->state = S_INIT;
1445 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1451 send_request(void *ipp)
1453 struct interface_info *ip = ipp;
1454 struct in_addr from, to;
1457 /* Figure out how long it's been since we started transmitting. */
1458 interval = cur_time - ip->client->first_sending;
1460 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1461 past the reboot timeout, go to INIT and see if we can
1462 DISCOVER an address... */
1463 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1464 means either that we're on a network with no DHCP server,
1465 or that our server is down. In the latter case, assuming
1466 that there is a backup DHCP server, DHCPDISCOVER will get
1467 us a new address, but we could also have successfully
1468 reused our old address. In the former case, we're hosed
1469 anyway. This is not a win-prone situation. */
1470 if ((ip->client->state == S_REBOOTING ||
1471 ip->client->state == S_REQUESTING) &&
1472 interval > ip->client->config->reboot_timeout) {
1474 ip->client->state = S_INIT;
1475 cancel_timeout(send_request, ip);
1480 /* If we're in the reboot state, make sure the media is set up
1482 if (ip->client->state == S_REBOOTING &&
1483 !ip->client->medium &&
1484 ip->client->active->medium ) {
1485 script_init("MEDIUM", ip->client->active->medium);
1487 /* If the medium we chose won't fly, go to INIT state. */
1491 /* Record the medium. */
1492 ip->client->medium = ip->client->active->medium;
1495 /* If the lease has expired, relinquish the address and go back
1496 to the INIT state. */
1497 if (ip->client->state != S_REQUESTING &&
1498 cur_time > ip->client->active->expiry) {
1499 /* Run the client script with the new parameters. */
1500 script_init("EXPIRE", NULL);
1501 script_write_params("old_", ip->client->active);
1502 if (ip->client->alias)
1503 script_write_params("alias_", ip->client->alias);
1506 /* Now do a preinit on the interface so that we can
1507 discover a new address. */
1508 script_init("PREINIT", NULL);
1509 if (ip->client->alias)
1510 script_write_params("alias_", ip->client->alias);
1513 ip->client->state = S_INIT;
1518 /* Do the exponential backoff... */
1519 if (!ip->client->interval)
1520 ip->client->interval = ip->client->config->initial_interval;
1522 ip->client->interval += ((arc4random() >> 2) %
1523 (2 * ip->client->interval));
1525 /* Don't backoff past cutoff. */
1526 if (ip->client->interval >
1527 ip->client->config->backoff_cutoff)
1528 ip->client->interval =
1529 ((ip->client->config->backoff_cutoff / 2) +
1530 ((arc4random() >> 2) % ip->client->interval));
1532 /* If the backoff would take us to the expiry time, just set the
1533 timeout to the expiry time. */
1534 if (ip->client->state != S_REQUESTING &&
1535 cur_time + ip->client->interval >
1536 ip->client->active->expiry)
1537 ip->client->interval =
1538 ip->client->active->expiry - cur_time + 1;
1540 /* If the lease T2 time has elapsed, or if we're not yet bound,
1541 broadcast the DHCPREQUEST rather than unicasting. */
1542 if (ip->client->state == S_REQUESTING ||
1543 ip->client->state == S_REBOOTING ||
1544 cur_time > ip->client->active->rebind)
1545 to.s_addr = INADDR_BROADCAST;
1547 memcpy(&to.s_addr, ip->client->destination.iabuf,
1550 if (ip->client->state != S_REQUESTING &&
1551 ip->client->state != S_REBOOTING)
1552 memcpy(&from, ip->client->active->address.iabuf,
1555 from.s_addr = INADDR_ANY;
1557 /* Record the number of seconds since we started sending. */
1558 if (ip->client->state == S_REQUESTING)
1559 ip->client->packet.secs = ip->client->secs;
1561 if (interval < 65536)
1562 ip->client->packet.secs = htons(interval);
1564 ip->client->packet.secs = htons(65535);
1567 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1570 /* Send out a packet. */
1571 send_packet_unpriv(privfd, &ip->client->packet,
1572 ip->client->packet_length, from, to);
1574 add_timeout(cur_time + ip->client->interval, send_request, ip);
1578 send_decline(void *ipp)
1580 struct interface_info *ip = ipp;
1582 note("DHCPDECLINE on %s to %s port %d", ip->name,
1583 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1585 /* Send out a packet. */
1586 send_packet_unpriv(privfd, &ip->client->packet,
1587 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1591 make_discover(struct interface_info *ip, struct client_lease *lease)
1593 unsigned char discover = DHCPDISCOVER;
1594 struct tree_cache *options[256];
1595 struct tree_cache option_elements[256];
1598 memset(option_elements, 0, sizeof(option_elements));
1599 memset(options, 0, sizeof(options));
1600 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1602 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1603 i = DHO_DHCP_MESSAGE_TYPE;
1604 options[i] = &option_elements[i];
1605 options[i]->value = &discover;
1606 options[i]->len = sizeof(discover);
1607 options[i]->buf_size = sizeof(discover);
1608 options[i]->timeout = 0xFFFFFFFF;
1610 /* Request the options we want */
1611 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1612 options[i] = &option_elements[i];
1613 options[i]->value = ip->client->config->requested_options;
1614 options[i]->len = ip->client->config->requested_option_count;
1615 options[i]->buf_size =
1616 ip->client->config->requested_option_count;
1617 options[i]->timeout = 0xFFFFFFFF;
1619 /* If we had an address, try to get it again. */
1621 ip->client->requested_address = lease->address;
1622 i = DHO_DHCP_REQUESTED_ADDRESS;
1623 options[i] = &option_elements[i];
1624 options[i]->value = lease->address.iabuf;
1625 options[i]->len = lease->address.len;
1626 options[i]->buf_size = lease->address.len;
1627 options[i]->timeout = 0xFFFFFFFF;
1629 ip->client->requested_address.len = 0;
1631 /* Send any options requested in the config file. */
1632 for (i = 0; i < 256; i++)
1634 ip->client->config->send_options[i].data) {
1635 options[i] = &option_elements[i];
1637 ip->client->config->send_options[i].data;
1639 ip->client->config->send_options[i].len;
1640 options[i]->buf_size =
1641 ip->client->config->send_options[i].len;
1642 options[i]->timeout = 0xFFFFFFFF;
1645 /* send host name if not set via config file. */
1646 if (!options[DHO_HOST_NAME]) {
1647 if (hostname[0] != '\0') {
1649 char* posDot = strchr(hostname, '.');
1651 len = posDot - hostname;
1653 len = strlen(hostname);
1654 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1655 options[DHO_HOST_NAME]->value = hostname;
1656 options[DHO_HOST_NAME]->len = len;
1657 options[DHO_HOST_NAME]->buf_size = len;
1658 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1662 /* set unique client identifier */
1663 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1664 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1665 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1666 ip->hw_address.hlen : sizeof(client_ident)-1;
1667 client_ident[0] = ip->hw_address.htype;
1668 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1669 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1670 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1671 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1672 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1673 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1676 /* Set up the option buffer... */
1677 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1678 options, 0, 0, 0, NULL, 0);
1679 if (ip->client->packet_length < BOOTP_MIN_LEN)
1680 ip->client->packet_length = BOOTP_MIN_LEN;
1682 ip->client->packet.op = BOOTREQUEST;
1683 ip->client->packet.htype = ip->hw_address.htype;
1684 ip->client->packet.hlen = ip->hw_address.hlen;
1685 ip->client->packet.hops = 0;
1686 ip->client->packet.xid = arc4random();
1687 ip->client->packet.secs = 0; /* filled in by send_discover. */
1688 ip->client->packet.flags = 0;
1690 memset(&(ip->client->packet.ciaddr),
1691 0, sizeof(ip->client->packet.ciaddr));
1692 memset(&(ip->client->packet.yiaddr),
1693 0, sizeof(ip->client->packet.yiaddr));
1694 memset(&(ip->client->packet.siaddr),
1695 0, sizeof(ip->client->packet.siaddr));
1696 memset(&(ip->client->packet.giaddr),
1697 0, sizeof(ip->client->packet.giaddr));
1698 memcpy(ip->client->packet.chaddr,
1699 ip->hw_address.haddr, ip->hw_address.hlen);
1704 make_request(struct interface_info *ip, struct client_lease * lease)
1706 unsigned char request = DHCPREQUEST;
1707 struct tree_cache *options[256];
1708 struct tree_cache option_elements[256];
1711 memset(options, 0, sizeof(options));
1712 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1714 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1715 i = DHO_DHCP_MESSAGE_TYPE;
1716 options[i] = &option_elements[i];
1717 options[i]->value = &request;
1718 options[i]->len = sizeof(request);
1719 options[i]->buf_size = sizeof(request);
1720 options[i]->timeout = 0xFFFFFFFF;
1722 /* Request the options we want */
1723 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1724 options[i] = &option_elements[i];
1725 options[i]->value = ip->client->config->requested_options;
1726 options[i]->len = ip->client->config->requested_option_count;
1727 options[i]->buf_size =
1728 ip->client->config->requested_option_count;
1729 options[i]->timeout = 0xFFFFFFFF;
1731 /* If we are requesting an address that hasn't yet been assigned
1732 to us, use the DHCP Requested Address option. */
1733 if (ip->client->state == S_REQUESTING) {
1734 /* Send back the server identifier... */
1735 i = DHO_DHCP_SERVER_IDENTIFIER;
1736 options[i] = &option_elements[i];
1737 options[i]->value = lease->options[i].data;
1738 options[i]->len = lease->options[i].len;
1739 options[i]->buf_size = lease->options[i].len;
1740 options[i]->timeout = 0xFFFFFFFF;
1742 if (ip->client->state == S_REQUESTING ||
1743 ip->client->state == S_REBOOTING) {
1744 ip->client->requested_address = lease->address;
1745 i = DHO_DHCP_REQUESTED_ADDRESS;
1746 options[i] = &option_elements[i];
1747 options[i]->value = lease->address.iabuf;
1748 options[i]->len = lease->address.len;
1749 options[i]->buf_size = lease->address.len;
1750 options[i]->timeout = 0xFFFFFFFF;
1752 ip->client->requested_address.len = 0;
1754 /* Send any options requested in the config file. */
1755 for (i = 0; i < 256; i++)
1757 ip->client->config->send_options[i].data) {
1758 options[i] = &option_elements[i];
1760 ip->client->config->send_options[i].data;
1762 ip->client->config->send_options[i].len;
1763 options[i]->buf_size =
1764 ip->client->config->send_options[i].len;
1765 options[i]->timeout = 0xFFFFFFFF;
1768 /* send host name if not set via config file. */
1769 if (!options[DHO_HOST_NAME]) {
1770 if (hostname[0] != '\0') {
1772 char* posDot = strchr(hostname, '.');
1774 len = posDot - hostname;
1776 len = strlen(hostname);
1777 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1778 options[DHO_HOST_NAME]->value = hostname;
1779 options[DHO_HOST_NAME]->len = len;
1780 options[DHO_HOST_NAME]->buf_size = len;
1781 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1785 /* set unique client identifier */
1786 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1787 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1788 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1789 ip->hw_address.hlen : sizeof(client_ident)-1;
1790 client_ident[0] = ip->hw_address.htype;
1791 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1792 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1793 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1794 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1795 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1796 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1799 /* Set up the option buffer... */
1800 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1801 options, 0, 0, 0, NULL, 0);
1802 if (ip->client->packet_length < BOOTP_MIN_LEN)
1803 ip->client->packet_length = BOOTP_MIN_LEN;
1805 ip->client->packet.op = BOOTREQUEST;
1806 ip->client->packet.htype = ip->hw_address.htype;
1807 ip->client->packet.hlen = ip->hw_address.hlen;
1808 ip->client->packet.hops = 0;
1809 ip->client->packet.xid = ip->client->xid;
1810 ip->client->packet.secs = 0; /* Filled in by send_request. */
1812 /* If we own the address we're requesting, put it in ciaddr;
1813 otherwise set ciaddr to zero. */
1814 if (ip->client->state == S_BOUND ||
1815 ip->client->state == S_RENEWING ||
1816 ip->client->state == S_REBINDING) {
1817 memcpy(&ip->client->packet.ciaddr,
1818 lease->address.iabuf, lease->address.len);
1819 ip->client->packet.flags = 0;
1821 memset(&ip->client->packet.ciaddr, 0,
1822 sizeof(ip->client->packet.ciaddr));
1823 ip->client->packet.flags = 0;
1826 memset(&ip->client->packet.yiaddr, 0,
1827 sizeof(ip->client->packet.yiaddr));
1828 memset(&ip->client->packet.siaddr, 0,
1829 sizeof(ip->client->packet.siaddr));
1830 memset(&ip->client->packet.giaddr, 0,
1831 sizeof(ip->client->packet.giaddr));
1832 memcpy(ip->client->packet.chaddr,
1833 ip->hw_address.haddr, ip->hw_address.hlen);
1837 make_decline(struct interface_info *ip, struct client_lease *lease)
1839 struct tree_cache *options[256], message_type_tree;
1840 struct tree_cache requested_address_tree;
1841 struct tree_cache server_id_tree, client_id_tree;
1842 unsigned char decline = DHCPDECLINE;
1845 memset(options, 0, sizeof(options));
1846 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1848 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1849 i = DHO_DHCP_MESSAGE_TYPE;
1850 options[i] = &message_type_tree;
1851 options[i]->value = &decline;
1852 options[i]->len = sizeof(decline);
1853 options[i]->buf_size = sizeof(decline);
1854 options[i]->timeout = 0xFFFFFFFF;
1856 /* Send back the server identifier... */
1857 i = DHO_DHCP_SERVER_IDENTIFIER;
1858 options[i] = &server_id_tree;
1859 options[i]->value = lease->options[i].data;
1860 options[i]->len = lease->options[i].len;
1861 options[i]->buf_size = lease->options[i].len;
1862 options[i]->timeout = 0xFFFFFFFF;
1864 /* Send back the address we're declining. */
1865 i = DHO_DHCP_REQUESTED_ADDRESS;
1866 options[i] = &requested_address_tree;
1867 options[i]->value = lease->address.iabuf;
1868 options[i]->len = lease->address.len;
1869 options[i]->buf_size = lease->address.len;
1870 options[i]->timeout = 0xFFFFFFFF;
1872 /* Send the uid if the user supplied one. */
1873 i = DHO_DHCP_CLIENT_IDENTIFIER;
1874 if (ip->client->config->send_options[i].len) {
1875 options[i] = &client_id_tree;
1876 options[i]->value = ip->client->config->send_options[i].data;
1877 options[i]->len = ip->client->config->send_options[i].len;
1878 options[i]->buf_size = ip->client->config->send_options[i].len;
1879 options[i]->timeout = 0xFFFFFFFF;
1883 /* Set up the option buffer... */
1884 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1885 options, 0, 0, 0, NULL, 0);
1886 if (ip->client->packet_length < BOOTP_MIN_LEN)
1887 ip->client->packet_length = BOOTP_MIN_LEN;
1889 ip->client->packet.op = BOOTREQUEST;
1890 ip->client->packet.htype = ip->hw_address.htype;
1891 ip->client->packet.hlen = ip->hw_address.hlen;
1892 ip->client->packet.hops = 0;
1893 ip->client->packet.xid = ip->client->xid;
1894 ip->client->packet.secs = 0; /* Filled in by send_request. */
1895 ip->client->packet.flags = 0;
1897 /* ciaddr must always be zero. */
1898 memset(&ip->client->packet.ciaddr, 0,
1899 sizeof(ip->client->packet.ciaddr));
1900 memset(&ip->client->packet.yiaddr, 0,
1901 sizeof(ip->client->packet.yiaddr));
1902 memset(&ip->client->packet.siaddr, 0,
1903 sizeof(ip->client->packet.siaddr));
1904 memset(&ip->client->packet.giaddr, 0,
1905 sizeof(ip->client->packet.giaddr));
1906 memcpy(ip->client->packet.chaddr,
1907 ip->hw_address.haddr, ip->hw_address.hlen);
1911 free_client_lease(struct client_lease *lease)
1915 if (lease->server_name)
1916 free(lease->server_name);
1917 if (lease->filename)
1918 free(lease->filename);
1919 for (i = 0; i < 256; i++) {
1920 if (lease->options[i].len)
1921 free(lease->options[i].data);
1926 static FILE *leaseFile;
1929 rewrite_client_leases(void)
1931 struct client_lease *lp;
1932 cap_rights_t rights;
1935 leaseFile = fopen(path_dhclient_db, "w");
1937 error("can't create %s: %m", path_dhclient_db);
1938 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1939 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1940 if (caph_rights_limit(fileno(leaseFile), &rights) < 0) {
1941 error("can't limit lease descriptor: %m");
1943 if (caph_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0) {
1944 error("can't limit lease descriptor fcntls: %m");
1951 for (lp = ifi->client->leases; lp; lp = lp->next)
1952 write_client_lease(ifi, lp, 1);
1953 if (ifi->client->active)
1954 write_client_lease(ifi, ifi->client->active, 1);
1957 ftruncate(fileno(leaseFile), ftello(leaseFile));
1958 fsync(fileno(leaseFile));
1962 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1965 static int leases_written;
1970 if (leases_written++ > 20) {
1971 rewrite_client_leases();
1976 /* If the lease came from the config file, we don't need to stash
1977 a copy in the lease database. */
1978 if (lease->is_static)
1981 if (!leaseFile) { /* XXX */
1982 leaseFile = fopen(path_dhclient_db, "w");
1984 error("can't create %s: %m", path_dhclient_db);
1987 fprintf(leaseFile, "lease {\n");
1988 if (lease->is_bootp)
1989 fprintf(leaseFile, " bootp;\n");
1990 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1991 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1992 if (lease->nextserver.len == sizeof(inaddr_any) &&
1993 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1994 sizeof(inaddr_any)))
1995 fprintf(leaseFile, " next-server %s;\n",
1996 piaddr(lease->nextserver));
1997 if (lease->filename)
1998 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1999 if (lease->server_name)
2000 fprintf(leaseFile, " server-name \"%s\";\n",
2001 lease->server_name);
2003 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
2004 for (i = 0; i < 256; i++)
2005 if (lease->options[i].len)
2006 fprintf(leaseFile, " option %s %s;\n",
2007 dhcp_options[i].name,
2008 pretty_print_option(i, lease->options[i].data,
2009 lease->options[i].len, 1, 1));
2011 t = gmtime(&lease->renewal);
2012 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
2013 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2014 t->tm_hour, t->tm_min, t->tm_sec);
2015 t = gmtime(&lease->rebind);
2016 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
2017 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2018 t->tm_hour, t->tm_min, t->tm_sec);
2019 t = gmtime(&lease->expiry);
2020 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
2021 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
2022 t->tm_hour, t->tm_min, t->tm_sec);
2023 fprintf(leaseFile, "}\n");
2028 script_init(const char *reason, struct string_list *medium)
2030 size_t len, mediumlen = 0;
2031 struct imsg_hdr hdr;
2035 if (medium != NULL && medium->string != NULL)
2036 mediumlen = strlen(medium->string);
2038 hdr.code = IMSG_SCRIPT_INIT;
2039 hdr.len = sizeof(struct imsg_hdr) +
2040 sizeof(size_t) + mediumlen +
2041 sizeof(size_t) + strlen(reason);
2043 if ((buf = buf_open(hdr.len)) == NULL)
2044 error("buf_open: %m");
2047 errs += buf_add(buf, &hdr, sizeof(hdr));
2048 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2050 errs += buf_add(buf, medium->string, mediumlen);
2051 len = strlen(reason);
2052 errs += buf_add(buf, &len, sizeof(len));
2053 errs += buf_add(buf, reason, len);
2056 error("buf_add: %m");
2058 if (buf_close(privfd, buf) == -1)
2059 error("buf_close: %m");
2063 priv_script_init(const char *reason, char *medium)
2065 struct interface_info *ip = ifi;
2068 ip->client->scriptEnvsize = 100;
2069 if (ip->client->scriptEnv == NULL)
2070 ip->client->scriptEnv =
2071 malloc(ip->client->scriptEnvsize * sizeof(char *));
2072 if (ip->client->scriptEnv == NULL)
2073 error("script_init: no memory for environment");
2075 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2076 if (ip->client->scriptEnv[0] == NULL)
2077 error("script_init: no memory for environment");
2079 ip->client->scriptEnv[1] = NULL;
2081 script_set_env(ip->client, "", "interface", ip->name);
2084 script_set_env(ip->client, "", "medium", medium);
2086 script_set_env(ip->client, "", "reason", reason);
2091 priv_script_write_params(const char *prefix, struct client_lease *lease)
2093 struct interface_info *ip = ifi;
2094 u_int8_t dbuf[1500], *dp = NULL;
2099 script_set_env(ip->client, prefix, "ip_address",
2100 piaddr(lease->address));
2102 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2104 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2105 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2107 dp = lease->options[DHO_SUBNET_MASK].data;
2108 len = lease->options[DHO_SUBNET_MASK].len;
2110 if (len && (len < sizeof(lease->address.iabuf))) {
2111 struct iaddr netmask, subnet, broadcast;
2113 memcpy(netmask.iabuf, dp, len);
2115 subnet = subnet_number(lease->address, netmask);
2117 script_set_env(ip->client, prefix, "network_number",
2119 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2120 broadcast = broadcast_addr(subnet, netmask);
2122 script_set_env(ip->client, prefix,
2123 "broadcast_address",
2129 if (lease->filename)
2130 script_set_env(ip->client, prefix, "filename", lease->filename);
2131 if (lease->server_name)
2132 script_set_env(ip->client, prefix, "server_name",
2133 lease->server_name);
2134 for (i = 0; i < 256; i++) {
2137 if (ip->client->config->defaults[i].len) {
2138 if (lease->options[i].len) {
2140 ip->client->config->default_actions[i]) {
2141 case ACTION_DEFAULT:
2142 dp = lease->options[i].data;
2143 len = lease->options[i].len;
2145 case ACTION_SUPERSEDE:
2148 config->defaults[i].data;
2150 config->defaults[i].len;
2152 case ACTION_PREPEND:
2154 config->defaults[i].len +
2155 lease->options[i].len;
2156 if (len >= sizeof(dbuf)) {
2157 warning("no space to %s %s",
2159 dhcp_options[i].name);
2165 config->defaults[i].data,
2167 config->defaults[i].len);
2168 memcpy(dp + ip->client->
2169 config->defaults[i].len,
2170 lease->options[i].data,
2171 lease->options[i].len);
2176 * When we append, we assume that we're
2177 * appending to text. Some MS servers
2178 * include a NUL byte at the end of
2179 * the search string provided.
2182 config->defaults[i].len +
2183 lease->options[i].len;
2184 if (len >= sizeof(dbuf)) {
2185 warning("no space to %s %s",
2187 dhcp_options[i].name);
2191 lease->options[i].data,
2192 lease->options[i].len);
2193 for (dp = dbuf + lease->options[i].len;
2194 dp > dbuf; dp--, len--)
2199 config->defaults[i].data,
2201 config->defaults[i].len);
2207 config->defaults[i].data;
2209 config->defaults[i].len;
2211 } else if (lease->options[i].len) {
2212 len = lease->options[i].len;
2213 dp = lease->options[i].data;
2220 if (dhcp_option_ev_name(name, sizeof(name),
2222 script_set_env(ip->client, prefix, name,
2223 pretty_print_option(i, dp, len, 0, 0));
2226 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2227 script_set_env(ip->client, prefix, "expiry", tbuf);
2231 script_write_params(const char *prefix, struct client_lease *lease)
2233 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2234 struct imsg_hdr hdr;
2238 if (lease->filename != NULL)
2239 fn_len = strlen(lease->filename);
2240 if (lease->server_name != NULL)
2241 sn_len = strlen(lease->server_name);
2243 pr_len = strlen(prefix);
2245 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2246 hdr.len = sizeof(hdr) + sizeof(*lease) +
2247 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2248 sizeof(pr_len) + pr_len;
2250 for (i = 0; i < 256; i++) {
2251 hdr.len += sizeof(lease->options[i].len);
2252 hdr.len += lease->options[i].len;
2255 scripttime = time(NULL);
2257 if ((buf = buf_open(hdr.len)) == NULL)
2258 error("buf_open: %m");
2261 errs += buf_add(buf, &hdr, sizeof(hdr));
2262 errs += buf_add(buf, lease, sizeof(*lease));
2263 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2264 errs += buf_add(buf, lease->filename, fn_len);
2265 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2266 errs += buf_add(buf, lease->server_name, sn_len);
2267 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2268 errs += buf_add(buf, prefix, pr_len);
2270 for (i = 0; i < 256; i++) {
2271 errs += buf_add(buf, &lease->options[i].len,
2272 sizeof(lease->options[i].len));
2273 errs += buf_add(buf, lease->options[i].data,
2274 lease->options[i].len);
2278 error("buf_add: %m");
2280 if (buf_close(privfd, buf) == -1)
2281 error("buf_close: %m");
2287 struct imsg_hdr hdr;
2291 hdr.code = IMSG_SCRIPT_GO;
2292 hdr.len = sizeof(struct imsg_hdr);
2294 if ((buf = buf_open(hdr.len)) == NULL)
2295 error("buf_open: %m");
2297 if (buf_add(buf, &hdr, sizeof(hdr)))
2298 error("buf_add: %m");
2300 if (buf_close(privfd, buf) == -1)
2301 error("buf_close: %m");
2303 bzero(&hdr, sizeof(hdr));
2304 buf_read(privfd, &hdr, sizeof(hdr));
2305 if (hdr.code != IMSG_SCRIPT_GO_RET)
2306 error("unexpected msg type %u", hdr.code);
2307 if (hdr.len != sizeof(hdr) + sizeof(int))
2308 error("received corrupted message");
2309 buf_read(privfd, &ret, sizeof(ret));
2311 scripttime = time(NULL);
2317 priv_script_go(void)
2319 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2320 static char client_path[] = CLIENT_PATH;
2321 struct interface_info *ip = ifi;
2322 int pid, wpid, wstatus;
2324 scripttime = time(NULL);
2327 scriptName = ip->client->config->script_name;
2328 envp = ip->client->scriptEnv;
2330 scriptName = top_level_config.script_name;
2332 epp[1] = client_path;
2337 argv[0] = scriptName;
2346 wpid = wait(&wstatus);
2347 } while (wpid != pid && wpid > 0);
2353 execve(scriptName, argv, envp);
2354 error("execve (%s, ...): %m", scriptName);
2358 script_flush_env(ip->client);
2360 return (WIFEXITED(wstatus) ?
2361 WEXITSTATUS(wstatus) : 128 + WTERMSIG(wstatus));
2365 script_set_env(struct client_state *client, const char *prefix,
2366 const char *name, const char *value)
2371 /* No `` or $() command substitution allowed in environment values! */
2372 for (j=0; j < strlen(value); j++)
2376 warning("illegal character (%c) in value '%s'",
2378 /* Ignore this option */
2382 namelen = strlen(name);
2384 for (i = 0; client->scriptEnv[i]; i++)
2385 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2386 client->scriptEnv[i][namelen] == '=')
2389 if (client->scriptEnv[i])
2390 /* Reuse the slot. */
2391 free(client->scriptEnv[i]);
2393 /* New variable. Expand if necessary. */
2394 if (i >= client->scriptEnvsize - 1) {
2395 char **newscriptEnv;
2396 int newscriptEnvsize = client->scriptEnvsize + 50;
2398 newscriptEnv = realloc(client->scriptEnv,
2400 if (newscriptEnv == NULL) {
2401 free(client->scriptEnv);
2402 client->scriptEnv = NULL;
2403 client->scriptEnvsize = 0;
2404 error("script_set_env: no memory for variable");
2406 client->scriptEnv = newscriptEnv;
2407 client->scriptEnvsize = newscriptEnvsize;
2409 /* need to set the NULL pointer at end of array beyond
2411 client->scriptEnv[i + 1] = NULL;
2413 /* Allocate space and format the variable in the appropriate slot. */
2414 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2416 if (client->scriptEnv[i] == NULL)
2417 error("script_set_env: no memory for variable assignment");
2418 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2419 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2423 script_flush_env(struct client_state *client)
2427 for (i = 0; client->scriptEnv[i]; i++) {
2428 free(client->scriptEnv[i]);
2429 client->scriptEnv[i] = NULL;
2431 client->scriptEnvsize = 0;
2435 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2439 for (i = 0; option->name[i]; i++) {
2440 if (i + 1 == buflen)
2442 if (option->name[i] == '-')
2445 buf[i] = option->name[i];
2455 static int state = 0;
2456 cap_rights_t rights;
2458 if (no_daemon || state)
2463 /* Stop logging to stderr... */
2466 if (daemonfd(-1, nullfd) == -1)
2469 cap_rights_init(&rights);
2471 if (pidfile != NULL) {
2472 pidfile_write(pidfile);
2474 if (caph_rights_limit(pidfile_fileno(pidfile), &rights) < 0)
2475 error("can't limit pidfile descriptor: %m");
2483 if (caph_rights_limit(STDIN_FILENO, &rights) < 0)
2484 error("can't limit stdin: %m");
2485 cap_rights_init(&rights, CAP_WRITE);
2486 if (caph_rights_limit(STDOUT_FILENO, &rights) < 0)
2487 error("can't limit stdout: %m");
2488 if (caph_rights_limit(STDERR_FILENO, &rights) < 0)
2489 error("can't limit stderr: %m");
2493 check_option(struct client_lease *l, int option)
2498 /* we use this, since this is what gets passed to dhclient-script */
2500 opbuf = pretty_print_option(option, l->options[option].data,
2501 l->options[option].len, 0, 0);
2503 sbuf = option_as_string(option, l->options[option].data,
2504 l->options[option].len);
2507 case DHO_SUBNET_MASK:
2508 case DHO_TIME_SERVERS:
2509 case DHO_NAME_SERVERS:
2511 case DHO_DOMAIN_NAME_SERVERS:
2512 case DHO_LOG_SERVERS:
2513 case DHO_COOKIE_SERVERS:
2514 case DHO_LPR_SERVERS:
2515 case DHO_IMPRESS_SERVERS:
2516 case DHO_RESOURCE_LOCATION_SERVERS:
2517 case DHO_SWAP_SERVER:
2518 case DHO_BROADCAST_ADDRESS:
2519 case DHO_NIS_SERVERS:
2520 case DHO_NTP_SERVERS:
2521 case DHO_NETBIOS_NAME_SERVERS:
2522 case DHO_NETBIOS_DD_SERVER:
2523 case DHO_FONT_SERVERS:
2524 case DHO_DHCP_SERVER_IDENTIFIER:
2525 case DHO_NISPLUS_SERVERS:
2526 case DHO_MOBILE_IP_HOME_AGENT:
2527 case DHO_SMTP_SERVER:
2528 case DHO_POP_SERVER:
2529 case DHO_NNTP_SERVER:
2530 case DHO_WWW_SERVER:
2531 case DHO_FINGER_SERVER:
2532 case DHO_IRC_SERVER:
2533 case DHO_STREETTALK_SERVER:
2534 case DHO_STREETTALK_DA_SERVER:
2535 if (!ipv4addrs(opbuf)) {
2536 warning("Invalid IP address in option: %s", opbuf);
2541 case DHO_NIS_DOMAIN:
2542 case DHO_NISPLUS_DOMAIN:
2543 case DHO_TFTP_SERVER_NAME:
2544 if (!res_hnok(sbuf)) {
2545 warning("Bogus Host Name option %d: %s (%s)", option,
2547 l->options[option].len = 0;
2548 free(l->options[option].data);
2551 case DHO_DOMAIN_NAME:
2552 case DHO_DOMAIN_SEARCH:
2553 if (!res_hnok(sbuf)) {
2554 if (!check_search(sbuf)) {
2555 warning("Bogus domain search list %d: %s (%s)",
2556 option, sbuf, opbuf);
2557 l->options[option].len = 0;
2558 free(l->options[option].data);
2563 case DHO_TIME_OFFSET:
2565 case DHO_MERIT_DUMP:
2567 case DHO_EXTENSIONS_PATH:
2568 case DHO_IP_FORWARDING:
2569 case DHO_NON_LOCAL_SOURCE_ROUTING:
2570 case DHO_POLICY_FILTER:
2571 case DHO_MAX_DGRAM_REASSEMBLY:
2572 case DHO_DEFAULT_IP_TTL:
2573 case DHO_PATH_MTU_AGING_TIMEOUT:
2574 case DHO_PATH_MTU_PLATEAU_TABLE:
2575 case DHO_INTERFACE_MTU:
2576 case DHO_ALL_SUBNETS_LOCAL:
2577 case DHO_PERFORM_MASK_DISCOVERY:
2578 case DHO_MASK_SUPPLIER:
2579 case DHO_ROUTER_DISCOVERY:
2580 case DHO_ROUTER_SOLICITATION_ADDRESS:
2581 case DHO_STATIC_ROUTES:
2582 case DHO_TRAILER_ENCAPSULATION:
2583 case DHO_ARP_CACHE_TIMEOUT:
2584 case DHO_IEEE802_3_ENCAPSULATION:
2585 case DHO_DEFAULT_TCP_TTL:
2586 case DHO_TCP_KEEPALIVE_INTERVAL:
2587 case DHO_TCP_KEEPALIVE_GARBAGE:
2588 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2589 case DHO_NETBIOS_NODE_TYPE:
2590 case DHO_NETBIOS_SCOPE:
2591 case DHO_X_DISPLAY_MANAGER:
2592 case DHO_DHCP_REQUESTED_ADDRESS:
2593 case DHO_DHCP_LEASE_TIME:
2594 case DHO_DHCP_OPTION_OVERLOAD:
2595 case DHO_DHCP_MESSAGE_TYPE:
2596 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2597 case DHO_DHCP_MESSAGE:
2598 case DHO_DHCP_MAX_MESSAGE_SIZE:
2599 case DHO_DHCP_RENEWAL_TIME:
2600 case DHO_DHCP_REBINDING_TIME:
2601 case DHO_DHCP_CLASS_IDENTIFIER:
2602 case DHO_DHCP_CLIENT_IDENTIFIER:
2603 case DHO_BOOTFILE_NAME:
2604 case DHO_DHCP_USER_CLASS_ID:
2607 case DHO_CLASSLESS_ROUTES:
2608 return (check_classless_option(l->options[option].data,
2609 l->options[option].len));
2611 warning("unknown dhcp option value 0x%x", option);
2612 return (unknown_ok);
2616 /* RFC 3442 The Classless Static Routes option checks */
2618 check_classless_option(unsigned char *data, int len)
2621 unsigned char width;
2622 in_addr_t addr, mask;
2625 warning("Too small length: %d", len);
2633 } else if (width < 9) {
2634 addr = (in_addr_t)(data[i] << 24);
2636 } else if (width < 17) {
2637 addr = (in_addr_t)(data[i] << 24) +
2638 (in_addr_t)(data[i + 1] << 16);
2640 } else if (width < 25) {
2641 addr = (in_addr_t)(data[i] << 24) +
2642 (in_addr_t)(data[i + 1] << 16) +
2643 (in_addr_t)(data[i + 2] << 8);
2645 } else if (width < 33) {
2646 addr = (in_addr_t)(data[i] << 24) +
2647 (in_addr_t)(data[i + 1] << 16) +
2648 (in_addr_t)(data[i + 2] << 8) +
2652 warning("Incorrect subnet width: %d", width);
2655 mask = (in_addr_t)(~0) << (32 - width);
2661 * ... After deriving a subnet number and subnet mask
2662 * from each destination descriptor, the DHCP client
2663 * MUST zero any bits in the subnet number where the
2664 * corresponding bit in the mask is zero...
2666 if ((addr & mask) != addr) {
2668 data[i - 1] = (unsigned char)(
2669 (addr >> (((32 - width)/8)*8)) & 0xFF);
2674 warning("Incorrect data length: %d (must be %d)", len, i);
2681 res_hnok(const char *dn)
2683 int pch = PERIOD, ch = *dn++;
2685 while (ch != '\0') {
2688 if (periodchar(ch)) {
2690 } else if (periodchar(pch)) {
2691 if (!borderchar(ch))
2693 } else if (periodchar(nch) || nch == '\0') {
2694 if (!borderchar(ch))
2697 if (!middlechar(ch))
2706 check_search(const char *srch)
2708 int pch = PERIOD, ch = *srch++;
2711 /* 256 char limit re resolv.conf(5) */
2712 if (strlen(srch) > 256)
2715 while (whitechar(ch))
2718 while (ch != '\0') {
2721 if (periodchar(ch) || whitechar(ch)) {
2723 } else if (periodchar(pch)) {
2724 if (!borderchar(ch))
2726 } else if (periodchar(nch) || nch == '\0') {
2727 if (!borderchar(ch))
2730 if (!middlechar(ch))
2733 if (!whitechar(ch)) {
2736 while (whitechar(nch)) {
2745 /* 6 domain limit re resolv.conf(5) */
2751 /* Does buf consist only of dotted decimal ipv4 addrs?
2752 * return how many if so,
2753 * otherwise, return 0
2756 ipv4addrs(const char * buf)
2761 while (inet_aton(buf, &jnk) == 1){
2763 while (periodchar(*buf) || digitchar(*buf))
2775 option_as_string(unsigned int code, unsigned char *data, int len)
2777 static char optbuf[32768]; /* XXX */
2779 int opleft = sizeof(optbuf);
2780 unsigned char *dp = data;
2783 error("option_as_string: bad code %d", code);
2785 for (; dp < data + len; dp++) {
2786 if (!isascii(*dp) || !isprint(*dp)) {
2787 if (dp + 1 != data + len || *dp != 0) {
2788 snprintf(op, opleft, "\\%03o", *dp);
2792 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2793 *dp == '`' || *dp == '\\') {
2807 warning("dhcp option too large");
2812 fork_privchld(int fd, int fd2)
2814 struct pollfd pfd[1];
2819 error("cannot fork");
2826 setproctitle("%s [priv]", ifi->name);
2829 dup2(nullfd, STDIN_FILENO);
2830 dup2(nullfd, STDOUT_FILENO);
2831 dup2(nullfd, STDERR_FILENO);
2839 pfd[0].events = POLLIN;
2840 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2842 error("poll error");
2844 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2847 dispatch_imsg(ifi, fd);