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 const 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(const char * buf);
135 int res_hnok(const char *dn);
136 int check_search(const char *srch);
137 const 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_",
215 _ifi->client->alias);
218 _ifi->client->state = S_INIT;
222 routehandler(struct protocol *p __unused)
224 char msg[2048], *addr;
225 struct rt_msghdr *rtm;
226 struct if_msghdr *ifm;
227 struct ifa_msghdr *ifam;
228 struct if_announcemsghdr *ifan;
229 struct ieee80211_join_event *jev;
230 struct client_lease *l;
231 time_t t = time(NULL);
232 struct sockaddr_in *sa;
237 n = read(routefd, &msg, sizeof(msg));
238 rtm = (struct rt_msghdr *)msg;
239 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
240 n < (ssize_t)rtm->rtm_msglen ||
241 rtm->rtm_version != RTM_VERSION)
244 switch (rtm->rtm_type) {
247 ifam = (struct ifa_msghdr *)rtm;
249 if (ifam->ifam_index != ifi->index)
251 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
253 if (scripttime == 0 || t < scripttime + 10)
256 sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
260 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
261 error("king bula sez: len mismatch");
262 memcpy(a.iabuf, &sa->sin_addr, a.len);
263 if (addr_eq(a, defaddr))
266 for (l = ifi->client->active; l != NULL; l = l->next)
267 if (addr_eq(a, l->address))
270 if (l == NULL) /* added/deleted addr is not the one we set */
273 addr = inet_ntoa(sa->sin_addr);
274 if (rtm->rtm_type == RTM_NEWADDR) {
276 * XXX: If someone other than us adds our address,
277 * should we assume they are taking over from us,
278 * delete the lease record, and exit without modifying
281 warning("My address (%s) was re-added", addr);
283 warning("My address (%s) was deleted, dhclient exiting",
289 ifm = (struct if_msghdr *)rtm;
290 if (ifm->ifm_index != ifi->index)
292 if ((rtm->rtm_flags & RTF_UP) == 0) {
293 warning("Interface %s is down, dhclient exiting",
297 linkstat = interface_link_status(ifi->name);
298 if (linkstat != ifi->linkstat) {
299 debug("%s link state %s -> %s", ifi->name,
300 ifi->linkstat ? "up" : "down",
301 linkstat ? "up" : "down");
302 ifi->linkstat = linkstat;
308 ifan = (struct if_announcemsghdr *)rtm;
309 if (ifan->ifan_what == IFAN_DEPARTURE &&
310 ifan->ifan_index == ifi->index) {
311 warning("Interface %s is gone, dhclient exiting",
317 ifan = (struct if_announcemsghdr *)rtm;
318 if (ifan->ifan_index != ifi->index)
320 switch (ifan->ifan_what) {
321 case RTM_IEEE80211_ASSOC:
322 case RTM_IEEE80211_REASSOC:
324 * Use assoc/reassoc event to kick state machine
325 * in case we roam. Otherwise fall back to the
326 * normal state machine just like a wired network.
328 jev = (struct ieee80211_join_event *) &ifan[1];
329 if (memcmp(curbssid, jev->iev_addr, 6)) {
333 memcpy(curbssid, jev->iev_addr, 6);
343 script_init("FAIL", NULL);
344 if (ifi->client->alias)
345 script_write_params("alias_", ifi->client->alias);
348 pidfile_remove(pidfile);
355 cap_channel_t *casper;
359 error("unable to start casper");
361 capsyslog = cap_service_open(casper, "system.syslog");
363 if (capsyslog == NULL)
364 error("unable to open system.syslog service");
368 main(int argc, char *argv[])
370 extern char *__progname;
371 int ch, fd, quiet = 0, i = 0;
373 int immediate_daemon = 0;
380 /* Initially, log errors to stderr as well as to syslogd. */
381 cap_openlog(capsyslog, __progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
382 cap_setlogmask(capsyslog, LOG_UPTO(LOG_DEBUG));
384 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
387 immediate_daemon = 1;
390 path_dhclient_conf = optarg;
396 path_dhclient_db = optarg;
399 path_dhclient_pidfile = optarg;
417 if (path_dhclient_pidfile == NULL) {
418 asprintf(&path_dhclient_pidfile,
419 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
420 if (path_dhclient_pidfile == NULL)
423 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
424 if (pidfile == NULL) {
426 error("dhclient already running, pid: %d.", otherpid);
428 error("dhclient already running.");
429 warning("Cannot open or create pidfile: %m");
432 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
434 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
435 error("Interface name too long");
436 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
437 _PATH_DHCLIENT_DB, ifi->name) == -1)
446 inaddr_broadcast.s_addr = INADDR_BROADCAST;
447 inaddr_any.s_addr = INADDR_ANY;
451 /* The next bit is potentially very time-consuming, so write out
452 the pidfile right away. We will write it out again with the
453 correct pid after daemonizing. */
455 pidfile_write(pidfile);
457 if (!interface_link_status(ifi->name)) {
458 fprintf(stderr, "%s: no link ...", ifi->name);
461 while (!interface_link_status(ifi->name)) {
462 fprintf(stderr, ".");
465 fprintf(stderr, " giving up\n");
470 fprintf(stderr, " got link\n");
474 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
475 error("cannot open %s: %m", _PATH_DEVNULL);
477 if ((pw = getpwnam("_dhcp")) == NULL) {
478 warning("no such user: _dhcp, falling back to \"nobody\"");
479 if ((pw = getpwnam("nobody")) == NULL)
480 error("no such user: nobody");
484 * Obtain hostname before entering capability mode - it won't be
485 * possible then, as reading kern.hostname is not permitted.
487 if (gethostname(hostname, sizeof(hostname)) < 0)
490 priv_script_init("PREINIT", NULL);
491 if (ifi->client->alias)
492 priv_script_write_params("alias_", ifi->client->alias);
495 /* set up the interface */
496 discover_interfaces(ifi);
498 if (pipe(pipe_fd) == -1)
501 fork_privchld(pipe_fd[0], pipe_fd[1]);
510 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
511 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
512 error("can't limit private descriptor: %m");
514 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
515 error("can't open and lock %s: %m", path_dhclient_db);
516 read_client_leases();
517 rewrite_client_leases();
520 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
521 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
522 if (shutdown(routefd, SHUT_WR) < 0)
523 error("can't shutdown route socket: %m");
524 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
525 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
526 error("can't limit route socket: %m");
528 if (chroot(_PATH_VAREMPTY) == -1)
530 if (chdir("/") == -1)
531 error("chdir(\"/\")");
533 if (setgroups(1, &pw->pw_gid) ||
534 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
535 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
536 error("can't drop privileges: %m");
540 setproctitle("%s", ifi->name);
542 if (CASPER_SUPPORT && cap_enter() < 0 && errno != ENOSYS)
543 error("can't enter capability mode: %m");
545 if (immediate_daemon)
548 ifi->client->state = S_INIT;
551 bootp_packet_handler = do_packet;
562 extern char *__progname;
564 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
565 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
572 * Each routine is called from the dhclient_state_machine() in one of
574 * -> entering INIT state
575 * -> recvpacket_flag == 0: timeout in this state
576 * -> otherwise: received a packet in this state
578 * Return conditions as handled by dhclient_state_machine():
579 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
580 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
581 * Returns 0: finish the nap which was interrupted for no good reason.
583 * Several per-interface variables are used to keep track of the process:
584 * active_lease: the lease that is being used on the interface
585 * (null pointer if not configured yet).
586 * offered_leases: leases corresponding to DHCPOFFER messages that have
587 * been sent to us by DHCP servers.
588 * acked_leases: leases corresponding to DHCPACK messages that have been
589 * sent to us by DHCP servers.
590 * sendpacket: DHCP packet we're trying to send.
591 * destination: IP address to send sendpacket to
592 * In addition, there are several relevant per-lease variables.
593 * T1_expiry, T2_expiry, lease_expiry: lease milestones
594 * In the active lease, these control the process of renewing the lease;
595 * In leases on the acked_leases list, this simply determines when we
596 * can no longer legitimately use the lease.
600 state_reboot(void *ipp)
602 struct interface_info *ip = ipp;
604 /* If we don't remember an active lease, go straight to INIT. */
605 if (!ip->client->active || ip->client->active->is_bootp) {
610 /* We are in the rebooting state. */
611 ip->client->state = S_REBOOTING;
613 /* make_request doesn't initialize xid because it normally comes
614 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
615 so pick an xid now. */
616 ip->client->xid = arc4random();
618 /* Make a DHCPREQUEST packet, and set appropriate per-interface
620 make_request(ip, ip->client->active);
621 ip->client->destination = iaddr_broadcast;
622 ip->client->first_sending = cur_time;
623 ip->client->interval = ip->client->config->initial_interval;
625 /* Zap the medium list... */
626 ip->client->medium = NULL;
628 /* Send out the first DHCPREQUEST packet. */
633 * Called when a lease has completely expired and we've
634 * been unable to renew it.
637 state_init(void *ipp)
639 struct interface_info *ip = ipp;
641 ASSERT_STATE(state, S_INIT);
643 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
645 make_discover(ip, ip->client->active);
646 ip->client->xid = ip->client->packet.xid;
647 ip->client->destination = iaddr_broadcast;
648 ip->client->state = S_SELECTING;
649 ip->client->first_sending = cur_time;
650 ip->client->interval = ip->client->config->initial_interval;
652 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
658 * state_selecting is called when one or more DHCPOFFER packets
659 * have been received and a configurable period of time has passed.
662 state_selecting(void *ipp)
664 struct interface_info *ip = ipp;
665 struct client_lease *lp, *next, *picked;
667 ASSERT_STATE(state, S_SELECTING);
669 /* Cancel state_selecting and send_discover timeouts, since either
670 one could have got us here. */
671 cancel_timeout(state_selecting, ip);
672 cancel_timeout(send_discover, ip);
674 /* We have received one or more DHCPOFFER packets. Currently,
675 the only criterion by which we judge leases is whether or
676 not we get a response when we arp for them. */
678 for (lp = ip->client->offered_leases; lp; lp = next) {
681 /* Check to see if we got an ARPREPLY for the address
682 in this particular lease. */
684 script_init("ARPCHECK", lp->medium);
685 script_write_params("check_", lp);
687 /* If the ARPCHECK code detects another
688 machine using the offered address, it exits
689 nonzero. We need to send a DHCPDECLINE and
692 make_decline(ip, lp);
700 free_client_lease(lp);
703 ip->client->offered_leases = NULL;
705 /* If we just tossed all the leases we were offered, go back
708 ip->client->state = S_INIT;
713 /* If it was a BOOTREPLY, we can just take the address right now. */
714 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
715 ip->client->new = picked;
717 /* Make up some lease expiry times
718 XXX these should be configurable. */
719 ip->client->new->expiry = cur_time + 12000;
720 ip->client->new->renewal += cur_time + 8000;
721 ip->client->new->rebind += cur_time + 10000;
723 ip->client->state = S_REQUESTING;
725 /* Bind to the address we received. */
730 /* Go to the REQUESTING state. */
731 ip->client->destination = iaddr_broadcast;
732 ip->client->state = S_REQUESTING;
733 ip->client->first_sending = cur_time;
734 ip->client->interval = ip->client->config->initial_interval;
736 /* Make a DHCPREQUEST packet from the lease we picked. */
737 make_request(ip, picked);
738 ip->client->xid = ip->client->packet.xid;
740 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
741 free_client_lease(picked);
743 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
747 /* state_requesting is called when we receive a DHCPACK message after
748 having sent out one or more DHCPREQUEST packets. */
751 dhcpack(struct packet *packet)
753 struct interface_info *ip = packet->interface;
754 struct client_lease *lease;
756 /* If we're not receptive to an offer right now, or if the offer
757 has an unrecognizable transaction id, then just drop it. */
758 if (packet->interface->client->xid != packet->raw->xid ||
759 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
760 (memcmp(packet->interface->hw_address.haddr,
761 packet->raw->chaddr, packet->raw->hlen)))
764 if (ip->client->state != S_REBOOTING &&
765 ip->client->state != S_REQUESTING &&
766 ip->client->state != S_RENEWING &&
767 ip->client->state != S_REBINDING)
770 note("DHCPACK from %s", piaddr(packet->client_addr));
772 lease = packet_to_lease(packet);
774 note("packet_to_lease failed.");
778 ip->client->new = lease;
780 /* Stop resending DHCPREQUEST. */
781 cancel_timeout(send_request, ip);
783 /* Figure out the lease time. */
784 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
786 ip->client->new->expiry = getULong(
787 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
788 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
789 ip->client->new->expiry = getULong(
790 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
792 ip->client->new->expiry = default_lease_time;
793 /* A number that looks negative here is really just very large,
794 because the lease expiry offset is unsigned. Also make sure that
795 the addition of cur_time below does not overflow (a 32 bit) time_t. */
796 if (ip->client->new->expiry < 0 ||
797 ip->client->new->expiry > TIME_MAX - cur_time)
798 ip->client->new->expiry = TIME_MAX - cur_time;
799 /* XXX should be fixed by resetting the client state */
800 if (ip->client->new->expiry < 60)
801 ip->client->new->expiry = 60;
803 /* Unless overridden in the config, take the server-provided renewal
804 * time if there is one. Otherwise figure it out according to the spec.
805 * Also make sure the renewal time does not exceed the expiry time.
807 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
809 ip->client->new->renewal = getULong(
810 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
811 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
812 ip->client->new->renewal = getULong(
813 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
815 ip->client->new->renewal = ip->client->new->expiry / 2;
816 if (ip->client->new->renewal < 0 ||
817 ip->client->new->renewal > ip->client->new->expiry / 2)
818 ip->client->new->renewal = ip->client->new->expiry / 2;
820 /* Same deal with the rebind time. */
821 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
823 ip->client->new->rebind = getULong(
824 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
825 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
826 ip->client->new->rebind = getULong(
827 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
829 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
830 if (ip->client->new->rebind < 0 ||
831 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
832 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
834 /* Convert the time offsets into seconds-since-the-epoch */
835 ip->client->new->expiry += cur_time;
836 ip->client->new->renewal += cur_time;
837 ip->client->new->rebind += cur_time;
843 bind_lease(struct interface_info *ip)
845 struct option_data *opt;
847 /* Remember the medium. */
848 ip->client->new->medium = ip->client->medium;
850 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
851 if (opt->len == sizeof(u_int16_t)) {
852 u_int16_t mtu = be16dec(opt->data);
854 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
856 interface_set_mtu_unpriv(privfd, mtu);
859 /* Write out the new lease. */
860 write_client_lease(ip, ip->client->new, 0);
862 /* Run the client script with the new parameters. */
863 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
864 (ip->client->state == S_RENEWING ? "RENEW" :
865 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
866 ip->client->new->medium);
867 if (ip->client->active && ip->client->state != S_REBOOTING)
868 script_write_params("old_", ip->client->active);
869 script_write_params("new_", ip->client->new);
870 if (ip->client->alias)
871 script_write_params("alias_", ip->client->alias);
874 /* Replace the old active lease with the new one. */
875 if (ip->client->active)
876 free_client_lease(ip->client->active);
877 ip->client->active = ip->client->new;
878 ip->client->new = NULL;
880 /* Set up a timeout to start the renewal process. */
881 add_timeout(ip->client->active->renewal, state_bound, ip);
883 note("bound to %s -- renewal in %d seconds.",
884 piaddr(ip->client->active->address),
885 (int)(ip->client->active->renewal - cur_time));
886 ip->client->state = S_BOUND;
887 reinitialize_interfaces();
892 * state_bound is called when we've successfully bound to a particular
893 * lease, but the renewal time on that lease has expired. We are
894 * expected to unicast a DHCPREQUEST to the server that gave us our
898 state_bound(void *ipp)
900 struct interface_info *ip = ipp;
902 ASSERT_STATE(state, S_BOUND);
904 /* T1 has expired. */
905 make_request(ip, ip->client->active);
906 ip->client->xid = ip->client->packet.xid;
908 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
909 memcpy(ip->client->destination.iabuf, ip->client->active->
910 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
911 ip->client->destination.len = 4;
913 ip->client->destination = iaddr_broadcast;
915 ip->client->first_sending = cur_time;
916 ip->client->interval = ip->client->config->initial_interval;
917 ip->client->state = S_RENEWING;
919 /* Send the first packet immediately. */
924 bootp(struct packet *packet)
926 struct iaddrlist *ap;
928 if (packet->raw->op != BOOTREPLY)
931 /* If there's a reject list, make sure this packet's sender isn't
933 for (ap = packet->interface->client->config->reject_list;
935 if (addr_eq(packet->client_addr, ap->addr)) {
936 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
944 dhcp(struct packet *packet)
946 struct iaddrlist *ap;
947 void (*handler)(struct packet *);
950 switch (packet->packet_type) {
967 /* If there's a reject list, make sure this packet's sender isn't
969 for (ap = packet->interface->client->config->reject_list;
971 if (addr_eq(packet->client_addr, ap->addr)) {
972 note("%s from %s rejected.", type, piaddr(ap->addr));
980 dhcpoffer(struct packet *packet)
982 struct interface_info *ip = packet->interface;
983 struct client_lease *lease, *lp;
985 int arp_timeout_needed, stop_selecting;
986 const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
987 "DHCPOFFER" : "BOOTREPLY";
989 /* If we're not receptive to an offer right now, or if the offer
990 has an unrecognizable transaction id, then just drop it. */
991 if (ip->client->state != S_SELECTING ||
992 packet->interface->client->xid != packet->raw->xid ||
993 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
994 (memcmp(packet->interface->hw_address.haddr,
995 packet->raw->chaddr, packet->raw->hlen)))
998 note("%s from %s", name, piaddr(packet->client_addr));
1001 /* If this lease doesn't supply the minimum required parameters,
1003 for (i = 0; ip->client->config->required_options[i]; i++) {
1004 if (!packet->options[ip->client->config->
1005 required_options[i]].len) {
1006 note("%s isn't satisfactory.", name);
1011 /* If we've already seen this lease, don't record it again. */
1012 for (lease = ip->client->offered_leases;
1013 lease; lease = lease->next) {
1014 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1015 !memcmp(lease->address.iabuf,
1016 &packet->raw->yiaddr, lease->address.len)) {
1017 debug("%s already seen.", name);
1022 lease = packet_to_lease(packet);
1024 note("packet_to_lease failed.");
1028 /* If this lease was acquired through a BOOTREPLY, record that
1030 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1031 lease->is_bootp = 1;
1033 /* Record the medium under which this lease was offered. */
1034 lease->medium = ip->client->medium;
1036 /* Send out an ARP Request for the offered IP address. */
1037 script_init("ARPSEND", lease->medium);
1038 script_write_params("check_", lease);
1039 /* If the script can't send an ARP request without waiting,
1040 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1042 arp_timeout_needed = 0;
1044 arp_timeout_needed = 2;
1046 /* Figure out when we're supposed to stop selecting. */
1048 ip->client->first_sending + ip->client->config->select_interval;
1050 /* If this is the lease we asked for, put it at the head of the
1051 list, and don't mess with the arp request timeout. */
1052 if (lease->address.len == ip->client->requested_address.len &&
1053 !memcmp(lease->address.iabuf,
1054 ip->client->requested_address.iabuf,
1055 ip->client->requested_address.len)) {
1056 lease->next = ip->client->offered_leases;
1057 ip->client->offered_leases = lease;
1059 /* If we already have an offer, and arping for this
1060 offer would take us past the selection timeout,
1061 then don't extend the timeout - just hope for the
1063 if (ip->client->offered_leases &&
1064 (cur_time + arp_timeout_needed) > stop_selecting)
1065 arp_timeout_needed = 0;
1067 /* Put the lease at the end of the list. */
1069 if (!ip->client->offered_leases)
1070 ip->client->offered_leases = lease;
1072 for (lp = ip->client->offered_leases; lp->next;
1079 /* If we're supposed to stop selecting before we've had time
1080 to wait for the ARPREPLY, add some delay to wait for
1082 if (stop_selecting - cur_time < arp_timeout_needed)
1083 stop_selecting = cur_time + arp_timeout_needed;
1085 /* If the selecting interval has expired, go immediately to
1086 state_selecting(). Otherwise, time out into
1087 state_selecting at the select interval. */
1088 if (stop_selecting <= 0)
1089 state_selecting(ip);
1091 add_timeout(stop_selecting, state_selecting, ip);
1092 cancel_timeout(send_discover, ip);
1096 /* Allocate a client_lease structure and initialize it from the parameters
1097 in the specified packet. */
1099 struct client_lease *
1100 packet_to_lease(struct packet *packet)
1102 struct client_lease *lease;
1105 lease = malloc(sizeof(struct client_lease));
1108 warning("dhcpoffer: no memory to record lease.");
1112 memset(lease, 0, sizeof(*lease));
1114 /* Copy the lease options. */
1115 for (i = 0; i < 256; i++) {
1116 if (packet->options[i].len) {
1117 lease->options[i].data =
1118 malloc(packet->options[i].len + 1);
1119 if (!lease->options[i].data) {
1120 warning("dhcpoffer: no memory for option %d", i);
1121 free_client_lease(lease);
1124 memcpy(lease->options[i].data,
1125 packet->options[i].data,
1126 packet->options[i].len);
1127 lease->options[i].len =
1128 packet->options[i].len;
1129 lease->options[i].data[lease->options[i].len] =
1132 if (!check_option(lease,i)) {
1133 /* ignore a bogus lease offer */
1134 warning("Invalid lease option - ignoring offer");
1135 free_client_lease(lease);
1141 lease->address.len = sizeof(packet->raw->yiaddr);
1142 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1144 lease->nextserver.len = sizeof(packet->raw->siaddr);
1145 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1147 /* If the server name was filled out, copy it.
1148 Do not attempt to validate the server name as a host name.
1149 RFC 2131 merely states that sname is NUL-terminated (which do
1150 do not assume) and that it is the server's host name. Since
1151 the ISC client and server allow arbitrary characters, we do
1153 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1154 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1155 packet->raw->sname[0]) {
1156 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1157 if (!lease->server_name) {
1158 warning("dhcpoffer: no memory for server name.");
1159 free_client_lease(lease);
1162 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1163 lease->server_name[DHCP_SNAME_LEN]='\0';
1166 /* Ditto for the filename. */
1167 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1168 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1169 packet->raw->file[0]) {
1170 /* Don't count on the NUL terminator. */
1171 lease->filename = malloc(DHCP_FILE_LEN + 1);
1172 if (!lease->filename) {
1173 warning("dhcpoffer: no memory for filename.");
1174 free_client_lease(lease);
1177 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1178 lease->filename[DHCP_FILE_LEN]='\0';
1184 dhcpnak(struct packet *packet)
1186 struct interface_info *ip = packet->interface;
1188 /* If we're not receptive to an offer right now, or if the offer
1189 has an unrecognizable transaction id, then just drop it. */
1190 if (packet->interface->client->xid != packet->raw->xid ||
1191 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1192 (memcmp(packet->interface->hw_address.haddr,
1193 packet->raw->chaddr, packet->raw->hlen)))
1196 if (ip->client->state != S_REBOOTING &&
1197 ip->client->state != S_REQUESTING &&
1198 ip->client->state != S_RENEWING &&
1199 ip->client->state != S_REBINDING)
1202 note("DHCPNAK from %s", piaddr(packet->client_addr));
1204 if (!ip->client->active) {
1205 note("DHCPNAK with no active lease.\n");
1209 free_client_lease(ip->client->active);
1210 ip->client->active = NULL;
1212 /* Stop sending DHCPREQUEST packets... */
1213 cancel_timeout(send_request, ip);
1215 ip->client->state = S_INIT;
1219 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1220 one after the right interval has expired. If we don't get an offer by
1221 the time we reach the panic interval, call the panic function. */
1224 send_discover(void *ipp)
1226 struct interface_info *ip = ipp;
1227 int interval, increase = 1;
1229 /* Figure out how long it's been since we started transmitting. */
1230 interval = cur_time - ip->client->first_sending;
1232 /* If we're past the panic timeout, call the script and tell it
1233 we haven't found anything for this interface yet. */
1234 if (interval > ip->client->config->timeout) {
1239 /* If we're selecting media, try the whole list before doing
1240 the exponential backoff, but if we've already received an
1241 offer, stop looping, because we obviously have it right. */
1242 if (!ip->client->offered_leases &&
1243 ip->client->config->media) {
1246 if (ip->client->medium) {
1247 ip->client->medium = ip->client->medium->next;
1250 if (!ip->client->medium) {
1252 error("No valid media types for %s!", ip->name);
1253 ip->client->medium = ip->client->config->media;
1257 note("Trying medium \"%s\" %d", ip->client->medium->string,
1259 script_init("MEDIUM", ip->client->medium);
1265 * If we're supposed to increase the interval, do so. If it's
1266 * currently zero (i.e., we haven't sent any packets yet), set
1267 * it to one; otherwise, add to it a random number between zero
1268 * and two times itself. On average, this means that it will
1269 * double with every transmission.
1272 if (!ip->client->interval)
1273 ip->client->interval =
1274 ip->client->config->initial_interval;
1276 ip->client->interval += (arc4random() >> 2) %
1277 (2 * ip->client->interval);
1280 /* Don't backoff past cutoff. */
1281 if (ip->client->interval >
1282 ip->client->config->backoff_cutoff)
1283 ip->client->interval =
1284 ((ip->client->config->backoff_cutoff / 2)
1285 + ((arc4random() >> 2) %
1286 ip->client->config->backoff_cutoff));
1287 } else if (!ip->client->interval)
1288 ip->client->interval =
1289 ip->client->config->initial_interval;
1291 /* If the backoff would take us to the panic timeout, just use that
1293 if (cur_time + ip->client->interval >
1294 ip->client->first_sending + ip->client->config->timeout)
1295 ip->client->interval =
1296 (ip->client->first_sending +
1297 ip->client->config->timeout) - cur_time + 1;
1299 /* Record the number of seconds since we started sending. */
1300 if (interval < 65536)
1301 ip->client->packet.secs = htons(interval);
1303 ip->client->packet.secs = htons(65535);
1304 ip->client->secs = ip->client->packet.secs;
1306 note("DHCPDISCOVER on %s to %s port %d interval %d",
1307 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1308 (int)ip->client->interval);
1310 /* Send out a packet. */
1311 send_packet_unpriv(privfd, &ip->client->packet,
1312 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1314 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1318 * state_panic gets called if we haven't received any offers in a preset
1319 * amount of time. When this happens, we try to use existing leases
1320 * that haven't yet expired, and failing that, we call the client script
1321 * and hope it can do something.
1324 state_panic(void *ipp)
1326 struct interface_info *ip = ipp;
1327 struct client_lease *loop = ip->client->active;
1328 struct client_lease *lp;
1330 note("No DHCPOFFERS received.");
1332 /* We may not have an active lease, but we may have some
1333 predefined leases that we can try. */
1334 if (!ip->client->active && ip->client->leases)
1337 /* Run through the list of leases and see if one can be used. */
1338 while (ip->client->active) {
1339 if (ip->client->active->expiry > cur_time) {
1340 note("Trying recorded lease %s",
1341 piaddr(ip->client->active->address));
1342 /* Run the client script with the existing
1344 script_init("TIMEOUT",
1345 ip->client->active->medium);
1346 script_write_params("new_", ip->client->active);
1347 if (ip->client->alias)
1348 script_write_params("alias_",
1351 /* If the old lease is still good and doesn't
1352 yet need renewal, go into BOUND state and
1353 timeout at the renewal time. */
1356 ip->client->active->renewal) {
1357 ip->client->state = S_BOUND;
1358 note("bound: renewal in %d seconds.",
1359 (int)(ip->client->active->renewal -
1362 ip->client->active->renewal,
1365 ip->client->state = S_BOUND;
1366 note("bound: immediate renewal.");
1369 reinitialize_interfaces();
1375 /* If there are no other leases, give up. */
1376 if (!ip->client->leases) {
1377 ip->client->leases = ip->client->active;
1378 ip->client->active = NULL;
1383 /* Otherwise, put the active lease at the end of the
1384 lease list, and try another lease.. */
1385 for (lp = ip->client->leases; lp->next; lp = lp->next)
1387 lp->next = ip->client->active;
1389 lp->next->next = NULL;
1390 ip->client->active = ip->client->leases;
1391 ip->client->leases = ip->client->leases->next;
1393 /* If we already tried this lease, we've exhausted the
1394 set of leases, so we might as well give up for
1396 if (ip->client->active == loop)
1399 loop = ip->client->active;
1402 /* No leases were available, or what was available didn't work, so
1403 tell the shell script that we failed to allocate an address,
1404 and try again later. */
1405 note("No working leases in persistent database - sleeping.\n");
1406 script_init("FAIL", NULL);
1407 if (ip->client->alias)
1408 script_write_params("alias_", ip->client->alias);
1410 ip->client->state = S_INIT;
1411 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1417 send_request(void *ipp)
1419 struct interface_info *ip = ipp;
1420 struct in_addr from, to;
1423 /* Figure out how long it's been since we started transmitting. */
1424 interval = cur_time - ip->client->first_sending;
1426 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1427 past the reboot timeout, go to INIT and see if we can
1428 DISCOVER an address... */
1429 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1430 means either that we're on a network with no DHCP server,
1431 or that our server is down. In the latter case, assuming
1432 that there is a backup DHCP server, DHCPDISCOVER will get
1433 us a new address, but we could also have successfully
1434 reused our old address. In the former case, we're hosed
1435 anyway. This is not a win-prone situation. */
1436 if ((ip->client->state == S_REBOOTING ||
1437 ip->client->state == S_REQUESTING) &&
1438 interval > ip->client->config->reboot_timeout) {
1440 ip->client->state = S_INIT;
1441 cancel_timeout(send_request, ip);
1446 /* If we're in the reboot state, make sure the media is set up
1448 if (ip->client->state == S_REBOOTING &&
1449 !ip->client->medium &&
1450 ip->client->active->medium ) {
1451 script_init("MEDIUM", ip->client->active->medium);
1453 /* If the medium we chose won't fly, go to INIT state. */
1457 /* Record the medium. */
1458 ip->client->medium = ip->client->active->medium;
1461 /* If the lease has expired, relinquish the address and go back
1462 to the INIT state. */
1463 if (ip->client->state != S_REQUESTING &&
1464 cur_time > ip->client->active->expiry) {
1465 /* Run the client script with the new parameters. */
1466 script_init("EXPIRE", NULL);
1467 script_write_params("old_", ip->client->active);
1468 if (ip->client->alias)
1469 script_write_params("alias_", ip->client->alias);
1472 /* Now do a preinit on the interface so that we can
1473 discover a new address. */
1474 script_init("PREINIT", NULL);
1475 if (ip->client->alias)
1476 script_write_params("alias_", ip->client->alias);
1479 ip->client->state = S_INIT;
1484 /* Do the exponential backoff... */
1485 if (!ip->client->interval)
1486 ip->client->interval = ip->client->config->initial_interval;
1488 ip->client->interval += ((arc4random() >> 2) %
1489 (2 * ip->client->interval));
1491 /* Don't backoff past cutoff. */
1492 if (ip->client->interval >
1493 ip->client->config->backoff_cutoff)
1494 ip->client->interval =
1495 ((ip->client->config->backoff_cutoff / 2) +
1496 ((arc4random() >> 2) % ip->client->interval));
1498 /* If the backoff would take us to the expiry time, just set the
1499 timeout to the expiry time. */
1500 if (ip->client->state != S_REQUESTING &&
1501 cur_time + ip->client->interval >
1502 ip->client->active->expiry)
1503 ip->client->interval =
1504 ip->client->active->expiry - cur_time + 1;
1506 /* If the lease T2 time has elapsed, or if we're not yet bound,
1507 broadcast the DHCPREQUEST rather than unicasting. */
1508 if (ip->client->state == S_REQUESTING ||
1509 ip->client->state == S_REBOOTING ||
1510 cur_time > ip->client->active->rebind)
1511 to.s_addr = INADDR_BROADCAST;
1513 memcpy(&to.s_addr, ip->client->destination.iabuf,
1516 if (ip->client->state != S_REQUESTING)
1517 memcpy(&from, ip->client->active->address.iabuf,
1520 from.s_addr = INADDR_ANY;
1522 /* Record the number of seconds since we started sending. */
1523 if (ip->client->state == S_REQUESTING)
1524 ip->client->packet.secs = ip->client->secs;
1526 if (interval < 65536)
1527 ip->client->packet.secs = htons(interval);
1529 ip->client->packet.secs = htons(65535);
1532 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1535 /* Send out a packet. */
1536 send_packet_unpriv(privfd, &ip->client->packet,
1537 ip->client->packet_length, from, to);
1539 add_timeout(cur_time + ip->client->interval, send_request, ip);
1543 send_decline(void *ipp)
1545 struct interface_info *ip = ipp;
1547 note("DHCPDECLINE on %s to %s port %d", ip->name,
1548 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1550 /* Send out a packet. */
1551 send_packet_unpriv(privfd, &ip->client->packet,
1552 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1556 make_discover(struct interface_info *ip, struct client_lease *lease)
1558 unsigned char discover = DHCPDISCOVER;
1559 struct tree_cache *options[256];
1560 struct tree_cache option_elements[256];
1563 memset(option_elements, 0, sizeof(option_elements));
1564 memset(options, 0, sizeof(options));
1565 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1567 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1568 i = DHO_DHCP_MESSAGE_TYPE;
1569 options[i] = &option_elements[i];
1570 options[i]->value = &discover;
1571 options[i]->len = sizeof(discover);
1572 options[i]->buf_size = sizeof(discover);
1573 options[i]->timeout = 0xFFFFFFFF;
1575 /* Request the options we want */
1576 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1577 options[i] = &option_elements[i];
1578 options[i]->value = ip->client->config->requested_options;
1579 options[i]->len = ip->client->config->requested_option_count;
1580 options[i]->buf_size =
1581 ip->client->config->requested_option_count;
1582 options[i]->timeout = 0xFFFFFFFF;
1584 /* If we had an address, try to get it again. */
1586 ip->client->requested_address = lease->address;
1587 i = DHO_DHCP_REQUESTED_ADDRESS;
1588 options[i] = &option_elements[i];
1589 options[i]->value = lease->address.iabuf;
1590 options[i]->len = lease->address.len;
1591 options[i]->buf_size = lease->address.len;
1592 options[i]->timeout = 0xFFFFFFFF;
1594 ip->client->requested_address.len = 0;
1596 /* Send any options requested in the config file. */
1597 for (i = 0; i < 256; i++)
1599 ip->client->config->send_options[i].data) {
1600 options[i] = &option_elements[i];
1602 ip->client->config->send_options[i].data;
1604 ip->client->config->send_options[i].len;
1605 options[i]->buf_size =
1606 ip->client->config->send_options[i].len;
1607 options[i]->timeout = 0xFFFFFFFF;
1610 /* send host name if not set via config file. */
1611 if (!options[DHO_HOST_NAME]) {
1612 if (hostname[0] != '\0') {
1614 char* posDot = strchr(hostname, '.');
1616 len = posDot - hostname;
1618 len = strlen(hostname);
1619 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1620 options[DHO_HOST_NAME]->value = hostname;
1621 options[DHO_HOST_NAME]->len = len;
1622 options[DHO_HOST_NAME]->buf_size = len;
1623 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1627 /* set unique client identifier */
1628 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1629 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1630 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1631 ip->hw_address.hlen : sizeof(client_ident)-1;
1632 client_ident[0] = ip->hw_address.htype;
1633 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1634 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1635 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1636 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1637 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1638 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1641 /* Set up the option buffer... */
1642 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1643 options, 0, 0, 0, NULL, 0);
1644 if (ip->client->packet_length < BOOTP_MIN_LEN)
1645 ip->client->packet_length = BOOTP_MIN_LEN;
1647 ip->client->packet.op = BOOTREQUEST;
1648 ip->client->packet.htype = ip->hw_address.htype;
1649 ip->client->packet.hlen = ip->hw_address.hlen;
1650 ip->client->packet.hops = 0;
1651 ip->client->packet.xid = arc4random();
1652 ip->client->packet.secs = 0; /* filled in by send_discover. */
1653 ip->client->packet.flags = 0;
1655 memset(&(ip->client->packet.ciaddr),
1656 0, sizeof(ip->client->packet.ciaddr));
1657 memset(&(ip->client->packet.yiaddr),
1658 0, sizeof(ip->client->packet.yiaddr));
1659 memset(&(ip->client->packet.siaddr),
1660 0, sizeof(ip->client->packet.siaddr));
1661 memset(&(ip->client->packet.giaddr),
1662 0, sizeof(ip->client->packet.giaddr));
1663 memcpy(ip->client->packet.chaddr,
1664 ip->hw_address.haddr, ip->hw_address.hlen);
1669 make_request(struct interface_info *ip, struct client_lease * lease)
1671 unsigned char request = DHCPREQUEST;
1672 struct tree_cache *options[256];
1673 struct tree_cache option_elements[256];
1676 memset(options, 0, sizeof(options));
1677 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1679 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1680 i = DHO_DHCP_MESSAGE_TYPE;
1681 options[i] = &option_elements[i];
1682 options[i]->value = &request;
1683 options[i]->len = sizeof(request);
1684 options[i]->buf_size = sizeof(request);
1685 options[i]->timeout = 0xFFFFFFFF;
1687 /* Request the options we want */
1688 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1689 options[i] = &option_elements[i];
1690 options[i]->value = ip->client->config->requested_options;
1691 options[i]->len = ip->client->config->requested_option_count;
1692 options[i]->buf_size =
1693 ip->client->config->requested_option_count;
1694 options[i]->timeout = 0xFFFFFFFF;
1696 /* If we are requesting an address that hasn't yet been assigned
1697 to us, use the DHCP Requested Address option. */
1698 if (ip->client->state == S_REQUESTING) {
1699 /* Send back the server identifier... */
1700 i = DHO_DHCP_SERVER_IDENTIFIER;
1701 options[i] = &option_elements[i];
1702 options[i]->value = lease->options[i].data;
1703 options[i]->len = lease->options[i].len;
1704 options[i]->buf_size = lease->options[i].len;
1705 options[i]->timeout = 0xFFFFFFFF;
1707 if (ip->client->state == S_REQUESTING ||
1708 ip->client->state == S_REBOOTING) {
1709 ip->client->requested_address = lease->address;
1710 i = DHO_DHCP_REQUESTED_ADDRESS;
1711 options[i] = &option_elements[i];
1712 options[i]->value = lease->address.iabuf;
1713 options[i]->len = lease->address.len;
1714 options[i]->buf_size = lease->address.len;
1715 options[i]->timeout = 0xFFFFFFFF;
1717 ip->client->requested_address.len = 0;
1719 /* Send any options requested in the config file. */
1720 for (i = 0; i < 256; i++)
1722 ip->client->config->send_options[i].data) {
1723 options[i] = &option_elements[i];
1725 ip->client->config->send_options[i].data;
1727 ip->client->config->send_options[i].len;
1728 options[i]->buf_size =
1729 ip->client->config->send_options[i].len;
1730 options[i]->timeout = 0xFFFFFFFF;
1733 /* send host name if not set via config file. */
1734 if (!options[DHO_HOST_NAME]) {
1735 if (hostname[0] != '\0') {
1737 char* posDot = strchr(hostname, '.');
1739 len = posDot - hostname;
1741 len = strlen(hostname);
1742 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1743 options[DHO_HOST_NAME]->value = hostname;
1744 options[DHO_HOST_NAME]->len = len;
1745 options[DHO_HOST_NAME]->buf_size = len;
1746 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1750 /* set unique client identifier */
1751 char client_ident[sizeof(struct hardware)];
1752 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1753 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1754 ip->hw_address.hlen : sizeof(client_ident)-1;
1755 client_ident[0] = ip->hw_address.htype;
1756 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1757 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1758 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1759 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1760 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1761 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1764 /* Set up the option buffer... */
1765 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1766 options, 0, 0, 0, NULL, 0);
1767 if (ip->client->packet_length < BOOTP_MIN_LEN)
1768 ip->client->packet_length = BOOTP_MIN_LEN;
1770 ip->client->packet.op = BOOTREQUEST;
1771 ip->client->packet.htype = ip->hw_address.htype;
1772 ip->client->packet.hlen = ip->hw_address.hlen;
1773 ip->client->packet.hops = 0;
1774 ip->client->packet.xid = ip->client->xid;
1775 ip->client->packet.secs = 0; /* Filled in by send_request. */
1777 /* If we own the address we're requesting, put it in ciaddr;
1778 otherwise set ciaddr to zero. */
1779 if (ip->client->state == S_BOUND ||
1780 ip->client->state == S_RENEWING ||
1781 ip->client->state == S_REBINDING) {
1782 memcpy(&ip->client->packet.ciaddr,
1783 lease->address.iabuf, lease->address.len);
1784 ip->client->packet.flags = 0;
1786 memset(&ip->client->packet.ciaddr, 0,
1787 sizeof(ip->client->packet.ciaddr));
1788 ip->client->packet.flags = 0;
1791 memset(&ip->client->packet.yiaddr, 0,
1792 sizeof(ip->client->packet.yiaddr));
1793 memset(&ip->client->packet.siaddr, 0,
1794 sizeof(ip->client->packet.siaddr));
1795 memset(&ip->client->packet.giaddr, 0,
1796 sizeof(ip->client->packet.giaddr));
1797 memcpy(ip->client->packet.chaddr,
1798 ip->hw_address.haddr, ip->hw_address.hlen);
1802 make_decline(struct interface_info *ip, struct client_lease *lease)
1804 struct tree_cache *options[256], message_type_tree;
1805 struct tree_cache requested_address_tree;
1806 struct tree_cache server_id_tree, client_id_tree;
1807 unsigned char decline = DHCPDECLINE;
1810 memset(options, 0, sizeof(options));
1811 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1813 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1814 i = DHO_DHCP_MESSAGE_TYPE;
1815 options[i] = &message_type_tree;
1816 options[i]->value = &decline;
1817 options[i]->len = sizeof(decline);
1818 options[i]->buf_size = sizeof(decline);
1819 options[i]->timeout = 0xFFFFFFFF;
1821 /* Send back the server identifier... */
1822 i = DHO_DHCP_SERVER_IDENTIFIER;
1823 options[i] = &server_id_tree;
1824 options[i]->value = lease->options[i].data;
1825 options[i]->len = lease->options[i].len;
1826 options[i]->buf_size = lease->options[i].len;
1827 options[i]->timeout = 0xFFFFFFFF;
1829 /* Send back the address we're declining. */
1830 i = DHO_DHCP_REQUESTED_ADDRESS;
1831 options[i] = &requested_address_tree;
1832 options[i]->value = lease->address.iabuf;
1833 options[i]->len = lease->address.len;
1834 options[i]->buf_size = lease->address.len;
1835 options[i]->timeout = 0xFFFFFFFF;
1837 /* Send the uid if the user supplied one. */
1838 i = DHO_DHCP_CLIENT_IDENTIFIER;
1839 if (ip->client->config->send_options[i].len) {
1840 options[i] = &client_id_tree;
1841 options[i]->value = ip->client->config->send_options[i].data;
1842 options[i]->len = ip->client->config->send_options[i].len;
1843 options[i]->buf_size = ip->client->config->send_options[i].len;
1844 options[i]->timeout = 0xFFFFFFFF;
1848 /* Set up the option buffer... */
1849 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1850 options, 0, 0, 0, NULL, 0);
1851 if (ip->client->packet_length < BOOTP_MIN_LEN)
1852 ip->client->packet_length = BOOTP_MIN_LEN;
1854 ip->client->packet.op = BOOTREQUEST;
1855 ip->client->packet.htype = ip->hw_address.htype;
1856 ip->client->packet.hlen = ip->hw_address.hlen;
1857 ip->client->packet.hops = 0;
1858 ip->client->packet.xid = ip->client->xid;
1859 ip->client->packet.secs = 0; /* Filled in by send_request. */
1860 ip->client->packet.flags = 0;
1862 /* ciaddr must always be zero. */
1863 memset(&ip->client->packet.ciaddr, 0,
1864 sizeof(ip->client->packet.ciaddr));
1865 memset(&ip->client->packet.yiaddr, 0,
1866 sizeof(ip->client->packet.yiaddr));
1867 memset(&ip->client->packet.siaddr, 0,
1868 sizeof(ip->client->packet.siaddr));
1869 memset(&ip->client->packet.giaddr, 0,
1870 sizeof(ip->client->packet.giaddr));
1871 memcpy(ip->client->packet.chaddr,
1872 ip->hw_address.haddr, ip->hw_address.hlen);
1876 free_client_lease(struct client_lease *lease)
1880 if (lease->server_name)
1881 free(lease->server_name);
1882 if (lease->filename)
1883 free(lease->filename);
1884 for (i = 0; i < 256; i++) {
1885 if (lease->options[i].len)
1886 free(lease->options[i].data);
1894 rewrite_client_leases(void)
1896 struct client_lease *lp;
1897 cap_rights_t rights;
1900 leaseFile = fopen(path_dhclient_db, "w");
1902 error("can't create %s: %m", path_dhclient_db);
1903 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1904 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1905 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1907 error("can't limit lease descriptor: %m");
1909 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1911 error("can't limit lease descriptor fcntls: %m");
1918 for (lp = ifi->client->leases; lp; lp = lp->next)
1919 write_client_lease(ifi, lp, 1);
1920 if (ifi->client->active)
1921 write_client_lease(ifi, ifi->client->active, 1);
1924 ftruncate(fileno(leaseFile), ftello(leaseFile));
1925 fsync(fileno(leaseFile));
1929 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1932 static int leases_written;
1937 if (leases_written++ > 20) {
1938 rewrite_client_leases();
1943 /* If the lease came from the config file, we don't need to stash
1944 a copy in the lease database. */
1945 if (lease->is_static)
1948 if (!leaseFile) { /* XXX */
1949 leaseFile = fopen(path_dhclient_db, "w");
1951 error("can't create %s: %m", path_dhclient_db);
1954 fprintf(leaseFile, "lease {\n");
1955 if (lease->is_bootp)
1956 fprintf(leaseFile, " bootp;\n");
1957 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1958 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1959 if (lease->nextserver.len == sizeof(inaddr_any) &&
1960 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1961 sizeof(inaddr_any)))
1962 fprintf(leaseFile, " next-server %s;\n",
1963 piaddr(lease->nextserver));
1964 if (lease->filename)
1965 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1966 if (lease->server_name)
1967 fprintf(leaseFile, " server-name \"%s\";\n",
1968 lease->server_name);
1970 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1971 for (i = 0; i < 256; i++)
1972 if (lease->options[i].len)
1973 fprintf(leaseFile, " option %s %s;\n",
1974 dhcp_options[i].name,
1975 pretty_print_option(i, lease->options[i].data,
1976 lease->options[i].len, 1, 1));
1978 t = gmtime(&lease->renewal);
1979 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1980 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1981 t->tm_hour, t->tm_min, t->tm_sec);
1982 t = gmtime(&lease->rebind);
1983 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1984 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1985 t->tm_hour, t->tm_min, t->tm_sec);
1986 t = gmtime(&lease->expiry);
1987 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1988 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1989 t->tm_hour, t->tm_min, t->tm_sec);
1990 fprintf(leaseFile, "}\n");
1995 script_init(const char *reason, struct string_list *medium)
1997 size_t len, mediumlen = 0;
1998 struct imsg_hdr hdr;
2002 if (medium != NULL && medium->string != NULL)
2003 mediumlen = strlen(medium->string);
2005 hdr.code = IMSG_SCRIPT_INIT;
2006 hdr.len = sizeof(struct imsg_hdr) +
2007 sizeof(size_t) + mediumlen +
2008 sizeof(size_t) + strlen(reason);
2010 if ((buf = buf_open(hdr.len)) == NULL)
2011 error("buf_open: %m");
2014 errs += buf_add(buf, &hdr, sizeof(hdr));
2015 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2017 errs += buf_add(buf, medium->string, mediumlen);
2018 len = strlen(reason);
2019 errs += buf_add(buf, &len, sizeof(len));
2020 errs += buf_add(buf, reason, len);
2023 error("buf_add: %m");
2025 if (buf_close(privfd, buf) == -1)
2026 error("buf_close: %m");
2030 priv_script_init(const char *reason, char *medium)
2032 struct interface_info *ip = ifi;
2035 ip->client->scriptEnvsize = 100;
2036 if (ip->client->scriptEnv == NULL)
2037 ip->client->scriptEnv =
2038 malloc(ip->client->scriptEnvsize * sizeof(char *));
2039 if (ip->client->scriptEnv == NULL)
2040 error("script_init: no memory for environment");
2042 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2043 if (ip->client->scriptEnv[0] == NULL)
2044 error("script_init: no memory for environment");
2046 ip->client->scriptEnv[1] = NULL;
2048 script_set_env(ip->client, "", "interface", ip->name);
2051 script_set_env(ip->client, "", "medium", medium);
2053 script_set_env(ip->client, "", "reason", reason);
2058 priv_script_write_params(const char *prefix, struct client_lease *lease)
2060 struct interface_info *ip = ifi;
2061 u_int8_t dbuf[1500], *dp = NULL;
2066 script_set_env(ip->client, prefix, "ip_address",
2067 piaddr(lease->address));
2069 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2071 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2072 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2074 dp = lease->options[DHO_SUBNET_MASK].data;
2075 len = lease->options[DHO_SUBNET_MASK].len;
2077 if (len && (len < sizeof(lease->address.iabuf))) {
2078 struct iaddr netmask, subnet, broadcast;
2080 memcpy(netmask.iabuf, dp, len);
2082 subnet = subnet_number(lease->address, netmask);
2084 script_set_env(ip->client, prefix, "network_number",
2086 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2087 broadcast = broadcast_addr(subnet, netmask);
2089 script_set_env(ip->client, prefix,
2090 "broadcast_address",
2096 if (lease->filename)
2097 script_set_env(ip->client, prefix, "filename", lease->filename);
2098 if (lease->server_name)
2099 script_set_env(ip->client, prefix, "server_name",
2100 lease->server_name);
2101 for (i = 0; i < 256; i++) {
2104 if (ip->client->config->defaults[i].len) {
2105 if (lease->options[i].len) {
2107 ip->client->config->default_actions[i]) {
2108 case ACTION_DEFAULT:
2109 dp = lease->options[i].data;
2110 len = lease->options[i].len;
2112 case ACTION_SUPERSEDE:
2115 config->defaults[i].data;
2117 config->defaults[i].len;
2119 case ACTION_PREPEND:
2121 config->defaults[i].len +
2122 lease->options[i].len;
2123 if (len >= sizeof(dbuf)) {
2124 warning("no space to %s %s",
2126 dhcp_options[i].name);
2132 config->defaults[i].data,
2134 config->defaults[i].len);
2135 memcpy(dp + ip->client->
2136 config->defaults[i].len,
2137 lease->options[i].data,
2138 lease->options[i].len);
2143 * When we append, we assume that we're
2144 * appending to text. Some MS servers
2145 * include a NUL byte at the end of
2146 * the search string provided.
2149 config->defaults[i].len +
2150 lease->options[i].len;
2151 if (len >= sizeof(dbuf)) {
2152 warning("no space to %s %s",
2154 dhcp_options[i].name);
2158 lease->options[i].data,
2159 lease->options[i].len);
2160 for (dp = dbuf + lease->options[i].len;
2161 dp > dbuf; dp--, len--)
2166 config->defaults[i].data,
2168 config->defaults[i].len);
2174 config->defaults[i].data;
2176 config->defaults[i].len;
2178 } else if (lease->options[i].len) {
2179 len = lease->options[i].len;
2180 dp = lease->options[i].data;
2187 if (dhcp_option_ev_name(name, sizeof(name),
2189 script_set_env(ip->client, prefix, name,
2190 pretty_print_option(i, dp, len, 0, 0));
2193 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2194 script_set_env(ip->client, prefix, "expiry", tbuf);
2198 script_write_params(const char *prefix, struct client_lease *lease)
2200 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2201 struct imsg_hdr hdr;
2205 if (lease->filename != NULL)
2206 fn_len = strlen(lease->filename);
2207 if (lease->server_name != NULL)
2208 sn_len = strlen(lease->server_name);
2210 pr_len = strlen(prefix);
2212 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2213 hdr.len = sizeof(hdr) + sizeof(*lease) +
2214 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2215 sizeof(pr_len) + pr_len;
2217 for (i = 0; i < 256; i++) {
2218 hdr.len += sizeof(lease->options[i].len);
2219 hdr.len += lease->options[i].len;
2222 scripttime = time(NULL);
2224 if ((buf = buf_open(hdr.len)) == NULL)
2225 error("buf_open: %m");
2228 errs += buf_add(buf, &hdr, sizeof(hdr));
2229 errs += buf_add(buf, lease, sizeof(*lease));
2230 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2231 errs += buf_add(buf, lease->filename, fn_len);
2232 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2233 errs += buf_add(buf, lease->server_name, sn_len);
2234 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2235 errs += buf_add(buf, prefix, pr_len);
2237 for (i = 0; i < 256; i++) {
2238 errs += buf_add(buf, &lease->options[i].len,
2239 sizeof(lease->options[i].len));
2240 errs += buf_add(buf, lease->options[i].data,
2241 lease->options[i].len);
2245 error("buf_add: %m");
2247 if (buf_close(privfd, buf) == -1)
2248 error("buf_close: %m");
2254 struct imsg_hdr hdr;
2258 hdr.code = IMSG_SCRIPT_GO;
2259 hdr.len = sizeof(struct imsg_hdr);
2261 if ((buf = buf_open(hdr.len)) == NULL)
2262 error("buf_open: %m");
2264 if (buf_add(buf, &hdr, sizeof(hdr)))
2265 error("buf_add: %m");
2267 if (buf_close(privfd, buf) == -1)
2268 error("buf_close: %m");
2270 bzero(&hdr, sizeof(hdr));
2271 buf_read(privfd, &hdr, sizeof(hdr));
2272 if (hdr.code != IMSG_SCRIPT_GO_RET)
2273 error("unexpected msg type %u", hdr.code);
2274 if (hdr.len != sizeof(hdr) + sizeof(int))
2275 error("received corrupted message");
2276 buf_read(privfd, &ret, sizeof(ret));
2278 scripttime = time(NULL);
2284 priv_script_go(void)
2286 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2287 static char client_path[] = CLIENT_PATH;
2288 struct interface_info *ip = ifi;
2289 int pid, wpid, wstatus;
2291 scripttime = time(NULL);
2294 scriptName = ip->client->config->script_name;
2295 envp = ip->client->scriptEnv;
2297 scriptName = top_level_config.script_name;
2299 epp[1] = client_path;
2304 argv[0] = scriptName;
2313 wpid = wait(&wstatus);
2314 } while (wpid != pid && wpid > 0);
2320 execve(scriptName, argv, envp);
2321 error("execve (%s, ...): %m", scriptName);
2325 script_flush_env(ip->client);
2327 return (wstatus & 0xff);
2331 script_set_env(struct client_state *client, const char *prefix,
2332 const char *name, const char *value)
2337 /* No `` or $() command substitution allowed in environment values! */
2338 for (j=0; j < strlen(value); j++)
2342 warning("illegal character (%c) in value '%s'",
2344 /* Ignore this option */
2348 namelen = strlen(name);
2350 for (i = 0; client->scriptEnv[i]; i++)
2351 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2352 client->scriptEnv[i][namelen] == '=')
2355 if (client->scriptEnv[i])
2356 /* Reuse the slot. */
2357 free(client->scriptEnv[i]);
2359 /* New variable. Expand if necessary. */
2360 if (i >= client->scriptEnvsize - 1) {
2361 char **newscriptEnv;
2362 int newscriptEnvsize = client->scriptEnvsize + 50;
2364 newscriptEnv = realloc(client->scriptEnv,
2366 if (newscriptEnv == NULL) {
2367 free(client->scriptEnv);
2368 client->scriptEnv = NULL;
2369 client->scriptEnvsize = 0;
2370 error("script_set_env: no memory for variable");
2372 client->scriptEnv = newscriptEnv;
2373 client->scriptEnvsize = newscriptEnvsize;
2375 /* need to set the NULL pointer at end of array beyond
2377 client->scriptEnv[i + 1] = NULL;
2379 /* Allocate space and format the variable in the appropriate slot. */
2380 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2382 if (client->scriptEnv[i] == NULL)
2383 error("script_set_env: no memory for variable assignment");
2384 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2385 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2389 script_flush_env(struct client_state *client)
2393 for (i = 0; client->scriptEnv[i]; i++) {
2394 free(client->scriptEnv[i]);
2395 client->scriptEnv[i] = NULL;
2397 client->scriptEnvsize = 0;
2401 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2405 for (i = 0; option->name[i]; i++) {
2406 if (i + 1 == buflen)
2408 if (option->name[i] == '-')
2411 buf[i] = option->name[i];
2421 static int state = 0;
2422 cap_rights_t rights;
2424 if (no_daemon || state)
2429 /* Stop logging to stderr... */
2432 if (daemonfd(-1, nullfd) == -1)
2435 cap_rights_init(&rights);
2437 if (pidfile != NULL) {
2438 pidfile_write(pidfile);
2439 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2441 error("can't limit pidfile descriptor: %m");
2450 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2451 error("can't limit stdin: %m");
2452 cap_rights_init(&rights, CAP_WRITE);
2453 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2454 error("can't limit stdout: %m");
2455 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2456 error("can't limit stderr: %m");
2460 check_option(struct client_lease *l, int option)
2465 /* we use this, since this is what gets passed to dhclient-script */
2467 opbuf = pretty_print_option(option, l->options[option].data,
2468 l->options[option].len, 0, 0);
2470 sbuf = option_as_string(option, l->options[option].data,
2471 l->options[option].len);
2474 case DHO_SUBNET_MASK:
2475 case DHO_TIME_SERVERS:
2476 case DHO_NAME_SERVERS:
2478 case DHO_DOMAIN_NAME_SERVERS:
2479 case DHO_LOG_SERVERS:
2480 case DHO_COOKIE_SERVERS:
2481 case DHO_LPR_SERVERS:
2482 case DHO_IMPRESS_SERVERS:
2483 case DHO_RESOURCE_LOCATION_SERVERS:
2484 case DHO_SWAP_SERVER:
2485 case DHO_BROADCAST_ADDRESS:
2486 case DHO_NIS_SERVERS:
2487 case DHO_NTP_SERVERS:
2488 case DHO_NETBIOS_NAME_SERVERS:
2489 case DHO_NETBIOS_DD_SERVER:
2490 case DHO_FONT_SERVERS:
2491 case DHO_DHCP_SERVER_IDENTIFIER:
2492 case DHO_NISPLUS_SERVERS:
2493 case DHO_MOBILE_IP_HOME_AGENT:
2494 case DHO_SMTP_SERVER:
2495 case DHO_POP_SERVER:
2496 case DHO_NNTP_SERVER:
2497 case DHO_WWW_SERVER:
2498 case DHO_FINGER_SERVER:
2499 case DHO_IRC_SERVER:
2500 case DHO_STREETTALK_SERVER:
2501 case DHO_STREETTALK_DA_SERVER:
2502 if (!ipv4addrs(opbuf)) {
2503 warning("Invalid IP address in option: %s", opbuf);
2508 case DHO_NIS_DOMAIN:
2509 case DHO_NISPLUS_DOMAIN:
2510 case DHO_TFTP_SERVER_NAME:
2511 if (!res_hnok(sbuf)) {
2512 warning("Bogus Host Name option %d: %s (%s)", option,
2514 l->options[option].len = 0;
2515 free(l->options[option].data);
2518 case DHO_DOMAIN_NAME:
2519 case DHO_DOMAIN_SEARCH:
2520 if (!res_hnok(sbuf)) {
2521 if (!check_search(sbuf)) {
2522 warning("Bogus domain search list %d: %s (%s)",
2523 option, sbuf, opbuf);
2524 l->options[option].len = 0;
2525 free(l->options[option].data);
2530 case DHO_TIME_OFFSET:
2532 case DHO_MERIT_DUMP:
2534 case DHO_EXTENSIONS_PATH:
2535 case DHO_IP_FORWARDING:
2536 case DHO_NON_LOCAL_SOURCE_ROUTING:
2537 case DHO_POLICY_FILTER:
2538 case DHO_MAX_DGRAM_REASSEMBLY:
2539 case DHO_DEFAULT_IP_TTL:
2540 case DHO_PATH_MTU_AGING_TIMEOUT:
2541 case DHO_PATH_MTU_PLATEAU_TABLE:
2542 case DHO_INTERFACE_MTU:
2543 case DHO_ALL_SUBNETS_LOCAL:
2544 case DHO_PERFORM_MASK_DISCOVERY:
2545 case DHO_MASK_SUPPLIER:
2546 case DHO_ROUTER_DISCOVERY:
2547 case DHO_ROUTER_SOLICITATION_ADDRESS:
2548 case DHO_STATIC_ROUTES:
2549 case DHO_TRAILER_ENCAPSULATION:
2550 case DHO_ARP_CACHE_TIMEOUT:
2551 case DHO_IEEE802_3_ENCAPSULATION:
2552 case DHO_DEFAULT_TCP_TTL:
2553 case DHO_TCP_KEEPALIVE_INTERVAL:
2554 case DHO_TCP_KEEPALIVE_GARBAGE:
2555 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2556 case DHO_NETBIOS_NODE_TYPE:
2557 case DHO_NETBIOS_SCOPE:
2558 case DHO_X_DISPLAY_MANAGER:
2559 case DHO_DHCP_REQUESTED_ADDRESS:
2560 case DHO_DHCP_LEASE_TIME:
2561 case DHO_DHCP_OPTION_OVERLOAD:
2562 case DHO_DHCP_MESSAGE_TYPE:
2563 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2564 case DHO_DHCP_MESSAGE:
2565 case DHO_DHCP_MAX_MESSAGE_SIZE:
2566 case DHO_DHCP_RENEWAL_TIME:
2567 case DHO_DHCP_REBINDING_TIME:
2568 case DHO_DHCP_CLASS_IDENTIFIER:
2569 case DHO_DHCP_CLIENT_IDENTIFIER:
2570 case DHO_BOOTFILE_NAME:
2571 case DHO_DHCP_USER_CLASS_ID:
2574 case DHO_CLASSLESS_ROUTES:
2575 return (check_classless_option(l->options[option].data,
2576 l->options[option].len));
2578 warning("unknown dhcp option value 0x%x", option);
2579 return (unknown_ok);
2583 /* RFC 3442 The Classless Static Routes option checks */
2585 check_classless_option(unsigned char *data, int len)
2588 unsigned char width;
2589 in_addr_t addr, mask;
2592 warning("Too small length: %d", len);
2600 } else if (width < 9) {
2601 addr = (in_addr_t)(data[i] << 24);
2603 } else if (width < 17) {
2604 addr = (in_addr_t)(data[i] << 24) +
2605 (in_addr_t)(data[i + 1] << 16);
2607 } else if (width < 25) {
2608 addr = (in_addr_t)(data[i] << 24) +
2609 (in_addr_t)(data[i + 1] << 16) +
2610 (in_addr_t)(data[i + 2] << 8);
2612 } else if (width < 33) {
2613 addr = (in_addr_t)(data[i] << 24) +
2614 (in_addr_t)(data[i + 1] << 16) +
2615 (in_addr_t)(data[i + 2] << 8) +
2619 warning("Incorrect subnet width: %d", width);
2622 mask = (in_addr_t)(~0) << (32 - width);
2628 * ... After deriving a subnet number and subnet mask
2629 * from each destination descriptor, the DHCP client
2630 * MUST zero any bits in the subnet number where the
2631 * corresponding bit in the mask is zero...
2633 if ((addr & mask) != addr) {
2635 data[i - 1] = (unsigned char)(
2636 (addr >> (((32 - width)/8)*8)) & 0xFF);
2641 warning("Incorrect data length: %d (must be %d)", len, i);
2648 res_hnok(const char *dn)
2650 int pch = PERIOD, ch = *dn++;
2652 while (ch != '\0') {
2655 if (periodchar(ch)) {
2657 } else if (periodchar(pch)) {
2658 if (!borderchar(ch))
2660 } else if (periodchar(nch) || nch == '\0') {
2661 if (!borderchar(ch))
2664 if (!middlechar(ch))
2673 check_search(const char *srch)
2675 int pch = PERIOD, ch = *srch++;
2678 /* 256 char limit re resolv.conf(5) */
2679 if (strlen(srch) > 256)
2682 while (whitechar(ch))
2685 while (ch != '\0') {
2688 if (periodchar(ch) || whitechar(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))
2700 if (!whitechar(ch)) {
2703 while (whitechar(nch)) {
2712 /* 6 domain limit re resolv.conf(5) */
2718 /* Does buf consist only of dotted decimal ipv4 addrs?
2719 * return how many if so,
2720 * otherwise, return 0
2723 ipv4addrs(const char * buf)
2728 while (inet_aton(buf, &jnk) == 1){
2730 while (periodchar(*buf) || digitchar(*buf))
2742 option_as_string(unsigned int code, unsigned char *data, int len)
2744 static char optbuf[32768]; /* XXX */
2746 int opleft = sizeof(optbuf);
2747 unsigned char *dp = data;
2750 error("option_as_string: bad code %d", code);
2752 for (; dp < data + len; dp++) {
2753 if (!isascii(*dp) || !isprint(*dp)) {
2754 if (dp + 1 != data + len || *dp != 0) {
2755 snprintf(op, opleft, "\\%03o", *dp);
2759 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2760 *dp == '`' || *dp == '\\') {
2774 warning("dhcp option too large");
2779 fork_privchld(int fd, int fd2)
2781 struct pollfd pfd[1];
2786 error("cannot fork");
2793 setproctitle("%s [priv]", ifi->name);
2796 dup2(nullfd, STDIN_FILENO);
2797 dup2(nullfd, STDOUT_FILENO);
2798 dup2(nullfd, STDERR_FILENO);
2806 pfd[0].events = POLLIN;
2807 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2809 error("poll error");
2811 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2814 dispatch_imsg(ifi, fd);