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 = { .len = 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 < (ssize_t)sizeof(rtm->rtm_msglen) ||
233 n < (ssize_t)rtm->rtm_msglen ||
234 rtm->rtm_version != RTM_VERSION)
237 switch (rtm->rtm_type) {
240 ifam = (struct ifa_msghdr *)rtm;
242 if (ifam->ifam_index != ifi->index)
244 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
246 if (scripttime == 0 || t < scripttime + 10)
249 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
253 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
254 error("king bula sez: len mismatch");
255 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
256 if (addr_eq(a, defaddr))
259 for (l = ifi->client->active; l != NULL; l = l->next)
260 if (addr_eq(a, l->address))
263 if (l == NULL) /* added/deleted addr is not the one we set */
266 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
267 if (rtm->rtm_type == RTM_NEWADDR) {
269 * XXX: If someone other than us adds our address,
270 * should we assume they are taking over from us,
271 * delete the lease record, and exit without modifying
274 warning("My address (%s) was re-added", addr);
276 warning("My address (%s) was deleted, dhclient exiting",
282 ifm = (struct if_msghdr *)rtm;
283 if (ifm->ifm_index != ifi->index)
285 if ((rtm->rtm_flags & RTF_UP) == 0) {
286 warning("Interface %s is down, dhclient exiting",
290 linkstat = interface_link_status(ifi->name);
291 if (linkstat != ifi->linkstat) {
292 debug("%s link state %s -> %s", ifi->name,
293 ifi->linkstat ? "up" : "down",
294 linkstat ? "up" : "down");
295 ifi->linkstat = linkstat;
301 ifan = (struct if_announcemsghdr *)rtm;
302 if (ifan->ifan_what == IFAN_DEPARTURE &&
303 ifan->ifan_index == ifi->index) {
304 warning("Interface %s is gone, dhclient exiting",
310 ifan = (struct if_announcemsghdr *)rtm;
311 if (ifan->ifan_index != ifi->index)
313 switch (ifan->ifan_what) {
314 case RTM_IEEE80211_ASSOC:
315 case RTM_IEEE80211_REASSOC:
317 * Use assoc/reassoc event to kick state machine
318 * in case we roam. Otherwise fall back to the
319 * normal state machine just like a wired network.
321 jev = (struct ieee80211_join_event *) &ifan[1];
322 if (memcmp(curbssid, jev->iev_addr, 6)) {
326 memcpy(curbssid, jev->iev_addr, 6);
336 script_init("FAIL", NULL);
337 if (ifi->client->alias)
338 script_write_params("alias_", ifi->client->alias);
341 pidfile_remove(pidfile);
346 main(int argc, char *argv[])
348 extern char *__progname;
349 int ch, fd, quiet = 0, i = 0;
351 int immediate_daemon = 0;
356 /* Initially, log errors to stderr as well as to syslogd. */
357 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
358 setlogmask(LOG_UPTO(LOG_DEBUG));
360 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
363 immediate_daemon = 1;
366 path_dhclient_conf = optarg;
372 path_dhclient_db = optarg;
375 path_dhclient_pidfile = optarg;
393 if (path_dhclient_pidfile == NULL) {
394 asprintf(&path_dhclient_pidfile,
395 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
396 if (path_dhclient_pidfile == NULL)
399 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
400 if (pidfile == NULL) {
402 error("dhclient already running, pid: %d.", otherpid);
404 error("dhclient already running.");
405 warning("Cannot open or create pidfile: %m");
408 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
410 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
411 error("Interface name too long");
412 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
413 _PATH_DHCLIENT_DB, ifi->name) == -1)
422 inaddr_broadcast.s_addr = INADDR_BROADCAST;
423 inaddr_any.s_addr = INADDR_ANY;
427 /* The next bit is potentially very time-consuming, so write out
428 the pidfile right away. We will write it out again with the
429 correct pid after daemonizing. */
431 pidfile_write(pidfile);
433 if (!interface_link_status(ifi->name)) {
434 fprintf(stderr, "%s: no link ...", ifi->name);
437 while (!interface_link_status(ifi->name)) {
438 fprintf(stderr, ".");
441 fprintf(stderr, " giving up\n");
446 fprintf(stderr, " got link\n");
450 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
451 error("cannot open %s: %m", _PATH_DEVNULL);
453 if ((pw = getpwnam("_dhcp")) == NULL) {
454 warning("no such user: _dhcp, falling back to \"nobody\"");
455 if ((pw = getpwnam("nobody")) == NULL)
456 error("no such user: nobody");
460 * Obtain hostname before entering capability mode - it won't be
461 * possible then, as reading kern.hostname is not permitted.
463 if (gethostname(hostname, sizeof(hostname)) < 0)
466 priv_script_init("PREINIT", NULL);
467 if (ifi->client->alias)
468 priv_script_write_params("alias_", ifi->client->alias);
471 /* set up the interface */
472 discover_interfaces(ifi);
474 if (pipe(pipe_fd) == -1)
477 fork_privchld(pipe_fd[0], pipe_fd[1]);
486 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
487 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
488 error("can't limit private descriptor: %m");
490 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
491 error("can't open and lock %s: %m", path_dhclient_db);
492 read_client_leases();
493 rewrite_client_leases();
496 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
497 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
498 if (shutdown(routefd, SHUT_WR) < 0)
499 error("can't shutdown route socket: %m");
500 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
501 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
502 error("can't limit route socket: %m");
504 if (chroot(_PATH_VAREMPTY) == -1)
506 if (chdir("/") == -1)
507 error("chdir(\"/\")");
509 if (setgroups(1, &pw->pw_gid) ||
510 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
511 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
512 error("can't drop privileges: %m");
516 setproctitle("%s", ifi->name);
518 if (cap_enter() < 0 && errno != ENOSYS)
519 error("can't enter capability mode: %m");
521 if (immediate_daemon)
524 ifi->client->state = S_INIT;
527 bootp_packet_handler = do_packet;
538 extern char *__progname;
540 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
541 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
548 * Each routine is called from the dhclient_state_machine() in one of
550 * -> entering INIT state
551 * -> recvpacket_flag == 0: timeout in this state
552 * -> otherwise: received a packet in this state
554 * Return conditions as handled by dhclient_state_machine():
555 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
556 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
557 * Returns 0: finish the nap which was interrupted for no good reason.
559 * Several per-interface variables are used to keep track of the process:
560 * active_lease: the lease that is being used on the interface
561 * (null pointer if not configured yet).
562 * offered_leases: leases corresponding to DHCPOFFER messages that have
563 * been sent to us by DHCP servers.
564 * acked_leases: leases corresponding to DHCPACK messages that have been
565 * sent to us by DHCP servers.
566 * sendpacket: DHCP packet we're trying to send.
567 * destination: IP address to send sendpacket to
568 * In addition, there are several relevant per-lease variables.
569 * T1_expiry, T2_expiry, lease_expiry: lease milestones
570 * In the active lease, these control the process of renewing the lease;
571 * In leases on the acked_leases list, this simply determines when we
572 * can no longer legitimately use the lease.
576 state_reboot(void *ipp)
578 struct interface_info *ip = ipp;
580 /* If we don't remember an active lease, go straight to INIT. */
581 if (!ip->client->active || ip->client->active->is_bootp) {
586 /* We are in the rebooting state. */
587 ip->client->state = S_REBOOTING;
589 /* make_request doesn't initialize xid because it normally comes
590 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
591 so pick an xid now. */
592 ip->client->xid = arc4random();
594 /* Make a DHCPREQUEST packet, and set appropriate per-interface
596 make_request(ip, ip->client->active);
597 ip->client->destination = iaddr_broadcast;
598 ip->client->first_sending = cur_time;
599 ip->client->interval = ip->client->config->initial_interval;
601 /* Zap the medium list... */
602 ip->client->medium = NULL;
604 /* Send out the first DHCPREQUEST packet. */
609 * Called when a lease has completely expired and we've
610 * been unable to renew it.
613 state_init(void *ipp)
615 struct interface_info *ip = ipp;
617 ASSERT_STATE(state, S_INIT);
619 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
621 make_discover(ip, ip->client->active);
622 ip->client->xid = ip->client->packet.xid;
623 ip->client->destination = iaddr_broadcast;
624 ip->client->state = S_SELECTING;
625 ip->client->first_sending = cur_time;
626 ip->client->interval = ip->client->config->initial_interval;
628 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
634 * state_selecting is called when one or more DHCPOFFER packets
635 * have been received and a configurable period of time has passed.
638 state_selecting(void *ipp)
640 struct interface_info *ip = ipp;
641 struct client_lease *lp, *next, *picked;
643 ASSERT_STATE(state, S_SELECTING);
645 /* Cancel state_selecting and send_discover timeouts, since either
646 one could have got us here. */
647 cancel_timeout(state_selecting, ip);
648 cancel_timeout(send_discover, ip);
650 /* We have received one or more DHCPOFFER packets. Currently,
651 the only criterion by which we judge leases is whether or
652 not we get a response when we arp for them. */
654 for (lp = ip->client->offered_leases; lp; lp = next) {
657 /* Check to see if we got an ARPREPLY for the address
658 in this particular lease. */
660 script_init("ARPCHECK", lp->medium);
661 script_write_params("check_", lp);
663 /* If the ARPCHECK code detects another
664 machine using the offered address, it exits
665 nonzero. We need to send a DHCPDECLINE and
668 make_decline(ip, lp);
676 free_client_lease(lp);
679 ip->client->offered_leases = NULL;
681 /* If we just tossed all the leases we were offered, go back
684 ip->client->state = S_INIT;
689 /* If it was a BOOTREPLY, we can just take the address right now. */
690 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
691 ip->client->new = picked;
693 /* Make up some lease expiry times
694 XXX these should be configurable. */
695 ip->client->new->expiry = cur_time + 12000;
696 ip->client->new->renewal += cur_time + 8000;
697 ip->client->new->rebind += cur_time + 10000;
699 ip->client->state = S_REQUESTING;
701 /* Bind to the address we received. */
706 /* Go to the REQUESTING state. */
707 ip->client->destination = iaddr_broadcast;
708 ip->client->state = S_REQUESTING;
709 ip->client->first_sending = cur_time;
710 ip->client->interval = ip->client->config->initial_interval;
712 /* Make a DHCPREQUEST packet from the lease we picked. */
713 make_request(ip, picked);
714 ip->client->xid = ip->client->packet.xid;
716 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
717 free_client_lease(picked);
719 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
723 /* state_requesting is called when we receive a DHCPACK message after
724 having sent out one or more DHCPREQUEST packets. */
727 dhcpack(struct packet *packet)
729 struct interface_info *ip = packet->interface;
730 struct client_lease *lease;
732 /* If we're not receptive to an offer right now, or if the offer
733 has an unrecognizable transaction id, then just drop it. */
734 if (packet->interface->client->xid != packet->raw->xid ||
735 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
736 (memcmp(packet->interface->hw_address.haddr,
737 packet->raw->chaddr, packet->raw->hlen)))
740 if (ip->client->state != S_REBOOTING &&
741 ip->client->state != S_REQUESTING &&
742 ip->client->state != S_RENEWING &&
743 ip->client->state != S_REBINDING)
746 note("DHCPACK from %s", piaddr(packet->client_addr));
748 lease = packet_to_lease(packet);
750 note("packet_to_lease failed.");
754 ip->client->new = lease;
756 /* Stop resending DHCPREQUEST. */
757 cancel_timeout(send_request, ip);
759 /* Figure out the lease time. */
760 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
762 ip->client->new->expiry = getULong(
763 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
764 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
765 ip->client->new->expiry = getULong(
766 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
768 ip->client->new->expiry = default_lease_time;
769 /* A number that looks negative here is really just very large,
770 because the lease expiry offset is unsigned. Also make sure that
771 the addition of cur_time below does not overflow (a 32 bit) time_t. */
772 if (ip->client->new->expiry < 0 ||
773 ip->client->new->expiry > TIME_MAX - cur_time)
774 ip->client->new->expiry = TIME_MAX - cur_time;
775 /* XXX should be fixed by resetting the client state */
776 if (ip->client->new->expiry < 60)
777 ip->client->new->expiry = 60;
779 /* Unless overridden in the config, take the server-provided renewal
780 * time if there is one. Otherwise figure it out according to the spec.
781 * Also make sure the renewal time does not exceed the expiry time.
783 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
785 ip->client->new->renewal = getULong(
786 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
787 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
788 ip->client->new->renewal = getULong(
789 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
791 ip->client->new->renewal = ip->client->new->expiry / 2;
792 if (ip->client->new->renewal < 0 ||
793 ip->client->new->renewal > ip->client->new->expiry / 2)
794 ip->client->new->renewal = ip->client->new->expiry / 2;
796 /* Same deal with the rebind time. */
797 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
799 ip->client->new->rebind = getULong(
800 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
801 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
802 ip->client->new->rebind = getULong(
803 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
805 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
806 if (ip->client->new->rebind < 0 ||
807 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
808 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
810 /* Convert the time offsets into seconds-since-the-epoch */
811 ip->client->new->expiry += cur_time;
812 ip->client->new->renewal += cur_time;
813 ip->client->new->rebind += cur_time;
819 bind_lease(struct interface_info *ip)
821 /* Remember the medium. */
822 ip->client->new->medium = ip->client->medium;
824 /* Write out the new lease. */
825 write_client_lease(ip, ip->client->new, 0);
827 /* Run the client script with the new parameters. */
828 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
829 (ip->client->state == S_RENEWING ? "RENEW" :
830 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
831 ip->client->new->medium);
832 if (ip->client->active && ip->client->state != S_REBOOTING)
833 script_write_params("old_", ip->client->active);
834 script_write_params("new_", ip->client->new);
835 if (ip->client->alias)
836 script_write_params("alias_", ip->client->alias);
839 /* Replace the old active lease with the new one. */
840 if (ip->client->active)
841 free_client_lease(ip->client->active);
842 ip->client->active = ip->client->new;
843 ip->client->new = NULL;
845 /* Set up a timeout to start the renewal process. */
846 add_timeout(ip->client->active->renewal, state_bound, ip);
848 note("bound to %s -- renewal in %d seconds.",
849 piaddr(ip->client->active->address),
850 (int)(ip->client->active->renewal - cur_time));
851 ip->client->state = S_BOUND;
852 reinitialize_interfaces();
857 * state_bound is called when we've successfully bound to a particular
858 * lease, but the renewal time on that lease has expired. We are
859 * expected to unicast a DHCPREQUEST to the server that gave us our
863 state_bound(void *ipp)
865 struct interface_info *ip = ipp;
867 ASSERT_STATE(state, S_BOUND);
869 /* T1 has expired. */
870 make_request(ip, ip->client->active);
871 ip->client->xid = ip->client->packet.xid;
873 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
874 memcpy(ip->client->destination.iabuf, ip->client->active->
875 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
876 ip->client->destination.len = 4;
878 ip->client->destination = iaddr_broadcast;
880 ip->client->first_sending = cur_time;
881 ip->client->interval = ip->client->config->initial_interval;
882 ip->client->state = S_RENEWING;
884 /* Send the first packet immediately. */
889 bootp(struct packet *packet)
891 struct iaddrlist *ap;
893 if (packet->raw->op != BOOTREPLY)
896 /* If there's a reject list, make sure this packet's sender isn't
898 for (ap = packet->interface->client->config->reject_list;
900 if (addr_eq(packet->client_addr, ap->addr)) {
901 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
909 dhcp(struct packet *packet)
911 struct iaddrlist *ap;
912 void (*handler)(struct packet *);
915 switch (packet->packet_type) {
932 /* If there's a reject list, make sure this packet's sender isn't
934 for (ap = packet->interface->client->config->reject_list;
936 if (addr_eq(packet->client_addr, ap->addr)) {
937 note("%s from %s rejected.", type, piaddr(ap->addr));
945 dhcpoffer(struct packet *packet)
947 struct interface_info *ip = packet->interface;
948 struct client_lease *lease, *lp;
950 int arp_timeout_needed, stop_selecting;
951 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
952 "DHCPOFFER" : "BOOTREPLY";
954 /* If we're not receptive to an offer right now, or if the offer
955 has an unrecognizable transaction id, then just drop it. */
956 if (ip->client->state != S_SELECTING ||
957 packet->interface->client->xid != packet->raw->xid ||
958 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
959 (memcmp(packet->interface->hw_address.haddr,
960 packet->raw->chaddr, packet->raw->hlen)))
963 note("%s from %s", name, piaddr(packet->client_addr));
966 /* If this lease doesn't supply the minimum required parameters,
968 for (i = 0; ip->client->config->required_options[i]; i++) {
969 if (!packet->options[ip->client->config->
970 required_options[i]].len) {
971 note("%s isn't satisfactory.", name);
976 /* If we've already seen this lease, don't record it again. */
977 for (lease = ip->client->offered_leases;
978 lease; lease = lease->next) {
979 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
980 !memcmp(lease->address.iabuf,
981 &packet->raw->yiaddr, lease->address.len)) {
982 debug("%s already seen.", name);
987 lease = packet_to_lease(packet);
989 note("packet_to_lease failed.");
993 /* If this lease was acquired through a BOOTREPLY, record that
995 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
998 /* Record the medium under which this lease was offered. */
999 lease->medium = ip->client->medium;
1001 /* Send out an ARP Request for the offered IP address. */
1002 script_init("ARPSEND", lease->medium);
1003 script_write_params("check_", lease);
1004 /* If the script can't send an ARP request without waiting,
1005 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1007 arp_timeout_needed = 0;
1009 arp_timeout_needed = 2;
1011 /* Figure out when we're supposed to stop selecting. */
1013 ip->client->first_sending + ip->client->config->select_interval;
1015 /* If this is the lease we asked for, put it at the head of the
1016 list, and don't mess with the arp request timeout. */
1017 if (lease->address.len == ip->client->requested_address.len &&
1018 !memcmp(lease->address.iabuf,
1019 ip->client->requested_address.iabuf,
1020 ip->client->requested_address.len)) {
1021 lease->next = ip->client->offered_leases;
1022 ip->client->offered_leases = lease;
1024 /* If we already have an offer, and arping for this
1025 offer would take us past the selection timeout,
1026 then don't extend the timeout - just hope for the
1028 if (ip->client->offered_leases &&
1029 (cur_time + arp_timeout_needed) > stop_selecting)
1030 arp_timeout_needed = 0;
1032 /* Put the lease at the end of the list. */
1034 if (!ip->client->offered_leases)
1035 ip->client->offered_leases = lease;
1037 for (lp = ip->client->offered_leases; lp->next;
1044 /* If we're supposed to stop selecting before we've had time
1045 to wait for the ARPREPLY, add some delay to wait for
1047 if (stop_selecting - cur_time < arp_timeout_needed)
1048 stop_selecting = cur_time + arp_timeout_needed;
1050 /* If the selecting interval has expired, go immediately to
1051 state_selecting(). Otherwise, time out into
1052 state_selecting at the select interval. */
1053 if (stop_selecting <= 0)
1054 state_selecting(ip);
1056 add_timeout(stop_selecting, state_selecting, ip);
1057 cancel_timeout(send_discover, ip);
1061 /* Allocate a client_lease structure and initialize it from the parameters
1062 in the specified packet. */
1064 struct client_lease *
1065 packet_to_lease(struct packet *packet)
1067 struct client_lease *lease;
1070 lease = malloc(sizeof(struct client_lease));
1073 warning("dhcpoffer: no memory to record lease.");
1077 memset(lease, 0, sizeof(*lease));
1079 /* Copy the lease options. */
1080 for (i = 0; i < 256; i++) {
1081 if (packet->options[i].len) {
1082 lease->options[i].data =
1083 malloc(packet->options[i].len + 1);
1084 if (!lease->options[i].data) {
1085 warning("dhcpoffer: no memory for option %d", i);
1086 free_client_lease(lease);
1089 memcpy(lease->options[i].data,
1090 packet->options[i].data,
1091 packet->options[i].len);
1092 lease->options[i].len =
1093 packet->options[i].len;
1094 lease->options[i].data[lease->options[i].len] =
1097 if (!check_option(lease,i)) {
1098 /* ignore a bogus lease offer */
1099 warning("Invalid lease option - ignoring offer");
1100 free_client_lease(lease);
1106 lease->address.len = sizeof(packet->raw->yiaddr);
1107 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1109 lease->nextserver.len = sizeof(packet->raw->siaddr);
1110 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1112 /* If the server name was filled out, copy it.
1113 Do not attempt to validate the server name as a host name.
1114 RFC 2131 merely states that sname is NUL-terminated (which do
1115 do not assume) and that it is the server's host name. Since
1116 the ISC client and server allow arbitrary characters, we do
1118 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1119 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1120 packet->raw->sname[0]) {
1121 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1122 if (!lease->server_name) {
1123 warning("dhcpoffer: no memory for server name.");
1124 free_client_lease(lease);
1127 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1128 lease->server_name[DHCP_SNAME_LEN]='\0';
1131 /* Ditto for the filename. */
1132 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1133 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1134 packet->raw->file[0]) {
1135 /* Don't count on the NUL terminator. */
1136 lease->filename = malloc(DHCP_FILE_LEN + 1);
1137 if (!lease->filename) {
1138 warning("dhcpoffer: no memory for filename.");
1139 free_client_lease(lease);
1142 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1143 lease->filename[DHCP_FILE_LEN]='\0';
1149 dhcpnak(struct packet *packet)
1151 struct interface_info *ip = packet->interface;
1153 /* If we're not receptive to an offer right now, or if the offer
1154 has an unrecognizable transaction id, then just drop it. */
1155 if (packet->interface->client->xid != packet->raw->xid ||
1156 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1157 (memcmp(packet->interface->hw_address.haddr,
1158 packet->raw->chaddr, packet->raw->hlen)))
1161 if (ip->client->state != S_REBOOTING &&
1162 ip->client->state != S_REQUESTING &&
1163 ip->client->state != S_RENEWING &&
1164 ip->client->state != S_REBINDING)
1167 note("DHCPNAK from %s", piaddr(packet->client_addr));
1169 if (!ip->client->active) {
1170 note("DHCPNAK with no active lease.\n");
1174 free_client_lease(ip->client->active);
1175 ip->client->active = NULL;
1177 /* Stop sending DHCPREQUEST packets... */
1178 cancel_timeout(send_request, ip);
1180 ip->client->state = S_INIT;
1184 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1185 one after the right interval has expired. If we don't get an offer by
1186 the time we reach the panic interval, call the panic function. */
1189 send_discover(void *ipp)
1191 struct interface_info *ip = ipp;
1192 int interval, increase = 1;
1194 /* Figure out how long it's been since we started transmitting. */
1195 interval = cur_time - ip->client->first_sending;
1197 /* If we're past the panic timeout, call the script and tell it
1198 we haven't found anything for this interface yet. */
1199 if (interval > ip->client->config->timeout) {
1204 /* If we're selecting media, try the whole list before doing
1205 the exponential backoff, but if we've already received an
1206 offer, stop looping, because we obviously have it right. */
1207 if (!ip->client->offered_leases &&
1208 ip->client->config->media) {
1211 if (ip->client->medium) {
1212 ip->client->medium = ip->client->medium->next;
1215 if (!ip->client->medium) {
1217 error("No valid media types for %s!", ip->name);
1218 ip->client->medium = ip->client->config->media;
1222 note("Trying medium \"%s\" %d", ip->client->medium->string,
1224 script_init("MEDIUM", ip->client->medium);
1230 * If we're supposed to increase the interval, do so. If it's
1231 * currently zero (i.e., we haven't sent any packets yet), set
1232 * it to one; otherwise, add to it a random number between zero
1233 * and two times itself. On average, this means that it will
1234 * double with every transmission.
1237 if (!ip->client->interval)
1238 ip->client->interval =
1239 ip->client->config->initial_interval;
1241 ip->client->interval += (arc4random() >> 2) %
1242 (2 * ip->client->interval);
1245 /* Don't backoff past cutoff. */
1246 if (ip->client->interval >
1247 ip->client->config->backoff_cutoff)
1248 ip->client->interval =
1249 ((ip->client->config->backoff_cutoff / 2)
1250 + ((arc4random() >> 2) %
1251 ip->client->config->backoff_cutoff));
1252 } else if (!ip->client->interval)
1253 ip->client->interval =
1254 ip->client->config->initial_interval;
1256 /* If the backoff would take us to the panic timeout, just use that
1258 if (cur_time + ip->client->interval >
1259 ip->client->first_sending + ip->client->config->timeout)
1260 ip->client->interval =
1261 (ip->client->first_sending +
1262 ip->client->config->timeout) - cur_time + 1;
1264 /* Record the number of seconds since we started sending. */
1265 if (interval < 65536)
1266 ip->client->packet.secs = htons(interval);
1268 ip->client->packet.secs = htons(65535);
1269 ip->client->secs = ip->client->packet.secs;
1271 note("DHCPDISCOVER on %s to %s port %d interval %d",
1272 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1273 (int)ip->client->interval);
1275 /* Send out a packet. */
1276 send_packet_unpriv(privfd, &ip->client->packet,
1277 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1279 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1283 * state_panic gets called if we haven't received any offers in a preset
1284 * amount of time. When this happens, we try to use existing leases
1285 * that haven't yet expired, and failing that, we call the client script
1286 * and hope it can do something.
1289 state_panic(void *ipp)
1291 struct interface_info *ip = ipp;
1292 struct client_lease *loop = ip->client->active;
1293 struct client_lease *lp;
1295 note("No DHCPOFFERS received.");
1297 /* We may not have an active lease, but we may have some
1298 predefined leases that we can try. */
1299 if (!ip->client->active && ip->client->leases)
1302 /* Run through the list of leases and see if one can be used. */
1303 while (ip->client->active) {
1304 if (ip->client->active->expiry > cur_time) {
1305 note("Trying recorded lease %s",
1306 piaddr(ip->client->active->address));
1307 /* Run the client script with the existing
1309 script_init("TIMEOUT",
1310 ip->client->active->medium);
1311 script_write_params("new_", ip->client->active);
1312 if (ip->client->alias)
1313 script_write_params("alias_",
1316 /* If the old lease is still good and doesn't
1317 yet need renewal, go into BOUND state and
1318 timeout at the renewal time. */
1321 ip->client->active->renewal) {
1322 ip->client->state = S_BOUND;
1323 note("bound: renewal in %d seconds.",
1324 (int)(ip->client->active->renewal -
1327 ip->client->active->renewal,
1330 ip->client->state = S_BOUND;
1331 note("bound: immediate renewal.");
1334 reinitialize_interfaces();
1340 /* If there are no other leases, give up. */
1341 if (!ip->client->leases) {
1342 ip->client->leases = ip->client->active;
1343 ip->client->active = NULL;
1348 /* Otherwise, put the active lease at the end of the
1349 lease list, and try another lease.. */
1350 for (lp = ip->client->leases; lp->next; lp = lp->next)
1352 lp->next = ip->client->active;
1354 lp->next->next = NULL;
1355 ip->client->active = ip->client->leases;
1356 ip->client->leases = ip->client->leases->next;
1358 /* If we already tried this lease, we've exhausted the
1359 set of leases, so we might as well give up for
1361 if (ip->client->active == loop)
1364 loop = ip->client->active;
1367 /* No leases were available, or what was available didn't work, so
1368 tell the shell script that we failed to allocate an address,
1369 and try again later. */
1370 note("No working leases in persistent database - sleeping.\n");
1371 script_init("FAIL", NULL);
1372 if (ip->client->alias)
1373 script_write_params("alias_", ip->client->alias);
1375 ip->client->state = S_INIT;
1376 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1382 send_request(void *ipp)
1384 struct interface_info *ip = ipp;
1385 struct in_addr from, to;
1388 /* Figure out how long it's been since we started transmitting. */
1389 interval = cur_time - ip->client->first_sending;
1391 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1392 past the reboot timeout, go to INIT and see if we can
1393 DISCOVER an address... */
1394 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1395 means either that we're on a network with no DHCP server,
1396 or that our server is down. In the latter case, assuming
1397 that there is a backup DHCP server, DHCPDISCOVER will get
1398 us a new address, but we could also have successfully
1399 reused our old address. In the former case, we're hosed
1400 anyway. This is not a win-prone situation. */
1401 if ((ip->client->state == S_REBOOTING ||
1402 ip->client->state == S_REQUESTING) &&
1403 interval > ip->client->config->reboot_timeout) {
1405 ip->client->state = S_INIT;
1406 cancel_timeout(send_request, ip);
1411 /* If we're in the reboot state, make sure the media is set up
1413 if (ip->client->state == S_REBOOTING &&
1414 !ip->client->medium &&
1415 ip->client->active->medium ) {
1416 script_init("MEDIUM", ip->client->active->medium);
1418 /* If the medium we chose won't fly, go to INIT state. */
1422 /* Record the medium. */
1423 ip->client->medium = ip->client->active->medium;
1426 /* If the lease has expired, relinquish the address and go back
1427 to the INIT state. */
1428 if (ip->client->state != S_REQUESTING &&
1429 cur_time > ip->client->active->expiry) {
1430 /* Run the client script with the new parameters. */
1431 script_init("EXPIRE", NULL);
1432 script_write_params("old_", ip->client->active);
1433 if (ip->client->alias)
1434 script_write_params("alias_", ip->client->alias);
1437 /* Now do a preinit on the interface so that we can
1438 discover a new address. */
1439 script_init("PREINIT", NULL);
1440 if (ip->client->alias)
1441 script_write_params("alias_", ip->client->alias);
1444 ip->client->state = S_INIT;
1449 /* Do the exponential backoff... */
1450 if (!ip->client->interval)
1451 ip->client->interval = ip->client->config->initial_interval;
1453 ip->client->interval += ((arc4random() >> 2) %
1454 (2 * ip->client->interval));
1456 /* Don't backoff past cutoff. */
1457 if (ip->client->interval >
1458 ip->client->config->backoff_cutoff)
1459 ip->client->interval =
1460 ((ip->client->config->backoff_cutoff / 2) +
1461 ((arc4random() >> 2) % ip->client->interval));
1463 /* If the backoff would take us to the expiry time, just set the
1464 timeout to the expiry time. */
1465 if (ip->client->state != S_REQUESTING &&
1466 cur_time + ip->client->interval >
1467 ip->client->active->expiry)
1468 ip->client->interval =
1469 ip->client->active->expiry - cur_time + 1;
1471 /* If the lease T2 time has elapsed, or if we're not yet bound,
1472 broadcast the DHCPREQUEST rather than unicasting. */
1473 if (ip->client->state == S_REQUESTING ||
1474 ip->client->state == S_REBOOTING ||
1475 cur_time > ip->client->active->rebind)
1476 to.s_addr = INADDR_BROADCAST;
1478 memcpy(&to.s_addr, ip->client->destination.iabuf,
1481 if (ip->client->state != S_REQUESTING)
1482 memcpy(&from, ip->client->active->address.iabuf,
1485 from.s_addr = INADDR_ANY;
1487 /* Record the number of seconds since we started sending. */
1488 if (ip->client->state == S_REQUESTING)
1489 ip->client->packet.secs = ip->client->secs;
1491 if (interval < 65536)
1492 ip->client->packet.secs = htons(interval);
1494 ip->client->packet.secs = htons(65535);
1497 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1500 /* Send out a packet. */
1501 send_packet_unpriv(privfd, &ip->client->packet,
1502 ip->client->packet_length, from, to);
1504 add_timeout(cur_time + ip->client->interval, send_request, ip);
1508 send_decline(void *ipp)
1510 struct interface_info *ip = ipp;
1512 note("DHCPDECLINE on %s to %s port %d", ip->name,
1513 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1515 /* Send out a packet. */
1516 send_packet_unpriv(privfd, &ip->client->packet,
1517 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1521 make_discover(struct interface_info *ip, struct client_lease *lease)
1523 unsigned char discover = DHCPDISCOVER;
1524 struct tree_cache *options[256];
1525 struct tree_cache option_elements[256];
1528 memset(option_elements, 0, sizeof(option_elements));
1529 memset(options, 0, sizeof(options));
1530 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1532 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1533 i = DHO_DHCP_MESSAGE_TYPE;
1534 options[i] = &option_elements[i];
1535 options[i]->value = &discover;
1536 options[i]->len = sizeof(discover);
1537 options[i]->buf_size = sizeof(discover);
1538 options[i]->timeout = 0xFFFFFFFF;
1540 /* Request the options we want */
1541 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1542 options[i] = &option_elements[i];
1543 options[i]->value = ip->client->config->requested_options;
1544 options[i]->len = ip->client->config->requested_option_count;
1545 options[i]->buf_size =
1546 ip->client->config->requested_option_count;
1547 options[i]->timeout = 0xFFFFFFFF;
1549 /* If we had an address, try to get it again. */
1551 ip->client->requested_address = lease->address;
1552 i = DHO_DHCP_REQUESTED_ADDRESS;
1553 options[i] = &option_elements[i];
1554 options[i]->value = lease->address.iabuf;
1555 options[i]->len = lease->address.len;
1556 options[i]->buf_size = lease->address.len;
1557 options[i]->timeout = 0xFFFFFFFF;
1559 ip->client->requested_address.len = 0;
1561 /* Send any options requested in the config file. */
1562 for (i = 0; i < 256; i++)
1564 ip->client->config->send_options[i].data) {
1565 options[i] = &option_elements[i];
1567 ip->client->config->send_options[i].data;
1569 ip->client->config->send_options[i].len;
1570 options[i]->buf_size =
1571 ip->client->config->send_options[i].len;
1572 options[i]->timeout = 0xFFFFFFFF;
1575 /* send host name if not set via config file. */
1576 if (!options[DHO_HOST_NAME]) {
1577 if (hostname[0] != '\0') {
1579 char* posDot = strchr(hostname, '.');
1581 len = posDot - hostname;
1583 len = strlen(hostname);
1584 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1585 options[DHO_HOST_NAME]->value = hostname;
1586 options[DHO_HOST_NAME]->len = len;
1587 options[DHO_HOST_NAME]->buf_size = len;
1588 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1592 /* set unique client identifier */
1593 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1594 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1595 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1596 ip->hw_address.hlen : sizeof(client_ident)-1;
1597 client_ident[0] = ip->hw_address.htype;
1598 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1599 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1600 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1601 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1602 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1603 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1606 /* Set up the option buffer... */
1607 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1608 options, 0, 0, 0, NULL, 0);
1609 if (ip->client->packet_length < BOOTP_MIN_LEN)
1610 ip->client->packet_length = BOOTP_MIN_LEN;
1612 ip->client->packet.op = BOOTREQUEST;
1613 ip->client->packet.htype = ip->hw_address.htype;
1614 ip->client->packet.hlen = ip->hw_address.hlen;
1615 ip->client->packet.hops = 0;
1616 ip->client->packet.xid = arc4random();
1617 ip->client->packet.secs = 0; /* filled in by send_discover. */
1618 ip->client->packet.flags = 0;
1620 memset(&(ip->client->packet.ciaddr),
1621 0, sizeof(ip->client->packet.ciaddr));
1622 memset(&(ip->client->packet.yiaddr),
1623 0, sizeof(ip->client->packet.yiaddr));
1624 memset(&(ip->client->packet.siaddr),
1625 0, sizeof(ip->client->packet.siaddr));
1626 memset(&(ip->client->packet.giaddr),
1627 0, sizeof(ip->client->packet.giaddr));
1628 memcpy(ip->client->packet.chaddr,
1629 ip->hw_address.haddr, ip->hw_address.hlen);
1634 make_request(struct interface_info *ip, struct client_lease * lease)
1636 unsigned char request = DHCPREQUEST;
1637 struct tree_cache *options[256];
1638 struct tree_cache option_elements[256];
1641 memset(options, 0, sizeof(options));
1642 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1644 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1645 i = DHO_DHCP_MESSAGE_TYPE;
1646 options[i] = &option_elements[i];
1647 options[i]->value = &request;
1648 options[i]->len = sizeof(request);
1649 options[i]->buf_size = sizeof(request);
1650 options[i]->timeout = 0xFFFFFFFF;
1652 /* Request the options we want */
1653 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1654 options[i] = &option_elements[i];
1655 options[i]->value = ip->client->config->requested_options;
1656 options[i]->len = ip->client->config->requested_option_count;
1657 options[i]->buf_size =
1658 ip->client->config->requested_option_count;
1659 options[i]->timeout = 0xFFFFFFFF;
1661 /* If we are requesting an address that hasn't yet been assigned
1662 to us, use the DHCP Requested Address option. */
1663 if (ip->client->state == S_REQUESTING) {
1664 /* Send back the server identifier... */
1665 i = DHO_DHCP_SERVER_IDENTIFIER;
1666 options[i] = &option_elements[i];
1667 options[i]->value = lease->options[i].data;
1668 options[i]->len = lease->options[i].len;
1669 options[i]->buf_size = lease->options[i].len;
1670 options[i]->timeout = 0xFFFFFFFF;
1672 if (ip->client->state == S_REQUESTING ||
1673 ip->client->state == S_REBOOTING) {
1674 ip->client->requested_address = lease->address;
1675 i = DHO_DHCP_REQUESTED_ADDRESS;
1676 options[i] = &option_elements[i];
1677 options[i]->value = lease->address.iabuf;
1678 options[i]->len = lease->address.len;
1679 options[i]->buf_size = lease->address.len;
1680 options[i]->timeout = 0xFFFFFFFF;
1682 ip->client->requested_address.len = 0;
1684 /* Send any options requested in the config file. */
1685 for (i = 0; i < 256; i++)
1687 ip->client->config->send_options[i].data) {
1688 options[i] = &option_elements[i];
1690 ip->client->config->send_options[i].data;
1692 ip->client->config->send_options[i].len;
1693 options[i]->buf_size =
1694 ip->client->config->send_options[i].len;
1695 options[i]->timeout = 0xFFFFFFFF;
1698 /* send host name if not set via config file. */
1699 if (!options[DHO_HOST_NAME]) {
1700 if (hostname[0] != '\0') {
1702 char* posDot = strchr(hostname, '.');
1704 len = posDot - hostname;
1706 len = strlen(hostname);
1707 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1708 options[DHO_HOST_NAME]->value = hostname;
1709 options[DHO_HOST_NAME]->len = len;
1710 options[DHO_HOST_NAME]->buf_size = len;
1711 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1715 /* set unique client identifier */
1716 char client_ident[sizeof(struct hardware)];
1717 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1718 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1719 ip->hw_address.hlen : sizeof(client_ident)-1;
1720 client_ident[0] = ip->hw_address.htype;
1721 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1722 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1723 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1724 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1725 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1726 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1729 /* Set up the option buffer... */
1730 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1731 options, 0, 0, 0, NULL, 0);
1732 if (ip->client->packet_length < BOOTP_MIN_LEN)
1733 ip->client->packet_length = BOOTP_MIN_LEN;
1735 ip->client->packet.op = BOOTREQUEST;
1736 ip->client->packet.htype = ip->hw_address.htype;
1737 ip->client->packet.hlen = ip->hw_address.hlen;
1738 ip->client->packet.hops = 0;
1739 ip->client->packet.xid = ip->client->xid;
1740 ip->client->packet.secs = 0; /* Filled in by send_request. */
1742 /* If we own the address we're requesting, put it in ciaddr;
1743 otherwise set ciaddr to zero. */
1744 if (ip->client->state == S_BOUND ||
1745 ip->client->state == S_RENEWING ||
1746 ip->client->state == S_REBINDING) {
1747 memcpy(&ip->client->packet.ciaddr,
1748 lease->address.iabuf, lease->address.len);
1749 ip->client->packet.flags = 0;
1751 memset(&ip->client->packet.ciaddr, 0,
1752 sizeof(ip->client->packet.ciaddr));
1753 ip->client->packet.flags = 0;
1756 memset(&ip->client->packet.yiaddr, 0,
1757 sizeof(ip->client->packet.yiaddr));
1758 memset(&ip->client->packet.siaddr, 0,
1759 sizeof(ip->client->packet.siaddr));
1760 memset(&ip->client->packet.giaddr, 0,
1761 sizeof(ip->client->packet.giaddr));
1762 memcpy(ip->client->packet.chaddr,
1763 ip->hw_address.haddr, ip->hw_address.hlen);
1767 make_decline(struct interface_info *ip, struct client_lease *lease)
1769 struct tree_cache *options[256], message_type_tree;
1770 struct tree_cache requested_address_tree;
1771 struct tree_cache server_id_tree, client_id_tree;
1772 unsigned char decline = DHCPDECLINE;
1775 memset(options, 0, sizeof(options));
1776 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1778 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1779 i = DHO_DHCP_MESSAGE_TYPE;
1780 options[i] = &message_type_tree;
1781 options[i]->value = &decline;
1782 options[i]->len = sizeof(decline);
1783 options[i]->buf_size = sizeof(decline);
1784 options[i]->timeout = 0xFFFFFFFF;
1786 /* Send back the server identifier... */
1787 i = DHO_DHCP_SERVER_IDENTIFIER;
1788 options[i] = &server_id_tree;
1789 options[i]->value = lease->options[i].data;
1790 options[i]->len = lease->options[i].len;
1791 options[i]->buf_size = lease->options[i].len;
1792 options[i]->timeout = 0xFFFFFFFF;
1794 /* Send back the address we're declining. */
1795 i = DHO_DHCP_REQUESTED_ADDRESS;
1796 options[i] = &requested_address_tree;
1797 options[i]->value = lease->address.iabuf;
1798 options[i]->len = lease->address.len;
1799 options[i]->buf_size = lease->address.len;
1800 options[i]->timeout = 0xFFFFFFFF;
1802 /* Send the uid if the user supplied one. */
1803 i = DHO_DHCP_CLIENT_IDENTIFIER;
1804 if (ip->client->config->send_options[i].len) {
1805 options[i] = &client_id_tree;
1806 options[i]->value = ip->client->config->send_options[i].data;
1807 options[i]->len = ip->client->config->send_options[i].len;
1808 options[i]->buf_size = ip->client->config->send_options[i].len;
1809 options[i]->timeout = 0xFFFFFFFF;
1813 /* Set up the option buffer... */
1814 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1815 options, 0, 0, 0, NULL, 0);
1816 if (ip->client->packet_length < BOOTP_MIN_LEN)
1817 ip->client->packet_length = BOOTP_MIN_LEN;
1819 ip->client->packet.op = BOOTREQUEST;
1820 ip->client->packet.htype = ip->hw_address.htype;
1821 ip->client->packet.hlen = ip->hw_address.hlen;
1822 ip->client->packet.hops = 0;
1823 ip->client->packet.xid = ip->client->xid;
1824 ip->client->packet.secs = 0; /* Filled in by send_request. */
1825 ip->client->packet.flags = 0;
1827 /* ciaddr must always be zero. */
1828 memset(&ip->client->packet.ciaddr, 0,
1829 sizeof(ip->client->packet.ciaddr));
1830 memset(&ip->client->packet.yiaddr, 0,
1831 sizeof(ip->client->packet.yiaddr));
1832 memset(&ip->client->packet.siaddr, 0,
1833 sizeof(ip->client->packet.siaddr));
1834 memset(&ip->client->packet.giaddr, 0,
1835 sizeof(ip->client->packet.giaddr));
1836 memcpy(ip->client->packet.chaddr,
1837 ip->hw_address.haddr, ip->hw_address.hlen);
1841 free_client_lease(struct client_lease *lease)
1845 if (lease->server_name)
1846 free(lease->server_name);
1847 if (lease->filename)
1848 free(lease->filename);
1849 for (i = 0; i < 256; i++) {
1850 if (lease->options[i].len)
1851 free(lease->options[i].data);
1859 rewrite_client_leases(void)
1861 struct client_lease *lp;
1862 cap_rights_t rights;
1865 leaseFile = fopen(path_dhclient_db, "w");
1867 error("can't create %s: %m", path_dhclient_db);
1868 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1869 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1870 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1872 error("can't limit lease descriptor: %m");
1874 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1876 error("can't limit lease descriptor fcntls: %m");
1883 for (lp = ifi->client->leases; lp; lp = lp->next)
1884 write_client_lease(ifi, lp, 1);
1885 if (ifi->client->active)
1886 write_client_lease(ifi, ifi->client->active, 1);
1889 ftruncate(fileno(leaseFile), ftello(leaseFile));
1890 fsync(fileno(leaseFile));
1894 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1897 static int leases_written;
1902 if (leases_written++ > 20) {
1903 rewrite_client_leases();
1908 /* If the lease came from the config file, we don't need to stash
1909 a copy in the lease database. */
1910 if (lease->is_static)
1913 if (!leaseFile) { /* XXX */
1914 leaseFile = fopen(path_dhclient_db, "w");
1916 error("can't create %s: %m", path_dhclient_db);
1919 fprintf(leaseFile, "lease {\n");
1920 if (lease->is_bootp)
1921 fprintf(leaseFile, " bootp;\n");
1922 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1923 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1924 if (lease->nextserver.len == sizeof(inaddr_any) &&
1925 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1926 sizeof(inaddr_any)))
1927 fprintf(leaseFile, " next-server %s;\n",
1928 piaddr(lease->nextserver));
1929 if (lease->filename)
1930 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1931 if (lease->server_name)
1932 fprintf(leaseFile, " server-name \"%s\";\n",
1933 lease->server_name);
1935 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1936 for (i = 0; i < 256; i++)
1937 if (lease->options[i].len)
1938 fprintf(leaseFile, " option %s %s;\n",
1939 dhcp_options[i].name,
1940 pretty_print_option(i, lease->options[i].data,
1941 lease->options[i].len, 1, 1));
1943 t = gmtime(&lease->renewal);
1944 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1945 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1946 t->tm_hour, t->tm_min, t->tm_sec);
1947 t = gmtime(&lease->rebind);
1948 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1949 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1950 t->tm_hour, t->tm_min, t->tm_sec);
1951 t = gmtime(&lease->expiry);
1952 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1953 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1954 t->tm_hour, t->tm_min, t->tm_sec);
1955 fprintf(leaseFile, "}\n");
1960 script_init(char *reason, struct string_list *medium)
1962 size_t len, mediumlen = 0;
1963 struct imsg_hdr hdr;
1967 if (medium != NULL && medium->string != NULL)
1968 mediumlen = strlen(medium->string);
1970 hdr.code = IMSG_SCRIPT_INIT;
1971 hdr.len = sizeof(struct imsg_hdr) +
1972 sizeof(size_t) + mediumlen +
1973 sizeof(size_t) + strlen(reason);
1975 if ((buf = buf_open(hdr.len)) == NULL)
1976 error("buf_open: %m");
1979 errs += buf_add(buf, &hdr, sizeof(hdr));
1980 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1982 errs += buf_add(buf, medium->string, mediumlen);
1983 len = strlen(reason);
1984 errs += buf_add(buf, &len, sizeof(len));
1985 errs += buf_add(buf, reason, len);
1988 error("buf_add: %m");
1990 if (buf_close(privfd, buf) == -1)
1991 error("buf_close: %m");
1995 priv_script_init(char *reason, char *medium)
1997 struct interface_info *ip = ifi;
2000 ip->client->scriptEnvsize = 100;
2001 if (ip->client->scriptEnv == NULL)
2002 ip->client->scriptEnv =
2003 malloc(ip->client->scriptEnvsize * sizeof(char *));
2004 if (ip->client->scriptEnv == NULL)
2005 error("script_init: no memory for environment");
2007 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2008 if (ip->client->scriptEnv[0] == NULL)
2009 error("script_init: no memory for environment");
2011 ip->client->scriptEnv[1] = NULL;
2013 script_set_env(ip->client, "", "interface", ip->name);
2016 script_set_env(ip->client, "", "medium", medium);
2018 script_set_env(ip->client, "", "reason", reason);
2023 priv_script_write_params(char *prefix, struct client_lease *lease)
2025 struct interface_info *ip = ifi;
2026 u_int8_t dbuf[1500], *dp = NULL;
2031 script_set_env(ip->client, prefix, "ip_address",
2032 piaddr(lease->address));
2034 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2036 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2037 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2039 dp = lease->options[DHO_SUBNET_MASK].data;
2040 len = lease->options[DHO_SUBNET_MASK].len;
2042 if (len && (len < sizeof(lease->address.iabuf))) {
2043 struct iaddr netmask, subnet, broadcast;
2045 memcpy(netmask.iabuf, dp, len);
2047 subnet = subnet_number(lease->address, netmask);
2049 script_set_env(ip->client, prefix, "network_number",
2051 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2052 broadcast = broadcast_addr(subnet, netmask);
2054 script_set_env(ip->client, prefix,
2055 "broadcast_address",
2061 if (lease->filename)
2062 script_set_env(ip->client, prefix, "filename", lease->filename);
2063 if (lease->server_name)
2064 script_set_env(ip->client, prefix, "server_name",
2065 lease->server_name);
2066 for (i = 0; i < 256; i++) {
2069 if (ip->client->config->defaults[i].len) {
2070 if (lease->options[i].len) {
2072 ip->client->config->default_actions[i]) {
2073 case ACTION_DEFAULT:
2074 dp = lease->options[i].data;
2075 len = lease->options[i].len;
2077 case ACTION_SUPERSEDE:
2080 config->defaults[i].data;
2082 config->defaults[i].len;
2084 case ACTION_PREPEND:
2086 config->defaults[i].len +
2087 lease->options[i].len;
2088 if (len >= sizeof(dbuf)) {
2089 warning("no space to %s %s",
2091 dhcp_options[i].name);
2097 config->defaults[i].data,
2099 config->defaults[i].len);
2100 memcpy(dp + ip->client->
2101 config->defaults[i].len,
2102 lease->options[i].data,
2103 lease->options[i].len);
2108 * When we append, we assume that we're
2109 * appending to text. Some MS servers
2110 * include a NUL byte at the end of
2111 * the search string provided.
2114 config->defaults[i].len +
2115 lease->options[i].len;
2116 if (len >= sizeof(dbuf)) {
2117 warning("no space to %s %s",
2119 dhcp_options[i].name);
2123 lease->options[i].data,
2124 lease->options[i].len);
2125 for (dp = dbuf + lease->options[i].len;
2126 dp > dbuf; dp--, len--)
2131 config->defaults[i].data,
2133 config->defaults[i].len);
2139 config->defaults[i].data;
2141 config->defaults[i].len;
2143 } else if (lease->options[i].len) {
2144 len = lease->options[i].len;
2145 dp = lease->options[i].data;
2152 if (dhcp_option_ev_name(name, sizeof(name),
2154 script_set_env(ip->client, prefix, name,
2155 pretty_print_option(i, dp, len, 0, 0));
2158 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2159 script_set_env(ip->client, prefix, "expiry", tbuf);
2163 script_write_params(char *prefix, struct client_lease *lease)
2165 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2166 struct imsg_hdr hdr;
2170 if (lease->filename != NULL)
2171 fn_len = strlen(lease->filename);
2172 if (lease->server_name != NULL)
2173 sn_len = strlen(lease->server_name);
2175 pr_len = strlen(prefix);
2177 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2178 hdr.len = sizeof(hdr) + sizeof(*lease) +
2179 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2180 sizeof(pr_len) + pr_len;
2182 for (i = 0; i < 256; i++) {
2183 hdr.len += sizeof(lease->options[i].len);
2184 hdr.len += lease->options[i].len;
2187 scripttime = time(NULL);
2189 if ((buf = buf_open(hdr.len)) == NULL)
2190 error("buf_open: %m");
2193 errs += buf_add(buf, &hdr, sizeof(hdr));
2194 errs += buf_add(buf, lease, sizeof(*lease));
2195 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2196 errs += buf_add(buf, lease->filename, fn_len);
2197 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2198 errs += buf_add(buf, lease->server_name, sn_len);
2199 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2200 errs += buf_add(buf, prefix, pr_len);
2202 for (i = 0; i < 256; i++) {
2203 errs += buf_add(buf, &lease->options[i].len,
2204 sizeof(lease->options[i].len));
2205 errs += buf_add(buf, lease->options[i].data,
2206 lease->options[i].len);
2210 error("buf_add: %m");
2212 if (buf_close(privfd, buf) == -1)
2213 error("buf_close: %m");
2219 struct imsg_hdr hdr;
2223 hdr.code = IMSG_SCRIPT_GO;
2224 hdr.len = sizeof(struct imsg_hdr);
2226 if ((buf = buf_open(hdr.len)) == NULL)
2227 error("buf_open: %m");
2229 if (buf_add(buf, &hdr, sizeof(hdr)))
2230 error("buf_add: %m");
2232 if (buf_close(privfd, buf) == -1)
2233 error("buf_close: %m");
2235 bzero(&hdr, sizeof(hdr));
2236 buf_read(privfd, &hdr, sizeof(hdr));
2237 if (hdr.code != IMSG_SCRIPT_GO_RET)
2238 error("unexpected msg type %u", hdr.code);
2239 if (hdr.len != sizeof(hdr) + sizeof(int))
2240 error("received corrupted message");
2241 buf_read(privfd, &ret, sizeof(ret));
2243 scripttime = time(NULL);
2249 priv_script_go(void)
2251 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2252 static char client_path[] = CLIENT_PATH;
2253 struct interface_info *ip = ifi;
2254 int pid, wpid, wstatus;
2256 scripttime = time(NULL);
2259 scriptName = ip->client->config->script_name;
2260 envp = ip->client->scriptEnv;
2262 scriptName = top_level_config.script_name;
2264 epp[1] = client_path;
2269 argv[0] = scriptName;
2278 wpid = wait(&wstatus);
2279 } while (wpid != pid && wpid > 0);
2285 execve(scriptName, argv, envp);
2286 error("execve (%s, ...): %m", scriptName);
2290 script_flush_env(ip->client);
2292 return (wstatus & 0xff);
2296 script_set_env(struct client_state *client, const char *prefix,
2297 const char *name, const char *value)
2302 /* No `` or $() command substitution allowed in environment values! */
2303 for (j=0; j < strlen(value); j++)
2307 warning("illegal character (%c) in value '%s'",
2309 /* Ignore this option */
2313 namelen = strlen(name);
2315 for (i = 0; client->scriptEnv[i]; i++)
2316 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2317 client->scriptEnv[i][namelen] == '=')
2320 if (client->scriptEnv[i])
2321 /* Reuse the slot. */
2322 free(client->scriptEnv[i]);
2324 /* New variable. Expand if necessary. */
2325 if (i >= client->scriptEnvsize - 1) {
2326 char **newscriptEnv;
2327 int newscriptEnvsize = client->scriptEnvsize + 50;
2329 newscriptEnv = realloc(client->scriptEnv,
2331 if (newscriptEnv == NULL) {
2332 free(client->scriptEnv);
2333 client->scriptEnv = NULL;
2334 client->scriptEnvsize = 0;
2335 error("script_set_env: no memory for variable");
2337 client->scriptEnv = newscriptEnv;
2338 client->scriptEnvsize = newscriptEnvsize;
2340 /* need to set the NULL pointer at end of array beyond
2342 client->scriptEnv[i + 1] = NULL;
2344 /* Allocate space and format the variable in the appropriate slot. */
2345 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2347 if (client->scriptEnv[i] == NULL)
2348 error("script_set_env: no memory for variable assignment");
2349 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2350 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2354 script_flush_env(struct client_state *client)
2358 for (i = 0; client->scriptEnv[i]; i++) {
2359 free(client->scriptEnv[i]);
2360 client->scriptEnv[i] = NULL;
2362 client->scriptEnvsize = 0;
2366 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2370 for (i = 0; option->name[i]; i++) {
2371 if (i + 1 == buflen)
2373 if (option->name[i] == '-')
2376 buf[i] = option->name[i];
2386 static int state = 0;
2387 cap_rights_t rights;
2389 if (no_daemon || state)
2394 /* Stop logging to stderr... */
2397 if (daemon(1, 0) == -1)
2400 cap_rights_init(&rights);
2402 if (pidfile != NULL) {
2403 pidfile_write(pidfile);
2404 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2406 error("can't limit pidfile descriptor: %m");
2410 /* we are chrooted, daemon(3) fails to open /dev/null */
2412 dup2(nullfd, STDIN_FILENO);
2413 dup2(nullfd, STDOUT_FILENO);
2414 dup2(nullfd, STDERR_FILENO);
2419 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2420 error("can't limit stdin: %m");
2421 cap_rights_init(&rights, CAP_WRITE);
2422 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2423 error("can't limit stdout: %m");
2424 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2425 error("can't limit stderr: %m");
2429 check_option(struct client_lease *l, int option)
2434 /* we use this, since this is what gets passed to dhclient-script */
2436 opbuf = pretty_print_option(option, l->options[option].data,
2437 l->options[option].len, 0, 0);
2439 sbuf = option_as_string(option, l->options[option].data,
2440 l->options[option].len);
2443 case DHO_SUBNET_MASK:
2444 case DHO_TIME_SERVERS:
2445 case DHO_NAME_SERVERS:
2447 case DHO_DOMAIN_NAME_SERVERS:
2448 case DHO_LOG_SERVERS:
2449 case DHO_COOKIE_SERVERS:
2450 case DHO_LPR_SERVERS:
2451 case DHO_IMPRESS_SERVERS:
2452 case DHO_RESOURCE_LOCATION_SERVERS:
2453 case DHO_SWAP_SERVER:
2454 case DHO_BROADCAST_ADDRESS:
2455 case DHO_NIS_SERVERS:
2456 case DHO_NTP_SERVERS:
2457 case DHO_NETBIOS_NAME_SERVERS:
2458 case DHO_NETBIOS_DD_SERVER:
2459 case DHO_FONT_SERVERS:
2460 case DHO_DHCP_SERVER_IDENTIFIER:
2461 case DHO_NISPLUS_SERVERS:
2462 case DHO_MOBILE_IP_HOME_AGENT:
2463 case DHO_SMTP_SERVER:
2464 case DHO_POP_SERVER:
2465 case DHO_NNTP_SERVER:
2466 case DHO_WWW_SERVER:
2467 case DHO_FINGER_SERVER:
2468 case DHO_IRC_SERVER:
2469 case DHO_STREETTALK_SERVER:
2470 case DHO_STREETTALK_DA_SERVER:
2471 if (!ipv4addrs(opbuf)) {
2472 warning("Invalid IP address in option: %s", opbuf);
2477 case DHO_NIS_DOMAIN:
2478 case DHO_NISPLUS_DOMAIN:
2479 case DHO_TFTP_SERVER_NAME:
2480 if (!res_hnok(sbuf)) {
2481 warning("Bogus Host Name option %d: %s (%s)", option,
2483 l->options[option].len = 0;
2484 free(l->options[option].data);
2487 case DHO_DOMAIN_NAME:
2488 case DHO_DOMAIN_SEARCH:
2489 if (!res_hnok(sbuf)) {
2490 if (!check_search(sbuf)) {
2491 warning("Bogus domain search list %d: %s (%s)",
2492 option, sbuf, opbuf);
2493 l->options[option].len = 0;
2494 free(l->options[option].data);
2499 case DHO_TIME_OFFSET:
2501 case DHO_MERIT_DUMP:
2503 case DHO_EXTENSIONS_PATH:
2504 case DHO_IP_FORWARDING:
2505 case DHO_NON_LOCAL_SOURCE_ROUTING:
2506 case DHO_POLICY_FILTER:
2507 case DHO_MAX_DGRAM_REASSEMBLY:
2508 case DHO_DEFAULT_IP_TTL:
2509 case DHO_PATH_MTU_AGING_TIMEOUT:
2510 case DHO_PATH_MTU_PLATEAU_TABLE:
2511 case DHO_INTERFACE_MTU:
2512 case DHO_ALL_SUBNETS_LOCAL:
2513 case DHO_PERFORM_MASK_DISCOVERY:
2514 case DHO_MASK_SUPPLIER:
2515 case DHO_ROUTER_DISCOVERY:
2516 case DHO_ROUTER_SOLICITATION_ADDRESS:
2517 case DHO_STATIC_ROUTES:
2518 case DHO_TRAILER_ENCAPSULATION:
2519 case DHO_ARP_CACHE_TIMEOUT:
2520 case DHO_IEEE802_3_ENCAPSULATION:
2521 case DHO_DEFAULT_TCP_TTL:
2522 case DHO_TCP_KEEPALIVE_INTERVAL:
2523 case DHO_TCP_KEEPALIVE_GARBAGE:
2524 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2525 case DHO_NETBIOS_NODE_TYPE:
2526 case DHO_NETBIOS_SCOPE:
2527 case DHO_X_DISPLAY_MANAGER:
2528 case DHO_DHCP_REQUESTED_ADDRESS:
2529 case DHO_DHCP_LEASE_TIME:
2530 case DHO_DHCP_OPTION_OVERLOAD:
2531 case DHO_DHCP_MESSAGE_TYPE:
2532 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2533 case DHO_DHCP_MESSAGE:
2534 case DHO_DHCP_MAX_MESSAGE_SIZE:
2535 case DHO_DHCP_RENEWAL_TIME:
2536 case DHO_DHCP_REBINDING_TIME:
2537 case DHO_DHCP_CLASS_IDENTIFIER:
2538 case DHO_DHCP_CLIENT_IDENTIFIER:
2539 case DHO_BOOTFILE_NAME:
2540 case DHO_DHCP_USER_CLASS_ID:
2543 case DHO_CLASSLESS_ROUTES:
2544 return (check_classless_option(l->options[option].data,
2545 l->options[option].len));
2547 warning("unknown dhcp option value 0x%x", option);
2548 return (unknown_ok);
2552 /* RFC 3442 The Classless Static Routes option checks */
2554 check_classless_option(unsigned char *data, int len)
2557 unsigned char width;
2558 in_addr_t addr, mask;
2561 warning("Too small length: %d", len);
2569 } else if (width < 9) {
2570 addr = (in_addr_t)(data[i] << 24);
2572 } else if (width < 17) {
2573 addr = (in_addr_t)(data[i] << 24) +
2574 (in_addr_t)(data[i + 1] << 16);
2576 } else if (width < 25) {
2577 addr = (in_addr_t)(data[i] << 24) +
2578 (in_addr_t)(data[i + 1] << 16) +
2579 (in_addr_t)(data[i + 2] << 8);
2581 } else if (width < 33) {
2582 addr = (in_addr_t)(data[i] << 24) +
2583 (in_addr_t)(data[i + 1] << 16) +
2584 (in_addr_t)(data[i + 2] << 8) +
2588 warning("Incorrect subnet width: %d", width);
2591 mask = (in_addr_t)(~0) << (32 - width);
2597 * ... After deriving a subnet number and subnet mask
2598 * from each destination descriptor, the DHCP client
2599 * MUST zero any bits in the subnet number where the
2600 * corresponding bit in the mask is zero...
2602 if ((addr & mask) != addr) {
2604 data[i - 1] = (unsigned char)(
2605 (addr >> (((32 - width)/8)*8)) & 0xFF);
2610 warning("Incorrect data length: %d (must be %d)", len, i);
2617 res_hnok(const char *dn)
2619 int pch = PERIOD, ch = *dn++;
2621 while (ch != '\0') {
2624 if (periodchar(ch)) {
2626 } else if (periodchar(pch)) {
2627 if (!borderchar(ch))
2629 } else if (periodchar(nch) || nch == '\0') {
2630 if (!borderchar(ch))
2633 if (!middlechar(ch))
2642 check_search(const char *srch)
2644 int pch = PERIOD, ch = *srch++;
2647 /* 256 char limit re resolv.conf(5) */
2648 if (strlen(srch) > 256)
2651 while (whitechar(ch))
2654 while (ch != '\0') {
2657 if (periodchar(ch) || whitechar(ch)) {
2659 } else if (periodchar(pch)) {
2660 if (!borderchar(ch))
2662 } else if (periodchar(nch) || nch == '\0') {
2663 if (!borderchar(ch))
2666 if (!middlechar(ch))
2669 if (!whitechar(ch)) {
2672 while (whitechar(nch)) {
2681 /* 6 domain limit re resolv.conf(5) */
2687 /* Does buf consist only of dotted decimal ipv4 addrs?
2688 * return how many if so,
2689 * otherwise, return 0
2692 ipv4addrs(char * buf)
2697 while (inet_aton(buf, &jnk) == 1){
2699 while (periodchar(*buf) || digitchar(*buf))
2711 option_as_string(unsigned int code, unsigned char *data, int len)
2713 static char optbuf[32768]; /* XXX */
2715 int opleft = sizeof(optbuf);
2716 unsigned char *dp = data;
2719 error("option_as_string: bad code %d", code);
2721 for (; dp < data + len; dp++) {
2722 if (!isascii(*dp) || !isprint(*dp)) {
2723 if (dp + 1 != data + len || *dp != 0) {
2724 snprintf(op, opleft, "\\%03o", *dp);
2728 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2729 *dp == '`' || *dp == '\\') {
2743 warning("dhcp option too large");
2748 fork_privchld(int fd, int fd2)
2750 struct pollfd pfd[1];
2755 error("cannot fork");
2762 setproctitle("%s [priv]", ifi->name);
2765 dup2(nullfd, STDIN_FILENO);
2766 dup2(nullfd, STDOUT_FILENO);
2767 dup2(nullfd, STDERR_FILENO);
2775 pfd[0].events = POLLIN;
2776 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2778 error("poll error");
2780 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2783 dispatch_imsg(ifi, fd);