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 <net80211/ieee80211_freebsd.h>
69 #ifndef _PATH_VAREMPTY
70 #define _PATH_VAREMPTY "/var/empty"
74 #define hyphenchar(c) ((c) == 0x2d)
75 #define bslashchar(c) ((c) == 0x5c)
76 #define periodchar(c) ((c) == PERIOD)
77 #define asterchar(c) ((c) == 0x2a)
78 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
79 ((c) >= 0x61 && (c) <= 0x7a))
80 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
81 #define whitechar(c) ((c) == ' ' || (c) == '\t')
83 #define borderchar(c) (alphachar(c) || digitchar(c))
84 #define middlechar(c) (borderchar(c) || hyphenchar(c))
85 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
87 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
89 cap_channel_t *capsyslog;
92 time_t default_lease_time = 43200; /* 12 hours... */
94 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
95 char *path_dhclient_db = NULL;
101 char hostname[_POSIX_HOST_NAME_MAX + 1];
103 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
104 struct in_addr inaddr_any, inaddr_broadcast;
106 char *path_dhclient_pidfile;
107 struct pidfh *pidfile;
110 * ASSERT_STATE() does nothing now; it used to be
111 * assert (state_is == state_shouldbe).
113 #define ASSERT_STATE(state_is, state_shouldbe) {}
116 * We need to check that the expiry, renewal and rebind times are not beyond
117 * the end of time (~2038 when a 32-bit time_t is being used).
119 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
126 struct interface_info *ifi;
128 int findproto(char *, int);
129 struct sockaddr *get_ifa(char *, int);
130 void routehandler(struct protocol *);
132 int check_option(struct client_lease *l, int option);
133 int check_classless_option(unsigned char *data, int len);
134 int ipv4addrs(char * buf);
135 int res_hnok(const char *dn);
136 int check_search(const char *srch);
137 char *option_as_string(unsigned int code, unsigned char *data, int len);
138 int fork_privchld(int, int);
141 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
142 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
144 /* Minimum MTU is 68 as per RFC791, p. 24 */
147 static time_t scripttime;
150 findproto(char *cp, int n)
157 for (i = 1; i; i <<= 1) {
159 sa = (struct sockaddr *)cp;
165 if (sa->sa_family == AF_INET)
167 if (sa->sa_family == AF_INET6)
180 get_ifa(char *cp, int n)
187 for (i = 1; i; i <<= 1)
189 sa = (struct sockaddr *)cp;
198 struct iaddr defaddr = { .len = 4 };
204 struct interface_info *ifi = arg;
207 * Clear existing state.
209 if (ifi->client->active != NULL) {
210 script_init("EXPIRE", NULL);
211 script_write_params("old_",
212 ifi->client->active);
213 if (ifi->client->alias)
214 script_write_params("alias_",
218 ifi->client->state = S_INIT;
223 routehandler(struct protocol *p)
225 char msg[2048], *addr;
226 struct rt_msghdr *rtm;
227 struct if_msghdr *ifm;
228 struct ifa_msghdr *ifam;
229 struct if_announcemsghdr *ifan;
230 struct ieee80211_join_event *jev;
231 struct client_lease *l;
232 time_t t = time(NULL);
238 n = read(routefd, &msg, sizeof(msg));
239 rtm = (struct rt_msghdr *)msg;
240 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
241 n < (ssize_t)rtm->rtm_msglen ||
242 rtm->rtm_version != RTM_VERSION)
245 switch (rtm->rtm_type) {
248 ifam = (struct ifa_msghdr *)rtm;
250 if (ifam->ifam_index != ifi->index)
252 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
254 if (scripttime == 0 || t < scripttime + 10)
257 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
261 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
262 error("king bula sez: len mismatch");
263 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
264 if (addr_eq(a, defaddr))
267 for (l = ifi->client->active; l != NULL; l = l->next)
268 if (addr_eq(a, l->address))
271 if (l == NULL) /* added/deleted addr is not the one we set */
274 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
275 if (rtm->rtm_type == RTM_NEWADDR) {
277 * XXX: If someone other than us adds our address,
278 * should we assume they are taking over from us,
279 * delete the lease record, and exit without modifying
282 warning("My address (%s) was re-added", addr);
284 warning("My address (%s) was deleted, dhclient exiting",
290 ifm = (struct if_msghdr *)rtm;
291 if (ifm->ifm_index != ifi->index)
293 if ((rtm->rtm_flags & RTF_UP) == 0) {
294 warning("Interface %s is down, dhclient exiting",
298 linkstat = interface_link_status(ifi->name);
299 if (linkstat != ifi->linkstat) {
300 debug("%s link state %s -> %s", ifi->name,
301 ifi->linkstat ? "up" : "down",
302 linkstat ? "up" : "down");
303 ifi->linkstat = linkstat;
309 ifan = (struct if_announcemsghdr *)rtm;
310 if (ifan->ifan_what == IFAN_DEPARTURE &&
311 ifan->ifan_index == ifi->index) {
312 warning("Interface %s is gone, dhclient exiting",
318 ifan = (struct if_announcemsghdr *)rtm;
319 if (ifan->ifan_index != ifi->index)
321 switch (ifan->ifan_what) {
322 case RTM_IEEE80211_ASSOC:
323 case RTM_IEEE80211_REASSOC:
325 * Use assoc/reassoc event to kick state machine
326 * in case we roam. Otherwise fall back to the
327 * normal state machine just like a wired network.
329 jev = (struct ieee80211_join_event *) &ifan[1];
330 if (memcmp(curbssid, jev->iev_addr, 6)) {
334 memcpy(curbssid, jev->iev_addr, 6);
344 script_init("FAIL", NULL);
345 if (ifi->client->alias)
346 script_write_params("alias_", ifi->client->alias);
349 pidfile_remove(pidfile);
356 cap_channel_t *casper;
360 error("unable to start casper");
362 capsyslog = cap_service_open(casper, "system.syslog");
364 if (capsyslog == NULL)
365 error("unable to open system.syslog service");
369 main(int argc, char *argv[])
371 extern char *__progname;
372 int ch, fd, quiet = 0, i = 0;
374 int immediate_daemon = 0;
381 /* Initially, log errors to stderr as well as to syslogd. */
382 cap_openlog(capsyslog, __progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
383 cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
385 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
388 immediate_daemon = 1;
391 path_dhclient_conf = optarg;
397 path_dhclient_db = optarg;
400 path_dhclient_pidfile = optarg;
418 if (path_dhclient_pidfile == NULL) {
419 asprintf(&path_dhclient_pidfile,
420 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
421 if (path_dhclient_pidfile == NULL)
424 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
425 if (pidfile == NULL) {
427 error("dhclient already running, pid: %d.", otherpid);
429 error("dhclient already running.");
430 warning("Cannot open or create pidfile: %m");
433 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
435 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
436 error("Interface name too long");
437 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
438 _PATH_DHCLIENT_DB, ifi->name) == -1)
447 inaddr_broadcast.s_addr = INADDR_BROADCAST;
448 inaddr_any.s_addr = INADDR_ANY;
452 /* The next bit is potentially very time-consuming, so write out
453 the pidfile right away. We will write it out again with the
454 correct pid after daemonizing. */
456 pidfile_write(pidfile);
458 if (!interface_link_status(ifi->name)) {
459 fprintf(stderr, "%s: no link ...", ifi->name);
462 while (!interface_link_status(ifi->name)) {
463 fprintf(stderr, ".");
466 fprintf(stderr, " giving up\n");
471 fprintf(stderr, " got link\n");
475 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
476 error("cannot open %s: %m", _PATH_DEVNULL);
478 if ((pw = getpwnam("_dhcp")) == NULL) {
479 warning("no such user: _dhcp, falling back to \"nobody\"");
480 if ((pw = getpwnam("nobody")) == NULL)
481 error("no such user: nobody");
485 * Obtain hostname before entering capability mode - it won't be
486 * possible then, as reading kern.hostname is not permitted.
488 if (gethostname(hostname, sizeof(hostname)) < 0)
491 priv_script_init("PREINIT", NULL);
492 if (ifi->client->alias)
493 priv_script_write_params("alias_", ifi->client->alias);
496 /* set up the interface */
497 discover_interfaces(ifi);
499 if (pipe(pipe_fd) == -1)
502 fork_privchld(pipe_fd[0], pipe_fd[1]);
511 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
512 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
513 error("can't limit private descriptor: %m");
515 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
516 error("can't open and lock %s: %m", path_dhclient_db);
517 read_client_leases();
518 rewrite_client_leases();
521 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
522 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
523 if (shutdown(routefd, SHUT_WR) < 0)
524 error("can't shutdown route socket: %m");
525 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
526 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
527 error("can't limit route socket: %m");
529 if (chroot(_PATH_VAREMPTY) == -1)
531 if (chdir("/") == -1)
532 error("chdir(\"/\")");
534 if (setgroups(1, &pw->pw_gid) ||
535 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
536 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
537 error("can't drop privileges: %m");
541 setproctitle("%s", ifi->name);
543 if (CASPER_SUPPORT && cap_enter() < 0 && errno != ENOSYS)
544 error("can't enter capability mode: %m");
546 if (immediate_daemon)
549 ifi->client->state = S_INIT;
552 bootp_packet_handler = do_packet;
563 extern char *__progname;
565 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
566 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
573 * Each routine is called from the dhclient_state_machine() in one of
575 * -> entering INIT state
576 * -> recvpacket_flag == 0: timeout in this state
577 * -> otherwise: received a packet in this state
579 * Return conditions as handled by dhclient_state_machine():
580 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
581 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
582 * Returns 0: finish the nap which was interrupted for no good reason.
584 * Several per-interface variables are used to keep track of the process:
585 * active_lease: the lease that is being used on the interface
586 * (null pointer if not configured yet).
587 * offered_leases: leases corresponding to DHCPOFFER messages that have
588 * been sent to us by DHCP servers.
589 * acked_leases: leases corresponding to DHCPACK messages that have been
590 * sent to us by DHCP servers.
591 * sendpacket: DHCP packet we're trying to send.
592 * destination: IP address to send sendpacket to
593 * In addition, there are several relevant per-lease variables.
594 * T1_expiry, T2_expiry, lease_expiry: lease milestones
595 * In the active lease, these control the process of renewing the lease;
596 * In leases on the acked_leases list, this simply determines when we
597 * can no longer legitimately use the lease.
601 state_reboot(void *ipp)
603 struct interface_info *ip = ipp;
605 /* If we don't remember an active lease, go straight to INIT. */
606 if (!ip->client->active || ip->client->active->is_bootp) {
611 /* We are in the rebooting state. */
612 ip->client->state = S_REBOOTING;
614 /* make_request doesn't initialize xid because it normally comes
615 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
616 so pick an xid now. */
617 ip->client->xid = arc4random();
619 /* Make a DHCPREQUEST packet, and set appropriate per-interface
621 make_request(ip, ip->client->active);
622 ip->client->destination = iaddr_broadcast;
623 ip->client->first_sending = cur_time;
624 ip->client->interval = ip->client->config->initial_interval;
626 /* Zap the medium list... */
627 ip->client->medium = NULL;
629 /* Send out the first DHCPREQUEST packet. */
634 * Called when a lease has completely expired and we've
635 * been unable to renew it.
638 state_init(void *ipp)
640 struct interface_info *ip = ipp;
642 ASSERT_STATE(state, S_INIT);
644 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
646 make_discover(ip, ip->client->active);
647 ip->client->xid = ip->client->packet.xid;
648 ip->client->destination = iaddr_broadcast;
649 ip->client->state = S_SELECTING;
650 ip->client->first_sending = cur_time;
651 ip->client->interval = ip->client->config->initial_interval;
653 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
659 * state_selecting is called when one or more DHCPOFFER packets
660 * have been received and a configurable period of time has passed.
663 state_selecting(void *ipp)
665 struct interface_info *ip = ipp;
666 struct client_lease *lp, *next, *picked;
668 ASSERT_STATE(state, S_SELECTING);
670 /* Cancel state_selecting and send_discover timeouts, since either
671 one could have got us here. */
672 cancel_timeout(state_selecting, ip);
673 cancel_timeout(send_discover, ip);
675 /* We have received one or more DHCPOFFER packets. Currently,
676 the only criterion by which we judge leases is whether or
677 not we get a response when we arp for them. */
679 for (lp = ip->client->offered_leases; lp; lp = next) {
682 /* Check to see if we got an ARPREPLY for the address
683 in this particular lease. */
685 script_init("ARPCHECK", lp->medium);
686 script_write_params("check_", lp);
688 /* If the ARPCHECK code detects another
689 machine using the offered address, it exits
690 nonzero. We need to send a DHCPDECLINE and
693 make_decline(ip, lp);
701 free_client_lease(lp);
704 ip->client->offered_leases = NULL;
706 /* If we just tossed all the leases we were offered, go back
709 ip->client->state = S_INIT;
714 /* If it was a BOOTREPLY, we can just take the address right now. */
715 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
716 ip->client->new = picked;
718 /* Make up some lease expiry times
719 XXX these should be configurable. */
720 ip->client->new->expiry = cur_time + 12000;
721 ip->client->new->renewal += cur_time + 8000;
722 ip->client->new->rebind += cur_time + 10000;
724 ip->client->state = S_REQUESTING;
726 /* Bind to the address we received. */
731 /* Go to the REQUESTING state. */
732 ip->client->destination = iaddr_broadcast;
733 ip->client->state = S_REQUESTING;
734 ip->client->first_sending = cur_time;
735 ip->client->interval = ip->client->config->initial_interval;
737 /* Make a DHCPREQUEST packet from the lease we picked. */
738 make_request(ip, picked);
739 ip->client->xid = ip->client->packet.xid;
741 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
742 free_client_lease(picked);
744 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
748 /* state_requesting is called when we receive a DHCPACK message after
749 having sent out one or more DHCPREQUEST packets. */
752 dhcpack(struct packet *packet)
754 struct interface_info *ip = packet->interface;
755 struct client_lease *lease;
757 /* If we're not receptive to an offer right now, or if the offer
758 has an unrecognizable transaction id, then just drop it. */
759 if (packet->interface->client->xid != packet->raw->xid ||
760 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
761 (memcmp(packet->interface->hw_address.haddr,
762 packet->raw->chaddr, packet->raw->hlen)))
765 if (ip->client->state != S_REBOOTING &&
766 ip->client->state != S_REQUESTING &&
767 ip->client->state != S_RENEWING &&
768 ip->client->state != S_REBINDING)
771 note("DHCPACK from %s", piaddr(packet->client_addr));
773 lease = packet_to_lease(packet);
775 note("packet_to_lease failed.");
779 ip->client->new = lease;
781 /* Stop resending DHCPREQUEST. */
782 cancel_timeout(send_request, ip);
784 /* Figure out the lease time. */
785 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
787 ip->client->new->expiry = getULong(
788 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
789 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
790 ip->client->new->expiry = getULong(
791 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
793 ip->client->new->expiry = default_lease_time;
794 /* A number that looks negative here is really just very large,
795 because the lease expiry offset is unsigned. Also make sure that
796 the addition of cur_time below does not overflow (a 32 bit) time_t. */
797 if (ip->client->new->expiry < 0 ||
798 ip->client->new->expiry > TIME_MAX - cur_time)
799 ip->client->new->expiry = TIME_MAX - cur_time;
800 /* XXX should be fixed by resetting the client state */
801 if (ip->client->new->expiry < 60)
802 ip->client->new->expiry = 60;
804 /* Unless overridden in the config, take the server-provided renewal
805 * time if there is one. Otherwise figure it out according to the spec.
806 * Also make sure the renewal time does not exceed the expiry time.
808 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
810 ip->client->new->renewal = getULong(
811 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
812 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
813 ip->client->new->renewal = getULong(
814 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
816 ip->client->new->renewal = ip->client->new->expiry / 2;
817 if (ip->client->new->renewal < 0 ||
818 ip->client->new->renewal > ip->client->new->expiry / 2)
819 ip->client->new->renewal = ip->client->new->expiry / 2;
821 /* Same deal with the rebind time. */
822 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
824 ip->client->new->rebind = getULong(
825 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
826 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
827 ip->client->new->rebind = getULong(
828 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
830 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
831 if (ip->client->new->rebind < 0 ||
832 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
833 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
835 /* Convert the time offsets into seconds-since-the-epoch */
836 ip->client->new->expiry += cur_time;
837 ip->client->new->renewal += cur_time;
838 ip->client->new->rebind += cur_time;
844 bind_lease(struct interface_info *ip)
846 struct option_data *opt;
848 /* Remember the medium. */
849 ip->client->new->medium = ip->client->medium;
851 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
852 if (opt->len == sizeof(u_int16_t)) {
853 u_int16_t mtu = be16dec(opt->data);
855 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
857 interface_set_mtu_unpriv(privfd, mtu);
860 /* Write out the new lease. */
861 write_client_lease(ip, ip->client->new, 0);
863 /* Run the client script with the new parameters. */
864 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
865 (ip->client->state == S_RENEWING ? "RENEW" :
866 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
867 ip->client->new->medium);
868 if (ip->client->active && ip->client->state != S_REBOOTING)
869 script_write_params("old_", ip->client->active);
870 script_write_params("new_", ip->client->new);
871 if (ip->client->alias)
872 script_write_params("alias_", ip->client->alias);
875 /* Replace the old active lease with the new one. */
876 if (ip->client->active)
877 free_client_lease(ip->client->active);
878 ip->client->active = ip->client->new;
879 ip->client->new = NULL;
881 /* Set up a timeout to start the renewal process. */
882 add_timeout(ip->client->active->renewal, state_bound, ip);
884 note("bound to %s -- renewal in %d seconds.",
885 piaddr(ip->client->active->address),
886 (int)(ip->client->active->renewal - cur_time));
887 ip->client->state = S_BOUND;
888 reinitialize_interfaces();
893 * state_bound is called when we've successfully bound to a particular
894 * lease, but the renewal time on that lease has expired. We are
895 * expected to unicast a DHCPREQUEST to the server that gave us our
899 state_bound(void *ipp)
901 struct interface_info *ip = ipp;
903 ASSERT_STATE(state, S_BOUND);
905 /* T1 has expired. */
906 make_request(ip, ip->client->active);
907 ip->client->xid = ip->client->packet.xid;
909 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
910 memcpy(ip->client->destination.iabuf, ip->client->active->
911 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
912 ip->client->destination.len = 4;
914 ip->client->destination = iaddr_broadcast;
916 ip->client->first_sending = cur_time;
917 ip->client->interval = ip->client->config->initial_interval;
918 ip->client->state = S_RENEWING;
920 /* Send the first packet immediately. */
925 bootp(struct packet *packet)
927 struct iaddrlist *ap;
929 if (packet->raw->op != BOOTREPLY)
932 /* If there's a reject list, make sure this packet's sender isn't
934 for (ap = packet->interface->client->config->reject_list;
936 if (addr_eq(packet->client_addr, ap->addr)) {
937 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
945 dhcp(struct packet *packet)
947 struct iaddrlist *ap;
948 void (*handler)(struct packet *);
951 switch (packet->packet_type) {
968 /* If there's a reject list, make sure this packet's sender isn't
970 for (ap = packet->interface->client->config->reject_list;
972 if (addr_eq(packet->client_addr, ap->addr)) {
973 note("%s from %s rejected.", type, piaddr(ap->addr));
981 dhcpoffer(struct packet *packet)
983 struct interface_info *ip = packet->interface;
984 struct client_lease *lease, *lp;
986 int arp_timeout_needed, stop_selecting;
987 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
988 "DHCPOFFER" : "BOOTREPLY";
990 /* If we're not receptive to an offer right now, or if the offer
991 has an unrecognizable transaction id, then just drop it. */
992 if (ip->client->state != S_SELECTING ||
993 packet->interface->client->xid != packet->raw->xid ||
994 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
995 (memcmp(packet->interface->hw_address.haddr,
996 packet->raw->chaddr, packet->raw->hlen)))
999 note("%s from %s", name, piaddr(packet->client_addr));
1002 /* If this lease doesn't supply the minimum required parameters,
1004 for (i = 0; ip->client->config->required_options[i]; i++) {
1005 if (!packet->options[ip->client->config->
1006 required_options[i]].len) {
1007 note("%s isn't satisfactory.", name);
1012 /* If we've already seen this lease, don't record it again. */
1013 for (lease = ip->client->offered_leases;
1014 lease; lease = lease->next) {
1015 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1016 !memcmp(lease->address.iabuf,
1017 &packet->raw->yiaddr, lease->address.len)) {
1018 debug("%s already seen.", name);
1023 lease = packet_to_lease(packet);
1025 note("packet_to_lease failed.");
1029 /* If this lease was acquired through a BOOTREPLY, record that
1031 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1032 lease->is_bootp = 1;
1034 /* Record the medium under which this lease was offered. */
1035 lease->medium = ip->client->medium;
1037 /* Send out an ARP Request for the offered IP address. */
1038 script_init("ARPSEND", lease->medium);
1039 script_write_params("check_", lease);
1040 /* If the script can't send an ARP request without waiting,
1041 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1043 arp_timeout_needed = 0;
1045 arp_timeout_needed = 2;
1047 /* Figure out when we're supposed to stop selecting. */
1049 ip->client->first_sending + ip->client->config->select_interval;
1051 /* If this is the lease we asked for, put it at the head of the
1052 list, and don't mess with the arp request timeout. */
1053 if (lease->address.len == ip->client->requested_address.len &&
1054 !memcmp(lease->address.iabuf,
1055 ip->client->requested_address.iabuf,
1056 ip->client->requested_address.len)) {
1057 lease->next = ip->client->offered_leases;
1058 ip->client->offered_leases = lease;
1060 /* If we already have an offer, and arping for this
1061 offer would take us past the selection timeout,
1062 then don't extend the timeout - just hope for the
1064 if (ip->client->offered_leases &&
1065 (cur_time + arp_timeout_needed) > stop_selecting)
1066 arp_timeout_needed = 0;
1068 /* Put the lease at the end of the list. */
1070 if (!ip->client->offered_leases)
1071 ip->client->offered_leases = lease;
1073 for (lp = ip->client->offered_leases; lp->next;
1080 /* If we're supposed to stop selecting before we've had time
1081 to wait for the ARPREPLY, add some delay to wait for
1083 if (stop_selecting - cur_time < arp_timeout_needed)
1084 stop_selecting = cur_time + arp_timeout_needed;
1086 /* If the selecting interval has expired, go immediately to
1087 state_selecting(). Otherwise, time out into
1088 state_selecting at the select interval. */
1089 if (stop_selecting <= 0)
1090 state_selecting(ip);
1092 add_timeout(stop_selecting, state_selecting, ip);
1093 cancel_timeout(send_discover, ip);
1097 /* Allocate a client_lease structure and initialize it from the parameters
1098 in the specified packet. */
1100 struct client_lease *
1101 packet_to_lease(struct packet *packet)
1103 struct client_lease *lease;
1106 lease = malloc(sizeof(struct client_lease));
1109 warning("dhcpoffer: no memory to record lease.");
1113 memset(lease, 0, sizeof(*lease));
1115 /* Copy the lease options. */
1116 for (i = 0; i < 256; i++) {
1117 if (packet->options[i].len) {
1118 lease->options[i].data =
1119 malloc(packet->options[i].len + 1);
1120 if (!lease->options[i].data) {
1121 warning("dhcpoffer: no memory for option %d", i);
1122 free_client_lease(lease);
1125 memcpy(lease->options[i].data,
1126 packet->options[i].data,
1127 packet->options[i].len);
1128 lease->options[i].len =
1129 packet->options[i].len;
1130 lease->options[i].data[lease->options[i].len] =
1133 if (!check_option(lease,i)) {
1134 /* ignore a bogus lease offer */
1135 warning("Invalid lease option - ignoring offer");
1136 free_client_lease(lease);
1142 lease->address.len = sizeof(packet->raw->yiaddr);
1143 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1145 lease->nextserver.len = sizeof(packet->raw->siaddr);
1146 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1148 /* If the server name was filled out, copy it.
1149 Do not attempt to validate the server name as a host name.
1150 RFC 2131 merely states that sname is NUL-terminated (which do
1151 do not assume) and that it is the server's host name. Since
1152 the ISC client and server allow arbitrary characters, we do
1154 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1155 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1156 packet->raw->sname[0]) {
1157 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1158 if (!lease->server_name) {
1159 warning("dhcpoffer: no memory for server name.");
1160 free_client_lease(lease);
1163 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1164 lease->server_name[DHCP_SNAME_LEN]='\0';
1167 /* Ditto for the filename. */
1168 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1169 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1170 packet->raw->file[0]) {
1171 /* Don't count on the NUL terminator. */
1172 lease->filename = malloc(DHCP_FILE_LEN + 1);
1173 if (!lease->filename) {
1174 warning("dhcpoffer: no memory for filename.");
1175 free_client_lease(lease);
1178 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1179 lease->filename[DHCP_FILE_LEN]='\0';
1185 dhcpnak(struct packet *packet)
1187 struct interface_info *ip = packet->interface;
1189 /* If we're not receptive to an offer right now, or if the offer
1190 has an unrecognizable transaction id, then just drop it. */
1191 if (packet->interface->client->xid != packet->raw->xid ||
1192 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1193 (memcmp(packet->interface->hw_address.haddr,
1194 packet->raw->chaddr, packet->raw->hlen)))
1197 if (ip->client->state != S_REBOOTING &&
1198 ip->client->state != S_REQUESTING &&
1199 ip->client->state != S_RENEWING &&
1200 ip->client->state != S_REBINDING)
1203 note("DHCPNAK from %s", piaddr(packet->client_addr));
1205 if (!ip->client->active) {
1206 note("DHCPNAK with no active lease.\n");
1210 free_client_lease(ip->client->active);
1211 ip->client->active = NULL;
1213 /* Stop sending DHCPREQUEST packets... */
1214 cancel_timeout(send_request, ip);
1216 ip->client->state = S_INIT;
1220 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1221 one after the right interval has expired. If we don't get an offer by
1222 the time we reach the panic interval, call the panic function. */
1225 send_discover(void *ipp)
1227 struct interface_info *ip = ipp;
1228 int interval, increase = 1;
1230 /* Figure out how long it's been since we started transmitting. */
1231 interval = cur_time - ip->client->first_sending;
1233 /* If we're past the panic timeout, call the script and tell it
1234 we haven't found anything for this interface yet. */
1235 if (interval > ip->client->config->timeout) {
1240 /* If we're selecting media, try the whole list before doing
1241 the exponential backoff, but if we've already received an
1242 offer, stop looping, because we obviously have it right. */
1243 if (!ip->client->offered_leases &&
1244 ip->client->config->media) {
1247 if (ip->client->medium) {
1248 ip->client->medium = ip->client->medium->next;
1251 if (!ip->client->medium) {
1253 error("No valid media types for %s!", ip->name);
1254 ip->client->medium = ip->client->config->media;
1258 note("Trying medium \"%s\" %d", ip->client->medium->string,
1260 script_init("MEDIUM", ip->client->medium);
1266 * If we're supposed to increase the interval, do so. If it's
1267 * currently zero (i.e., we haven't sent any packets yet), set
1268 * it to one; otherwise, add to it a random number between zero
1269 * and two times itself. On average, this means that it will
1270 * double with every transmission.
1273 if (!ip->client->interval)
1274 ip->client->interval =
1275 ip->client->config->initial_interval;
1277 ip->client->interval += (arc4random() >> 2) %
1278 (2 * ip->client->interval);
1281 /* Don't backoff past cutoff. */
1282 if (ip->client->interval >
1283 ip->client->config->backoff_cutoff)
1284 ip->client->interval =
1285 ((ip->client->config->backoff_cutoff / 2)
1286 + ((arc4random() >> 2) %
1287 ip->client->config->backoff_cutoff));
1288 } else if (!ip->client->interval)
1289 ip->client->interval =
1290 ip->client->config->initial_interval;
1292 /* If the backoff would take us to the panic timeout, just use that
1294 if (cur_time + ip->client->interval >
1295 ip->client->first_sending + ip->client->config->timeout)
1296 ip->client->interval =
1297 (ip->client->first_sending +
1298 ip->client->config->timeout) - cur_time + 1;
1300 /* Record the number of seconds since we started sending. */
1301 if (interval < 65536)
1302 ip->client->packet.secs = htons(interval);
1304 ip->client->packet.secs = htons(65535);
1305 ip->client->secs = ip->client->packet.secs;
1307 note("DHCPDISCOVER on %s to %s port %d interval %d",
1308 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1309 (int)ip->client->interval);
1311 /* Send out a packet. */
1312 send_packet_unpriv(privfd, &ip->client->packet,
1313 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1315 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1319 * state_panic gets called if we haven't received any offers in a preset
1320 * amount of time. When this happens, we try to use existing leases
1321 * that haven't yet expired, and failing that, we call the client script
1322 * and hope it can do something.
1325 state_panic(void *ipp)
1327 struct interface_info *ip = ipp;
1328 struct client_lease *loop = ip->client->active;
1329 struct client_lease *lp;
1331 note("No DHCPOFFERS received.");
1333 /* We may not have an active lease, but we may have some
1334 predefined leases that we can try. */
1335 if (!ip->client->active && ip->client->leases)
1338 /* Run through the list of leases and see if one can be used. */
1339 while (ip->client->active) {
1340 if (ip->client->active->expiry > cur_time) {
1341 note("Trying recorded lease %s",
1342 piaddr(ip->client->active->address));
1343 /* Run the client script with the existing
1345 script_init("TIMEOUT",
1346 ip->client->active->medium);
1347 script_write_params("new_", ip->client->active);
1348 if (ip->client->alias)
1349 script_write_params("alias_",
1352 /* If the old lease is still good and doesn't
1353 yet need renewal, go into BOUND state and
1354 timeout at the renewal time. */
1357 ip->client->active->renewal) {
1358 ip->client->state = S_BOUND;
1359 note("bound: renewal in %d seconds.",
1360 (int)(ip->client->active->renewal -
1363 ip->client->active->renewal,
1366 ip->client->state = S_BOUND;
1367 note("bound: immediate renewal.");
1370 reinitialize_interfaces();
1376 /* If there are no other leases, give up. */
1377 if (!ip->client->leases) {
1378 ip->client->leases = ip->client->active;
1379 ip->client->active = NULL;
1384 /* Otherwise, put the active lease at the end of the
1385 lease list, and try another lease.. */
1386 for (lp = ip->client->leases; lp->next; lp = lp->next)
1388 lp->next = ip->client->active;
1390 lp->next->next = NULL;
1391 ip->client->active = ip->client->leases;
1392 ip->client->leases = ip->client->leases->next;
1394 /* If we already tried this lease, we've exhausted the
1395 set of leases, so we might as well give up for
1397 if (ip->client->active == loop)
1400 loop = ip->client->active;
1403 /* No leases were available, or what was available didn't work, so
1404 tell the shell script that we failed to allocate an address,
1405 and try again later. */
1406 note("No working leases in persistent database - sleeping.\n");
1407 script_init("FAIL", NULL);
1408 if (ip->client->alias)
1409 script_write_params("alias_", ip->client->alias);
1411 ip->client->state = S_INIT;
1412 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1418 send_request(void *ipp)
1420 struct interface_info *ip = ipp;
1421 struct in_addr from, to;
1424 /* Figure out how long it's been since we started transmitting. */
1425 interval = cur_time - ip->client->first_sending;
1427 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1428 past the reboot timeout, go to INIT and see if we can
1429 DISCOVER an address... */
1430 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1431 means either that we're on a network with no DHCP server,
1432 or that our server is down. In the latter case, assuming
1433 that there is a backup DHCP server, DHCPDISCOVER will get
1434 us a new address, but we could also have successfully
1435 reused our old address. In the former case, we're hosed
1436 anyway. This is not a win-prone situation. */
1437 if ((ip->client->state == S_REBOOTING ||
1438 ip->client->state == S_REQUESTING) &&
1439 interval > ip->client->config->reboot_timeout) {
1441 ip->client->state = S_INIT;
1442 cancel_timeout(send_request, ip);
1447 /* If we're in the reboot state, make sure the media is set up
1449 if (ip->client->state == S_REBOOTING &&
1450 !ip->client->medium &&
1451 ip->client->active->medium ) {
1452 script_init("MEDIUM", ip->client->active->medium);
1454 /* If the medium we chose won't fly, go to INIT state. */
1458 /* Record the medium. */
1459 ip->client->medium = ip->client->active->medium;
1462 /* If the lease has expired, relinquish the address and go back
1463 to the INIT state. */
1464 if (ip->client->state != S_REQUESTING &&
1465 cur_time > ip->client->active->expiry) {
1466 /* Run the client script with the new parameters. */
1467 script_init("EXPIRE", NULL);
1468 script_write_params("old_", ip->client->active);
1469 if (ip->client->alias)
1470 script_write_params("alias_", ip->client->alias);
1473 /* Now do a preinit on the interface so that we can
1474 discover a new address. */
1475 script_init("PREINIT", NULL);
1476 if (ip->client->alias)
1477 script_write_params("alias_", ip->client->alias);
1480 ip->client->state = S_INIT;
1485 /* Do the exponential backoff... */
1486 if (!ip->client->interval)
1487 ip->client->interval = ip->client->config->initial_interval;
1489 ip->client->interval += ((arc4random() >> 2) %
1490 (2 * ip->client->interval));
1492 /* Don't backoff past cutoff. */
1493 if (ip->client->interval >
1494 ip->client->config->backoff_cutoff)
1495 ip->client->interval =
1496 ((ip->client->config->backoff_cutoff / 2) +
1497 ((arc4random() >> 2) % ip->client->interval));
1499 /* If the backoff would take us to the expiry time, just set the
1500 timeout to the expiry time. */
1501 if (ip->client->state != S_REQUESTING &&
1502 cur_time + ip->client->interval >
1503 ip->client->active->expiry)
1504 ip->client->interval =
1505 ip->client->active->expiry - cur_time + 1;
1507 /* If the lease T2 time has elapsed, or if we're not yet bound,
1508 broadcast the DHCPREQUEST rather than unicasting. */
1509 if (ip->client->state == S_REQUESTING ||
1510 ip->client->state == S_REBOOTING ||
1511 cur_time > ip->client->active->rebind)
1512 to.s_addr = INADDR_BROADCAST;
1514 memcpy(&to.s_addr, ip->client->destination.iabuf,
1517 if (ip->client->state != S_REQUESTING)
1518 memcpy(&from, ip->client->active->address.iabuf,
1521 from.s_addr = INADDR_ANY;
1523 /* Record the number of seconds since we started sending. */
1524 if (ip->client->state == S_REQUESTING)
1525 ip->client->packet.secs = ip->client->secs;
1527 if (interval < 65536)
1528 ip->client->packet.secs = htons(interval);
1530 ip->client->packet.secs = htons(65535);
1533 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1536 /* Send out a packet. */
1537 send_packet_unpriv(privfd, &ip->client->packet,
1538 ip->client->packet_length, from, to);
1540 add_timeout(cur_time + ip->client->interval, send_request, ip);
1544 send_decline(void *ipp)
1546 struct interface_info *ip = ipp;
1548 note("DHCPDECLINE on %s to %s port %d", ip->name,
1549 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1551 /* Send out a packet. */
1552 send_packet_unpriv(privfd, &ip->client->packet,
1553 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1557 make_discover(struct interface_info *ip, struct client_lease *lease)
1559 unsigned char discover = DHCPDISCOVER;
1560 struct tree_cache *options[256];
1561 struct tree_cache option_elements[256];
1564 memset(option_elements, 0, sizeof(option_elements));
1565 memset(options, 0, sizeof(options));
1566 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1568 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1569 i = DHO_DHCP_MESSAGE_TYPE;
1570 options[i] = &option_elements[i];
1571 options[i]->value = &discover;
1572 options[i]->len = sizeof(discover);
1573 options[i]->buf_size = sizeof(discover);
1574 options[i]->timeout = 0xFFFFFFFF;
1576 /* Request the options we want */
1577 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1578 options[i] = &option_elements[i];
1579 options[i]->value = ip->client->config->requested_options;
1580 options[i]->len = ip->client->config->requested_option_count;
1581 options[i]->buf_size =
1582 ip->client->config->requested_option_count;
1583 options[i]->timeout = 0xFFFFFFFF;
1585 /* If we had an address, try to get it again. */
1587 ip->client->requested_address = lease->address;
1588 i = DHO_DHCP_REQUESTED_ADDRESS;
1589 options[i] = &option_elements[i];
1590 options[i]->value = lease->address.iabuf;
1591 options[i]->len = lease->address.len;
1592 options[i]->buf_size = lease->address.len;
1593 options[i]->timeout = 0xFFFFFFFF;
1595 ip->client->requested_address.len = 0;
1597 /* Send any options requested in the config file. */
1598 for (i = 0; i < 256; i++)
1600 ip->client->config->send_options[i].data) {
1601 options[i] = &option_elements[i];
1603 ip->client->config->send_options[i].data;
1605 ip->client->config->send_options[i].len;
1606 options[i]->buf_size =
1607 ip->client->config->send_options[i].len;
1608 options[i]->timeout = 0xFFFFFFFF;
1611 /* send host name if not set via config file. */
1612 if (!options[DHO_HOST_NAME]) {
1613 if (hostname[0] != '\0') {
1615 char* posDot = strchr(hostname, '.');
1617 len = posDot - hostname;
1619 len = strlen(hostname);
1620 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1621 options[DHO_HOST_NAME]->value = hostname;
1622 options[DHO_HOST_NAME]->len = len;
1623 options[DHO_HOST_NAME]->buf_size = len;
1624 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1628 /* set unique client identifier */
1629 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1630 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1631 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1632 ip->hw_address.hlen : sizeof(client_ident)-1;
1633 client_ident[0] = ip->hw_address.htype;
1634 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1635 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1636 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1637 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1638 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1639 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1642 /* Set up the option buffer... */
1643 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1644 options, 0, 0, 0, NULL, 0);
1645 if (ip->client->packet_length < BOOTP_MIN_LEN)
1646 ip->client->packet_length = BOOTP_MIN_LEN;
1648 ip->client->packet.op = BOOTREQUEST;
1649 ip->client->packet.htype = ip->hw_address.htype;
1650 ip->client->packet.hlen = ip->hw_address.hlen;
1651 ip->client->packet.hops = 0;
1652 ip->client->packet.xid = arc4random();
1653 ip->client->packet.secs = 0; /* filled in by send_discover. */
1654 ip->client->packet.flags = 0;
1656 memset(&(ip->client->packet.ciaddr),
1657 0, sizeof(ip->client->packet.ciaddr));
1658 memset(&(ip->client->packet.yiaddr),
1659 0, sizeof(ip->client->packet.yiaddr));
1660 memset(&(ip->client->packet.siaddr),
1661 0, sizeof(ip->client->packet.siaddr));
1662 memset(&(ip->client->packet.giaddr),
1663 0, sizeof(ip->client->packet.giaddr));
1664 memcpy(ip->client->packet.chaddr,
1665 ip->hw_address.haddr, ip->hw_address.hlen);
1670 make_request(struct interface_info *ip, struct client_lease * lease)
1672 unsigned char request = DHCPREQUEST;
1673 struct tree_cache *options[256];
1674 struct tree_cache option_elements[256];
1677 memset(options, 0, sizeof(options));
1678 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1680 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1681 i = DHO_DHCP_MESSAGE_TYPE;
1682 options[i] = &option_elements[i];
1683 options[i]->value = &request;
1684 options[i]->len = sizeof(request);
1685 options[i]->buf_size = sizeof(request);
1686 options[i]->timeout = 0xFFFFFFFF;
1688 /* Request the options we want */
1689 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1690 options[i] = &option_elements[i];
1691 options[i]->value = ip->client->config->requested_options;
1692 options[i]->len = ip->client->config->requested_option_count;
1693 options[i]->buf_size =
1694 ip->client->config->requested_option_count;
1695 options[i]->timeout = 0xFFFFFFFF;
1697 /* If we are requesting an address that hasn't yet been assigned
1698 to us, use the DHCP Requested Address option. */
1699 if (ip->client->state == S_REQUESTING) {
1700 /* Send back the server identifier... */
1701 i = DHO_DHCP_SERVER_IDENTIFIER;
1702 options[i] = &option_elements[i];
1703 options[i]->value = lease->options[i].data;
1704 options[i]->len = lease->options[i].len;
1705 options[i]->buf_size = lease->options[i].len;
1706 options[i]->timeout = 0xFFFFFFFF;
1708 if (ip->client->state == S_REQUESTING ||
1709 ip->client->state == S_REBOOTING) {
1710 ip->client->requested_address = lease->address;
1711 i = DHO_DHCP_REQUESTED_ADDRESS;
1712 options[i] = &option_elements[i];
1713 options[i]->value = lease->address.iabuf;
1714 options[i]->len = lease->address.len;
1715 options[i]->buf_size = lease->address.len;
1716 options[i]->timeout = 0xFFFFFFFF;
1718 ip->client->requested_address.len = 0;
1720 /* Send any options requested in the config file. */
1721 for (i = 0; i < 256; i++)
1723 ip->client->config->send_options[i].data) {
1724 options[i] = &option_elements[i];
1726 ip->client->config->send_options[i].data;
1728 ip->client->config->send_options[i].len;
1729 options[i]->buf_size =
1730 ip->client->config->send_options[i].len;
1731 options[i]->timeout = 0xFFFFFFFF;
1734 /* send host name if not set via config file. */
1735 if (!options[DHO_HOST_NAME]) {
1736 if (hostname[0] != '\0') {
1738 char* posDot = strchr(hostname, '.');
1740 len = posDot - hostname;
1742 len = strlen(hostname);
1743 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1744 options[DHO_HOST_NAME]->value = hostname;
1745 options[DHO_HOST_NAME]->len = len;
1746 options[DHO_HOST_NAME]->buf_size = len;
1747 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1751 /* set unique client identifier */
1752 char client_ident[sizeof(struct hardware)];
1753 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1754 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1755 ip->hw_address.hlen : sizeof(client_ident)-1;
1756 client_ident[0] = ip->hw_address.htype;
1757 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1758 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1759 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1760 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1761 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1762 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1765 /* Set up the option buffer... */
1766 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1767 options, 0, 0, 0, NULL, 0);
1768 if (ip->client->packet_length < BOOTP_MIN_LEN)
1769 ip->client->packet_length = BOOTP_MIN_LEN;
1771 ip->client->packet.op = BOOTREQUEST;
1772 ip->client->packet.htype = ip->hw_address.htype;
1773 ip->client->packet.hlen = ip->hw_address.hlen;
1774 ip->client->packet.hops = 0;
1775 ip->client->packet.xid = ip->client->xid;
1776 ip->client->packet.secs = 0; /* Filled in by send_request. */
1778 /* If we own the address we're requesting, put it in ciaddr;
1779 otherwise set ciaddr to zero. */
1780 if (ip->client->state == S_BOUND ||
1781 ip->client->state == S_RENEWING ||
1782 ip->client->state == S_REBINDING) {
1783 memcpy(&ip->client->packet.ciaddr,
1784 lease->address.iabuf, lease->address.len);
1785 ip->client->packet.flags = 0;
1787 memset(&ip->client->packet.ciaddr, 0,
1788 sizeof(ip->client->packet.ciaddr));
1789 ip->client->packet.flags = 0;
1792 memset(&ip->client->packet.yiaddr, 0,
1793 sizeof(ip->client->packet.yiaddr));
1794 memset(&ip->client->packet.siaddr, 0,
1795 sizeof(ip->client->packet.siaddr));
1796 memset(&ip->client->packet.giaddr, 0,
1797 sizeof(ip->client->packet.giaddr));
1798 memcpy(ip->client->packet.chaddr,
1799 ip->hw_address.haddr, ip->hw_address.hlen);
1803 make_decline(struct interface_info *ip, struct client_lease *lease)
1805 struct tree_cache *options[256], message_type_tree;
1806 struct tree_cache requested_address_tree;
1807 struct tree_cache server_id_tree, client_id_tree;
1808 unsigned char decline = DHCPDECLINE;
1811 memset(options, 0, sizeof(options));
1812 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1814 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1815 i = DHO_DHCP_MESSAGE_TYPE;
1816 options[i] = &message_type_tree;
1817 options[i]->value = &decline;
1818 options[i]->len = sizeof(decline);
1819 options[i]->buf_size = sizeof(decline);
1820 options[i]->timeout = 0xFFFFFFFF;
1822 /* Send back the server identifier... */
1823 i = DHO_DHCP_SERVER_IDENTIFIER;
1824 options[i] = &server_id_tree;
1825 options[i]->value = lease->options[i].data;
1826 options[i]->len = lease->options[i].len;
1827 options[i]->buf_size = lease->options[i].len;
1828 options[i]->timeout = 0xFFFFFFFF;
1830 /* Send back the address we're declining. */
1831 i = DHO_DHCP_REQUESTED_ADDRESS;
1832 options[i] = &requested_address_tree;
1833 options[i]->value = lease->address.iabuf;
1834 options[i]->len = lease->address.len;
1835 options[i]->buf_size = lease->address.len;
1836 options[i]->timeout = 0xFFFFFFFF;
1838 /* Send the uid if the user supplied one. */
1839 i = DHO_DHCP_CLIENT_IDENTIFIER;
1840 if (ip->client->config->send_options[i].len) {
1841 options[i] = &client_id_tree;
1842 options[i]->value = ip->client->config->send_options[i].data;
1843 options[i]->len = ip->client->config->send_options[i].len;
1844 options[i]->buf_size = ip->client->config->send_options[i].len;
1845 options[i]->timeout = 0xFFFFFFFF;
1849 /* Set up the option buffer... */
1850 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1851 options, 0, 0, 0, NULL, 0);
1852 if (ip->client->packet_length < BOOTP_MIN_LEN)
1853 ip->client->packet_length = BOOTP_MIN_LEN;
1855 ip->client->packet.op = BOOTREQUEST;
1856 ip->client->packet.htype = ip->hw_address.htype;
1857 ip->client->packet.hlen = ip->hw_address.hlen;
1858 ip->client->packet.hops = 0;
1859 ip->client->packet.xid = ip->client->xid;
1860 ip->client->packet.secs = 0; /* Filled in by send_request. */
1861 ip->client->packet.flags = 0;
1863 /* ciaddr must always be zero. */
1864 memset(&ip->client->packet.ciaddr, 0,
1865 sizeof(ip->client->packet.ciaddr));
1866 memset(&ip->client->packet.yiaddr, 0,
1867 sizeof(ip->client->packet.yiaddr));
1868 memset(&ip->client->packet.siaddr, 0,
1869 sizeof(ip->client->packet.siaddr));
1870 memset(&ip->client->packet.giaddr, 0,
1871 sizeof(ip->client->packet.giaddr));
1872 memcpy(ip->client->packet.chaddr,
1873 ip->hw_address.haddr, ip->hw_address.hlen);
1877 free_client_lease(struct client_lease *lease)
1881 if (lease->server_name)
1882 free(lease->server_name);
1883 if (lease->filename)
1884 free(lease->filename);
1885 for (i = 0; i < 256; i++) {
1886 if (lease->options[i].len)
1887 free(lease->options[i].data);
1895 rewrite_client_leases(void)
1897 struct client_lease *lp;
1898 cap_rights_t rights;
1901 leaseFile = fopen(path_dhclient_db, "w");
1903 error("can't create %s: %m", path_dhclient_db);
1904 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1905 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1906 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1908 error("can't limit lease descriptor: %m");
1910 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1912 error("can't limit lease descriptor fcntls: %m");
1919 for (lp = ifi->client->leases; lp; lp = lp->next)
1920 write_client_lease(ifi, lp, 1);
1921 if (ifi->client->active)
1922 write_client_lease(ifi, ifi->client->active, 1);
1925 ftruncate(fileno(leaseFile), ftello(leaseFile));
1926 fsync(fileno(leaseFile));
1930 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1933 static int leases_written;
1938 if (leases_written++ > 20) {
1939 rewrite_client_leases();
1944 /* If the lease came from the config file, we don't need to stash
1945 a copy in the lease database. */
1946 if (lease->is_static)
1949 if (!leaseFile) { /* XXX */
1950 leaseFile = fopen(path_dhclient_db, "w");
1952 error("can't create %s: %m", path_dhclient_db);
1955 fprintf(leaseFile, "lease {\n");
1956 if (lease->is_bootp)
1957 fprintf(leaseFile, " bootp;\n");
1958 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1959 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1960 if (lease->nextserver.len == sizeof(inaddr_any) &&
1961 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1962 sizeof(inaddr_any)))
1963 fprintf(leaseFile, " next-server %s;\n",
1964 piaddr(lease->nextserver));
1965 if (lease->filename)
1966 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1967 if (lease->server_name)
1968 fprintf(leaseFile, " server-name \"%s\";\n",
1969 lease->server_name);
1971 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1972 for (i = 0; i < 256; i++)
1973 if (lease->options[i].len)
1974 fprintf(leaseFile, " option %s %s;\n",
1975 dhcp_options[i].name,
1976 pretty_print_option(i, lease->options[i].data,
1977 lease->options[i].len, 1, 1));
1979 t = gmtime(&lease->renewal);
1980 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1981 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1982 t->tm_hour, t->tm_min, t->tm_sec);
1983 t = gmtime(&lease->rebind);
1984 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1985 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1986 t->tm_hour, t->tm_min, t->tm_sec);
1987 t = gmtime(&lease->expiry);
1988 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1989 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1990 t->tm_hour, t->tm_min, t->tm_sec);
1991 fprintf(leaseFile, "}\n");
1996 script_init(char *reason, struct string_list *medium)
1998 size_t len, mediumlen = 0;
1999 struct imsg_hdr hdr;
2003 if (medium != NULL && medium->string != NULL)
2004 mediumlen = strlen(medium->string);
2006 hdr.code = IMSG_SCRIPT_INIT;
2007 hdr.len = sizeof(struct imsg_hdr) +
2008 sizeof(size_t) + mediumlen +
2009 sizeof(size_t) + strlen(reason);
2011 if ((buf = buf_open(hdr.len)) == NULL)
2012 error("buf_open: %m");
2015 errs += buf_add(buf, &hdr, sizeof(hdr));
2016 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2018 errs += buf_add(buf, medium->string, mediumlen);
2019 len = strlen(reason);
2020 errs += buf_add(buf, &len, sizeof(len));
2021 errs += buf_add(buf, reason, len);
2024 error("buf_add: %m");
2026 if (buf_close(privfd, buf) == -1)
2027 error("buf_close: %m");
2031 priv_script_init(char *reason, char *medium)
2033 struct interface_info *ip = ifi;
2036 ip->client->scriptEnvsize = 100;
2037 if (ip->client->scriptEnv == NULL)
2038 ip->client->scriptEnv =
2039 malloc(ip->client->scriptEnvsize * sizeof(char *));
2040 if (ip->client->scriptEnv == NULL)
2041 error("script_init: no memory for environment");
2043 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2044 if (ip->client->scriptEnv[0] == NULL)
2045 error("script_init: no memory for environment");
2047 ip->client->scriptEnv[1] = NULL;
2049 script_set_env(ip->client, "", "interface", ip->name);
2052 script_set_env(ip->client, "", "medium", medium);
2054 script_set_env(ip->client, "", "reason", reason);
2059 priv_script_write_params(char *prefix, struct client_lease *lease)
2061 struct interface_info *ip = ifi;
2062 u_int8_t dbuf[1500], *dp = NULL;
2067 script_set_env(ip->client, prefix, "ip_address",
2068 piaddr(lease->address));
2070 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2072 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2073 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2075 dp = lease->options[DHO_SUBNET_MASK].data;
2076 len = lease->options[DHO_SUBNET_MASK].len;
2078 if (len && (len < sizeof(lease->address.iabuf))) {
2079 struct iaddr netmask, subnet, broadcast;
2081 memcpy(netmask.iabuf, dp, len);
2083 subnet = subnet_number(lease->address, netmask);
2085 script_set_env(ip->client, prefix, "network_number",
2087 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2088 broadcast = broadcast_addr(subnet, netmask);
2090 script_set_env(ip->client, prefix,
2091 "broadcast_address",
2097 if (lease->filename)
2098 script_set_env(ip->client, prefix, "filename", lease->filename);
2099 if (lease->server_name)
2100 script_set_env(ip->client, prefix, "server_name",
2101 lease->server_name);
2102 for (i = 0; i < 256; i++) {
2105 if (ip->client->config->defaults[i].len) {
2106 if (lease->options[i].len) {
2108 ip->client->config->default_actions[i]) {
2109 case ACTION_DEFAULT:
2110 dp = lease->options[i].data;
2111 len = lease->options[i].len;
2113 case ACTION_SUPERSEDE:
2116 config->defaults[i].data;
2118 config->defaults[i].len;
2120 case ACTION_PREPEND:
2122 config->defaults[i].len +
2123 lease->options[i].len;
2124 if (len >= sizeof(dbuf)) {
2125 warning("no space to %s %s",
2127 dhcp_options[i].name);
2133 config->defaults[i].data,
2135 config->defaults[i].len);
2136 memcpy(dp + ip->client->
2137 config->defaults[i].len,
2138 lease->options[i].data,
2139 lease->options[i].len);
2144 * When we append, we assume that we're
2145 * appending to text. Some MS servers
2146 * include a NUL byte at the end of
2147 * the search string provided.
2150 config->defaults[i].len +
2151 lease->options[i].len;
2152 if (len >= sizeof(dbuf)) {
2153 warning("no space to %s %s",
2155 dhcp_options[i].name);
2159 lease->options[i].data,
2160 lease->options[i].len);
2161 for (dp = dbuf + lease->options[i].len;
2162 dp > dbuf; dp--, len--)
2167 config->defaults[i].data,
2169 config->defaults[i].len);
2175 config->defaults[i].data;
2177 config->defaults[i].len;
2179 } else if (lease->options[i].len) {
2180 len = lease->options[i].len;
2181 dp = lease->options[i].data;
2188 if (dhcp_option_ev_name(name, sizeof(name),
2190 script_set_env(ip->client, prefix, name,
2191 pretty_print_option(i, dp, len, 0, 0));
2194 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2195 script_set_env(ip->client, prefix, "expiry", tbuf);
2199 script_write_params(char *prefix, struct client_lease *lease)
2201 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2202 struct imsg_hdr hdr;
2206 if (lease->filename != NULL)
2207 fn_len = strlen(lease->filename);
2208 if (lease->server_name != NULL)
2209 sn_len = strlen(lease->server_name);
2211 pr_len = strlen(prefix);
2213 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2214 hdr.len = sizeof(hdr) + sizeof(*lease) +
2215 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2216 sizeof(pr_len) + pr_len;
2218 for (i = 0; i < 256; i++) {
2219 hdr.len += sizeof(lease->options[i].len);
2220 hdr.len += lease->options[i].len;
2223 scripttime = time(NULL);
2225 if ((buf = buf_open(hdr.len)) == NULL)
2226 error("buf_open: %m");
2229 errs += buf_add(buf, &hdr, sizeof(hdr));
2230 errs += buf_add(buf, lease, sizeof(*lease));
2231 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2232 errs += buf_add(buf, lease->filename, fn_len);
2233 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2234 errs += buf_add(buf, lease->server_name, sn_len);
2235 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2236 errs += buf_add(buf, prefix, pr_len);
2238 for (i = 0; i < 256; i++) {
2239 errs += buf_add(buf, &lease->options[i].len,
2240 sizeof(lease->options[i].len));
2241 errs += buf_add(buf, lease->options[i].data,
2242 lease->options[i].len);
2246 error("buf_add: %m");
2248 if (buf_close(privfd, buf) == -1)
2249 error("buf_close: %m");
2255 struct imsg_hdr hdr;
2259 hdr.code = IMSG_SCRIPT_GO;
2260 hdr.len = sizeof(struct imsg_hdr);
2262 if ((buf = buf_open(hdr.len)) == NULL)
2263 error("buf_open: %m");
2265 if (buf_add(buf, &hdr, sizeof(hdr)))
2266 error("buf_add: %m");
2268 if (buf_close(privfd, buf) == -1)
2269 error("buf_close: %m");
2271 bzero(&hdr, sizeof(hdr));
2272 buf_read(privfd, &hdr, sizeof(hdr));
2273 if (hdr.code != IMSG_SCRIPT_GO_RET)
2274 error("unexpected msg type %u", hdr.code);
2275 if (hdr.len != sizeof(hdr) + sizeof(int))
2276 error("received corrupted message");
2277 buf_read(privfd, &ret, sizeof(ret));
2279 scripttime = time(NULL);
2285 priv_script_go(void)
2287 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2288 static char client_path[] = CLIENT_PATH;
2289 struct interface_info *ip = ifi;
2290 int pid, wpid, wstatus;
2292 scripttime = time(NULL);
2295 scriptName = ip->client->config->script_name;
2296 envp = ip->client->scriptEnv;
2298 scriptName = top_level_config.script_name;
2300 epp[1] = client_path;
2305 argv[0] = scriptName;
2314 wpid = wait(&wstatus);
2315 } while (wpid != pid && wpid > 0);
2321 execve(scriptName, argv, envp);
2322 error("execve (%s, ...): %m", scriptName);
2326 script_flush_env(ip->client);
2328 return (wstatus & 0xff);
2332 script_set_env(struct client_state *client, const char *prefix,
2333 const char *name, const char *value)
2338 /* No `` or $() command substitution allowed in environment values! */
2339 for (j=0; j < strlen(value); j++)
2343 warning("illegal character (%c) in value '%s'",
2345 /* Ignore this option */
2349 namelen = strlen(name);
2351 for (i = 0; client->scriptEnv[i]; i++)
2352 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2353 client->scriptEnv[i][namelen] == '=')
2356 if (client->scriptEnv[i])
2357 /* Reuse the slot. */
2358 free(client->scriptEnv[i]);
2360 /* New variable. Expand if necessary. */
2361 if (i >= client->scriptEnvsize - 1) {
2362 char **newscriptEnv;
2363 int newscriptEnvsize = client->scriptEnvsize + 50;
2365 newscriptEnv = realloc(client->scriptEnv,
2367 if (newscriptEnv == NULL) {
2368 free(client->scriptEnv);
2369 client->scriptEnv = NULL;
2370 client->scriptEnvsize = 0;
2371 error("script_set_env: no memory for variable");
2373 client->scriptEnv = newscriptEnv;
2374 client->scriptEnvsize = newscriptEnvsize;
2376 /* need to set the NULL pointer at end of array beyond
2378 client->scriptEnv[i + 1] = NULL;
2380 /* Allocate space and format the variable in the appropriate slot. */
2381 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2383 if (client->scriptEnv[i] == NULL)
2384 error("script_set_env: no memory for variable assignment");
2385 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2386 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2390 script_flush_env(struct client_state *client)
2394 for (i = 0; client->scriptEnv[i]; i++) {
2395 free(client->scriptEnv[i]);
2396 client->scriptEnv[i] = NULL;
2398 client->scriptEnvsize = 0;
2402 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2406 for (i = 0; option->name[i]; i++) {
2407 if (i + 1 == buflen)
2409 if (option->name[i] == '-')
2412 buf[i] = option->name[i];
2422 static int state = 0;
2423 cap_rights_t rights;
2425 if (no_daemon || state)
2430 /* Stop logging to stderr... */
2433 if (daemon(1, 1) == -1)
2436 cap_rights_init(&rights);
2438 if (pidfile != NULL) {
2439 pidfile_write(pidfile);
2440 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2442 error("can't limit pidfile descriptor: %m");
2446 /* we are chrooted, daemon(3) fails to open /dev/null */
2448 dup2(nullfd, STDIN_FILENO);
2449 dup2(nullfd, STDOUT_FILENO);
2450 dup2(nullfd, STDERR_FILENO);
2455 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2456 error("can't limit stdin: %m");
2457 cap_rights_init(&rights, CAP_WRITE);
2458 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2459 error("can't limit stdout: %m");
2460 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2461 error("can't limit stderr: %m");
2465 check_option(struct client_lease *l, int option)
2470 /* we use this, since this is what gets passed to dhclient-script */
2472 opbuf = pretty_print_option(option, l->options[option].data,
2473 l->options[option].len, 0, 0);
2475 sbuf = option_as_string(option, l->options[option].data,
2476 l->options[option].len);
2479 case DHO_SUBNET_MASK:
2480 case DHO_TIME_SERVERS:
2481 case DHO_NAME_SERVERS:
2483 case DHO_DOMAIN_NAME_SERVERS:
2484 case DHO_LOG_SERVERS:
2485 case DHO_COOKIE_SERVERS:
2486 case DHO_LPR_SERVERS:
2487 case DHO_IMPRESS_SERVERS:
2488 case DHO_RESOURCE_LOCATION_SERVERS:
2489 case DHO_SWAP_SERVER:
2490 case DHO_BROADCAST_ADDRESS:
2491 case DHO_NIS_SERVERS:
2492 case DHO_NTP_SERVERS:
2493 case DHO_NETBIOS_NAME_SERVERS:
2494 case DHO_NETBIOS_DD_SERVER:
2495 case DHO_FONT_SERVERS:
2496 case DHO_DHCP_SERVER_IDENTIFIER:
2497 case DHO_NISPLUS_SERVERS:
2498 case DHO_MOBILE_IP_HOME_AGENT:
2499 case DHO_SMTP_SERVER:
2500 case DHO_POP_SERVER:
2501 case DHO_NNTP_SERVER:
2502 case DHO_WWW_SERVER:
2503 case DHO_FINGER_SERVER:
2504 case DHO_IRC_SERVER:
2505 case DHO_STREETTALK_SERVER:
2506 case DHO_STREETTALK_DA_SERVER:
2507 if (!ipv4addrs(opbuf)) {
2508 warning("Invalid IP address in option: %s", opbuf);
2513 case DHO_NIS_DOMAIN:
2514 case DHO_NISPLUS_DOMAIN:
2515 case DHO_TFTP_SERVER_NAME:
2516 if (!res_hnok(sbuf)) {
2517 warning("Bogus Host Name option %d: %s (%s)", option,
2519 l->options[option].len = 0;
2520 free(l->options[option].data);
2523 case DHO_DOMAIN_NAME:
2524 case DHO_DOMAIN_SEARCH:
2525 if (!res_hnok(sbuf)) {
2526 if (!check_search(sbuf)) {
2527 warning("Bogus domain search list %d: %s (%s)",
2528 option, sbuf, opbuf);
2529 l->options[option].len = 0;
2530 free(l->options[option].data);
2535 case DHO_TIME_OFFSET:
2537 case DHO_MERIT_DUMP:
2539 case DHO_EXTENSIONS_PATH:
2540 case DHO_IP_FORWARDING:
2541 case DHO_NON_LOCAL_SOURCE_ROUTING:
2542 case DHO_POLICY_FILTER:
2543 case DHO_MAX_DGRAM_REASSEMBLY:
2544 case DHO_DEFAULT_IP_TTL:
2545 case DHO_PATH_MTU_AGING_TIMEOUT:
2546 case DHO_PATH_MTU_PLATEAU_TABLE:
2547 case DHO_INTERFACE_MTU:
2548 case DHO_ALL_SUBNETS_LOCAL:
2549 case DHO_PERFORM_MASK_DISCOVERY:
2550 case DHO_MASK_SUPPLIER:
2551 case DHO_ROUTER_DISCOVERY:
2552 case DHO_ROUTER_SOLICITATION_ADDRESS:
2553 case DHO_STATIC_ROUTES:
2554 case DHO_TRAILER_ENCAPSULATION:
2555 case DHO_ARP_CACHE_TIMEOUT:
2556 case DHO_IEEE802_3_ENCAPSULATION:
2557 case DHO_DEFAULT_TCP_TTL:
2558 case DHO_TCP_KEEPALIVE_INTERVAL:
2559 case DHO_TCP_KEEPALIVE_GARBAGE:
2560 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2561 case DHO_NETBIOS_NODE_TYPE:
2562 case DHO_NETBIOS_SCOPE:
2563 case DHO_X_DISPLAY_MANAGER:
2564 case DHO_DHCP_REQUESTED_ADDRESS:
2565 case DHO_DHCP_LEASE_TIME:
2566 case DHO_DHCP_OPTION_OVERLOAD:
2567 case DHO_DHCP_MESSAGE_TYPE:
2568 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2569 case DHO_DHCP_MESSAGE:
2570 case DHO_DHCP_MAX_MESSAGE_SIZE:
2571 case DHO_DHCP_RENEWAL_TIME:
2572 case DHO_DHCP_REBINDING_TIME:
2573 case DHO_DHCP_CLASS_IDENTIFIER:
2574 case DHO_DHCP_CLIENT_IDENTIFIER:
2575 case DHO_BOOTFILE_NAME:
2576 case DHO_DHCP_USER_CLASS_ID:
2579 case DHO_CLASSLESS_ROUTES:
2580 return (check_classless_option(l->options[option].data,
2581 l->options[option].len));
2583 warning("unknown dhcp option value 0x%x", option);
2584 return (unknown_ok);
2588 /* RFC 3442 The Classless Static Routes option checks */
2590 check_classless_option(unsigned char *data, int len)
2593 unsigned char width;
2594 in_addr_t addr, mask;
2597 warning("Too small length: %d", len);
2605 } else if (width < 9) {
2606 addr = (in_addr_t)(data[i] << 24);
2608 } else if (width < 17) {
2609 addr = (in_addr_t)(data[i] << 24) +
2610 (in_addr_t)(data[i + 1] << 16);
2612 } else if (width < 25) {
2613 addr = (in_addr_t)(data[i] << 24) +
2614 (in_addr_t)(data[i + 1] << 16) +
2615 (in_addr_t)(data[i + 2] << 8);
2617 } else if (width < 33) {
2618 addr = (in_addr_t)(data[i] << 24) +
2619 (in_addr_t)(data[i + 1] << 16) +
2620 (in_addr_t)(data[i + 2] << 8) +
2624 warning("Incorrect subnet width: %d", width);
2627 mask = (in_addr_t)(~0) << (32 - width);
2633 * ... After deriving a subnet number and subnet mask
2634 * from each destination descriptor, the DHCP client
2635 * MUST zero any bits in the subnet number where the
2636 * corresponding bit in the mask is zero...
2638 if ((addr & mask) != addr) {
2640 data[i - 1] = (unsigned char)(
2641 (addr >> (((32 - width)/8)*8)) & 0xFF);
2646 warning("Incorrect data length: %d (must be %d)", len, i);
2653 res_hnok(const char *dn)
2655 int pch = PERIOD, ch = *dn++;
2657 while (ch != '\0') {
2660 if (periodchar(ch)) {
2662 } else if (periodchar(pch)) {
2663 if (!borderchar(ch))
2665 } else if (periodchar(nch) || nch == '\0') {
2666 if (!borderchar(ch))
2669 if (!middlechar(ch))
2678 check_search(const char *srch)
2680 int pch = PERIOD, ch = *srch++;
2683 /* 256 char limit re resolv.conf(5) */
2684 if (strlen(srch) > 256)
2687 while (whitechar(ch))
2690 while (ch != '\0') {
2693 if (periodchar(ch) || whitechar(ch)) {
2695 } else if (periodchar(pch)) {
2696 if (!borderchar(ch))
2698 } else if (periodchar(nch) || nch == '\0') {
2699 if (!borderchar(ch))
2702 if (!middlechar(ch))
2705 if (!whitechar(ch)) {
2708 while (whitechar(nch)) {
2717 /* 6 domain limit re resolv.conf(5) */
2723 /* Does buf consist only of dotted decimal ipv4 addrs?
2724 * return how many if so,
2725 * otherwise, return 0
2728 ipv4addrs(char * buf)
2733 while (inet_aton(buf, &jnk) == 1){
2735 while (periodchar(*buf) || digitchar(*buf))
2747 option_as_string(unsigned int code, unsigned char *data, int len)
2749 static char optbuf[32768]; /* XXX */
2751 int opleft = sizeof(optbuf);
2752 unsigned char *dp = data;
2755 error("option_as_string: bad code %d", code);
2757 for (; dp < data + len; dp++) {
2758 if (!isascii(*dp) || !isprint(*dp)) {
2759 if (dp + 1 != data + len || *dp != 0) {
2760 snprintf(op, opleft, "\\%03o", *dp);
2764 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2765 *dp == '`' || *dp == '\\') {
2779 warning("dhcp option too large");
2784 fork_privchld(int fd, int fd2)
2786 struct pollfd pfd[1];
2791 error("cannot fork");
2798 setproctitle("%s [priv]", ifi->name);
2801 dup2(nullfd, STDIN_FILENO);
2802 dup2(nullfd, STDOUT_FILENO);
2803 dup2(nullfd, STDERR_FILENO);
2811 pfd[0].events = POLLIN;
2812 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2814 error("poll error");
2816 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2819 dispatch_imsg(ifi, fd);