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"
90 time_t default_lease_time = 43200; /* 12 hours... */
92 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
93 char *path_dhclient_db = NULL;
99 char hostname[_POSIX_HOST_NAME_MAX + 1];
101 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
102 struct in_addr inaddr_any, inaddr_broadcast;
104 char *path_dhclient_pidfile;
105 struct pidfh *pidfile;
108 * ASSERT_STATE() does nothing now; it used to be
109 * assert (state_is == state_shouldbe).
111 #define ASSERT_STATE(state_is, state_shouldbe) {}
114 * We need to check that the expiry, renewal and rebind times are not beyond
115 * the end of time (~2038 when a 32-bit time_t is being used).
117 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
124 struct interface_info *ifi;
126 int findproto(char *, int);
127 struct sockaddr *get_ifa(char *, int);
128 void routehandler(struct protocol *);
130 int check_option(struct client_lease *l, int option);
131 int check_classless_option(unsigned char *data, int len);
132 int ipv4addrs(char * buf);
133 int res_hnok(const char *dn);
134 int check_search(const char *srch);
135 char *option_as_string(unsigned int code, unsigned char *data, int len);
136 int fork_privchld(int, int);
139 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
140 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
142 /* Minimum MTU is 68 as per RFC791, p. 24 */
145 static time_t scripttime;
148 findproto(char *cp, int n)
155 for (i = 1; i; i <<= 1) {
157 sa = (struct sockaddr *)cp;
163 if (sa->sa_family == AF_INET)
165 if (sa->sa_family == AF_INET6)
178 get_ifa(char *cp, int n)
185 for (i = 1; i; i <<= 1)
187 sa = (struct sockaddr *)cp;
196 struct iaddr defaddr = { .len = 4 };
202 struct interface_info *ifi = arg;
205 * Clear existing state.
207 if (ifi->client->active != NULL) {
208 script_init("EXPIRE", NULL);
209 script_write_params("old_",
210 ifi->client->active);
211 if (ifi->client->alias)
212 script_write_params("alias_",
216 ifi->client->state = S_INIT;
221 routehandler(struct protocol *p)
223 char msg[2048], *addr;
224 struct rt_msghdr *rtm;
225 struct if_msghdr *ifm;
226 struct ifa_msghdr *ifam;
227 struct if_announcemsghdr *ifan;
228 struct ieee80211_join_event *jev;
229 struct client_lease *l;
230 time_t t = time(NULL);
236 n = read(routefd, &msg, sizeof(msg));
237 rtm = (struct rt_msghdr *)msg;
238 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
239 n < (ssize_t)rtm->rtm_msglen ||
240 rtm->rtm_version != RTM_VERSION)
243 switch (rtm->rtm_type) {
246 ifam = (struct ifa_msghdr *)rtm;
248 if (ifam->ifam_index != ifi->index)
250 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
252 if (scripttime == 0 || t < scripttime + 10)
255 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
259 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
260 error("king bula sez: len mismatch");
261 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
262 if (addr_eq(a, defaddr))
265 for (l = ifi->client->active; l != NULL; l = l->next)
266 if (addr_eq(a, l->address))
269 if (l == NULL) /* added/deleted addr is not the one we set */
272 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
273 if (rtm->rtm_type == RTM_NEWADDR) {
275 * XXX: If someone other than us adds our address,
276 * should we assume they are taking over from us,
277 * delete the lease record, and exit without modifying
280 warning("My address (%s) was re-added", addr);
282 warning("My address (%s) was deleted, dhclient exiting",
288 ifm = (struct if_msghdr *)rtm;
289 if (ifm->ifm_index != ifi->index)
291 if ((rtm->rtm_flags & RTF_UP) == 0) {
292 warning("Interface %s is down, dhclient exiting",
296 linkstat = interface_link_status(ifi->name);
297 if (linkstat != ifi->linkstat) {
298 debug("%s link state %s -> %s", ifi->name,
299 ifi->linkstat ? "up" : "down",
300 linkstat ? "up" : "down");
301 ifi->linkstat = linkstat;
307 ifan = (struct if_announcemsghdr *)rtm;
308 if (ifan->ifan_what == IFAN_DEPARTURE &&
309 ifan->ifan_index == ifi->index) {
310 warning("Interface %s is gone, dhclient exiting",
316 ifan = (struct if_announcemsghdr *)rtm;
317 if (ifan->ifan_index != ifi->index)
319 switch (ifan->ifan_what) {
320 case RTM_IEEE80211_ASSOC:
321 case RTM_IEEE80211_REASSOC:
323 * Use assoc/reassoc event to kick state machine
324 * in case we roam. Otherwise fall back to the
325 * normal state machine just like a wired network.
327 jev = (struct ieee80211_join_event *) &ifan[1];
328 if (memcmp(curbssid, jev->iev_addr, 6)) {
332 memcpy(curbssid, jev->iev_addr, 6);
342 script_init("FAIL", NULL);
343 if (ifi->client->alias)
344 script_write_params("alias_", ifi->client->alias);
347 pidfile_remove(pidfile);
352 main(int argc, char *argv[])
354 extern char *__progname;
355 int ch, fd, quiet = 0, i = 0;
357 int immediate_daemon = 0;
362 /* Initially, log errors to stderr as well as to syslogd. */
363 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
364 setlogmask(LOG_UPTO(LOG_DEBUG));
366 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
369 immediate_daemon = 1;
372 path_dhclient_conf = optarg;
378 path_dhclient_db = optarg;
381 path_dhclient_pidfile = optarg;
399 if (path_dhclient_pidfile == NULL) {
400 asprintf(&path_dhclient_pidfile,
401 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
402 if (path_dhclient_pidfile == NULL)
405 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
406 if (pidfile == NULL) {
408 error("dhclient already running, pid: %d.", otherpid);
410 error("dhclient already running.");
411 warning("Cannot open or create pidfile: %m");
414 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
416 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
417 error("Interface name too long");
418 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
419 _PATH_DHCLIENT_DB, ifi->name) == -1)
428 inaddr_broadcast.s_addr = INADDR_BROADCAST;
429 inaddr_any.s_addr = INADDR_ANY;
433 /* The next bit is potentially very time-consuming, so write out
434 the pidfile right away. We will write it out again with the
435 correct pid after daemonizing. */
437 pidfile_write(pidfile);
439 if (!interface_link_status(ifi->name)) {
440 fprintf(stderr, "%s: no link ...", ifi->name);
443 while (!interface_link_status(ifi->name)) {
444 fprintf(stderr, ".");
447 fprintf(stderr, " giving up\n");
452 fprintf(stderr, " got link\n");
456 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
457 error("cannot open %s: %m", _PATH_DEVNULL);
459 if ((pw = getpwnam("_dhcp")) == NULL) {
460 warning("no such user: _dhcp, falling back to \"nobody\"");
461 if ((pw = getpwnam("nobody")) == NULL)
462 error("no such user: nobody");
466 * Obtain hostname before entering capability mode - it won't be
467 * possible then, as reading kern.hostname is not permitted.
469 if (gethostname(hostname, sizeof(hostname)) < 0)
472 priv_script_init("PREINIT", NULL);
473 if (ifi->client->alias)
474 priv_script_write_params("alias_", ifi->client->alias);
477 /* set up the interface */
478 discover_interfaces(ifi);
480 if (pipe(pipe_fd) == -1)
483 fork_privchld(pipe_fd[0], pipe_fd[1]);
492 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
493 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
494 error("can't limit private descriptor: %m");
496 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
497 error("can't open and lock %s: %m", path_dhclient_db);
498 read_client_leases();
499 rewrite_client_leases();
502 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
503 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
504 if (shutdown(routefd, SHUT_WR) < 0)
505 error("can't shutdown route socket: %m");
506 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
507 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
508 error("can't limit route socket: %m");
510 if (chroot(_PATH_VAREMPTY) == -1)
512 if (chdir("/") == -1)
513 error("chdir(\"/\")");
515 if (setgroups(1, &pw->pw_gid) ||
516 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
517 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
518 error("can't drop privileges: %m");
522 setproctitle("%s", ifi->name);
524 if (cap_enter() < 0 && errno != ENOSYS)
525 error("can't enter capability mode: %m");
527 if (immediate_daemon)
530 ifi->client->state = S_INIT;
533 bootp_packet_handler = do_packet;
544 extern char *__progname;
546 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
547 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
554 * Each routine is called from the dhclient_state_machine() in one of
556 * -> entering INIT state
557 * -> recvpacket_flag == 0: timeout in this state
558 * -> otherwise: received a packet in this state
560 * Return conditions as handled by dhclient_state_machine():
561 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
562 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
563 * Returns 0: finish the nap which was interrupted for no good reason.
565 * Several per-interface variables are used to keep track of the process:
566 * active_lease: the lease that is being used on the interface
567 * (null pointer if not configured yet).
568 * offered_leases: leases corresponding to DHCPOFFER messages that have
569 * been sent to us by DHCP servers.
570 * acked_leases: leases corresponding to DHCPACK messages that have been
571 * sent to us by DHCP servers.
572 * sendpacket: DHCP packet we're trying to send.
573 * destination: IP address to send sendpacket to
574 * In addition, there are several relevant per-lease variables.
575 * T1_expiry, T2_expiry, lease_expiry: lease milestones
576 * In the active lease, these control the process of renewing the lease;
577 * In leases on the acked_leases list, this simply determines when we
578 * can no longer legitimately use the lease.
582 state_reboot(void *ipp)
584 struct interface_info *ip = ipp;
586 /* If we don't remember an active lease, go straight to INIT. */
587 if (!ip->client->active || ip->client->active->is_bootp) {
592 /* We are in the rebooting state. */
593 ip->client->state = S_REBOOTING;
595 /* make_request doesn't initialize xid because it normally comes
596 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
597 so pick an xid now. */
598 ip->client->xid = arc4random();
600 /* Make a DHCPREQUEST packet, and set appropriate per-interface
602 make_request(ip, ip->client->active);
603 ip->client->destination = iaddr_broadcast;
604 ip->client->first_sending = cur_time;
605 ip->client->interval = ip->client->config->initial_interval;
607 /* Zap the medium list... */
608 ip->client->medium = NULL;
610 /* Send out the first DHCPREQUEST packet. */
615 * Called when a lease has completely expired and we've
616 * been unable to renew it.
619 state_init(void *ipp)
621 struct interface_info *ip = ipp;
623 ASSERT_STATE(state, S_INIT);
625 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
627 make_discover(ip, ip->client->active);
628 ip->client->xid = ip->client->packet.xid;
629 ip->client->destination = iaddr_broadcast;
630 ip->client->state = S_SELECTING;
631 ip->client->first_sending = cur_time;
632 ip->client->interval = ip->client->config->initial_interval;
634 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
640 * state_selecting is called when one or more DHCPOFFER packets
641 * have been received and a configurable period of time has passed.
644 state_selecting(void *ipp)
646 struct interface_info *ip = ipp;
647 struct client_lease *lp, *next, *picked;
649 ASSERT_STATE(state, S_SELECTING);
651 /* Cancel state_selecting and send_discover timeouts, since either
652 one could have got us here. */
653 cancel_timeout(state_selecting, ip);
654 cancel_timeout(send_discover, ip);
656 /* We have received one or more DHCPOFFER packets. Currently,
657 the only criterion by which we judge leases is whether or
658 not we get a response when we arp for them. */
660 for (lp = ip->client->offered_leases; lp; lp = next) {
663 /* Check to see if we got an ARPREPLY for the address
664 in this particular lease. */
666 script_init("ARPCHECK", lp->medium);
667 script_write_params("check_", lp);
669 /* If the ARPCHECK code detects another
670 machine using the offered address, it exits
671 nonzero. We need to send a DHCPDECLINE and
674 make_decline(ip, lp);
682 free_client_lease(lp);
685 ip->client->offered_leases = NULL;
687 /* If we just tossed all the leases we were offered, go back
690 ip->client->state = S_INIT;
695 /* If it was a BOOTREPLY, we can just take the address right now. */
696 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
697 ip->client->new = picked;
699 /* Make up some lease expiry times
700 XXX these should be configurable. */
701 ip->client->new->expiry = cur_time + 12000;
702 ip->client->new->renewal += cur_time + 8000;
703 ip->client->new->rebind += cur_time + 10000;
705 ip->client->state = S_REQUESTING;
707 /* Bind to the address we received. */
712 /* Go to the REQUESTING state. */
713 ip->client->destination = iaddr_broadcast;
714 ip->client->state = S_REQUESTING;
715 ip->client->first_sending = cur_time;
716 ip->client->interval = ip->client->config->initial_interval;
718 /* Make a DHCPREQUEST packet from the lease we picked. */
719 make_request(ip, picked);
720 ip->client->xid = ip->client->packet.xid;
722 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
723 free_client_lease(picked);
725 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
729 /* state_requesting is called when we receive a DHCPACK message after
730 having sent out one or more DHCPREQUEST packets. */
733 dhcpack(struct packet *packet)
735 struct interface_info *ip = packet->interface;
736 struct client_lease *lease;
738 /* If we're not receptive to an offer right now, or if the offer
739 has an unrecognizable transaction id, then just drop it. */
740 if (packet->interface->client->xid != packet->raw->xid ||
741 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
742 (memcmp(packet->interface->hw_address.haddr,
743 packet->raw->chaddr, packet->raw->hlen)))
746 if (ip->client->state != S_REBOOTING &&
747 ip->client->state != S_REQUESTING &&
748 ip->client->state != S_RENEWING &&
749 ip->client->state != S_REBINDING)
752 note("DHCPACK from %s", piaddr(packet->client_addr));
754 lease = packet_to_lease(packet);
756 note("packet_to_lease failed.");
760 ip->client->new = lease;
762 /* Stop resending DHCPREQUEST. */
763 cancel_timeout(send_request, ip);
765 /* Figure out the lease time. */
766 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
768 ip->client->new->expiry = getULong(
769 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
770 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
771 ip->client->new->expiry = getULong(
772 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
774 ip->client->new->expiry = default_lease_time;
775 /* A number that looks negative here is really just very large,
776 because the lease expiry offset is unsigned. Also make sure that
777 the addition of cur_time below does not overflow (a 32 bit) time_t. */
778 if (ip->client->new->expiry < 0 ||
779 ip->client->new->expiry > TIME_MAX - cur_time)
780 ip->client->new->expiry = TIME_MAX - cur_time;
781 /* XXX should be fixed by resetting the client state */
782 if (ip->client->new->expiry < 60)
783 ip->client->new->expiry = 60;
785 /* Unless overridden in the config, take the server-provided renewal
786 * time if there is one. Otherwise figure it out according to the spec.
787 * Also make sure the renewal time does not exceed the expiry time.
789 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
791 ip->client->new->renewal = getULong(
792 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
793 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
794 ip->client->new->renewal = getULong(
795 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
797 ip->client->new->renewal = ip->client->new->expiry / 2;
798 if (ip->client->new->renewal < 0 ||
799 ip->client->new->renewal > ip->client->new->expiry / 2)
800 ip->client->new->renewal = ip->client->new->expiry / 2;
802 /* Same deal with the rebind time. */
803 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
805 ip->client->new->rebind = getULong(
806 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
807 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
808 ip->client->new->rebind = getULong(
809 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
811 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
812 if (ip->client->new->rebind < 0 ||
813 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
814 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
816 /* Convert the time offsets into seconds-since-the-epoch */
817 ip->client->new->expiry += cur_time;
818 ip->client->new->renewal += cur_time;
819 ip->client->new->rebind += cur_time;
825 bind_lease(struct interface_info *ip)
827 struct option_data *opt;
829 /* Remember the medium. */
830 ip->client->new->medium = ip->client->medium;
832 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
833 if (opt->len == sizeof(u_int16_t)) {
834 u_int16_t mtu = be16dec(opt->data);
836 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
838 interface_set_mtu_unpriv(privfd, mtu);
841 /* Write out the new lease. */
842 write_client_lease(ip, ip->client->new, 0);
844 /* Run the client script with the new parameters. */
845 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
846 (ip->client->state == S_RENEWING ? "RENEW" :
847 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
848 ip->client->new->medium);
849 if (ip->client->active && ip->client->state != S_REBOOTING)
850 script_write_params("old_", ip->client->active);
851 script_write_params("new_", ip->client->new);
852 if (ip->client->alias)
853 script_write_params("alias_", ip->client->alias);
856 /* Replace the old active lease with the new one. */
857 if (ip->client->active)
858 free_client_lease(ip->client->active);
859 ip->client->active = ip->client->new;
860 ip->client->new = NULL;
862 /* Set up a timeout to start the renewal process. */
863 add_timeout(ip->client->active->renewal, state_bound, ip);
865 note("bound to %s -- renewal in %d seconds.",
866 piaddr(ip->client->active->address),
867 (int)(ip->client->active->renewal - cur_time));
868 ip->client->state = S_BOUND;
869 reinitialize_interfaces();
874 * state_bound is called when we've successfully bound to a particular
875 * lease, but the renewal time on that lease has expired. We are
876 * expected to unicast a DHCPREQUEST to the server that gave us our
880 state_bound(void *ipp)
882 struct interface_info *ip = ipp;
884 ASSERT_STATE(state, S_BOUND);
886 /* T1 has expired. */
887 make_request(ip, ip->client->active);
888 ip->client->xid = ip->client->packet.xid;
890 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
891 memcpy(ip->client->destination.iabuf, ip->client->active->
892 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
893 ip->client->destination.len = 4;
895 ip->client->destination = iaddr_broadcast;
897 ip->client->first_sending = cur_time;
898 ip->client->interval = ip->client->config->initial_interval;
899 ip->client->state = S_RENEWING;
901 /* Send the first packet immediately. */
906 bootp(struct packet *packet)
908 struct iaddrlist *ap;
910 if (packet->raw->op != BOOTREPLY)
913 /* If there's a reject list, make sure this packet's sender isn't
915 for (ap = packet->interface->client->config->reject_list;
917 if (addr_eq(packet->client_addr, ap->addr)) {
918 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
926 dhcp(struct packet *packet)
928 struct iaddrlist *ap;
929 void (*handler)(struct packet *);
932 switch (packet->packet_type) {
949 /* If there's a reject list, make sure this packet's sender isn't
951 for (ap = packet->interface->client->config->reject_list;
953 if (addr_eq(packet->client_addr, ap->addr)) {
954 note("%s from %s rejected.", type, piaddr(ap->addr));
962 dhcpoffer(struct packet *packet)
964 struct interface_info *ip = packet->interface;
965 struct client_lease *lease, *lp;
967 int arp_timeout_needed, stop_selecting;
968 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
969 "DHCPOFFER" : "BOOTREPLY";
971 /* If we're not receptive to an offer right now, or if the offer
972 has an unrecognizable transaction id, then just drop it. */
973 if (ip->client->state != S_SELECTING ||
974 packet->interface->client->xid != packet->raw->xid ||
975 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
976 (memcmp(packet->interface->hw_address.haddr,
977 packet->raw->chaddr, packet->raw->hlen)))
980 note("%s from %s", name, piaddr(packet->client_addr));
983 /* If this lease doesn't supply the minimum required parameters,
985 for (i = 0; ip->client->config->required_options[i]; i++) {
986 if (!packet->options[ip->client->config->
987 required_options[i]].len) {
988 note("%s isn't satisfactory.", name);
993 /* If we've already seen this lease, don't record it again. */
994 for (lease = ip->client->offered_leases;
995 lease; lease = lease->next) {
996 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
997 !memcmp(lease->address.iabuf,
998 &packet->raw->yiaddr, lease->address.len)) {
999 debug("%s already seen.", name);
1004 lease = packet_to_lease(packet);
1006 note("packet_to_lease failed.");
1010 /* If this lease was acquired through a BOOTREPLY, record that
1012 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1013 lease->is_bootp = 1;
1015 /* Record the medium under which this lease was offered. */
1016 lease->medium = ip->client->medium;
1018 /* Send out an ARP Request for the offered IP address. */
1019 script_init("ARPSEND", lease->medium);
1020 script_write_params("check_", lease);
1021 /* If the script can't send an ARP request without waiting,
1022 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1024 arp_timeout_needed = 0;
1026 arp_timeout_needed = 2;
1028 /* Figure out when we're supposed to stop selecting. */
1030 ip->client->first_sending + ip->client->config->select_interval;
1032 /* If this is the lease we asked for, put it at the head of the
1033 list, and don't mess with the arp request timeout. */
1034 if (lease->address.len == ip->client->requested_address.len &&
1035 !memcmp(lease->address.iabuf,
1036 ip->client->requested_address.iabuf,
1037 ip->client->requested_address.len)) {
1038 lease->next = ip->client->offered_leases;
1039 ip->client->offered_leases = lease;
1041 /* If we already have an offer, and arping for this
1042 offer would take us past the selection timeout,
1043 then don't extend the timeout - just hope for the
1045 if (ip->client->offered_leases &&
1046 (cur_time + arp_timeout_needed) > stop_selecting)
1047 arp_timeout_needed = 0;
1049 /* Put the lease at the end of the list. */
1051 if (!ip->client->offered_leases)
1052 ip->client->offered_leases = lease;
1054 for (lp = ip->client->offered_leases; lp->next;
1061 /* If we're supposed to stop selecting before we've had time
1062 to wait for the ARPREPLY, add some delay to wait for
1064 if (stop_selecting - cur_time < arp_timeout_needed)
1065 stop_selecting = cur_time + arp_timeout_needed;
1067 /* If the selecting interval has expired, go immediately to
1068 state_selecting(). Otherwise, time out into
1069 state_selecting at the select interval. */
1070 if (stop_selecting <= 0)
1071 state_selecting(ip);
1073 add_timeout(stop_selecting, state_selecting, ip);
1074 cancel_timeout(send_discover, ip);
1078 /* Allocate a client_lease structure and initialize it from the parameters
1079 in the specified packet. */
1081 struct client_lease *
1082 packet_to_lease(struct packet *packet)
1084 struct client_lease *lease;
1087 lease = malloc(sizeof(struct client_lease));
1090 warning("dhcpoffer: no memory to record lease.");
1094 memset(lease, 0, sizeof(*lease));
1096 /* Copy the lease options. */
1097 for (i = 0; i < 256; i++) {
1098 if (packet->options[i].len) {
1099 lease->options[i].data =
1100 malloc(packet->options[i].len + 1);
1101 if (!lease->options[i].data) {
1102 warning("dhcpoffer: no memory for option %d", i);
1103 free_client_lease(lease);
1106 memcpy(lease->options[i].data,
1107 packet->options[i].data,
1108 packet->options[i].len);
1109 lease->options[i].len =
1110 packet->options[i].len;
1111 lease->options[i].data[lease->options[i].len] =
1114 if (!check_option(lease,i)) {
1115 /* ignore a bogus lease offer */
1116 warning("Invalid lease option - ignoring offer");
1117 free_client_lease(lease);
1123 lease->address.len = sizeof(packet->raw->yiaddr);
1124 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1126 lease->nextserver.len = sizeof(packet->raw->siaddr);
1127 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1129 /* If the server name was filled out, copy it.
1130 Do not attempt to validate the server name as a host name.
1131 RFC 2131 merely states that sname is NUL-terminated (which do
1132 do not assume) and that it is the server's host name. Since
1133 the ISC client and server allow arbitrary characters, we do
1135 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1136 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1137 packet->raw->sname[0]) {
1138 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1139 if (!lease->server_name) {
1140 warning("dhcpoffer: no memory for server name.");
1141 free_client_lease(lease);
1144 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1145 lease->server_name[DHCP_SNAME_LEN]='\0';
1148 /* Ditto for the filename. */
1149 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1150 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1151 packet->raw->file[0]) {
1152 /* Don't count on the NUL terminator. */
1153 lease->filename = malloc(DHCP_FILE_LEN + 1);
1154 if (!lease->filename) {
1155 warning("dhcpoffer: no memory for filename.");
1156 free_client_lease(lease);
1159 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1160 lease->filename[DHCP_FILE_LEN]='\0';
1166 dhcpnak(struct packet *packet)
1168 struct interface_info *ip = packet->interface;
1170 /* If we're not receptive to an offer right now, or if the offer
1171 has an unrecognizable transaction id, then just drop it. */
1172 if (packet->interface->client->xid != packet->raw->xid ||
1173 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1174 (memcmp(packet->interface->hw_address.haddr,
1175 packet->raw->chaddr, packet->raw->hlen)))
1178 if (ip->client->state != S_REBOOTING &&
1179 ip->client->state != S_REQUESTING &&
1180 ip->client->state != S_RENEWING &&
1181 ip->client->state != S_REBINDING)
1184 note("DHCPNAK from %s", piaddr(packet->client_addr));
1186 if (!ip->client->active) {
1187 note("DHCPNAK with no active lease.\n");
1191 free_client_lease(ip->client->active);
1192 ip->client->active = NULL;
1194 /* Stop sending DHCPREQUEST packets... */
1195 cancel_timeout(send_request, ip);
1197 ip->client->state = S_INIT;
1201 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1202 one after the right interval has expired. If we don't get an offer by
1203 the time we reach the panic interval, call the panic function. */
1206 send_discover(void *ipp)
1208 struct interface_info *ip = ipp;
1209 int interval, increase = 1;
1211 /* Figure out how long it's been since we started transmitting. */
1212 interval = cur_time - ip->client->first_sending;
1214 /* If we're past the panic timeout, call the script and tell it
1215 we haven't found anything for this interface yet. */
1216 if (interval > ip->client->config->timeout) {
1221 /* If we're selecting media, try the whole list before doing
1222 the exponential backoff, but if we've already received an
1223 offer, stop looping, because we obviously have it right. */
1224 if (!ip->client->offered_leases &&
1225 ip->client->config->media) {
1228 if (ip->client->medium) {
1229 ip->client->medium = ip->client->medium->next;
1232 if (!ip->client->medium) {
1234 error("No valid media types for %s!", ip->name);
1235 ip->client->medium = ip->client->config->media;
1239 note("Trying medium \"%s\" %d", ip->client->medium->string,
1241 script_init("MEDIUM", ip->client->medium);
1247 * If we're supposed to increase the interval, do so. If it's
1248 * currently zero (i.e., we haven't sent any packets yet), set
1249 * it to one; otherwise, add to it a random number between zero
1250 * and two times itself. On average, this means that it will
1251 * double with every transmission.
1254 if (!ip->client->interval)
1255 ip->client->interval =
1256 ip->client->config->initial_interval;
1258 ip->client->interval += (arc4random() >> 2) %
1259 (2 * ip->client->interval);
1262 /* Don't backoff past cutoff. */
1263 if (ip->client->interval >
1264 ip->client->config->backoff_cutoff)
1265 ip->client->interval =
1266 ((ip->client->config->backoff_cutoff / 2)
1267 + ((arc4random() >> 2) %
1268 ip->client->config->backoff_cutoff));
1269 } else if (!ip->client->interval)
1270 ip->client->interval =
1271 ip->client->config->initial_interval;
1273 /* If the backoff would take us to the panic timeout, just use that
1275 if (cur_time + ip->client->interval >
1276 ip->client->first_sending + ip->client->config->timeout)
1277 ip->client->interval =
1278 (ip->client->first_sending +
1279 ip->client->config->timeout) - cur_time + 1;
1281 /* Record the number of seconds since we started sending. */
1282 if (interval < 65536)
1283 ip->client->packet.secs = htons(interval);
1285 ip->client->packet.secs = htons(65535);
1286 ip->client->secs = ip->client->packet.secs;
1288 note("DHCPDISCOVER on %s to %s port %d interval %d",
1289 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1290 (int)ip->client->interval);
1292 /* Send out a packet. */
1293 send_packet_unpriv(privfd, &ip->client->packet,
1294 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1296 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1300 * state_panic gets called if we haven't received any offers in a preset
1301 * amount of time. When this happens, we try to use existing leases
1302 * that haven't yet expired, and failing that, we call the client script
1303 * and hope it can do something.
1306 state_panic(void *ipp)
1308 struct interface_info *ip = ipp;
1309 struct client_lease *loop = ip->client->active;
1310 struct client_lease *lp;
1312 note("No DHCPOFFERS received.");
1314 /* We may not have an active lease, but we may have some
1315 predefined leases that we can try. */
1316 if (!ip->client->active && ip->client->leases)
1319 /* Run through the list of leases and see if one can be used. */
1320 while (ip->client->active) {
1321 if (ip->client->active->expiry > cur_time) {
1322 note("Trying recorded lease %s",
1323 piaddr(ip->client->active->address));
1324 /* Run the client script with the existing
1326 script_init("TIMEOUT",
1327 ip->client->active->medium);
1328 script_write_params("new_", ip->client->active);
1329 if (ip->client->alias)
1330 script_write_params("alias_",
1333 /* If the old lease is still good and doesn't
1334 yet need renewal, go into BOUND state and
1335 timeout at the renewal time. */
1338 ip->client->active->renewal) {
1339 ip->client->state = S_BOUND;
1340 note("bound: renewal in %d seconds.",
1341 (int)(ip->client->active->renewal -
1344 ip->client->active->renewal,
1347 ip->client->state = S_BOUND;
1348 note("bound: immediate renewal.");
1351 reinitialize_interfaces();
1357 /* If there are no other leases, give up. */
1358 if (!ip->client->leases) {
1359 ip->client->leases = ip->client->active;
1360 ip->client->active = NULL;
1365 /* Otherwise, put the active lease at the end of the
1366 lease list, and try another lease.. */
1367 for (lp = ip->client->leases; lp->next; lp = lp->next)
1369 lp->next = ip->client->active;
1371 lp->next->next = NULL;
1372 ip->client->active = ip->client->leases;
1373 ip->client->leases = ip->client->leases->next;
1375 /* If we already tried this lease, we've exhausted the
1376 set of leases, so we might as well give up for
1378 if (ip->client->active == loop)
1381 loop = ip->client->active;
1384 /* No leases were available, or what was available didn't work, so
1385 tell the shell script that we failed to allocate an address,
1386 and try again later. */
1387 note("No working leases in persistent database - sleeping.\n");
1388 script_init("FAIL", NULL);
1389 if (ip->client->alias)
1390 script_write_params("alias_", ip->client->alias);
1392 ip->client->state = S_INIT;
1393 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1399 send_request(void *ipp)
1401 struct interface_info *ip = ipp;
1402 struct in_addr from, to;
1405 /* Figure out how long it's been since we started transmitting. */
1406 interval = cur_time - ip->client->first_sending;
1408 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1409 past the reboot timeout, go to INIT and see if we can
1410 DISCOVER an address... */
1411 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1412 means either that we're on a network with no DHCP server,
1413 or that our server is down. In the latter case, assuming
1414 that there is a backup DHCP server, DHCPDISCOVER will get
1415 us a new address, but we could also have successfully
1416 reused our old address. In the former case, we're hosed
1417 anyway. This is not a win-prone situation. */
1418 if ((ip->client->state == S_REBOOTING ||
1419 ip->client->state == S_REQUESTING) &&
1420 interval > ip->client->config->reboot_timeout) {
1422 ip->client->state = S_INIT;
1423 cancel_timeout(send_request, ip);
1428 /* If we're in the reboot state, make sure the media is set up
1430 if (ip->client->state == S_REBOOTING &&
1431 !ip->client->medium &&
1432 ip->client->active->medium ) {
1433 script_init("MEDIUM", ip->client->active->medium);
1435 /* If the medium we chose won't fly, go to INIT state. */
1439 /* Record the medium. */
1440 ip->client->medium = ip->client->active->medium;
1443 /* If the lease has expired, relinquish the address and go back
1444 to the INIT state. */
1445 if (ip->client->state != S_REQUESTING &&
1446 cur_time > ip->client->active->expiry) {
1447 /* Run the client script with the new parameters. */
1448 script_init("EXPIRE", NULL);
1449 script_write_params("old_", ip->client->active);
1450 if (ip->client->alias)
1451 script_write_params("alias_", ip->client->alias);
1454 /* Now do a preinit on the interface so that we can
1455 discover a new address. */
1456 script_init("PREINIT", NULL);
1457 if (ip->client->alias)
1458 script_write_params("alias_", ip->client->alias);
1461 ip->client->state = S_INIT;
1466 /* Do the exponential backoff... */
1467 if (!ip->client->interval)
1468 ip->client->interval = ip->client->config->initial_interval;
1470 ip->client->interval += ((arc4random() >> 2) %
1471 (2 * ip->client->interval));
1473 /* Don't backoff past cutoff. */
1474 if (ip->client->interval >
1475 ip->client->config->backoff_cutoff)
1476 ip->client->interval =
1477 ((ip->client->config->backoff_cutoff / 2) +
1478 ((arc4random() >> 2) % ip->client->interval));
1480 /* If the backoff would take us to the expiry time, just set the
1481 timeout to the expiry time. */
1482 if (ip->client->state != S_REQUESTING &&
1483 cur_time + ip->client->interval >
1484 ip->client->active->expiry)
1485 ip->client->interval =
1486 ip->client->active->expiry - cur_time + 1;
1488 /* If the lease T2 time has elapsed, or if we're not yet bound,
1489 broadcast the DHCPREQUEST rather than unicasting. */
1490 if (ip->client->state == S_REQUESTING ||
1491 ip->client->state == S_REBOOTING ||
1492 cur_time > ip->client->active->rebind)
1493 to.s_addr = INADDR_BROADCAST;
1495 memcpy(&to.s_addr, ip->client->destination.iabuf,
1498 if (ip->client->state != S_REQUESTING &&
1499 ip->client->state != S_REBOOTING)
1500 memcpy(&from, ip->client->active->address.iabuf,
1503 from.s_addr = INADDR_ANY;
1505 /* Record the number of seconds since we started sending. */
1506 if (ip->client->state == S_REQUESTING)
1507 ip->client->packet.secs = ip->client->secs;
1509 if (interval < 65536)
1510 ip->client->packet.secs = htons(interval);
1512 ip->client->packet.secs = htons(65535);
1515 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1518 /* Send out a packet. */
1519 send_packet_unpriv(privfd, &ip->client->packet,
1520 ip->client->packet_length, from, to);
1522 add_timeout(cur_time + ip->client->interval, send_request, ip);
1526 send_decline(void *ipp)
1528 struct interface_info *ip = ipp;
1530 note("DHCPDECLINE on %s to %s port %d", ip->name,
1531 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1533 /* Send out a packet. */
1534 send_packet_unpriv(privfd, &ip->client->packet,
1535 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1539 make_discover(struct interface_info *ip, struct client_lease *lease)
1541 unsigned char discover = DHCPDISCOVER;
1542 struct tree_cache *options[256];
1543 struct tree_cache option_elements[256];
1546 memset(option_elements, 0, sizeof(option_elements));
1547 memset(options, 0, sizeof(options));
1548 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1550 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1551 i = DHO_DHCP_MESSAGE_TYPE;
1552 options[i] = &option_elements[i];
1553 options[i]->value = &discover;
1554 options[i]->len = sizeof(discover);
1555 options[i]->buf_size = sizeof(discover);
1556 options[i]->timeout = 0xFFFFFFFF;
1558 /* Request the options we want */
1559 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1560 options[i] = &option_elements[i];
1561 options[i]->value = ip->client->config->requested_options;
1562 options[i]->len = ip->client->config->requested_option_count;
1563 options[i]->buf_size =
1564 ip->client->config->requested_option_count;
1565 options[i]->timeout = 0xFFFFFFFF;
1567 /* If we had an address, try to get it again. */
1569 ip->client->requested_address = lease->address;
1570 i = DHO_DHCP_REQUESTED_ADDRESS;
1571 options[i] = &option_elements[i];
1572 options[i]->value = lease->address.iabuf;
1573 options[i]->len = lease->address.len;
1574 options[i]->buf_size = lease->address.len;
1575 options[i]->timeout = 0xFFFFFFFF;
1577 ip->client->requested_address.len = 0;
1579 /* Send any options requested in the config file. */
1580 for (i = 0; i < 256; i++)
1582 ip->client->config->send_options[i].data) {
1583 options[i] = &option_elements[i];
1585 ip->client->config->send_options[i].data;
1587 ip->client->config->send_options[i].len;
1588 options[i]->buf_size =
1589 ip->client->config->send_options[i].len;
1590 options[i]->timeout = 0xFFFFFFFF;
1593 /* send host name if not set via config file. */
1594 if (!options[DHO_HOST_NAME]) {
1595 if (hostname[0] != '\0') {
1597 char* posDot = strchr(hostname, '.');
1599 len = posDot - hostname;
1601 len = strlen(hostname);
1602 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1603 options[DHO_HOST_NAME]->value = hostname;
1604 options[DHO_HOST_NAME]->len = len;
1605 options[DHO_HOST_NAME]->buf_size = len;
1606 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1610 /* set unique client identifier */
1611 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1612 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1613 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1614 ip->hw_address.hlen : sizeof(client_ident)-1;
1615 client_ident[0] = ip->hw_address.htype;
1616 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1617 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1618 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1619 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1620 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1621 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1624 /* Set up the option buffer... */
1625 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1626 options, 0, 0, 0, NULL, 0);
1627 if (ip->client->packet_length < BOOTP_MIN_LEN)
1628 ip->client->packet_length = BOOTP_MIN_LEN;
1630 ip->client->packet.op = BOOTREQUEST;
1631 ip->client->packet.htype = ip->hw_address.htype;
1632 ip->client->packet.hlen = ip->hw_address.hlen;
1633 ip->client->packet.hops = 0;
1634 ip->client->packet.xid = arc4random();
1635 ip->client->packet.secs = 0; /* filled in by send_discover. */
1636 ip->client->packet.flags = 0;
1638 memset(&(ip->client->packet.ciaddr),
1639 0, sizeof(ip->client->packet.ciaddr));
1640 memset(&(ip->client->packet.yiaddr),
1641 0, sizeof(ip->client->packet.yiaddr));
1642 memset(&(ip->client->packet.siaddr),
1643 0, sizeof(ip->client->packet.siaddr));
1644 memset(&(ip->client->packet.giaddr),
1645 0, sizeof(ip->client->packet.giaddr));
1646 memcpy(ip->client->packet.chaddr,
1647 ip->hw_address.haddr, ip->hw_address.hlen);
1652 make_request(struct interface_info *ip, struct client_lease * lease)
1654 unsigned char request = DHCPREQUEST;
1655 struct tree_cache *options[256];
1656 struct tree_cache option_elements[256];
1659 memset(options, 0, sizeof(options));
1660 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1662 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1663 i = DHO_DHCP_MESSAGE_TYPE;
1664 options[i] = &option_elements[i];
1665 options[i]->value = &request;
1666 options[i]->len = sizeof(request);
1667 options[i]->buf_size = sizeof(request);
1668 options[i]->timeout = 0xFFFFFFFF;
1670 /* Request the options we want */
1671 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1672 options[i] = &option_elements[i];
1673 options[i]->value = ip->client->config->requested_options;
1674 options[i]->len = ip->client->config->requested_option_count;
1675 options[i]->buf_size =
1676 ip->client->config->requested_option_count;
1677 options[i]->timeout = 0xFFFFFFFF;
1679 /* If we are requesting an address that hasn't yet been assigned
1680 to us, use the DHCP Requested Address option. */
1681 if (ip->client->state == S_REQUESTING) {
1682 /* Send back the server identifier... */
1683 i = DHO_DHCP_SERVER_IDENTIFIER;
1684 options[i] = &option_elements[i];
1685 options[i]->value = lease->options[i].data;
1686 options[i]->len = lease->options[i].len;
1687 options[i]->buf_size = lease->options[i].len;
1688 options[i]->timeout = 0xFFFFFFFF;
1690 if (ip->client->state == S_REQUESTING ||
1691 ip->client->state == S_REBOOTING) {
1692 ip->client->requested_address = lease->address;
1693 i = DHO_DHCP_REQUESTED_ADDRESS;
1694 options[i] = &option_elements[i];
1695 options[i]->value = lease->address.iabuf;
1696 options[i]->len = lease->address.len;
1697 options[i]->buf_size = lease->address.len;
1698 options[i]->timeout = 0xFFFFFFFF;
1700 ip->client->requested_address.len = 0;
1702 /* Send any options requested in the config file. */
1703 for (i = 0; i < 256; i++)
1705 ip->client->config->send_options[i].data) {
1706 options[i] = &option_elements[i];
1708 ip->client->config->send_options[i].data;
1710 ip->client->config->send_options[i].len;
1711 options[i]->buf_size =
1712 ip->client->config->send_options[i].len;
1713 options[i]->timeout = 0xFFFFFFFF;
1716 /* send host name if not set via config file. */
1717 if (!options[DHO_HOST_NAME]) {
1718 if (hostname[0] != '\0') {
1720 char* posDot = strchr(hostname, '.');
1722 len = posDot - hostname;
1724 len = strlen(hostname);
1725 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1726 options[DHO_HOST_NAME]->value = hostname;
1727 options[DHO_HOST_NAME]->len = len;
1728 options[DHO_HOST_NAME]->buf_size = len;
1729 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1733 /* set unique client identifier */
1734 char client_ident[sizeof(struct hardware)];
1735 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1736 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1737 ip->hw_address.hlen : sizeof(client_ident)-1;
1738 client_ident[0] = ip->hw_address.htype;
1739 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1740 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1741 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1742 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1743 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1744 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1747 /* Set up the option buffer... */
1748 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1749 options, 0, 0, 0, NULL, 0);
1750 if (ip->client->packet_length < BOOTP_MIN_LEN)
1751 ip->client->packet_length = BOOTP_MIN_LEN;
1753 ip->client->packet.op = BOOTREQUEST;
1754 ip->client->packet.htype = ip->hw_address.htype;
1755 ip->client->packet.hlen = ip->hw_address.hlen;
1756 ip->client->packet.hops = 0;
1757 ip->client->packet.xid = ip->client->xid;
1758 ip->client->packet.secs = 0; /* Filled in by send_request. */
1760 /* If we own the address we're requesting, put it in ciaddr;
1761 otherwise set ciaddr to zero. */
1762 if (ip->client->state == S_BOUND ||
1763 ip->client->state == S_RENEWING ||
1764 ip->client->state == S_REBINDING) {
1765 memcpy(&ip->client->packet.ciaddr,
1766 lease->address.iabuf, lease->address.len);
1767 ip->client->packet.flags = 0;
1769 memset(&ip->client->packet.ciaddr, 0,
1770 sizeof(ip->client->packet.ciaddr));
1771 ip->client->packet.flags = 0;
1774 memset(&ip->client->packet.yiaddr, 0,
1775 sizeof(ip->client->packet.yiaddr));
1776 memset(&ip->client->packet.siaddr, 0,
1777 sizeof(ip->client->packet.siaddr));
1778 memset(&ip->client->packet.giaddr, 0,
1779 sizeof(ip->client->packet.giaddr));
1780 memcpy(ip->client->packet.chaddr,
1781 ip->hw_address.haddr, ip->hw_address.hlen);
1785 make_decline(struct interface_info *ip, struct client_lease *lease)
1787 struct tree_cache *options[256], message_type_tree;
1788 struct tree_cache requested_address_tree;
1789 struct tree_cache server_id_tree, client_id_tree;
1790 unsigned char decline = DHCPDECLINE;
1793 memset(options, 0, sizeof(options));
1794 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1796 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1797 i = DHO_DHCP_MESSAGE_TYPE;
1798 options[i] = &message_type_tree;
1799 options[i]->value = &decline;
1800 options[i]->len = sizeof(decline);
1801 options[i]->buf_size = sizeof(decline);
1802 options[i]->timeout = 0xFFFFFFFF;
1804 /* Send back the server identifier... */
1805 i = DHO_DHCP_SERVER_IDENTIFIER;
1806 options[i] = &server_id_tree;
1807 options[i]->value = lease->options[i].data;
1808 options[i]->len = lease->options[i].len;
1809 options[i]->buf_size = lease->options[i].len;
1810 options[i]->timeout = 0xFFFFFFFF;
1812 /* Send back the address we're declining. */
1813 i = DHO_DHCP_REQUESTED_ADDRESS;
1814 options[i] = &requested_address_tree;
1815 options[i]->value = lease->address.iabuf;
1816 options[i]->len = lease->address.len;
1817 options[i]->buf_size = lease->address.len;
1818 options[i]->timeout = 0xFFFFFFFF;
1820 /* Send the uid if the user supplied one. */
1821 i = DHO_DHCP_CLIENT_IDENTIFIER;
1822 if (ip->client->config->send_options[i].len) {
1823 options[i] = &client_id_tree;
1824 options[i]->value = ip->client->config->send_options[i].data;
1825 options[i]->len = ip->client->config->send_options[i].len;
1826 options[i]->buf_size = ip->client->config->send_options[i].len;
1827 options[i]->timeout = 0xFFFFFFFF;
1831 /* Set up the option buffer... */
1832 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1833 options, 0, 0, 0, NULL, 0);
1834 if (ip->client->packet_length < BOOTP_MIN_LEN)
1835 ip->client->packet_length = BOOTP_MIN_LEN;
1837 ip->client->packet.op = BOOTREQUEST;
1838 ip->client->packet.htype = ip->hw_address.htype;
1839 ip->client->packet.hlen = ip->hw_address.hlen;
1840 ip->client->packet.hops = 0;
1841 ip->client->packet.xid = ip->client->xid;
1842 ip->client->packet.secs = 0; /* Filled in by send_request. */
1843 ip->client->packet.flags = 0;
1845 /* ciaddr must always be zero. */
1846 memset(&ip->client->packet.ciaddr, 0,
1847 sizeof(ip->client->packet.ciaddr));
1848 memset(&ip->client->packet.yiaddr, 0,
1849 sizeof(ip->client->packet.yiaddr));
1850 memset(&ip->client->packet.siaddr, 0,
1851 sizeof(ip->client->packet.siaddr));
1852 memset(&ip->client->packet.giaddr, 0,
1853 sizeof(ip->client->packet.giaddr));
1854 memcpy(ip->client->packet.chaddr,
1855 ip->hw_address.haddr, ip->hw_address.hlen);
1859 free_client_lease(struct client_lease *lease)
1863 if (lease->server_name)
1864 free(lease->server_name);
1865 if (lease->filename)
1866 free(lease->filename);
1867 for (i = 0; i < 256; i++) {
1868 if (lease->options[i].len)
1869 free(lease->options[i].data);
1877 rewrite_client_leases(void)
1879 struct client_lease *lp;
1880 cap_rights_t rights;
1883 leaseFile = fopen(path_dhclient_db, "w");
1885 error("can't create %s: %m", path_dhclient_db);
1886 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1887 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1888 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1890 error("can't limit lease descriptor: %m");
1892 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1894 error("can't limit lease descriptor fcntls: %m");
1901 for (lp = ifi->client->leases; lp; lp = lp->next)
1902 write_client_lease(ifi, lp, 1);
1903 if (ifi->client->active)
1904 write_client_lease(ifi, ifi->client->active, 1);
1907 ftruncate(fileno(leaseFile), ftello(leaseFile));
1908 fsync(fileno(leaseFile));
1912 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1915 static int leases_written;
1920 if (leases_written++ > 20) {
1921 rewrite_client_leases();
1926 /* If the lease came from the config file, we don't need to stash
1927 a copy in the lease database. */
1928 if (lease->is_static)
1931 if (!leaseFile) { /* XXX */
1932 leaseFile = fopen(path_dhclient_db, "w");
1934 error("can't create %s: %m", path_dhclient_db);
1937 fprintf(leaseFile, "lease {\n");
1938 if (lease->is_bootp)
1939 fprintf(leaseFile, " bootp;\n");
1940 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1941 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1942 if (lease->nextserver.len == sizeof(inaddr_any) &&
1943 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1944 sizeof(inaddr_any)))
1945 fprintf(leaseFile, " next-server %s;\n",
1946 piaddr(lease->nextserver));
1947 if (lease->filename)
1948 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1949 if (lease->server_name)
1950 fprintf(leaseFile, " server-name \"%s\";\n",
1951 lease->server_name);
1953 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1954 for (i = 0; i < 256; i++)
1955 if (lease->options[i].len)
1956 fprintf(leaseFile, " option %s %s;\n",
1957 dhcp_options[i].name,
1958 pretty_print_option(i, lease->options[i].data,
1959 lease->options[i].len, 1, 1));
1961 t = gmtime(&lease->renewal);
1962 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1963 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1964 t->tm_hour, t->tm_min, t->tm_sec);
1965 t = gmtime(&lease->rebind);
1966 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1967 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1968 t->tm_hour, t->tm_min, t->tm_sec);
1969 t = gmtime(&lease->expiry);
1970 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1971 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1972 t->tm_hour, t->tm_min, t->tm_sec);
1973 fprintf(leaseFile, "}\n");
1978 script_init(char *reason, struct string_list *medium)
1980 size_t len, mediumlen = 0;
1981 struct imsg_hdr hdr;
1985 if (medium != NULL && medium->string != NULL)
1986 mediumlen = strlen(medium->string);
1988 hdr.code = IMSG_SCRIPT_INIT;
1989 hdr.len = sizeof(struct imsg_hdr) +
1990 sizeof(size_t) + mediumlen +
1991 sizeof(size_t) + strlen(reason);
1993 if ((buf = buf_open(hdr.len)) == NULL)
1994 error("buf_open: %m");
1997 errs += buf_add(buf, &hdr, sizeof(hdr));
1998 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2000 errs += buf_add(buf, medium->string, mediumlen);
2001 len = strlen(reason);
2002 errs += buf_add(buf, &len, sizeof(len));
2003 errs += buf_add(buf, reason, len);
2006 error("buf_add: %m");
2008 if (buf_close(privfd, buf) == -1)
2009 error("buf_close: %m");
2013 priv_script_init(char *reason, char *medium)
2015 struct interface_info *ip = ifi;
2018 ip->client->scriptEnvsize = 100;
2019 if (ip->client->scriptEnv == NULL)
2020 ip->client->scriptEnv =
2021 malloc(ip->client->scriptEnvsize * sizeof(char *));
2022 if (ip->client->scriptEnv == NULL)
2023 error("script_init: no memory for environment");
2025 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2026 if (ip->client->scriptEnv[0] == NULL)
2027 error("script_init: no memory for environment");
2029 ip->client->scriptEnv[1] = NULL;
2031 script_set_env(ip->client, "", "interface", ip->name);
2034 script_set_env(ip->client, "", "medium", medium);
2036 script_set_env(ip->client, "", "reason", reason);
2041 priv_script_write_params(char *prefix, struct client_lease *lease)
2043 struct interface_info *ip = ifi;
2044 u_int8_t dbuf[1500], *dp = NULL;
2049 script_set_env(ip->client, prefix, "ip_address",
2050 piaddr(lease->address));
2052 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2054 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2055 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2057 dp = lease->options[DHO_SUBNET_MASK].data;
2058 len = lease->options[DHO_SUBNET_MASK].len;
2060 if (len && (len < sizeof(lease->address.iabuf))) {
2061 struct iaddr netmask, subnet, broadcast;
2063 memcpy(netmask.iabuf, dp, len);
2065 subnet = subnet_number(lease->address, netmask);
2067 script_set_env(ip->client, prefix, "network_number",
2069 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2070 broadcast = broadcast_addr(subnet, netmask);
2072 script_set_env(ip->client, prefix,
2073 "broadcast_address",
2079 if (lease->filename)
2080 script_set_env(ip->client, prefix, "filename", lease->filename);
2081 if (lease->server_name)
2082 script_set_env(ip->client, prefix, "server_name",
2083 lease->server_name);
2084 for (i = 0; i < 256; i++) {
2087 if (ip->client->config->defaults[i].len) {
2088 if (lease->options[i].len) {
2090 ip->client->config->default_actions[i]) {
2091 case ACTION_DEFAULT:
2092 dp = lease->options[i].data;
2093 len = lease->options[i].len;
2095 case ACTION_SUPERSEDE:
2098 config->defaults[i].data;
2100 config->defaults[i].len;
2102 case ACTION_PREPEND:
2104 config->defaults[i].len +
2105 lease->options[i].len;
2106 if (len >= sizeof(dbuf)) {
2107 warning("no space to %s %s",
2109 dhcp_options[i].name);
2115 config->defaults[i].data,
2117 config->defaults[i].len);
2118 memcpy(dp + ip->client->
2119 config->defaults[i].len,
2120 lease->options[i].data,
2121 lease->options[i].len);
2126 * When we append, we assume that we're
2127 * appending to text. Some MS servers
2128 * include a NUL byte at the end of
2129 * the search string provided.
2132 config->defaults[i].len +
2133 lease->options[i].len;
2134 if (len >= sizeof(dbuf)) {
2135 warning("no space to %s %s",
2137 dhcp_options[i].name);
2141 lease->options[i].data,
2142 lease->options[i].len);
2143 for (dp = dbuf + lease->options[i].len;
2144 dp > dbuf; dp--, len--)
2149 config->defaults[i].data,
2151 config->defaults[i].len);
2157 config->defaults[i].data;
2159 config->defaults[i].len;
2161 } else if (lease->options[i].len) {
2162 len = lease->options[i].len;
2163 dp = lease->options[i].data;
2170 if (dhcp_option_ev_name(name, sizeof(name),
2172 script_set_env(ip->client, prefix, name,
2173 pretty_print_option(i, dp, len, 0, 0));
2176 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2177 script_set_env(ip->client, prefix, "expiry", tbuf);
2181 script_write_params(char *prefix, struct client_lease *lease)
2183 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2184 struct imsg_hdr hdr;
2188 if (lease->filename != NULL)
2189 fn_len = strlen(lease->filename);
2190 if (lease->server_name != NULL)
2191 sn_len = strlen(lease->server_name);
2193 pr_len = strlen(prefix);
2195 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2196 hdr.len = sizeof(hdr) + sizeof(*lease) +
2197 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2198 sizeof(pr_len) + pr_len;
2200 for (i = 0; i < 256; i++) {
2201 hdr.len += sizeof(lease->options[i].len);
2202 hdr.len += lease->options[i].len;
2205 scripttime = time(NULL);
2207 if ((buf = buf_open(hdr.len)) == NULL)
2208 error("buf_open: %m");
2211 errs += buf_add(buf, &hdr, sizeof(hdr));
2212 errs += buf_add(buf, lease, sizeof(*lease));
2213 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2214 errs += buf_add(buf, lease->filename, fn_len);
2215 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2216 errs += buf_add(buf, lease->server_name, sn_len);
2217 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2218 errs += buf_add(buf, prefix, pr_len);
2220 for (i = 0; i < 256; i++) {
2221 errs += buf_add(buf, &lease->options[i].len,
2222 sizeof(lease->options[i].len));
2223 errs += buf_add(buf, lease->options[i].data,
2224 lease->options[i].len);
2228 error("buf_add: %m");
2230 if (buf_close(privfd, buf) == -1)
2231 error("buf_close: %m");
2237 struct imsg_hdr hdr;
2241 hdr.code = IMSG_SCRIPT_GO;
2242 hdr.len = sizeof(struct imsg_hdr);
2244 if ((buf = buf_open(hdr.len)) == NULL)
2245 error("buf_open: %m");
2247 if (buf_add(buf, &hdr, sizeof(hdr)))
2248 error("buf_add: %m");
2250 if (buf_close(privfd, buf) == -1)
2251 error("buf_close: %m");
2253 bzero(&hdr, sizeof(hdr));
2254 buf_read(privfd, &hdr, sizeof(hdr));
2255 if (hdr.code != IMSG_SCRIPT_GO_RET)
2256 error("unexpected msg type %u", hdr.code);
2257 if (hdr.len != sizeof(hdr) + sizeof(int))
2258 error("received corrupted message");
2259 buf_read(privfd, &ret, sizeof(ret));
2261 scripttime = time(NULL);
2267 priv_script_go(void)
2269 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2270 static char client_path[] = CLIENT_PATH;
2271 struct interface_info *ip = ifi;
2272 int pid, wpid, wstatus;
2274 scripttime = time(NULL);
2277 scriptName = ip->client->config->script_name;
2278 envp = ip->client->scriptEnv;
2280 scriptName = top_level_config.script_name;
2282 epp[1] = client_path;
2287 argv[0] = scriptName;
2296 wpid = wait(&wstatus);
2297 } while (wpid != pid && wpid > 0);
2303 execve(scriptName, argv, envp);
2304 error("execve (%s, ...): %m", scriptName);
2308 script_flush_env(ip->client);
2310 return (wstatus & 0xff);
2314 script_set_env(struct client_state *client, const char *prefix,
2315 const char *name, const char *value)
2320 /* No `` or $() command substitution allowed in environment values! */
2321 for (j=0; j < strlen(value); j++)
2325 warning("illegal character (%c) in value '%s'",
2327 /* Ignore this option */
2331 namelen = strlen(name);
2333 for (i = 0; client->scriptEnv[i]; i++)
2334 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2335 client->scriptEnv[i][namelen] == '=')
2338 if (client->scriptEnv[i])
2339 /* Reuse the slot. */
2340 free(client->scriptEnv[i]);
2342 /* New variable. Expand if necessary. */
2343 if (i >= client->scriptEnvsize - 1) {
2344 char **newscriptEnv;
2345 int newscriptEnvsize = client->scriptEnvsize + 50;
2347 newscriptEnv = realloc(client->scriptEnv,
2349 if (newscriptEnv == NULL) {
2350 free(client->scriptEnv);
2351 client->scriptEnv = NULL;
2352 client->scriptEnvsize = 0;
2353 error("script_set_env: no memory for variable");
2355 client->scriptEnv = newscriptEnv;
2356 client->scriptEnvsize = newscriptEnvsize;
2358 /* need to set the NULL pointer at end of array beyond
2360 client->scriptEnv[i + 1] = NULL;
2362 /* Allocate space and format the variable in the appropriate slot. */
2363 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2365 if (client->scriptEnv[i] == NULL)
2366 error("script_set_env: no memory for variable assignment");
2367 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2368 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2372 script_flush_env(struct client_state *client)
2376 for (i = 0; client->scriptEnv[i]; i++) {
2377 free(client->scriptEnv[i]);
2378 client->scriptEnv[i] = NULL;
2380 client->scriptEnvsize = 0;
2384 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2388 for (i = 0; option->name[i]; i++) {
2389 if (i + 1 == buflen)
2391 if (option->name[i] == '-')
2394 buf[i] = option->name[i];
2404 static int state = 0;
2405 cap_rights_t rights;
2407 if (no_daemon || state)
2412 /* Stop logging to stderr... */
2415 if (daemon(1, 0) == -1)
2418 cap_rights_init(&rights);
2420 if (pidfile != NULL) {
2421 pidfile_write(pidfile);
2422 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2424 error("can't limit pidfile descriptor: %m");
2428 /* we are chrooted, daemon(3) fails to open /dev/null */
2430 dup2(nullfd, STDIN_FILENO);
2431 dup2(nullfd, STDOUT_FILENO);
2432 dup2(nullfd, STDERR_FILENO);
2437 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2438 error("can't limit stdin: %m");
2439 cap_rights_init(&rights, CAP_WRITE);
2440 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2441 error("can't limit stdout: %m");
2442 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2443 error("can't limit stderr: %m");
2447 check_option(struct client_lease *l, int option)
2452 /* we use this, since this is what gets passed to dhclient-script */
2454 opbuf = pretty_print_option(option, l->options[option].data,
2455 l->options[option].len, 0, 0);
2457 sbuf = option_as_string(option, l->options[option].data,
2458 l->options[option].len);
2461 case DHO_SUBNET_MASK:
2462 case DHO_TIME_SERVERS:
2463 case DHO_NAME_SERVERS:
2465 case DHO_DOMAIN_NAME_SERVERS:
2466 case DHO_LOG_SERVERS:
2467 case DHO_COOKIE_SERVERS:
2468 case DHO_LPR_SERVERS:
2469 case DHO_IMPRESS_SERVERS:
2470 case DHO_RESOURCE_LOCATION_SERVERS:
2471 case DHO_SWAP_SERVER:
2472 case DHO_BROADCAST_ADDRESS:
2473 case DHO_NIS_SERVERS:
2474 case DHO_NTP_SERVERS:
2475 case DHO_NETBIOS_NAME_SERVERS:
2476 case DHO_NETBIOS_DD_SERVER:
2477 case DHO_FONT_SERVERS:
2478 case DHO_DHCP_SERVER_IDENTIFIER:
2479 case DHO_NISPLUS_SERVERS:
2480 case DHO_MOBILE_IP_HOME_AGENT:
2481 case DHO_SMTP_SERVER:
2482 case DHO_POP_SERVER:
2483 case DHO_NNTP_SERVER:
2484 case DHO_WWW_SERVER:
2485 case DHO_FINGER_SERVER:
2486 case DHO_IRC_SERVER:
2487 case DHO_STREETTALK_SERVER:
2488 case DHO_STREETTALK_DA_SERVER:
2489 if (!ipv4addrs(opbuf)) {
2490 warning("Invalid IP address in option: %s", opbuf);
2495 case DHO_NIS_DOMAIN:
2496 case DHO_NISPLUS_DOMAIN:
2497 case DHO_TFTP_SERVER_NAME:
2498 if (!res_hnok(sbuf)) {
2499 warning("Bogus Host Name option %d: %s (%s)", option,
2501 l->options[option].len = 0;
2502 free(l->options[option].data);
2505 case DHO_DOMAIN_NAME:
2506 case DHO_DOMAIN_SEARCH:
2507 if (!res_hnok(sbuf)) {
2508 if (!check_search(sbuf)) {
2509 warning("Bogus domain search list %d: %s (%s)",
2510 option, sbuf, opbuf);
2511 l->options[option].len = 0;
2512 free(l->options[option].data);
2517 case DHO_TIME_OFFSET:
2519 case DHO_MERIT_DUMP:
2521 case DHO_EXTENSIONS_PATH:
2522 case DHO_IP_FORWARDING:
2523 case DHO_NON_LOCAL_SOURCE_ROUTING:
2524 case DHO_POLICY_FILTER:
2525 case DHO_MAX_DGRAM_REASSEMBLY:
2526 case DHO_DEFAULT_IP_TTL:
2527 case DHO_PATH_MTU_AGING_TIMEOUT:
2528 case DHO_PATH_MTU_PLATEAU_TABLE:
2529 case DHO_INTERFACE_MTU:
2530 case DHO_ALL_SUBNETS_LOCAL:
2531 case DHO_PERFORM_MASK_DISCOVERY:
2532 case DHO_MASK_SUPPLIER:
2533 case DHO_ROUTER_DISCOVERY:
2534 case DHO_ROUTER_SOLICITATION_ADDRESS:
2535 case DHO_STATIC_ROUTES:
2536 case DHO_TRAILER_ENCAPSULATION:
2537 case DHO_ARP_CACHE_TIMEOUT:
2538 case DHO_IEEE802_3_ENCAPSULATION:
2539 case DHO_DEFAULT_TCP_TTL:
2540 case DHO_TCP_KEEPALIVE_INTERVAL:
2541 case DHO_TCP_KEEPALIVE_GARBAGE:
2542 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2543 case DHO_NETBIOS_NODE_TYPE:
2544 case DHO_NETBIOS_SCOPE:
2545 case DHO_X_DISPLAY_MANAGER:
2546 case DHO_DHCP_REQUESTED_ADDRESS:
2547 case DHO_DHCP_LEASE_TIME:
2548 case DHO_DHCP_OPTION_OVERLOAD:
2549 case DHO_DHCP_MESSAGE_TYPE:
2550 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2551 case DHO_DHCP_MESSAGE:
2552 case DHO_DHCP_MAX_MESSAGE_SIZE:
2553 case DHO_DHCP_RENEWAL_TIME:
2554 case DHO_DHCP_REBINDING_TIME:
2555 case DHO_DHCP_CLASS_IDENTIFIER:
2556 case DHO_DHCP_CLIENT_IDENTIFIER:
2557 case DHO_BOOTFILE_NAME:
2558 case DHO_DHCP_USER_CLASS_ID:
2561 case DHO_CLASSLESS_ROUTES:
2562 return (check_classless_option(l->options[option].data,
2563 l->options[option].len));
2565 warning("unknown dhcp option value 0x%x", option);
2566 return (unknown_ok);
2570 /* RFC 3442 The Classless Static Routes option checks */
2572 check_classless_option(unsigned char *data, int len)
2575 unsigned char width;
2576 in_addr_t addr, mask;
2579 warning("Too small length: %d", len);
2587 } else if (width < 9) {
2588 addr = (in_addr_t)(data[i] << 24);
2590 } else if (width < 17) {
2591 addr = (in_addr_t)(data[i] << 24) +
2592 (in_addr_t)(data[i + 1] << 16);
2594 } else if (width < 25) {
2595 addr = (in_addr_t)(data[i] << 24) +
2596 (in_addr_t)(data[i + 1] << 16) +
2597 (in_addr_t)(data[i + 2] << 8);
2599 } else if (width < 33) {
2600 addr = (in_addr_t)(data[i] << 24) +
2601 (in_addr_t)(data[i + 1] << 16) +
2602 (in_addr_t)(data[i + 2] << 8) +
2606 warning("Incorrect subnet width: %d", width);
2609 mask = (in_addr_t)(~0) << (32 - width);
2615 * ... After deriving a subnet number and subnet mask
2616 * from each destination descriptor, the DHCP client
2617 * MUST zero any bits in the subnet number where the
2618 * corresponding bit in the mask is zero...
2620 if ((addr & mask) != addr) {
2622 data[i - 1] = (unsigned char)(
2623 (addr >> (((32 - width)/8)*8)) & 0xFF);
2628 warning("Incorrect data length: %d (must be %d)", len, i);
2635 res_hnok(const char *dn)
2637 int pch = PERIOD, ch = *dn++;
2639 while (ch != '\0') {
2642 if (periodchar(ch)) {
2644 } else if (periodchar(pch)) {
2645 if (!borderchar(ch))
2647 } else if (periodchar(nch) || nch == '\0') {
2648 if (!borderchar(ch))
2651 if (!middlechar(ch))
2660 check_search(const char *srch)
2662 int pch = PERIOD, ch = *srch++;
2665 /* 256 char limit re resolv.conf(5) */
2666 if (strlen(srch) > 256)
2669 while (whitechar(ch))
2672 while (ch != '\0') {
2675 if (periodchar(ch) || whitechar(ch)) {
2677 } else if (periodchar(pch)) {
2678 if (!borderchar(ch))
2680 } else if (periodchar(nch) || nch == '\0') {
2681 if (!borderchar(ch))
2684 if (!middlechar(ch))
2687 if (!whitechar(ch)) {
2690 while (whitechar(nch)) {
2699 /* 6 domain limit re resolv.conf(5) */
2705 /* Does buf consist only of dotted decimal ipv4 addrs?
2706 * return how many if so,
2707 * otherwise, return 0
2710 ipv4addrs(char * buf)
2715 while (inet_aton(buf, &jnk) == 1){
2717 while (periodchar(*buf) || digitchar(*buf))
2729 option_as_string(unsigned int code, unsigned char *data, int len)
2731 static char optbuf[32768]; /* XXX */
2733 int opleft = sizeof(optbuf);
2734 unsigned char *dp = data;
2737 error("option_as_string: bad code %d", code);
2739 for (; dp < data + len; dp++) {
2740 if (!isascii(*dp) || !isprint(*dp)) {
2741 if (dp + 1 != data + len || *dp != 0) {
2742 snprintf(op, opleft, "\\%03o", *dp);
2746 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2747 *dp == '`' || *dp == '\\') {
2761 warning("dhcp option too large");
2766 fork_privchld(int fd, int fd2)
2768 struct pollfd pfd[1];
2773 error("cannot fork");
2780 setproctitle("%s [priv]", ifi->name);
2783 dup2(nullfd, STDIN_FILENO);
2784 dup2(nullfd, STDOUT_FILENO);
2785 dup2(nullfd, STDERR_FILENO);
2793 pfd[0].events = POLLIN;
2794 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2796 error("poll error");
2798 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2801 dispatch_imsg(ifi, fd);