1 /* $OpenBSD: dhclient.c,v 1.63 2005/02/06 17:10:13 krw Exp $ */
4 * Copyright 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 1995, 1996, 1997, 1998, 1999
6 * The Internet Software Consortium. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of The Internet Software Consortium nor the names
18 * of its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * This software has been written for the Internet Software Consortium
36 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37 * Enterprises. To learn more about the Internet Software Consortium,
38 * see ``http://www.vix.com/isc''. To learn more about Vixie
39 * Enterprises, see ``http://www.vix.com''.
41 * This client was substantially modified and enhanced by Elliot Poger
42 * for use on Linux while he was working on the MosquitoNet project at
45 * The current version owes much to Elliot's Linux enhancements, but
46 * was substantially reorganized and partially rewritten by Ted Lemon
47 * so as to use the same networking framework that the Internet Software
48 * Consortium DHCP server uses. Much system-specific configuration code
49 * was moved into a shell script so that as support for more operating
50 * systems is added, it will not be necessary to port and maintain
51 * system-specific configuration code to these operating systems - instead,
52 * the shell script can invoke the native tools to accomplish the same
56 #include <sys/cdefs.h>
57 __FBSDID("$FreeBSD$");
62 #include <sys/capsicum.h>
64 #include <net80211/ieee80211_freebsd.h>
66 #ifndef _PATH_VAREMPTY
67 #define _PATH_VAREMPTY "/var/empty"
71 #define hyphenchar(c) ((c) == 0x2d)
72 #define bslashchar(c) ((c) == 0x5c)
73 #define periodchar(c) ((c) == PERIOD)
74 #define asterchar(c) ((c) == 0x2a)
75 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
76 ((c) >= 0x61 && (c) <= 0x7a))
77 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
78 #define whitechar(c) ((c) == ' ' || (c) == '\t')
80 #define borderchar(c) (alphachar(c) || digitchar(c))
81 #define middlechar(c) (borderchar(c) || hyphenchar(c))
82 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
84 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
87 time_t default_lease_time = 43200; /* 12 hours... */
89 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
90 char *path_dhclient_db = NULL;
96 char hostname[_POSIX_HOST_NAME_MAX + 1];
98 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
99 struct in_addr inaddr_any, inaddr_broadcast;
101 char *path_dhclient_pidfile;
102 struct pidfh *pidfile;
105 * ASSERT_STATE() does nothing now; it used to be
106 * assert (state_is == state_shouldbe).
108 #define ASSERT_STATE(state_is, state_shouldbe) {}
111 * We need to check that the expiry, renewal and rebind times are not beyond
112 * the end of time (~2038 when a 32-bit time_t is being used).
114 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
121 struct interface_info *ifi;
123 int findproto(char *, int);
124 struct sockaddr *get_ifa(char *, int);
125 void routehandler(struct protocol *);
127 int check_option(struct client_lease *l, int option);
128 int check_classless_option(unsigned char *data, int len);
129 int ipv4addrs(char * buf);
130 int res_hnok(const char *dn);
131 int check_search(const char *srch);
132 char *option_as_string(unsigned int code, unsigned char *data, int len);
133 int fork_privchld(int, int);
136 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
137 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
139 static time_t scripttime;
142 findproto(char *cp, int n)
149 for (i = 1; i; i <<= 1) {
151 sa = (struct sockaddr *)cp;
157 if (sa->sa_family == AF_INET)
159 if (sa->sa_family == AF_INET6)
172 get_ifa(char *cp, int n)
179 for (i = 1; i; i <<= 1)
181 sa = (struct sockaddr *)cp;
190 struct iaddr defaddr = { 4 };
196 struct interface_info *ifi = arg;
199 * Clear existing state.
201 if (ifi->client->active != NULL) {
202 script_init("EXPIRE", NULL);
203 script_write_params("old_",
204 ifi->client->active);
205 if (ifi->client->alias)
206 script_write_params("alias_",
210 ifi->client->state = S_INIT;
215 routehandler(struct protocol *p)
217 char msg[2048], *addr;
218 struct rt_msghdr *rtm;
219 struct if_msghdr *ifm;
220 struct ifa_msghdr *ifam;
221 struct if_announcemsghdr *ifan;
222 struct ieee80211_join_event *jev;
223 struct client_lease *l;
224 time_t t = time(NULL);
230 n = read(routefd, &msg, sizeof(msg));
231 rtm = (struct rt_msghdr *)msg;
232 if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
233 rtm->rtm_version != RTM_VERSION)
236 switch (rtm->rtm_type) {
239 ifam = (struct ifa_msghdr *)rtm;
241 if (ifam->ifam_index != ifi->index)
243 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
245 if (scripttime == 0 || t < scripttime + 10)
248 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
252 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
253 error("king bula sez: len mismatch");
254 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
255 if (addr_eq(a, defaddr))
258 for (l = ifi->client->active; l != NULL; l = l->next)
259 if (addr_eq(a, l->address))
262 if (l == NULL) /* added/deleted addr is not the one we set */
265 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
266 if (rtm->rtm_type == RTM_NEWADDR) {
268 * XXX: If someone other than us adds our address,
269 * should we assume they are taking over from us,
270 * delete the lease record, and exit without modifying
273 warning("My address (%s) was re-added", addr);
275 warning("My address (%s) was deleted, dhclient exiting",
281 ifm = (struct if_msghdr *)rtm;
282 if (ifm->ifm_index != ifi->index)
284 if ((rtm->rtm_flags & RTF_UP) == 0) {
285 warning("Interface %s is down, dhclient exiting",
289 linkstat = interface_link_status(ifi->name);
290 if (linkstat != ifi->linkstat) {
291 debug("%s link state %s -> %s", ifi->name,
292 ifi->linkstat ? "up" : "down",
293 linkstat ? "up" : "down");
294 ifi->linkstat = linkstat;
300 ifan = (struct if_announcemsghdr *)rtm;
301 if (ifan->ifan_what == IFAN_DEPARTURE &&
302 ifan->ifan_index == ifi->index) {
303 warning("Interface %s is gone, dhclient exiting",
309 ifan = (struct if_announcemsghdr *)rtm;
310 if (ifan->ifan_index != ifi->index)
312 switch (ifan->ifan_what) {
313 case RTM_IEEE80211_ASSOC:
314 case RTM_IEEE80211_REASSOC:
316 * Use assoc/reassoc event to kick state machine
317 * in case we roam. Otherwise fall back to the
318 * normal state machine just like a wired network.
320 jev = (struct ieee80211_join_event *) &ifan[1];
321 if (memcmp(curbssid, jev->iev_addr, 6)) {
325 memcpy(curbssid, jev->iev_addr, 6);
335 script_init("FAIL", NULL);
336 if (ifi->client->alias)
337 script_write_params("alias_", ifi->client->alias);
340 pidfile_remove(pidfile);
345 main(int argc, char *argv[])
347 extern char *__progname;
348 int ch, fd, quiet = 0, i = 0;
350 int immediate_daemon = 0;
355 /* Initially, log errors to stderr as well as to syslogd. */
356 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
357 setlogmask(LOG_UPTO(LOG_DEBUG));
359 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
362 immediate_daemon = 1;
365 path_dhclient_conf = optarg;
371 path_dhclient_db = optarg;
374 path_dhclient_pidfile = optarg;
392 if (path_dhclient_pidfile == NULL) {
393 asprintf(&path_dhclient_pidfile,
394 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
395 if (path_dhclient_pidfile == NULL)
398 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
399 if (pidfile == NULL) {
401 error("dhclient already running, pid: %d.", otherpid);
403 error("dhclient already running.");
404 warning("Cannot open or create pidfile: %m");
407 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
409 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
410 error("Interface name too long");
411 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
412 _PATH_DHCLIENT_DB, ifi->name) == -1)
421 inaddr_broadcast.s_addr = INADDR_BROADCAST;
422 inaddr_any.s_addr = INADDR_ANY;
426 /* The next bit is potentially very time-consuming, so write out
427 the pidfile right away. We will write it out again with the
428 correct pid after daemonizing. */
430 pidfile_write(pidfile);
432 if (!interface_link_status(ifi->name)) {
433 fprintf(stderr, "%s: no link ...", ifi->name);
436 while (!interface_link_status(ifi->name)) {
437 fprintf(stderr, ".");
440 fprintf(stderr, " giving up\n");
445 fprintf(stderr, " got link\n");
449 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
450 error("cannot open %s: %m", _PATH_DEVNULL);
452 if ((pw = getpwnam("_dhcp")) == NULL) {
453 warning("no such user: _dhcp, falling back to \"nobody\"");
454 if ((pw = getpwnam("nobody")) == NULL)
455 error("no such user: nobody");
459 * Obtain hostname before entering capability mode - it won't be
460 * possible then, as reading kern.hostname is not permitted.
462 if (gethostname(hostname, sizeof(hostname)) < 0)
465 priv_script_init("PREINIT", NULL);
466 if (ifi->client->alias)
467 priv_script_write_params("alias_", ifi->client->alias);
470 /* set up the interface */
471 discover_interfaces(ifi);
473 if (pipe(pipe_fd) == -1)
476 fork_privchld(pipe_fd[0], pipe_fd[1]);
485 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
486 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
487 error("can't limit private descriptor: %m");
489 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
490 error("can't open and lock %s: %m", path_dhclient_db);
491 read_client_leases();
492 rewrite_client_leases();
495 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
496 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
497 if (shutdown(routefd, SHUT_WR) < 0)
498 error("can't shutdown route socket: %m");
499 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
500 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
501 error("can't limit route socket: %m");
503 if (chroot(_PATH_VAREMPTY) == -1)
505 if (chdir("/") == -1)
506 error("chdir(\"/\")");
508 if (setgroups(1, &pw->pw_gid) ||
509 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
510 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
511 error("can't drop privileges: %m");
515 setproctitle("%s", ifi->name);
517 if (cap_enter() < 0 && errno != ENOSYS)
518 error("can't enter capability mode: %m");
520 if (immediate_daemon)
523 ifi->client->state = S_INIT;
526 bootp_packet_handler = do_packet;
537 extern char *__progname;
539 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
540 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
547 * Each routine is called from the dhclient_state_machine() in one of
549 * -> entering INIT state
550 * -> recvpacket_flag == 0: timeout in this state
551 * -> otherwise: received a packet in this state
553 * Return conditions as handled by dhclient_state_machine():
554 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
555 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
556 * Returns 0: finish the nap which was interrupted for no good reason.
558 * Several per-interface variables are used to keep track of the process:
559 * active_lease: the lease that is being used on the interface
560 * (null pointer if not configured yet).
561 * offered_leases: leases corresponding to DHCPOFFER messages that have
562 * been sent to us by DHCP servers.
563 * acked_leases: leases corresponding to DHCPACK messages that have been
564 * sent to us by DHCP servers.
565 * sendpacket: DHCP packet we're trying to send.
566 * destination: IP address to send sendpacket to
567 * In addition, there are several relevant per-lease variables.
568 * T1_expiry, T2_expiry, lease_expiry: lease milestones
569 * In the active lease, these control the process of renewing the lease;
570 * In leases on the acked_leases list, this simply determines when we
571 * can no longer legitimately use the lease.
575 state_reboot(void *ipp)
577 struct interface_info *ip = ipp;
579 /* If we don't remember an active lease, go straight to INIT. */
580 if (!ip->client->active || ip->client->active->is_bootp) {
585 /* We are in the rebooting state. */
586 ip->client->state = S_REBOOTING;
588 /* make_request doesn't initialize xid because it normally comes
589 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
590 so pick an xid now. */
591 ip->client->xid = arc4random();
593 /* Make a DHCPREQUEST packet, and set appropriate per-interface
595 make_request(ip, ip->client->active);
596 ip->client->destination = iaddr_broadcast;
597 ip->client->first_sending = cur_time;
598 ip->client->interval = ip->client->config->initial_interval;
600 /* Zap the medium list... */
601 ip->client->medium = NULL;
603 /* Send out the first DHCPREQUEST packet. */
608 * Called when a lease has completely expired and we've
609 * been unable to renew it.
612 state_init(void *ipp)
614 struct interface_info *ip = ipp;
616 ASSERT_STATE(state, S_INIT);
618 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
620 make_discover(ip, ip->client->active);
621 ip->client->xid = ip->client->packet.xid;
622 ip->client->destination = iaddr_broadcast;
623 ip->client->state = S_SELECTING;
624 ip->client->first_sending = cur_time;
625 ip->client->interval = ip->client->config->initial_interval;
627 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
633 * state_selecting is called when one or more DHCPOFFER packets
634 * have been received and a configurable period of time has passed.
637 state_selecting(void *ipp)
639 struct interface_info *ip = ipp;
640 struct client_lease *lp, *next, *picked;
642 ASSERT_STATE(state, S_SELECTING);
644 /* Cancel state_selecting and send_discover timeouts, since either
645 one could have got us here. */
646 cancel_timeout(state_selecting, ip);
647 cancel_timeout(send_discover, ip);
649 /* We have received one or more DHCPOFFER packets. Currently,
650 the only criterion by which we judge leases is whether or
651 not we get a response when we arp for them. */
653 for (lp = ip->client->offered_leases; lp; lp = next) {
656 /* Check to see if we got an ARPREPLY for the address
657 in this particular lease. */
659 script_init("ARPCHECK", lp->medium);
660 script_write_params("check_", lp);
662 /* If the ARPCHECK code detects another
663 machine using the offered address, it exits
664 nonzero. We need to send a DHCPDECLINE and
667 make_decline(ip, lp);
675 free_client_lease(lp);
678 ip->client->offered_leases = NULL;
680 /* If we just tossed all the leases we were offered, go back
683 ip->client->state = S_INIT;
688 /* If it was a BOOTREPLY, we can just take the address right now. */
689 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
690 ip->client->new = picked;
692 /* Make up some lease expiry times
693 XXX these should be configurable. */
694 ip->client->new->expiry = cur_time + 12000;
695 ip->client->new->renewal += cur_time + 8000;
696 ip->client->new->rebind += cur_time + 10000;
698 ip->client->state = S_REQUESTING;
700 /* Bind to the address we received. */
705 /* Go to the REQUESTING state. */
706 ip->client->destination = iaddr_broadcast;
707 ip->client->state = S_REQUESTING;
708 ip->client->first_sending = cur_time;
709 ip->client->interval = ip->client->config->initial_interval;
711 /* Make a DHCPREQUEST packet from the lease we picked. */
712 make_request(ip, picked);
713 ip->client->xid = ip->client->packet.xid;
715 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
716 free_client_lease(picked);
718 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
722 /* state_requesting is called when we receive a DHCPACK message after
723 having sent out one or more DHCPREQUEST packets. */
726 dhcpack(struct packet *packet)
728 struct interface_info *ip = packet->interface;
729 struct client_lease *lease;
731 /* If we're not receptive to an offer right now, or if the offer
732 has an unrecognizable transaction id, then just drop it. */
733 if (packet->interface->client->xid != packet->raw->xid ||
734 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
735 (memcmp(packet->interface->hw_address.haddr,
736 packet->raw->chaddr, packet->raw->hlen)))
739 if (ip->client->state != S_REBOOTING &&
740 ip->client->state != S_REQUESTING &&
741 ip->client->state != S_RENEWING &&
742 ip->client->state != S_REBINDING)
745 note("DHCPACK from %s", piaddr(packet->client_addr));
747 lease = packet_to_lease(packet);
749 note("packet_to_lease failed.");
753 ip->client->new = lease;
755 /* Stop resending DHCPREQUEST. */
756 cancel_timeout(send_request, ip);
758 /* Figure out the lease time. */
759 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
761 ip->client->new->expiry = getULong(
762 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
763 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
764 ip->client->new->expiry = getULong(
765 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
767 ip->client->new->expiry = default_lease_time;
768 /* A number that looks negative here is really just very large,
769 because the lease expiry offset is unsigned. Also make sure that
770 the addition of cur_time below does not overflow (a 32 bit) time_t. */
771 if (ip->client->new->expiry < 0 ||
772 ip->client->new->expiry > TIME_MAX - cur_time)
773 ip->client->new->expiry = TIME_MAX - cur_time;
774 /* XXX should be fixed by resetting the client state */
775 if (ip->client->new->expiry < 60)
776 ip->client->new->expiry = 60;
778 /* Unless overridden in the config, take the server-provided renewal
779 * time if there is one. Otherwise figure it out according to the spec.
780 * Also make sure the renewal time does not exceed the expiry time.
782 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
784 ip->client->new->renewal = getULong(
785 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
786 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
787 ip->client->new->renewal = getULong(
788 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
790 ip->client->new->renewal = ip->client->new->expiry / 2;
791 if (ip->client->new->renewal < 0 ||
792 ip->client->new->renewal > ip->client->new->expiry / 2)
793 ip->client->new->renewal = ip->client->new->expiry / 2;
795 /* Same deal with the rebind time. */
796 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
798 ip->client->new->rebind = getULong(
799 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
800 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
801 ip->client->new->rebind = getULong(
802 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
804 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
805 if (ip->client->new->rebind < 0 ||
806 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
807 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
809 /* Convert the time offsets into seconds-since-the-epoch */
810 ip->client->new->expiry += cur_time;
811 ip->client->new->renewal += cur_time;
812 ip->client->new->rebind += cur_time;
818 bind_lease(struct interface_info *ip)
820 /* Remember the medium. */
821 ip->client->new->medium = ip->client->medium;
823 /* Write out the new lease. */
824 write_client_lease(ip, ip->client->new, 0);
826 /* Run the client script with the new parameters. */
827 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
828 (ip->client->state == S_RENEWING ? "RENEW" :
829 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
830 ip->client->new->medium);
831 if (ip->client->active && ip->client->state != S_REBOOTING)
832 script_write_params("old_", ip->client->active);
833 script_write_params("new_", ip->client->new);
834 if (ip->client->alias)
835 script_write_params("alias_", ip->client->alias);
838 /* Replace the old active lease with the new one. */
839 if (ip->client->active)
840 free_client_lease(ip->client->active);
841 ip->client->active = ip->client->new;
842 ip->client->new = NULL;
844 /* Set up a timeout to start the renewal process. */
845 add_timeout(ip->client->active->renewal, state_bound, ip);
847 note("bound to %s -- renewal in %d seconds.",
848 piaddr(ip->client->active->address),
849 (int)(ip->client->active->renewal - cur_time));
850 ip->client->state = S_BOUND;
851 reinitialize_interfaces();
856 * state_bound is called when we've successfully bound to a particular
857 * lease, but the renewal time on that lease has expired. We are
858 * expected to unicast a DHCPREQUEST to the server that gave us our
862 state_bound(void *ipp)
864 struct interface_info *ip = ipp;
866 ASSERT_STATE(state, S_BOUND);
868 /* T1 has expired. */
869 make_request(ip, ip->client->active);
870 ip->client->xid = ip->client->packet.xid;
872 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
873 memcpy(ip->client->destination.iabuf, ip->client->active->
874 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
875 ip->client->destination.len = 4;
877 ip->client->destination = iaddr_broadcast;
879 ip->client->first_sending = cur_time;
880 ip->client->interval = ip->client->config->initial_interval;
881 ip->client->state = S_RENEWING;
883 /* Send the first packet immediately. */
888 bootp(struct packet *packet)
890 struct iaddrlist *ap;
892 if (packet->raw->op != BOOTREPLY)
895 /* If there's a reject list, make sure this packet's sender isn't
897 for (ap = packet->interface->client->config->reject_list;
899 if (addr_eq(packet->client_addr, ap->addr)) {
900 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
908 dhcp(struct packet *packet)
910 struct iaddrlist *ap;
911 void (*handler)(struct packet *);
914 switch (packet->packet_type) {
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("%s from %s rejected.", type, piaddr(ap->addr));
944 dhcpoffer(struct packet *packet)
946 struct interface_info *ip = packet->interface;
947 struct client_lease *lease, *lp;
949 int arp_timeout_needed, stop_selecting;
950 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
951 "DHCPOFFER" : "BOOTREPLY";
953 /* If we're not receptive to an offer right now, or if the offer
954 has an unrecognizable transaction id, then just drop it. */
955 if (ip->client->state != S_SELECTING ||
956 packet->interface->client->xid != packet->raw->xid ||
957 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
958 (memcmp(packet->interface->hw_address.haddr,
959 packet->raw->chaddr, packet->raw->hlen)))
962 note("%s from %s", name, piaddr(packet->client_addr));
965 /* If this lease doesn't supply the minimum required parameters,
967 for (i = 0; ip->client->config->required_options[i]; i++) {
968 if (!packet->options[ip->client->config->
969 required_options[i]].len) {
970 note("%s isn't satisfactory.", name);
975 /* If we've already seen this lease, don't record it again. */
976 for (lease = ip->client->offered_leases;
977 lease; lease = lease->next) {
978 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
979 !memcmp(lease->address.iabuf,
980 &packet->raw->yiaddr, lease->address.len)) {
981 debug("%s already seen.", name);
986 lease = packet_to_lease(packet);
988 note("packet_to_lease failed.");
992 /* If this lease was acquired through a BOOTREPLY, record that
994 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
997 /* Record the medium under which this lease was offered. */
998 lease->medium = ip->client->medium;
1000 /* Send out an ARP Request for the offered IP address. */
1001 script_init("ARPSEND", lease->medium);
1002 script_write_params("check_", lease);
1003 /* If the script can't send an ARP request without waiting,
1004 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1006 arp_timeout_needed = 0;
1008 arp_timeout_needed = 2;
1010 /* Figure out when we're supposed to stop selecting. */
1012 ip->client->first_sending + ip->client->config->select_interval;
1014 /* If this is the lease we asked for, put it at the head of the
1015 list, and don't mess with the arp request timeout. */
1016 if (lease->address.len == ip->client->requested_address.len &&
1017 !memcmp(lease->address.iabuf,
1018 ip->client->requested_address.iabuf,
1019 ip->client->requested_address.len)) {
1020 lease->next = ip->client->offered_leases;
1021 ip->client->offered_leases = lease;
1023 /* If we already have an offer, and arping for this
1024 offer would take us past the selection timeout,
1025 then don't extend the timeout - just hope for the
1027 if (ip->client->offered_leases &&
1028 (cur_time + arp_timeout_needed) > stop_selecting)
1029 arp_timeout_needed = 0;
1031 /* Put the lease at the end of the list. */
1033 if (!ip->client->offered_leases)
1034 ip->client->offered_leases = lease;
1036 for (lp = ip->client->offered_leases; lp->next;
1043 /* If we're supposed to stop selecting before we've had time
1044 to wait for the ARPREPLY, add some delay to wait for
1046 if (stop_selecting - cur_time < arp_timeout_needed)
1047 stop_selecting = cur_time + arp_timeout_needed;
1049 /* If the selecting interval has expired, go immediately to
1050 state_selecting(). Otherwise, time out into
1051 state_selecting at the select interval. */
1052 if (stop_selecting <= 0)
1053 state_selecting(ip);
1055 add_timeout(stop_selecting, state_selecting, ip);
1056 cancel_timeout(send_discover, ip);
1060 /* Allocate a client_lease structure and initialize it from the parameters
1061 in the specified packet. */
1063 struct client_lease *
1064 packet_to_lease(struct packet *packet)
1066 struct client_lease *lease;
1069 lease = malloc(sizeof(struct client_lease));
1072 warning("dhcpoffer: no memory to record lease.");
1076 memset(lease, 0, sizeof(*lease));
1078 /* Copy the lease options. */
1079 for (i = 0; i < 256; i++) {
1080 if (packet->options[i].len) {
1081 lease->options[i].data =
1082 malloc(packet->options[i].len + 1);
1083 if (!lease->options[i].data) {
1084 warning("dhcpoffer: no memory for option %d", i);
1085 free_client_lease(lease);
1088 memcpy(lease->options[i].data,
1089 packet->options[i].data,
1090 packet->options[i].len);
1091 lease->options[i].len =
1092 packet->options[i].len;
1093 lease->options[i].data[lease->options[i].len] =
1096 if (!check_option(lease,i)) {
1097 /* ignore a bogus lease offer */
1098 warning("Invalid lease option - ignoring offer");
1099 free_client_lease(lease);
1105 lease->address.len = sizeof(packet->raw->yiaddr);
1106 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1108 lease->nextserver.len = sizeof(packet->raw->siaddr);
1109 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1111 /* If the server name was filled out, copy it.
1112 Do not attempt to validate the server name as a host name.
1113 RFC 2131 merely states that sname is NUL-terminated (which do
1114 do not assume) and that it is the server's host name. Since
1115 the ISC client and server allow arbitrary characters, we do
1117 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1118 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1119 packet->raw->sname[0]) {
1120 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1121 if (!lease->server_name) {
1122 warning("dhcpoffer: no memory for server name.");
1123 free_client_lease(lease);
1126 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1127 lease->server_name[DHCP_SNAME_LEN]='\0';
1130 /* Ditto for the filename. */
1131 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1132 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1133 packet->raw->file[0]) {
1134 /* Don't count on the NUL terminator. */
1135 lease->filename = malloc(DHCP_FILE_LEN + 1);
1136 if (!lease->filename) {
1137 warning("dhcpoffer: no memory for filename.");
1138 free_client_lease(lease);
1141 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1142 lease->filename[DHCP_FILE_LEN]='\0';
1148 dhcpnak(struct packet *packet)
1150 struct interface_info *ip = packet->interface;
1152 /* If we're not receptive to an offer right now, or if the offer
1153 has an unrecognizable transaction id, then just drop it. */
1154 if (packet->interface->client->xid != packet->raw->xid ||
1155 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1156 (memcmp(packet->interface->hw_address.haddr,
1157 packet->raw->chaddr, packet->raw->hlen)))
1160 if (ip->client->state != S_REBOOTING &&
1161 ip->client->state != S_REQUESTING &&
1162 ip->client->state != S_RENEWING &&
1163 ip->client->state != S_REBINDING)
1166 note("DHCPNAK from %s", piaddr(packet->client_addr));
1168 if (!ip->client->active) {
1169 note("DHCPNAK with no active lease.\n");
1173 free_client_lease(ip->client->active);
1174 ip->client->active = NULL;
1176 /* Stop sending DHCPREQUEST packets... */
1177 cancel_timeout(send_request, ip);
1179 ip->client->state = S_INIT;
1183 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1184 one after the right interval has expired. If we don't get an offer by
1185 the time we reach the panic interval, call the panic function. */
1188 send_discover(void *ipp)
1190 struct interface_info *ip = ipp;
1191 int interval, increase = 1;
1193 /* Figure out how long it's been since we started transmitting. */
1194 interval = cur_time - ip->client->first_sending;
1196 /* If we're past the panic timeout, call the script and tell it
1197 we haven't found anything for this interface yet. */
1198 if (interval > ip->client->config->timeout) {
1203 /* If we're selecting media, try the whole list before doing
1204 the exponential backoff, but if we've already received an
1205 offer, stop looping, because we obviously have it right. */
1206 if (!ip->client->offered_leases &&
1207 ip->client->config->media) {
1210 if (ip->client->medium) {
1211 ip->client->medium = ip->client->medium->next;
1214 if (!ip->client->medium) {
1216 error("No valid media types for %s!", ip->name);
1217 ip->client->medium = ip->client->config->media;
1221 note("Trying medium \"%s\" %d", ip->client->medium->string,
1223 script_init("MEDIUM", ip->client->medium);
1229 * If we're supposed to increase the interval, do so. If it's
1230 * currently zero (i.e., we haven't sent any packets yet), set
1231 * it to one; otherwise, add to it a random number between zero
1232 * and two times itself. On average, this means that it will
1233 * double with every transmission.
1236 if (!ip->client->interval)
1237 ip->client->interval =
1238 ip->client->config->initial_interval;
1240 ip->client->interval += (arc4random() >> 2) %
1241 (2 * ip->client->interval);
1244 /* Don't backoff past cutoff. */
1245 if (ip->client->interval >
1246 ip->client->config->backoff_cutoff)
1247 ip->client->interval =
1248 ((ip->client->config->backoff_cutoff / 2)
1249 + ((arc4random() >> 2) %
1250 ip->client->config->backoff_cutoff));
1251 } else if (!ip->client->interval)
1252 ip->client->interval =
1253 ip->client->config->initial_interval;
1255 /* If the backoff would take us to the panic timeout, just use that
1257 if (cur_time + ip->client->interval >
1258 ip->client->first_sending + ip->client->config->timeout)
1259 ip->client->interval =
1260 (ip->client->first_sending +
1261 ip->client->config->timeout) - cur_time + 1;
1263 /* Record the number of seconds since we started sending. */
1264 if (interval < 65536)
1265 ip->client->packet.secs = htons(interval);
1267 ip->client->packet.secs = htons(65535);
1268 ip->client->secs = ip->client->packet.secs;
1270 note("DHCPDISCOVER on %s to %s port %d interval %d",
1271 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1272 (int)ip->client->interval);
1274 /* Send out a packet. */
1275 send_packet_unpriv(privfd, &ip->client->packet,
1276 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1278 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1282 * state_panic gets called if we haven't received any offers in a preset
1283 * amount of time. When this happens, we try to use existing leases
1284 * that haven't yet expired, and failing that, we call the client script
1285 * and hope it can do something.
1288 state_panic(void *ipp)
1290 struct interface_info *ip = ipp;
1291 struct client_lease *loop = ip->client->active;
1292 struct client_lease *lp;
1294 note("No DHCPOFFERS received.");
1296 /* We may not have an active lease, but we may have some
1297 predefined leases that we can try. */
1298 if (!ip->client->active && ip->client->leases)
1301 /* Run through the list of leases and see if one can be used. */
1302 while (ip->client->active) {
1303 if (ip->client->active->expiry > cur_time) {
1304 note("Trying recorded lease %s",
1305 piaddr(ip->client->active->address));
1306 /* Run the client script with the existing
1308 script_init("TIMEOUT",
1309 ip->client->active->medium);
1310 script_write_params("new_", ip->client->active);
1311 if (ip->client->alias)
1312 script_write_params("alias_",
1315 /* If the old lease is still good and doesn't
1316 yet need renewal, go into BOUND state and
1317 timeout at the renewal time. */
1320 ip->client->active->renewal) {
1321 ip->client->state = S_BOUND;
1322 note("bound: renewal in %d seconds.",
1323 (int)(ip->client->active->renewal -
1326 ip->client->active->renewal,
1329 ip->client->state = S_BOUND;
1330 note("bound: immediate renewal.");
1333 reinitialize_interfaces();
1339 /* If there are no other leases, give up. */
1340 if (!ip->client->leases) {
1341 ip->client->leases = ip->client->active;
1342 ip->client->active = NULL;
1347 /* Otherwise, put the active lease at the end of the
1348 lease list, and try another lease.. */
1349 for (lp = ip->client->leases; lp->next; lp = lp->next)
1351 lp->next = ip->client->active;
1353 lp->next->next = NULL;
1354 ip->client->active = ip->client->leases;
1355 ip->client->leases = ip->client->leases->next;
1357 /* If we already tried this lease, we've exhausted the
1358 set of leases, so we might as well give up for
1360 if (ip->client->active == loop)
1363 loop = ip->client->active;
1366 /* No leases were available, or what was available didn't work, so
1367 tell the shell script that we failed to allocate an address,
1368 and try again later. */
1369 note("No working leases in persistent database - sleeping.\n");
1370 script_init("FAIL", NULL);
1371 if (ip->client->alias)
1372 script_write_params("alias_", ip->client->alias);
1374 ip->client->state = S_INIT;
1375 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1381 send_request(void *ipp)
1383 struct interface_info *ip = ipp;
1384 struct in_addr from, to;
1387 /* Figure out how long it's been since we started transmitting. */
1388 interval = cur_time - ip->client->first_sending;
1390 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1391 past the reboot timeout, go to INIT and see if we can
1392 DISCOVER an address... */
1393 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1394 means either that we're on a network with no DHCP server,
1395 or that our server is down. In the latter case, assuming
1396 that there is a backup DHCP server, DHCPDISCOVER will get
1397 us a new address, but we could also have successfully
1398 reused our old address. In the former case, we're hosed
1399 anyway. This is not a win-prone situation. */
1400 if ((ip->client->state == S_REBOOTING ||
1401 ip->client->state == S_REQUESTING) &&
1402 interval > ip->client->config->reboot_timeout) {
1404 ip->client->state = S_INIT;
1405 cancel_timeout(send_request, ip);
1410 /* If we're in the reboot state, make sure the media is set up
1412 if (ip->client->state == S_REBOOTING &&
1413 !ip->client->medium &&
1414 ip->client->active->medium ) {
1415 script_init("MEDIUM", ip->client->active->medium);
1417 /* If the medium we chose won't fly, go to INIT state. */
1421 /* Record the medium. */
1422 ip->client->medium = ip->client->active->medium;
1425 /* If the lease has expired, relinquish the address and go back
1426 to the INIT state. */
1427 if (ip->client->state != S_REQUESTING &&
1428 cur_time > ip->client->active->expiry) {
1429 /* Run the client script with the new parameters. */
1430 script_init("EXPIRE", NULL);
1431 script_write_params("old_", ip->client->active);
1432 if (ip->client->alias)
1433 script_write_params("alias_", ip->client->alias);
1436 /* Now do a preinit on the interface so that we can
1437 discover a new address. */
1438 script_init("PREINIT", NULL);
1439 if (ip->client->alias)
1440 script_write_params("alias_", ip->client->alias);
1443 ip->client->state = S_INIT;
1448 /* Do the exponential backoff... */
1449 if (!ip->client->interval)
1450 ip->client->interval = ip->client->config->initial_interval;
1452 ip->client->interval += ((arc4random() >> 2) %
1453 (2 * ip->client->interval));
1455 /* Don't backoff past cutoff. */
1456 if (ip->client->interval >
1457 ip->client->config->backoff_cutoff)
1458 ip->client->interval =
1459 ((ip->client->config->backoff_cutoff / 2) +
1460 ((arc4random() >> 2) % ip->client->interval));
1462 /* If the backoff would take us to the expiry time, just set the
1463 timeout to the expiry time. */
1464 if (ip->client->state != S_REQUESTING &&
1465 cur_time + ip->client->interval >
1466 ip->client->active->expiry)
1467 ip->client->interval =
1468 ip->client->active->expiry - cur_time + 1;
1470 /* If the lease T2 time has elapsed, or if we're not yet bound,
1471 broadcast the DHCPREQUEST rather than unicasting. */
1472 if (ip->client->state == S_REQUESTING ||
1473 ip->client->state == S_REBOOTING ||
1474 cur_time > ip->client->active->rebind)
1475 to.s_addr = INADDR_BROADCAST;
1477 memcpy(&to.s_addr, ip->client->destination.iabuf,
1480 if (ip->client->state != S_REQUESTING)
1481 memcpy(&from, ip->client->active->address.iabuf,
1484 from.s_addr = INADDR_ANY;
1486 /* Record the number of seconds since we started sending. */
1487 if (ip->client->state == S_REQUESTING)
1488 ip->client->packet.secs = ip->client->secs;
1490 if (interval < 65536)
1491 ip->client->packet.secs = htons(interval);
1493 ip->client->packet.secs = htons(65535);
1496 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1499 /* Send out a packet. */
1500 send_packet_unpriv(privfd, &ip->client->packet,
1501 ip->client->packet_length, from, to);
1503 add_timeout(cur_time + ip->client->interval, send_request, ip);
1507 send_decline(void *ipp)
1509 struct interface_info *ip = ipp;
1511 note("DHCPDECLINE on %s to %s port %d", ip->name,
1512 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1514 /* Send out a packet. */
1515 send_packet_unpriv(privfd, &ip->client->packet,
1516 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1520 make_discover(struct interface_info *ip, struct client_lease *lease)
1522 unsigned char discover = DHCPDISCOVER;
1523 struct tree_cache *options[256];
1524 struct tree_cache option_elements[256];
1527 memset(option_elements, 0, sizeof(option_elements));
1528 memset(options, 0, sizeof(options));
1529 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1531 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1532 i = DHO_DHCP_MESSAGE_TYPE;
1533 options[i] = &option_elements[i];
1534 options[i]->value = &discover;
1535 options[i]->len = sizeof(discover);
1536 options[i]->buf_size = sizeof(discover);
1537 options[i]->timeout = 0xFFFFFFFF;
1539 /* Request the options we want */
1540 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1541 options[i] = &option_elements[i];
1542 options[i]->value = ip->client->config->requested_options;
1543 options[i]->len = ip->client->config->requested_option_count;
1544 options[i]->buf_size =
1545 ip->client->config->requested_option_count;
1546 options[i]->timeout = 0xFFFFFFFF;
1548 /* If we had an address, try to get it again. */
1550 ip->client->requested_address = lease->address;
1551 i = DHO_DHCP_REQUESTED_ADDRESS;
1552 options[i] = &option_elements[i];
1553 options[i]->value = lease->address.iabuf;
1554 options[i]->len = lease->address.len;
1555 options[i]->buf_size = lease->address.len;
1556 options[i]->timeout = 0xFFFFFFFF;
1558 ip->client->requested_address.len = 0;
1560 /* Send any options requested in the config file. */
1561 for (i = 0; i < 256; i++)
1563 ip->client->config->send_options[i].data) {
1564 options[i] = &option_elements[i];
1566 ip->client->config->send_options[i].data;
1568 ip->client->config->send_options[i].len;
1569 options[i]->buf_size =
1570 ip->client->config->send_options[i].len;
1571 options[i]->timeout = 0xFFFFFFFF;
1574 /* send host name if not set via config file. */
1575 if (!options[DHO_HOST_NAME]) {
1576 if (hostname[0] != '\0') {
1578 char* posDot = strchr(hostname, '.');
1580 len = posDot - hostname;
1582 len = strlen(hostname);
1583 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1584 options[DHO_HOST_NAME]->value = hostname;
1585 options[DHO_HOST_NAME]->len = len;
1586 options[DHO_HOST_NAME]->buf_size = len;
1587 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1591 /* set unique client identifier */
1592 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1593 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1594 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1595 ip->hw_address.hlen : sizeof(client_ident)-1;
1596 client_ident[0] = ip->hw_address.htype;
1597 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1598 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1599 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1600 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1601 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1602 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1605 /* Set up the option buffer... */
1606 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1607 options, 0, 0, 0, NULL, 0);
1608 if (ip->client->packet_length < BOOTP_MIN_LEN)
1609 ip->client->packet_length = BOOTP_MIN_LEN;
1611 ip->client->packet.op = BOOTREQUEST;
1612 ip->client->packet.htype = ip->hw_address.htype;
1613 ip->client->packet.hlen = ip->hw_address.hlen;
1614 ip->client->packet.hops = 0;
1615 ip->client->packet.xid = arc4random();
1616 ip->client->packet.secs = 0; /* filled in by send_discover. */
1617 ip->client->packet.flags = 0;
1619 memset(&(ip->client->packet.ciaddr),
1620 0, sizeof(ip->client->packet.ciaddr));
1621 memset(&(ip->client->packet.yiaddr),
1622 0, sizeof(ip->client->packet.yiaddr));
1623 memset(&(ip->client->packet.siaddr),
1624 0, sizeof(ip->client->packet.siaddr));
1625 memset(&(ip->client->packet.giaddr),
1626 0, sizeof(ip->client->packet.giaddr));
1627 memcpy(ip->client->packet.chaddr,
1628 ip->hw_address.haddr, ip->hw_address.hlen);
1633 make_request(struct interface_info *ip, struct client_lease * lease)
1635 unsigned char request = DHCPREQUEST;
1636 struct tree_cache *options[256];
1637 struct tree_cache option_elements[256];
1640 memset(options, 0, sizeof(options));
1641 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1643 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1644 i = DHO_DHCP_MESSAGE_TYPE;
1645 options[i] = &option_elements[i];
1646 options[i]->value = &request;
1647 options[i]->len = sizeof(request);
1648 options[i]->buf_size = sizeof(request);
1649 options[i]->timeout = 0xFFFFFFFF;
1651 /* Request the options we want */
1652 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1653 options[i] = &option_elements[i];
1654 options[i]->value = ip->client->config->requested_options;
1655 options[i]->len = ip->client->config->requested_option_count;
1656 options[i]->buf_size =
1657 ip->client->config->requested_option_count;
1658 options[i]->timeout = 0xFFFFFFFF;
1660 /* If we are requesting an address that hasn't yet been assigned
1661 to us, use the DHCP Requested Address option. */
1662 if (ip->client->state == S_REQUESTING) {
1663 /* Send back the server identifier... */
1664 i = DHO_DHCP_SERVER_IDENTIFIER;
1665 options[i] = &option_elements[i];
1666 options[i]->value = lease->options[i].data;
1667 options[i]->len = lease->options[i].len;
1668 options[i]->buf_size = lease->options[i].len;
1669 options[i]->timeout = 0xFFFFFFFF;
1671 if (ip->client->state == S_REQUESTING ||
1672 ip->client->state == S_REBOOTING) {
1673 ip->client->requested_address = lease->address;
1674 i = DHO_DHCP_REQUESTED_ADDRESS;
1675 options[i] = &option_elements[i];
1676 options[i]->value = lease->address.iabuf;
1677 options[i]->len = lease->address.len;
1678 options[i]->buf_size = lease->address.len;
1679 options[i]->timeout = 0xFFFFFFFF;
1681 ip->client->requested_address.len = 0;
1683 /* Send any options requested in the config file. */
1684 for (i = 0; i < 256; i++)
1686 ip->client->config->send_options[i].data) {
1687 options[i] = &option_elements[i];
1689 ip->client->config->send_options[i].data;
1691 ip->client->config->send_options[i].len;
1692 options[i]->buf_size =
1693 ip->client->config->send_options[i].len;
1694 options[i]->timeout = 0xFFFFFFFF;
1697 /* send host name if not set via config file. */
1698 if (!options[DHO_HOST_NAME]) {
1699 if (hostname[0] != '\0') {
1701 char* posDot = strchr(hostname, '.');
1703 len = posDot - hostname;
1705 len = strlen(hostname);
1706 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1707 options[DHO_HOST_NAME]->value = hostname;
1708 options[DHO_HOST_NAME]->len = len;
1709 options[DHO_HOST_NAME]->buf_size = len;
1710 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1714 /* set unique client identifier */
1715 char client_ident[sizeof(struct hardware)];
1716 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1717 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1718 ip->hw_address.hlen : sizeof(client_ident)-1;
1719 client_ident[0] = ip->hw_address.htype;
1720 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1721 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1722 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1723 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1724 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1725 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1728 /* Set up the option buffer... */
1729 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1730 options, 0, 0, 0, NULL, 0);
1731 if (ip->client->packet_length < BOOTP_MIN_LEN)
1732 ip->client->packet_length = BOOTP_MIN_LEN;
1734 ip->client->packet.op = BOOTREQUEST;
1735 ip->client->packet.htype = ip->hw_address.htype;
1736 ip->client->packet.hlen = ip->hw_address.hlen;
1737 ip->client->packet.hops = 0;
1738 ip->client->packet.xid = ip->client->xid;
1739 ip->client->packet.secs = 0; /* Filled in by send_request. */
1741 /* If we own the address we're requesting, put it in ciaddr;
1742 otherwise set ciaddr to zero. */
1743 if (ip->client->state == S_BOUND ||
1744 ip->client->state == S_RENEWING ||
1745 ip->client->state == S_REBINDING) {
1746 memcpy(&ip->client->packet.ciaddr,
1747 lease->address.iabuf, lease->address.len);
1748 ip->client->packet.flags = 0;
1750 memset(&ip->client->packet.ciaddr, 0,
1751 sizeof(ip->client->packet.ciaddr));
1752 ip->client->packet.flags = 0;
1755 memset(&ip->client->packet.yiaddr, 0,
1756 sizeof(ip->client->packet.yiaddr));
1757 memset(&ip->client->packet.siaddr, 0,
1758 sizeof(ip->client->packet.siaddr));
1759 memset(&ip->client->packet.giaddr, 0,
1760 sizeof(ip->client->packet.giaddr));
1761 memcpy(ip->client->packet.chaddr,
1762 ip->hw_address.haddr, ip->hw_address.hlen);
1766 make_decline(struct interface_info *ip, struct client_lease *lease)
1768 struct tree_cache *options[256], message_type_tree;
1769 struct tree_cache requested_address_tree;
1770 struct tree_cache server_id_tree, client_id_tree;
1771 unsigned char decline = DHCPDECLINE;
1774 memset(options, 0, sizeof(options));
1775 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1777 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1778 i = DHO_DHCP_MESSAGE_TYPE;
1779 options[i] = &message_type_tree;
1780 options[i]->value = &decline;
1781 options[i]->len = sizeof(decline);
1782 options[i]->buf_size = sizeof(decline);
1783 options[i]->timeout = 0xFFFFFFFF;
1785 /* Send back the server identifier... */
1786 i = DHO_DHCP_SERVER_IDENTIFIER;
1787 options[i] = &server_id_tree;
1788 options[i]->value = lease->options[i].data;
1789 options[i]->len = lease->options[i].len;
1790 options[i]->buf_size = lease->options[i].len;
1791 options[i]->timeout = 0xFFFFFFFF;
1793 /* Send back the address we're declining. */
1794 i = DHO_DHCP_REQUESTED_ADDRESS;
1795 options[i] = &requested_address_tree;
1796 options[i]->value = lease->address.iabuf;
1797 options[i]->len = lease->address.len;
1798 options[i]->buf_size = lease->address.len;
1799 options[i]->timeout = 0xFFFFFFFF;
1801 /* Send the uid if the user supplied one. */
1802 i = DHO_DHCP_CLIENT_IDENTIFIER;
1803 if (ip->client->config->send_options[i].len) {
1804 options[i] = &client_id_tree;
1805 options[i]->value = ip->client->config->send_options[i].data;
1806 options[i]->len = ip->client->config->send_options[i].len;
1807 options[i]->buf_size = ip->client->config->send_options[i].len;
1808 options[i]->timeout = 0xFFFFFFFF;
1812 /* Set up the option buffer... */
1813 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1814 options, 0, 0, 0, NULL, 0);
1815 if (ip->client->packet_length < BOOTP_MIN_LEN)
1816 ip->client->packet_length = BOOTP_MIN_LEN;
1818 ip->client->packet.op = BOOTREQUEST;
1819 ip->client->packet.htype = ip->hw_address.htype;
1820 ip->client->packet.hlen = ip->hw_address.hlen;
1821 ip->client->packet.hops = 0;
1822 ip->client->packet.xid = ip->client->xid;
1823 ip->client->packet.secs = 0; /* Filled in by send_request. */
1824 ip->client->packet.flags = 0;
1826 /* ciaddr must always be zero. */
1827 memset(&ip->client->packet.ciaddr, 0,
1828 sizeof(ip->client->packet.ciaddr));
1829 memset(&ip->client->packet.yiaddr, 0,
1830 sizeof(ip->client->packet.yiaddr));
1831 memset(&ip->client->packet.siaddr, 0,
1832 sizeof(ip->client->packet.siaddr));
1833 memset(&ip->client->packet.giaddr, 0,
1834 sizeof(ip->client->packet.giaddr));
1835 memcpy(ip->client->packet.chaddr,
1836 ip->hw_address.haddr, ip->hw_address.hlen);
1840 free_client_lease(struct client_lease *lease)
1844 if (lease->server_name)
1845 free(lease->server_name);
1846 if (lease->filename)
1847 free(lease->filename);
1848 for (i = 0; i < 256; i++) {
1849 if (lease->options[i].len)
1850 free(lease->options[i].data);
1858 rewrite_client_leases(void)
1860 struct client_lease *lp;
1861 cap_rights_t rights;
1864 leaseFile = fopen(path_dhclient_db, "w");
1866 error("can't create %s: %m", path_dhclient_db);
1867 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1868 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1869 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1871 error("can't limit lease descriptor: %m");
1873 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1875 error("can't limit lease descriptor fcntls: %m");
1882 for (lp = ifi->client->leases; lp; lp = lp->next)
1883 write_client_lease(ifi, lp, 1);
1884 if (ifi->client->active)
1885 write_client_lease(ifi, ifi->client->active, 1);
1888 ftruncate(fileno(leaseFile), ftello(leaseFile));
1889 fsync(fileno(leaseFile));
1893 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1896 static int leases_written;
1901 if (leases_written++ > 20) {
1902 rewrite_client_leases();
1907 /* If the lease came from the config file, we don't need to stash
1908 a copy in the lease database. */
1909 if (lease->is_static)
1912 if (!leaseFile) { /* XXX */
1913 leaseFile = fopen(path_dhclient_db, "w");
1915 error("can't create %s: %m", path_dhclient_db);
1918 fprintf(leaseFile, "lease {\n");
1919 if (lease->is_bootp)
1920 fprintf(leaseFile, " bootp;\n");
1921 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1922 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1923 if (lease->nextserver.len == sizeof(inaddr_any) &&
1924 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1925 sizeof(inaddr_any)))
1926 fprintf(leaseFile, " next-server %s;\n",
1927 piaddr(lease->nextserver));
1928 if (lease->filename)
1929 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1930 if (lease->server_name)
1931 fprintf(leaseFile, " server-name \"%s\";\n",
1932 lease->server_name);
1934 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1935 for (i = 0; i < 256; i++)
1936 if (lease->options[i].len)
1937 fprintf(leaseFile, " option %s %s;\n",
1938 dhcp_options[i].name,
1939 pretty_print_option(i, lease->options[i].data,
1940 lease->options[i].len, 1, 1));
1942 t = gmtime(&lease->renewal);
1943 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1944 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1945 t->tm_hour, t->tm_min, t->tm_sec);
1946 t = gmtime(&lease->rebind);
1947 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1948 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1949 t->tm_hour, t->tm_min, t->tm_sec);
1950 t = gmtime(&lease->expiry);
1951 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1952 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1953 t->tm_hour, t->tm_min, t->tm_sec);
1954 fprintf(leaseFile, "}\n");
1959 script_init(char *reason, struct string_list *medium)
1961 size_t len, mediumlen = 0;
1962 struct imsg_hdr hdr;
1966 if (medium != NULL && medium->string != NULL)
1967 mediumlen = strlen(medium->string);
1969 hdr.code = IMSG_SCRIPT_INIT;
1970 hdr.len = sizeof(struct imsg_hdr) +
1971 sizeof(size_t) + mediumlen +
1972 sizeof(size_t) + strlen(reason);
1974 if ((buf = buf_open(hdr.len)) == NULL)
1975 error("buf_open: %m");
1978 errs += buf_add(buf, &hdr, sizeof(hdr));
1979 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1981 errs += buf_add(buf, medium->string, mediumlen);
1982 len = strlen(reason);
1983 errs += buf_add(buf, &len, sizeof(len));
1984 errs += buf_add(buf, reason, len);
1987 error("buf_add: %m");
1989 if (buf_close(privfd, buf) == -1)
1990 error("buf_close: %m");
1994 priv_script_init(char *reason, char *medium)
1996 struct interface_info *ip = ifi;
1999 ip->client->scriptEnvsize = 100;
2000 if (ip->client->scriptEnv == NULL)
2001 ip->client->scriptEnv =
2002 malloc(ip->client->scriptEnvsize * sizeof(char *));
2003 if (ip->client->scriptEnv == NULL)
2004 error("script_init: no memory for environment");
2006 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2007 if (ip->client->scriptEnv[0] == NULL)
2008 error("script_init: no memory for environment");
2010 ip->client->scriptEnv[1] = NULL;
2012 script_set_env(ip->client, "", "interface", ip->name);
2015 script_set_env(ip->client, "", "medium", medium);
2017 script_set_env(ip->client, "", "reason", reason);
2022 priv_script_write_params(char *prefix, struct client_lease *lease)
2024 struct interface_info *ip = ifi;
2025 u_int8_t dbuf[1500], *dp = NULL;
2029 script_set_env(ip->client, prefix, "ip_address",
2030 piaddr(lease->address));
2032 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2034 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2035 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2037 dp = lease->options[DHO_SUBNET_MASK].data;
2038 len = lease->options[DHO_SUBNET_MASK].len;
2040 if (len && (len < sizeof(lease->address.iabuf))) {
2041 struct iaddr netmask, subnet, broadcast;
2043 memcpy(netmask.iabuf, dp, len);
2045 subnet = subnet_number(lease->address, netmask);
2047 script_set_env(ip->client, prefix, "network_number",
2049 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2050 broadcast = broadcast_addr(subnet, netmask);
2052 script_set_env(ip->client, prefix,
2053 "broadcast_address",
2059 if (lease->filename)
2060 script_set_env(ip->client, prefix, "filename", lease->filename);
2061 if (lease->server_name)
2062 script_set_env(ip->client, prefix, "server_name",
2063 lease->server_name);
2064 for (i = 0; i < 256; i++) {
2067 if (ip->client->config->defaults[i].len) {
2068 if (lease->options[i].len) {
2070 ip->client->config->default_actions[i]) {
2071 case ACTION_DEFAULT:
2072 dp = lease->options[i].data;
2073 len = lease->options[i].len;
2075 case ACTION_SUPERSEDE:
2078 config->defaults[i].data;
2080 config->defaults[i].len;
2082 case ACTION_PREPEND:
2084 config->defaults[i].len +
2085 lease->options[i].len;
2086 if (len >= sizeof(dbuf)) {
2087 warning("no space to %s %s",
2089 dhcp_options[i].name);
2095 config->defaults[i].data,
2097 config->defaults[i].len);
2098 memcpy(dp + ip->client->
2099 config->defaults[i].len,
2100 lease->options[i].data,
2101 lease->options[i].len);
2106 * When we append, we assume that we're
2107 * appending to text. Some MS servers
2108 * include a NUL byte at the end of
2109 * the search string provided.
2112 config->defaults[i].len +
2113 lease->options[i].len;
2114 if (len >= sizeof(dbuf)) {
2115 warning("no space to %s %s",
2117 dhcp_options[i].name);
2121 lease->options[i].data,
2122 lease->options[i].len);
2123 for (dp = dbuf + lease->options[i].len;
2124 dp > dbuf; dp--, len--)
2129 config->defaults[i].data,
2131 config->defaults[i].len);
2137 config->defaults[i].data;
2139 config->defaults[i].len;
2141 } else if (lease->options[i].len) {
2142 len = lease->options[i].len;
2143 dp = lease->options[i].data;
2150 if (dhcp_option_ev_name(name, sizeof(name),
2152 script_set_env(ip->client, prefix, name,
2153 pretty_print_option(i, dp, len, 0, 0));
2156 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2157 script_set_env(ip->client, prefix, "expiry", tbuf);
2161 script_write_params(char *prefix, struct client_lease *lease)
2163 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2164 struct imsg_hdr hdr;
2168 if (lease->filename != NULL)
2169 fn_len = strlen(lease->filename);
2170 if (lease->server_name != NULL)
2171 sn_len = strlen(lease->server_name);
2173 pr_len = strlen(prefix);
2175 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2176 hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2177 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2178 sizeof(size_t) + pr_len;
2180 for (i = 0; i < 256; i++)
2181 hdr.len += sizeof(int) + lease->options[i].len;
2183 scripttime = time(NULL);
2185 if ((buf = buf_open(hdr.len)) == NULL)
2186 error("buf_open: %m");
2189 errs += buf_add(buf, &hdr, sizeof(hdr));
2190 errs += buf_add(buf, lease, sizeof(struct client_lease));
2191 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2192 errs += buf_add(buf, lease->filename, fn_len);
2193 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2194 errs += buf_add(buf, lease->server_name, sn_len);
2195 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2196 errs += buf_add(buf, prefix, pr_len);
2198 for (i = 0; i < 256; i++) {
2199 errs += buf_add(buf, &lease->options[i].len,
2200 sizeof(lease->options[i].len));
2201 errs += buf_add(buf, lease->options[i].data,
2202 lease->options[i].len);
2206 error("buf_add: %m");
2208 if (buf_close(privfd, buf) == -1)
2209 error("buf_close: %m");
2215 struct imsg_hdr hdr;
2219 hdr.code = IMSG_SCRIPT_GO;
2220 hdr.len = sizeof(struct imsg_hdr);
2222 if ((buf = buf_open(hdr.len)) == NULL)
2223 error("buf_open: %m");
2225 if (buf_add(buf, &hdr, sizeof(hdr)))
2226 error("buf_add: %m");
2228 if (buf_close(privfd, buf) == -1)
2229 error("buf_close: %m");
2231 bzero(&hdr, sizeof(hdr));
2232 buf_read(privfd, &hdr, sizeof(hdr));
2233 if (hdr.code != IMSG_SCRIPT_GO_RET)
2234 error("unexpected msg type %u", hdr.code);
2235 if (hdr.len != sizeof(hdr) + sizeof(int))
2236 error("received corrupted message");
2237 buf_read(privfd, &ret, sizeof(ret));
2239 scripttime = time(NULL);
2245 priv_script_go(void)
2247 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2248 static char client_path[] = CLIENT_PATH;
2249 struct interface_info *ip = ifi;
2250 int pid, wpid, wstatus;
2252 scripttime = time(NULL);
2255 scriptName = ip->client->config->script_name;
2256 envp = ip->client->scriptEnv;
2258 scriptName = top_level_config.script_name;
2260 epp[1] = client_path;
2265 argv[0] = scriptName;
2274 wpid = wait(&wstatus);
2275 } while (wpid != pid && wpid > 0);
2281 execve(scriptName, argv, envp);
2282 error("execve (%s, ...): %m", scriptName);
2286 script_flush_env(ip->client);
2288 return (wstatus & 0xff);
2292 script_set_env(struct client_state *client, const char *prefix,
2293 const char *name, const char *value)
2297 /* No `` or $() command substitution allowed in environment values! */
2298 for (j=0; j < strlen(value); j++)
2302 warning("illegal character (%c) in value '%s'",
2304 /* Ignore this option */
2308 namelen = strlen(name);
2310 for (i = 0; client->scriptEnv[i]; i++)
2311 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2312 client->scriptEnv[i][namelen] == '=')
2315 if (client->scriptEnv[i])
2316 /* Reuse the slot. */
2317 free(client->scriptEnv[i]);
2319 /* New variable. Expand if necessary. */
2320 if (i >= client->scriptEnvsize - 1) {
2321 char **newscriptEnv;
2322 int newscriptEnvsize = client->scriptEnvsize + 50;
2324 newscriptEnv = realloc(client->scriptEnv,
2326 if (newscriptEnv == NULL) {
2327 free(client->scriptEnv);
2328 client->scriptEnv = NULL;
2329 client->scriptEnvsize = 0;
2330 error("script_set_env: no memory for variable");
2332 client->scriptEnv = newscriptEnv;
2333 client->scriptEnvsize = newscriptEnvsize;
2335 /* need to set the NULL pointer at end of array beyond
2337 client->scriptEnv[i + 1] = NULL;
2339 /* Allocate space and format the variable in the appropriate slot. */
2340 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2342 if (client->scriptEnv[i] == NULL)
2343 error("script_set_env: no memory for variable assignment");
2344 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2345 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2349 script_flush_env(struct client_state *client)
2353 for (i = 0; client->scriptEnv[i]; i++) {
2354 free(client->scriptEnv[i]);
2355 client->scriptEnv[i] = NULL;
2357 client->scriptEnvsize = 0;
2361 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2365 for (i = 0; option->name[i]; i++) {
2366 if (i + 1 == buflen)
2368 if (option->name[i] == '-')
2371 buf[i] = option->name[i];
2381 static int state = 0;
2382 cap_rights_t rights;
2384 if (no_daemon || state)
2389 /* Stop logging to stderr... */
2392 if (daemon(1, 0) == -1)
2395 cap_rights_init(&rights);
2397 if (pidfile != NULL) {
2398 pidfile_write(pidfile);
2399 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2401 error("can't limit pidfile descriptor: %m");
2405 /* we are chrooted, daemon(3) fails to open /dev/null */
2407 dup2(nullfd, STDIN_FILENO);
2408 dup2(nullfd, STDOUT_FILENO);
2409 dup2(nullfd, STDERR_FILENO);
2414 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2415 error("can't limit stdin: %m");
2416 cap_rights_init(&rights, CAP_WRITE);
2417 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2418 error("can't limit stdout: %m");
2419 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2420 error("can't limit stderr: %m");
2424 check_option(struct client_lease *l, int option)
2429 /* we use this, since this is what gets passed to dhclient-script */
2431 opbuf = pretty_print_option(option, l->options[option].data,
2432 l->options[option].len, 0, 0);
2434 sbuf = option_as_string(option, l->options[option].data,
2435 l->options[option].len);
2438 case DHO_SUBNET_MASK:
2439 case DHO_TIME_SERVERS:
2440 case DHO_NAME_SERVERS:
2442 case DHO_DOMAIN_NAME_SERVERS:
2443 case DHO_LOG_SERVERS:
2444 case DHO_COOKIE_SERVERS:
2445 case DHO_LPR_SERVERS:
2446 case DHO_IMPRESS_SERVERS:
2447 case DHO_RESOURCE_LOCATION_SERVERS:
2448 case DHO_SWAP_SERVER:
2449 case DHO_BROADCAST_ADDRESS:
2450 case DHO_NIS_SERVERS:
2451 case DHO_NTP_SERVERS:
2452 case DHO_NETBIOS_NAME_SERVERS:
2453 case DHO_NETBIOS_DD_SERVER:
2454 case DHO_FONT_SERVERS:
2455 case DHO_DHCP_SERVER_IDENTIFIER:
2456 case DHO_NISPLUS_SERVERS:
2457 case DHO_MOBILE_IP_HOME_AGENT:
2458 case DHO_SMTP_SERVER:
2459 case DHO_POP_SERVER:
2460 case DHO_NNTP_SERVER:
2461 case DHO_WWW_SERVER:
2462 case DHO_FINGER_SERVER:
2463 case DHO_IRC_SERVER:
2464 case DHO_STREETTALK_SERVER:
2465 case DHO_STREETTALK_DA_SERVER:
2466 if (!ipv4addrs(opbuf)) {
2467 warning("Invalid IP address in option: %s", opbuf);
2472 case DHO_NIS_DOMAIN:
2473 case DHO_NISPLUS_DOMAIN:
2474 case DHO_TFTP_SERVER_NAME:
2475 if (!res_hnok(sbuf)) {
2476 warning("Bogus Host Name option %d: %s (%s)", option,
2478 l->options[option].len = 0;
2479 free(l->options[option].data);
2482 case DHO_DOMAIN_NAME:
2483 case DHO_DOMAIN_SEARCH:
2484 if (!res_hnok(sbuf)) {
2485 if (!check_search(sbuf)) {
2486 warning("Bogus domain search list %d: %s (%s)",
2487 option, sbuf, opbuf);
2488 l->options[option].len = 0;
2489 free(l->options[option].data);
2494 case DHO_TIME_OFFSET:
2496 case DHO_MERIT_DUMP:
2498 case DHO_EXTENSIONS_PATH:
2499 case DHO_IP_FORWARDING:
2500 case DHO_NON_LOCAL_SOURCE_ROUTING:
2501 case DHO_POLICY_FILTER:
2502 case DHO_MAX_DGRAM_REASSEMBLY:
2503 case DHO_DEFAULT_IP_TTL:
2504 case DHO_PATH_MTU_AGING_TIMEOUT:
2505 case DHO_PATH_MTU_PLATEAU_TABLE:
2506 case DHO_INTERFACE_MTU:
2507 case DHO_ALL_SUBNETS_LOCAL:
2508 case DHO_PERFORM_MASK_DISCOVERY:
2509 case DHO_MASK_SUPPLIER:
2510 case DHO_ROUTER_DISCOVERY:
2511 case DHO_ROUTER_SOLICITATION_ADDRESS:
2512 case DHO_STATIC_ROUTES:
2513 case DHO_TRAILER_ENCAPSULATION:
2514 case DHO_ARP_CACHE_TIMEOUT:
2515 case DHO_IEEE802_3_ENCAPSULATION:
2516 case DHO_DEFAULT_TCP_TTL:
2517 case DHO_TCP_KEEPALIVE_INTERVAL:
2518 case DHO_TCP_KEEPALIVE_GARBAGE:
2519 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2520 case DHO_NETBIOS_NODE_TYPE:
2521 case DHO_NETBIOS_SCOPE:
2522 case DHO_X_DISPLAY_MANAGER:
2523 case DHO_DHCP_REQUESTED_ADDRESS:
2524 case DHO_DHCP_LEASE_TIME:
2525 case DHO_DHCP_OPTION_OVERLOAD:
2526 case DHO_DHCP_MESSAGE_TYPE:
2527 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2528 case DHO_DHCP_MESSAGE:
2529 case DHO_DHCP_MAX_MESSAGE_SIZE:
2530 case DHO_DHCP_RENEWAL_TIME:
2531 case DHO_DHCP_REBINDING_TIME:
2532 case DHO_DHCP_CLASS_IDENTIFIER:
2533 case DHO_DHCP_CLIENT_IDENTIFIER:
2534 case DHO_BOOTFILE_NAME:
2535 case DHO_DHCP_USER_CLASS_ID:
2538 case DHO_CLASSLESS_ROUTES:
2539 return (check_classless_option(l->options[option].data,
2540 l->options[option].len));
2542 warning("unknown dhcp option value 0x%x", option);
2543 return (unknown_ok);
2547 /* RFC 3442 The Classless Static Routes option checks */
2549 check_classless_option(unsigned char *data, int len)
2552 unsigned char width;
2553 in_addr_t addr, mask;
2556 warning("Too small length: %d", len);
2564 } else if (width < 9) {
2565 addr = (in_addr_t)(data[i] << 24);
2567 } else if (width < 17) {
2568 addr = (in_addr_t)(data[i] << 24) +
2569 (in_addr_t)(data[i + 1] << 16);
2571 } else if (width < 25) {
2572 addr = (in_addr_t)(data[i] << 24) +
2573 (in_addr_t)(data[i + 1] << 16) +
2574 (in_addr_t)(data[i + 2] << 8);
2576 } else if (width < 33) {
2577 addr = (in_addr_t)(data[i] << 24) +
2578 (in_addr_t)(data[i + 1] << 16) +
2579 (in_addr_t)(data[i + 2] << 8) +
2583 warning("Incorrect subnet width: %d", width);
2586 mask = (in_addr_t)(~0) << (32 - width);
2592 * ... After deriving a subnet number and subnet mask
2593 * from each destination descriptor, the DHCP client
2594 * MUST zero any bits in the subnet number where the
2595 * corresponding bit in the mask is zero...
2597 if ((addr & mask) != addr) {
2599 data[i - 1] = (unsigned char)(
2600 (addr >> (((32 - width)/8)*8)) & 0xFF);
2605 warning("Incorrect data length: %d (must be %d)", len, i);
2612 res_hnok(const char *dn)
2614 int pch = PERIOD, ch = *dn++;
2616 while (ch != '\0') {
2619 if (periodchar(ch)) {
2621 } else if (periodchar(pch)) {
2622 if (!borderchar(ch))
2624 } else if (periodchar(nch) || nch == '\0') {
2625 if (!borderchar(ch))
2628 if (!middlechar(ch))
2637 check_search(const char *srch)
2639 int pch = PERIOD, ch = *srch++;
2642 /* 256 char limit re resolv.conf(5) */
2643 if (strlen(srch) > 256)
2646 while (whitechar(ch))
2649 while (ch != '\0') {
2652 if (periodchar(ch) || whitechar(ch)) {
2654 } else if (periodchar(pch)) {
2655 if (!borderchar(ch))
2657 } else if (periodchar(nch) || nch == '\0') {
2658 if (!borderchar(ch))
2661 if (!middlechar(ch))
2664 if (!whitechar(ch)) {
2667 while (whitechar(nch)) {
2676 /* 6 domain limit re resolv.conf(5) */
2682 /* Does buf consist only of dotted decimal ipv4 addrs?
2683 * return how many if so,
2684 * otherwise, return 0
2687 ipv4addrs(char * buf)
2692 while (inet_aton(buf, &jnk) == 1){
2694 while (periodchar(*buf) || digitchar(*buf))
2706 option_as_string(unsigned int code, unsigned char *data, int len)
2708 static char optbuf[32768]; /* XXX */
2710 int opleft = sizeof(optbuf);
2711 unsigned char *dp = data;
2714 error("option_as_string: bad code %d", code);
2716 for (; dp < data + len; dp++) {
2717 if (!isascii(*dp) || !isprint(*dp)) {
2718 if (dp + 1 != data + len || *dp != 0) {
2719 snprintf(op, opleft, "\\%03o", *dp);
2723 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2724 *dp == '`' || *dp == '\\') {
2738 warning("dhcp option too large");
2743 fork_privchld(int fd, int fd2)
2745 struct pollfd pfd[1];
2750 error("cannot fork");
2757 setproctitle("%s [priv]", ifi->name);
2760 dup2(nullfd, STDIN_FILENO);
2761 dup2(nullfd, STDOUT_FILENO);
2762 dup2(nullfd, STDERR_FILENO);
2770 pfd[0].events = POLLIN;
2771 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2773 error("poll error");
2775 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2778 dispatch_imsg(ifi, fd);