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>
63 #include <sys/endian.h>
65 #include <net80211/ieee80211_freebsd.h>
67 #ifndef _PATH_VAREMPTY
68 #define _PATH_VAREMPTY "/var/empty"
72 #define hyphenchar(c) ((c) == 0x2d)
73 #define bslashchar(c) ((c) == 0x5c)
74 #define periodchar(c) ((c) == PERIOD)
75 #define asterchar(c) ((c) == 0x2a)
76 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
77 ((c) >= 0x61 && (c) <= 0x7a))
78 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
79 #define whitechar(c) ((c) == ' ' || (c) == '\t')
81 #define borderchar(c) (alphachar(c) || digitchar(c))
82 #define middlechar(c) (borderchar(c) || hyphenchar(c))
83 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
85 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
88 time_t default_lease_time = 43200; /* 12 hours... */
90 const char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
91 char *path_dhclient_db = NULL;
97 char hostname[_POSIX_HOST_NAME_MAX + 1];
99 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
100 struct in_addr inaddr_any, inaddr_broadcast;
102 char *path_dhclient_pidfile;
103 struct pidfh *pidfile;
106 * ASSERT_STATE() does nothing now; it used to be
107 * assert (state_is == state_shouldbe).
109 #define ASSERT_STATE(state_is, state_shouldbe) {}
112 * We need to check that the expiry, renewal and rebind times are not beyond
113 * the end of time (~2038 when a 32-bit time_t is being used).
115 #define TIME_MAX ((((time_t) 1 << (sizeof(time_t) * CHAR_BIT - 2)) - 1) * 2 + 1)
122 struct interface_info *ifi;
124 int findproto(char *, int);
125 struct sockaddr *get_ifa(char *, int);
126 void routehandler(struct protocol *);
128 int check_option(struct client_lease *l, int option);
129 int check_classless_option(unsigned char *data, int len);
130 int ipv4addrs(const char * buf);
131 int res_hnok(const char *dn);
132 int check_search(const char *srch);
133 const char *option_as_string(unsigned int code, unsigned char *data, int len);
134 int fork_privchld(int, int);
137 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
138 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
140 /* Minimum MTU is 68 as per RFC791, p. 24 */
143 static time_t scripttime;
146 findproto(char *cp, int n)
153 for (i = 1; i; i <<= 1) {
155 sa = (struct sockaddr *)cp;
161 if (sa->sa_family == AF_INET)
163 if (sa->sa_family == AF_INET6)
176 get_ifa(char *cp, int n)
183 for (i = 1; i; i <<= 1)
185 sa = (struct sockaddr *)cp;
194 struct iaddr defaddr = { .len = 4 };
200 struct interface_info *_ifi = arg;
203 * Clear existing state.
205 if (_ifi->client->active != NULL) {
206 script_init("EXPIRE", NULL);
207 script_write_params("old_",
208 _ifi->client->active);
209 if (_ifi->client->alias)
210 script_write_params("alias_",
211 _ifi->client->alias);
214 _ifi->client->state = S_INIT;
218 routehandler(struct protocol *p __unused)
220 char msg[2048], *addr;
221 struct rt_msghdr *rtm;
222 struct if_msghdr *ifm;
223 struct ifa_msghdr *ifam;
224 struct if_announcemsghdr *ifan;
225 struct ieee80211_join_event *jev;
226 struct client_lease *l;
227 time_t t = time(NULL);
228 struct sockaddr_in *sa;
233 n = read(routefd, &msg, sizeof(msg));
234 rtm = (struct rt_msghdr *)msg;
235 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
236 n < (ssize_t)rtm->rtm_msglen ||
237 rtm->rtm_version != RTM_VERSION)
240 switch (rtm->rtm_type) {
243 ifam = (struct ifa_msghdr *)rtm;
245 if (ifam->ifam_index != ifi->index)
247 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
249 if (scripttime == 0 || t < scripttime + 10)
252 sa = (struct sockaddr_in*)get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
256 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
257 error("king bula sez: len mismatch");
258 memcpy(a.iabuf, &sa->sin_addr, a.len);
259 if (addr_eq(a, defaddr))
262 for (l = ifi->client->active; l != NULL; l = l->next)
263 if (addr_eq(a, l->address))
266 if (l == NULL) /* added/deleted addr is not the one we set */
269 addr = inet_ntoa(sa->sin_addr);
270 if (rtm->rtm_type == RTM_NEWADDR) {
272 * XXX: If someone other than us adds our address,
273 * should we assume they are taking over from us,
274 * delete the lease record, and exit without modifying
277 warning("My address (%s) was re-added", addr);
279 warning("My address (%s) was deleted, dhclient exiting",
285 ifm = (struct if_msghdr *)rtm;
286 if (ifm->ifm_index != ifi->index)
288 if ((rtm->rtm_flags & RTF_UP) == 0) {
289 warning("Interface %s is down, dhclient exiting",
293 linkstat = interface_link_status(ifi->name);
294 if (linkstat != ifi->linkstat) {
295 debug("%s link state %s -> %s", ifi->name,
296 ifi->linkstat ? "up" : "down",
297 linkstat ? "up" : "down");
298 ifi->linkstat = linkstat;
304 ifan = (struct if_announcemsghdr *)rtm;
305 if (ifan->ifan_what == IFAN_DEPARTURE &&
306 ifan->ifan_index == ifi->index) {
307 warning("Interface %s is gone, dhclient exiting",
313 ifan = (struct if_announcemsghdr *)rtm;
314 if (ifan->ifan_index != ifi->index)
316 switch (ifan->ifan_what) {
317 case RTM_IEEE80211_ASSOC:
318 case RTM_IEEE80211_REASSOC:
320 * Use assoc/reassoc event to kick state machine
321 * in case we roam. Otherwise fall back to the
322 * normal state machine just like a wired network.
324 jev = (struct ieee80211_join_event *) &ifan[1];
325 if (memcmp(curbssid, jev->iev_addr, 6)) {
329 memcpy(curbssid, jev->iev_addr, 6);
339 script_init("FAIL", NULL);
340 if (ifi->client->alias)
341 script_write_params("alias_", ifi->client->alias);
344 pidfile_remove(pidfile);
349 main(int argc, char *argv[])
351 extern char *__progname;
352 int ch, fd, quiet = 0, i = 0;
354 int immediate_daemon = 0;
359 /* Initially, log errors to stderr as well as to syslogd. */
360 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
361 setlogmask(LOG_UPTO(LOG_DEBUG));
363 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
366 immediate_daemon = 1;
369 path_dhclient_conf = optarg;
375 path_dhclient_db = optarg;
378 path_dhclient_pidfile = optarg;
396 if (path_dhclient_pidfile == NULL) {
397 asprintf(&path_dhclient_pidfile,
398 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
399 if (path_dhclient_pidfile == NULL)
402 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
403 if (pidfile == NULL) {
405 error("dhclient already running, pid: %d.", otherpid);
407 error("dhclient already running.");
408 warning("Cannot open or create pidfile: %m");
411 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
413 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
414 error("Interface name too long");
415 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
416 _PATH_DHCLIENT_DB, ifi->name) == -1)
425 inaddr_broadcast.s_addr = INADDR_BROADCAST;
426 inaddr_any.s_addr = INADDR_ANY;
430 /* The next bit is potentially very time-consuming, so write out
431 the pidfile right away. We will write it out again with the
432 correct pid after daemonizing. */
434 pidfile_write(pidfile);
436 if (!interface_link_status(ifi->name)) {
437 fprintf(stderr, "%s: no link ...", ifi->name);
440 while (!interface_link_status(ifi->name)) {
441 fprintf(stderr, ".");
444 fprintf(stderr, " giving up\n");
449 fprintf(stderr, " got link\n");
453 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
454 error("cannot open %s: %m", _PATH_DEVNULL);
456 if ((pw = getpwnam("_dhcp")) == NULL) {
457 warning("no such user: _dhcp, falling back to \"nobody\"");
458 if ((pw = getpwnam("nobody")) == NULL)
459 error("no such user: nobody");
463 * Obtain hostname before entering capability mode - it won't be
464 * possible then, as reading kern.hostname is not permitted.
466 if (gethostname(hostname, sizeof(hostname)) < 0)
469 priv_script_init("PREINIT", NULL);
470 if (ifi->client->alias)
471 priv_script_write_params("alias_", ifi->client->alias);
474 /* set up the interface */
475 discover_interfaces(ifi);
477 if (pipe(pipe_fd) == -1)
480 fork_privchld(pipe_fd[0], pipe_fd[1]);
489 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
490 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
491 error("can't limit private descriptor: %m");
493 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
494 error("can't open and lock %s: %m", path_dhclient_db);
495 read_client_leases();
496 rewrite_client_leases();
499 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
500 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
501 if (shutdown(routefd, SHUT_WR) < 0)
502 error("can't shutdown route socket: %m");
503 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
504 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
505 error("can't limit route socket: %m");
507 if (chroot(_PATH_VAREMPTY) == -1)
509 if (chdir("/") == -1)
510 error("chdir(\"/\")");
512 if (setgroups(1, &pw->pw_gid) ||
513 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
514 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
515 error("can't drop privileges: %m");
519 setproctitle("%s", ifi->name);
521 if (cap_enter() < 0 && errno != ENOSYS)
522 error("can't enter capability mode: %m");
524 if (immediate_daemon)
527 ifi->client->state = S_INIT;
530 bootp_packet_handler = do_packet;
541 extern char *__progname;
543 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
544 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
551 * Each routine is called from the dhclient_state_machine() in one of
553 * -> entering INIT state
554 * -> recvpacket_flag == 0: timeout in this state
555 * -> otherwise: received a packet in this state
557 * Return conditions as handled by dhclient_state_machine():
558 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
559 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
560 * Returns 0: finish the nap which was interrupted for no good reason.
562 * Several per-interface variables are used to keep track of the process:
563 * active_lease: the lease that is being used on the interface
564 * (null pointer if not configured yet).
565 * offered_leases: leases corresponding to DHCPOFFER messages that have
566 * been sent to us by DHCP servers.
567 * acked_leases: leases corresponding to DHCPACK messages that have been
568 * sent to us by DHCP servers.
569 * sendpacket: DHCP packet we're trying to send.
570 * destination: IP address to send sendpacket to
571 * In addition, there are several relevant per-lease variables.
572 * T1_expiry, T2_expiry, lease_expiry: lease milestones
573 * In the active lease, these control the process of renewing the lease;
574 * In leases on the acked_leases list, this simply determines when we
575 * can no longer legitimately use the lease.
579 state_reboot(void *ipp)
581 struct interface_info *ip = ipp;
583 /* If we don't remember an active lease, go straight to INIT. */
584 if (!ip->client->active || ip->client->active->is_bootp) {
589 /* We are in the rebooting state. */
590 ip->client->state = S_REBOOTING;
592 /* make_request doesn't initialize xid because it normally comes
593 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
594 so pick an xid now. */
595 ip->client->xid = arc4random();
597 /* Make a DHCPREQUEST packet, and set appropriate per-interface
599 make_request(ip, ip->client->active);
600 ip->client->destination = iaddr_broadcast;
601 ip->client->first_sending = cur_time;
602 ip->client->interval = ip->client->config->initial_interval;
604 /* Zap the medium list... */
605 ip->client->medium = NULL;
607 /* Send out the first DHCPREQUEST packet. */
612 * Called when a lease has completely expired and we've
613 * been unable to renew it.
616 state_init(void *ipp)
618 struct interface_info *ip = ipp;
620 ASSERT_STATE(state, S_INIT);
622 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
624 make_discover(ip, ip->client->active);
625 ip->client->xid = ip->client->packet.xid;
626 ip->client->destination = iaddr_broadcast;
627 ip->client->state = S_SELECTING;
628 ip->client->first_sending = cur_time;
629 ip->client->interval = ip->client->config->initial_interval;
631 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
637 * state_selecting is called when one or more DHCPOFFER packets
638 * have been received and a configurable period of time has passed.
641 state_selecting(void *ipp)
643 struct interface_info *ip = ipp;
644 struct client_lease *lp, *next, *picked;
646 ASSERT_STATE(state, S_SELECTING);
648 /* Cancel state_selecting and send_discover timeouts, since either
649 one could have got us here. */
650 cancel_timeout(state_selecting, ip);
651 cancel_timeout(send_discover, ip);
653 /* We have received one or more DHCPOFFER packets. Currently,
654 the only criterion by which we judge leases is whether or
655 not we get a response when we arp for them. */
657 for (lp = ip->client->offered_leases; lp; lp = next) {
660 /* Check to see if we got an ARPREPLY for the address
661 in this particular lease. */
663 script_init("ARPCHECK", lp->medium);
664 script_write_params("check_", lp);
666 /* If the ARPCHECK code detects another
667 machine using the offered address, it exits
668 nonzero. We need to send a DHCPDECLINE and
671 make_decline(ip, lp);
679 free_client_lease(lp);
682 ip->client->offered_leases = NULL;
684 /* If we just tossed all the leases we were offered, go back
687 ip->client->state = S_INIT;
692 /* If it was a BOOTREPLY, we can just take the address right now. */
693 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
694 ip->client->new = picked;
696 /* Make up some lease expiry times
697 XXX these should be configurable. */
698 ip->client->new->expiry = cur_time + 12000;
699 ip->client->new->renewal += cur_time + 8000;
700 ip->client->new->rebind += cur_time + 10000;
702 ip->client->state = S_REQUESTING;
704 /* Bind to the address we received. */
709 /* Go to the REQUESTING state. */
710 ip->client->destination = iaddr_broadcast;
711 ip->client->state = S_REQUESTING;
712 ip->client->first_sending = cur_time;
713 ip->client->interval = ip->client->config->initial_interval;
715 /* Make a DHCPREQUEST packet from the lease we picked. */
716 make_request(ip, picked);
717 ip->client->xid = ip->client->packet.xid;
719 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
720 free_client_lease(picked);
722 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
726 /* state_requesting is called when we receive a DHCPACK message after
727 having sent out one or more DHCPREQUEST packets. */
730 dhcpack(struct packet *packet)
732 struct interface_info *ip = packet->interface;
733 struct client_lease *lease;
735 /* If we're not receptive to an offer right now, or if the offer
736 has an unrecognizable transaction id, then just drop it. */
737 if (packet->interface->client->xid != packet->raw->xid ||
738 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
739 (memcmp(packet->interface->hw_address.haddr,
740 packet->raw->chaddr, packet->raw->hlen)))
743 if (ip->client->state != S_REBOOTING &&
744 ip->client->state != S_REQUESTING &&
745 ip->client->state != S_RENEWING &&
746 ip->client->state != S_REBINDING)
749 note("DHCPACK from %s", piaddr(packet->client_addr));
751 lease = packet_to_lease(packet);
753 note("packet_to_lease failed.");
757 ip->client->new = lease;
759 /* Stop resending DHCPREQUEST. */
760 cancel_timeout(send_request, ip);
762 /* Figure out the lease time. */
763 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
765 ip->client->new->expiry = getULong(
766 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
767 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
768 ip->client->new->expiry = getULong(
769 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
771 ip->client->new->expiry = default_lease_time;
772 /* A number that looks negative here is really just very large,
773 because the lease expiry offset is unsigned. Also make sure that
774 the addition of cur_time below does not overflow (a 32 bit) time_t. */
775 if (ip->client->new->expiry < 0 ||
776 ip->client->new->expiry > TIME_MAX - cur_time)
777 ip->client->new->expiry = TIME_MAX - cur_time;
778 /* XXX should be fixed by resetting the client state */
779 if (ip->client->new->expiry < 60)
780 ip->client->new->expiry = 60;
782 /* Unless overridden in the config, take the server-provided renewal
783 * time if there is one. Otherwise figure it out according to the spec.
784 * Also make sure the renewal time does not exceed the expiry time.
786 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
788 ip->client->new->renewal = getULong(
789 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
790 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
791 ip->client->new->renewal = getULong(
792 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
794 ip->client->new->renewal = ip->client->new->expiry / 2;
795 if (ip->client->new->renewal < 0 ||
796 ip->client->new->renewal > ip->client->new->expiry / 2)
797 ip->client->new->renewal = ip->client->new->expiry / 2;
799 /* Same deal with the rebind time. */
800 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
802 ip->client->new->rebind = getULong(
803 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
804 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
805 ip->client->new->rebind = getULong(
806 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
808 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
809 if (ip->client->new->rebind < 0 ||
810 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
811 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
813 /* Convert the time offsets into seconds-since-the-epoch */
814 ip->client->new->expiry += cur_time;
815 ip->client->new->renewal += cur_time;
816 ip->client->new->rebind += cur_time;
822 bind_lease(struct interface_info *ip)
824 struct option_data *opt;
826 /* Remember the medium. */
827 ip->client->new->medium = ip->client->medium;
829 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
830 if (opt->len == sizeof(u_int16_t)) {
832 bool supersede = (ip->client->config->default_actions[DHO_INTERFACE_MTU] ==
836 mtu = getUShort(ip->client->config->defaults[DHO_INTERFACE_MTU].data);
838 mtu = be16dec(opt->data);
841 /* Treat 0 like a user intentionally doesn't want to change MTU and,
842 * therefore, warning is not needed */
843 if (!supersede || mtu != 0)
844 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
846 interface_set_mtu_unpriv(privfd, mtu);
850 /* Write out the new lease. */
851 write_client_lease(ip, ip->client->new, 0);
853 /* Run the client script with the new parameters. */
854 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
855 (ip->client->state == S_RENEWING ? "RENEW" :
856 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
857 ip->client->new->medium);
858 if (ip->client->active && ip->client->state != S_REBOOTING)
859 script_write_params("old_", ip->client->active);
860 script_write_params("new_", ip->client->new);
861 if (ip->client->alias)
862 script_write_params("alias_", ip->client->alias);
865 /* Replace the old active lease with the new one. */
866 if (ip->client->active)
867 free_client_lease(ip->client->active);
868 ip->client->active = ip->client->new;
869 ip->client->new = NULL;
871 /* Set up a timeout to start the renewal process. */
872 add_timeout(ip->client->active->renewal, state_bound, ip);
874 note("bound to %s -- renewal in %d seconds.",
875 piaddr(ip->client->active->address),
876 (int)(ip->client->active->renewal - cur_time));
877 ip->client->state = S_BOUND;
878 reinitialize_interfaces();
883 * state_bound is called when we've successfully bound to a particular
884 * lease, but the renewal time on that lease has expired. We are
885 * expected to unicast a DHCPREQUEST to the server that gave us our
889 state_bound(void *ipp)
891 struct interface_info *ip = ipp;
893 ASSERT_STATE(state, S_BOUND);
895 /* T1 has expired. */
896 make_request(ip, ip->client->active);
897 ip->client->xid = ip->client->packet.xid;
899 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
900 memcpy(ip->client->destination.iabuf, ip->client->active->
901 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
902 ip->client->destination.len = 4;
904 ip->client->destination = iaddr_broadcast;
906 ip->client->first_sending = cur_time;
907 ip->client->interval = ip->client->config->initial_interval;
908 ip->client->state = S_RENEWING;
910 /* Send the first packet immediately. */
915 bootp(struct packet *packet)
917 struct iaddrlist *ap;
919 if (packet->raw->op != BOOTREPLY)
922 /* If there's a reject list, make sure this packet's sender isn't
924 for (ap = packet->interface->client->config->reject_list;
926 if (addr_eq(packet->client_addr, ap->addr)) {
927 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
935 dhcp(struct packet *packet)
937 struct iaddrlist *ap;
938 void (*handler)(struct packet *);
941 switch (packet->packet_type) {
958 /* If there's a reject list, make sure this packet's sender isn't
960 for (ap = packet->interface->client->config->reject_list;
962 if (addr_eq(packet->client_addr, ap->addr)) {
963 note("%s from %s rejected.", type, piaddr(ap->addr));
971 dhcpoffer(struct packet *packet)
973 struct interface_info *ip = packet->interface;
974 struct client_lease *lease, *lp;
976 int arp_timeout_needed, stop_selecting;
977 const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
978 "DHCPOFFER" : "BOOTREPLY";
980 /* If we're not receptive to an offer right now, or if the offer
981 has an unrecognizable transaction id, then just drop it. */
982 if (ip->client->state != S_SELECTING ||
983 packet->interface->client->xid != packet->raw->xid ||
984 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
985 (memcmp(packet->interface->hw_address.haddr,
986 packet->raw->chaddr, packet->raw->hlen)))
989 note("%s from %s", name, piaddr(packet->client_addr));
992 /* If this lease doesn't supply the minimum required parameters,
994 for (i = 0; ip->client->config->required_options[i]; i++) {
995 if (!packet->options[ip->client->config->
996 required_options[i]].len) {
997 note("%s isn't satisfactory.", name);
1002 /* If we've already seen this lease, don't record it again. */
1003 for (lease = ip->client->offered_leases;
1004 lease; lease = lease->next) {
1005 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
1006 !memcmp(lease->address.iabuf,
1007 &packet->raw->yiaddr, lease->address.len)) {
1008 debug("%s already seen.", name);
1013 lease = packet_to_lease(packet);
1015 note("packet_to_lease failed.");
1019 /* If this lease was acquired through a BOOTREPLY, record that
1021 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1022 lease->is_bootp = 1;
1024 /* Record the medium under which this lease was offered. */
1025 lease->medium = ip->client->medium;
1027 /* Send out an ARP Request for the offered IP address. */
1028 script_init("ARPSEND", lease->medium);
1029 script_write_params("check_", lease);
1030 /* If the script can't send an ARP request without waiting,
1031 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1033 arp_timeout_needed = 0;
1035 arp_timeout_needed = 2;
1037 /* Figure out when we're supposed to stop selecting. */
1039 ip->client->first_sending + ip->client->config->select_interval;
1041 /* If this is the lease we asked for, put it at the head of the
1042 list, and don't mess with the arp request timeout. */
1043 if (lease->address.len == ip->client->requested_address.len &&
1044 !memcmp(lease->address.iabuf,
1045 ip->client->requested_address.iabuf,
1046 ip->client->requested_address.len)) {
1047 lease->next = ip->client->offered_leases;
1048 ip->client->offered_leases = lease;
1050 /* If we already have an offer, and arping for this
1051 offer would take us past the selection timeout,
1052 then don't extend the timeout - just hope for the
1054 if (ip->client->offered_leases &&
1055 (cur_time + arp_timeout_needed) > stop_selecting)
1056 arp_timeout_needed = 0;
1058 /* Put the lease at the end of the list. */
1060 if (!ip->client->offered_leases)
1061 ip->client->offered_leases = lease;
1063 for (lp = ip->client->offered_leases; lp->next;
1070 /* If we're supposed to stop selecting before we've had time
1071 to wait for the ARPREPLY, add some delay to wait for
1073 if (stop_selecting - cur_time < arp_timeout_needed)
1074 stop_selecting = cur_time + arp_timeout_needed;
1076 /* If the selecting interval has expired, go immediately to
1077 state_selecting(). Otherwise, time out into
1078 state_selecting at the select interval. */
1079 if (stop_selecting <= 0)
1080 state_selecting(ip);
1082 add_timeout(stop_selecting, state_selecting, ip);
1083 cancel_timeout(send_discover, ip);
1087 /* Allocate a client_lease structure and initialize it from the parameters
1088 in the specified packet. */
1090 struct client_lease *
1091 packet_to_lease(struct packet *packet)
1093 struct client_lease *lease;
1096 lease = malloc(sizeof(struct client_lease));
1099 warning("dhcpoffer: no memory to record lease.");
1103 memset(lease, 0, sizeof(*lease));
1105 /* Copy the lease options. */
1106 for (i = 0; i < 256; i++) {
1107 if (packet->options[i].len) {
1108 lease->options[i].data =
1109 malloc(packet->options[i].len + 1);
1110 if (!lease->options[i].data) {
1111 warning("dhcpoffer: no memory for option %d", i);
1112 free_client_lease(lease);
1115 memcpy(lease->options[i].data,
1116 packet->options[i].data,
1117 packet->options[i].len);
1118 lease->options[i].len =
1119 packet->options[i].len;
1120 lease->options[i].data[lease->options[i].len] =
1123 if (!check_option(lease,i)) {
1124 /* ignore a bogus lease offer */
1125 warning("Invalid lease option - ignoring offer");
1126 free_client_lease(lease);
1132 lease->address.len = sizeof(packet->raw->yiaddr);
1133 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1135 lease->nextserver.len = sizeof(packet->raw->siaddr);
1136 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1138 /* If the server name was filled out, copy it.
1139 Do not attempt to validate the server name as a host name.
1140 RFC 2131 merely states that sname is NUL-terminated (which do
1141 do not assume) and that it is the server's host name. Since
1142 the ISC client and server allow arbitrary characters, we do
1144 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1145 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1146 packet->raw->sname[0]) {
1147 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1148 if (!lease->server_name) {
1149 warning("dhcpoffer: no memory for server name.");
1150 free_client_lease(lease);
1153 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1154 lease->server_name[DHCP_SNAME_LEN]='\0';
1157 /* Ditto for the filename. */
1158 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1159 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1160 packet->raw->file[0]) {
1161 /* Don't count on the NUL terminator. */
1162 lease->filename = malloc(DHCP_FILE_LEN + 1);
1163 if (!lease->filename) {
1164 warning("dhcpoffer: no memory for filename.");
1165 free_client_lease(lease);
1168 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1169 lease->filename[DHCP_FILE_LEN]='\0';
1175 dhcpnak(struct packet *packet)
1177 struct interface_info *ip = packet->interface;
1179 /* If we're not receptive to an offer right now, or if the offer
1180 has an unrecognizable transaction id, then just drop it. */
1181 if (packet->interface->client->xid != packet->raw->xid ||
1182 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1183 (memcmp(packet->interface->hw_address.haddr,
1184 packet->raw->chaddr, packet->raw->hlen)))
1187 if (ip->client->state != S_REBOOTING &&
1188 ip->client->state != S_REQUESTING &&
1189 ip->client->state != S_RENEWING &&
1190 ip->client->state != S_REBINDING)
1193 note("DHCPNAK from %s", piaddr(packet->client_addr));
1195 if (!ip->client->active) {
1196 note("DHCPNAK with no active lease.\n");
1200 free_client_lease(ip->client->active);
1201 ip->client->active = NULL;
1203 /* Stop sending DHCPREQUEST packets... */
1204 cancel_timeout(send_request, ip);
1206 ip->client->state = S_INIT;
1210 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1211 one after the right interval has expired. If we don't get an offer by
1212 the time we reach the panic interval, call the panic function. */
1215 send_discover(void *ipp)
1217 struct interface_info *ip = ipp;
1218 int interval, increase = 1;
1220 /* Figure out how long it's been since we started transmitting. */
1221 interval = cur_time - ip->client->first_sending;
1223 /* If we're past the panic timeout, call the script and tell it
1224 we haven't found anything for this interface yet. */
1225 if (interval > ip->client->config->timeout) {
1230 /* If we're selecting media, try the whole list before doing
1231 the exponential backoff, but if we've already received an
1232 offer, stop looping, because we obviously have it right. */
1233 if (!ip->client->offered_leases &&
1234 ip->client->config->media) {
1237 if (ip->client->medium) {
1238 ip->client->medium = ip->client->medium->next;
1241 if (!ip->client->medium) {
1243 error("No valid media types for %s!", ip->name);
1244 ip->client->medium = ip->client->config->media;
1248 note("Trying medium \"%s\" %d", ip->client->medium->string,
1250 script_init("MEDIUM", ip->client->medium);
1256 * If we're supposed to increase the interval, do so. If it's
1257 * currently zero (i.e., we haven't sent any packets yet), set
1258 * it to one; otherwise, add to it a random number between zero
1259 * and two times itself. On average, this means that it will
1260 * double with every transmission.
1263 if (!ip->client->interval)
1264 ip->client->interval =
1265 ip->client->config->initial_interval;
1267 ip->client->interval += (arc4random() >> 2) %
1268 (2 * ip->client->interval);
1271 /* Don't backoff past cutoff. */
1272 if (ip->client->interval >
1273 ip->client->config->backoff_cutoff)
1274 ip->client->interval =
1275 ((ip->client->config->backoff_cutoff / 2)
1276 + ((arc4random() >> 2) %
1277 ip->client->config->backoff_cutoff));
1278 } else if (!ip->client->interval)
1279 ip->client->interval =
1280 ip->client->config->initial_interval;
1282 /* If the backoff would take us to the panic timeout, just use that
1284 if (cur_time + ip->client->interval >
1285 ip->client->first_sending + ip->client->config->timeout)
1286 ip->client->interval =
1287 (ip->client->first_sending +
1288 ip->client->config->timeout) - cur_time + 1;
1290 /* Record the number of seconds since we started sending. */
1291 if (interval < 65536)
1292 ip->client->packet.secs = htons(interval);
1294 ip->client->packet.secs = htons(65535);
1295 ip->client->secs = ip->client->packet.secs;
1297 note("DHCPDISCOVER on %s to %s port %d interval %d",
1298 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1299 (int)ip->client->interval);
1301 /* Send out a packet. */
1302 send_packet_unpriv(privfd, &ip->client->packet,
1303 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1305 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1309 * state_panic gets called if we haven't received any offers in a preset
1310 * amount of time. When this happens, we try to use existing leases
1311 * that haven't yet expired, and failing that, we call the client script
1312 * and hope it can do something.
1315 state_panic(void *ipp)
1317 struct interface_info *ip = ipp;
1318 struct client_lease *loop = ip->client->active;
1319 struct client_lease *lp;
1321 note("No DHCPOFFERS received.");
1323 /* We may not have an active lease, but we may have some
1324 predefined leases that we can try. */
1325 if (!ip->client->active && ip->client->leases)
1328 /* Run through the list of leases and see if one can be used. */
1329 while (ip->client->active) {
1330 if (ip->client->active->expiry > cur_time) {
1331 note("Trying recorded lease %s",
1332 piaddr(ip->client->active->address));
1333 /* Run the client script with the existing
1335 script_init("TIMEOUT",
1336 ip->client->active->medium);
1337 script_write_params("new_", ip->client->active);
1338 if (ip->client->alias)
1339 script_write_params("alias_",
1342 /* If the old lease is still good and doesn't
1343 yet need renewal, go into BOUND state and
1344 timeout at the renewal time. */
1347 ip->client->active->renewal) {
1348 ip->client->state = S_BOUND;
1349 note("bound: renewal in %d seconds.",
1350 (int)(ip->client->active->renewal -
1353 ip->client->active->renewal,
1356 ip->client->state = S_BOUND;
1357 note("bound: immediate renewal.");
1360 reinitialize_interfaces();
1366 /* If there are no other leases, give up. */
1367 if (!ip->client->leases) {
1368 ip->client->leases = ip->client->active;
1369 ip->client->active = NULL;
1374 /* Otherwise, put the active lease at the end of the
1375 lease list, and try another lease.. */
1376 for (lp = ip->client->leases; lp->next; lp = lp->next)
1378 lp->next = ip->client->active;
1380 lp->next->next = NULL;
1381 ip->client->active = ip->client->leases;
1382 ip->client->leases = ip->client->leases->next;
1384 /* If we already tried this lease, we've exhausted the
1385 set of leases, so we might as well give up for
1387 if (ip->client->active == loop)
1390 loop = ip->client->active;
1393 /* No leases were available, or what was available didn't work, so
1394 tell the shell script that we failed to allocate an address,
1395 and try again later. */
1396 note("No working leases in persistent database - sleeping.\n");
1397 script_init("FAIL", NULL);
1398 if (ip->client->alias)
1399 script_write_params("alias_", ip->client->alias);
1401 ip->client->state = S_INIT;
1402 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1408 send_request(void *ipp)
1410 struct interface_info *ip = ipp;
1411 struct in_addr from, to;
1414 /* Figure out how long it's been since we started transmitting. */
1415 interval = cur_time - ip->client->first_sending;
1417 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1418 past the reboot timeout, go to INIT and see if we can
1419 DISCOVER an address... */
1420 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1421 means either that we're on a network with no DHCP server,
1422 or that our server is down. In the latter case, assuming
1423 that there is a backup DHCP server, DHCPDISCOVER will get
1424 us a new address, but we could also have successfully
1425 reused our old address. In the former case, we're hosed
1426 anyway. This is not a win-prone situation. */
1427 if ((ip->client->state == S_REBOOTING ||
1428 ip->client->state == S_REQUESTING) &&
1429 interval > ip->client->config->reboot_timeout) {
1431 ip->client->state = S_INIT;
1432 cancel_timeout(send_request, ip);
1437 /* If we're in the reboot state, make sure the media is set up
1439 if (ip->client->state == S_REBOOTING &&
1440 !ip->client->medium &&
1441 ip->client->active->medium ) {
1442 script_init("MEDIUM", ip->client->active->medium);
1444 /* If the medium we chose won't fly, go to INIT state. */
1448 /* Record the medium. */
1449 ip->client->medium = ip->client->active->medium;
1452 /* If the lease has expired, relinquish the address and go back
1453 to the INIT state. */
1454 if (ip->client->state != S_REQUESTING &&
1455 cur_time > ip->client->active->expiry) {
1456 /* Run the client script with the new parameters. */
1457 script_init("EXPIRE", NULL);
1458 script_write_params("old_", ip->client->active);
1459 if (ip->client->alias)
1460 script_write_params("alias_", ip->client->alias);
1463 /* Now do a preinit on the interface so that we can
1464 discover a new address. */
1465 script_init("PREINIT", NULL);
1466 if (ip->client->alias)
1467 script_write_params("alias_", ip->client->alias);
1470 ip->client->state = S_INIT;
1475 /* Do the exponential backoff... */
1476 if (!ip->client->interval)
1477 ip->client->interval = ip->client->config->initial_interval;
1479 ip->client->interval += ((arc4random() >> 2) %
1480 (2 * ip->client->interval));
1482 /* Don't backoff past cutoff. */
1483 if (ip->client->interval >
1484 ip->client->config->backoff_cutoff)
1485 ip->client->interval =
1486 ((ip->client->config->backoff_cutoff / 2) +
1487 ((arc4random() >> 2) % ip->client->interval));
1489 /* If the backoff would take us to the expiry time, just set the
1490 timeout to the expiry time. */
1491 if (ip->client->state != S_REQUESTING &&
1492 cur_time + ip->client->interval >
1493 ip->client->active->expiry)
1494 ip->client->interval =
1495 ip->client->active->expiry - cur_time + 1;
1497 /* If the lease T2 time has elapsed, or if we're not yet bound,
1498 broadcast the DHCPREQUEST rather than unicasting. */
1499 if (ip->client->state == S_REQUESTING ||
1500 ip->client->state == S_REBOOTING ||
1501 cur_time > ip->client->active->rebind)
1502 to.s_addr = INADDR_BROADCAST;
1504 memcpy(&to.s_addr, ip->client->destination.iabuf,
1507 if (ip->client->state != S_REQUESTING &&
1508 ip->client->state != S_REBOOTING)
1509 memcpy(&from, ip->client->active->address.iabuf,
1512 from.s_addr = INADDR_ANY;
1514 /* Record the number of seconds since we started sending. */
1515 if (ip->client->state == S_REQUESTING)
1516 ip->client->packet.secs = ip->client->secs;
1518 if (interval < 65536)
1519 ip->client->packet.secs = htons(interval);
1521 ip->client->packet.secs = htons(65535);
1524 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1527 /* Send out a packet. */
1528 send_packet_unpriv(privfd, &ip->client->packet,
1529 ip->client->packet_length, from, to);
1531 add_timeout(cur_time + ip->client->interval, send_request, ip);
1535 send_decline(void *ipp)
1537 struct interface_info *ip = ipp;
1539 note("DHCPDECLINE on %s to %s port %d", ip->name,
1540 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1542 /* Send out a packet. */
1543 send_packet_unpriv(privfd, &ip->client->packet,
1544 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1548 make_discover(struct interface_info *ip, struct client_lease *lease)
1550 unsigned char discover = DHCPDISCOVER;
1551 struct tree_cache *options[256];
1552 struct tree_cache option_elements[256];
1555 memset(option_elements, 0, sizeof(option_elements));
1556 memset(options, 0, sizeof(options));
1557 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1559 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1560 i = DHO_DHCP_MESSAGE_TYPE;
1561 options[i] = &option_elements[i];
1562 options[i]->value = &discover;
1563 options[i]->len = sizeof(discover);
1564 options[i]->buf_size = sizeof(discover);
1565 options[i]->timeout = 0xFFFFFFFF;
1567 /* Request the options we want */
1568 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1569 options[i] = &option_elements[i];
1570 options[i]->value = ip->client->config->requested_options;
1571 options[i]->len = ip->client->config->requested_option_count;
1572 options[i]->buf_size =
1573 ip->client->config->requested_option_count;
1574 options[i]->timeout = 0xFFFFFFFF;
1576 /* If we had an address, try to get it again. */
1578 ip->client->requested_address = lease->address;
1579 i = DHO_DHCP_REQUESTED_ADDRESS;
1580 options[i] = &option_elements[i];
1581 options[i]->value = lease->address.iabuf;
1582 options[i]->len = lease->address.len;
1583 options[i]->buf_size = lease->address.len;
1584 options[i]->timeout = 0xFFFFFFFF;
1586 ip->client->requested_address.len = 0;
1588 /* Send any options requested in the config file. */
1589 for (i = 0; i < 256; i++)
1591 ip->client->config->send_options[i].data) {
1592 options[i] = &option_elements[i];
1594 ip->client->config->send_options[i].data;
1596 ip->client->config->send_options[i].len;
1597 options[i]->buf_size =
1598 ip->client->config->send_options[i].len;
1599 options[i]->timeout = 0xFFFFFFFF;
1602 /* send host name if not set via config file. */
1603 if (!options[DHO_HOST_NAME]) {
1604 if (hostname[0] != '\0') {
1606 char* posDot = strchr(hostname, '.');
1608 len = posDot - hostname;
1610 len = strlen(hostname);
1611 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1612 options[DHO_HOST_NAME]->value = hostname;
1613 options[DHO_HOST_NAME]->len = len;
1614 options[DHO_HOST_NAME]->buf_size = len;
1615 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1619 /* set unique client identifier */
1620 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1621 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1622 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1623 ip->hw_address.hlen : sizeof(client_ident)-1;
1624 client_ident[0] = ip->hw_address.htype;
1625 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1626 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1627 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1628 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1629 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1630 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1633 /* Set up the option buffer... */
1634 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1635 options, 0, 0, 0, NULL, 0);
1636 if (ip->client->packet_length < BOOTP_MIN_LEN)
1637 ip->client->packet_length = BOOTP_MIN_LEN;
1639 ip->client->packet.op = BOOTREQUEST;
1640 ip->client->packet.htype = ip->hw_address.htype;
1641 ip->client->packet.hlen = ip->hw_address.hlen;
1642 ip->client->packet.hops = 0;
1643 ip->client->packet.xid = arc4random();
1644 ip->client->packet.secs = 0; /* filled in by send_discover. */
1645 ip->client->packet.flags = 0;
1647 memset(&(ip->client->packet.ciaddr),
1648 0, sizeof(ip->client->packet.ciaddr));
1649 memset(&(ip->client->packet.yiaddr),
1650 0, sizeof(ip->client->packet.yiaddr));
1651 memset(&(ip->client->packet.siaddr),
1652 0, sizeof(ip->client->packet.siaddr));
1653 memset(&(ip->client->packet.giaddr),
1654 0, sizeof(ip->client->packet.giaddr));
1655 memcpy(ip->client->packet.chaddr,
1656 ip->hw_address.haddr, ip->hw_address.hlen);
1661 make_request(struct interface_info *ip, struct client_lease * lease)
1663 unsigned char request = DHCPREQUEST;
1664 struct tree_cache *options[256];
1665 struct tree_cache option_elements[256];
1668 memset(options, 0, sizeof(options));
1669 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1671 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1672 i = DHO_DHCP_MESSAGE_TYPE;
1673 options[i] = &option_elements[i];
1674 options[i]->value = &request;
1675 options[i]->len = sizeof(request);
1676 options[i]->buf_size = sizeof(request);
1677 options[i]->timeout = 0xFFFFFFFF;
1679 /* Request the options we want */
1680 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1681 options[i] = &option_elements[i];
1682 options[i]->value = ip->client->config->requested_options;
1683 options[i]->len = ip->client->config->requested_option_count;
1684 options[i]->buf_size =
1685 ip->client->config->requested_option_count;
1686 options[i]->timeout = 0xFFFFFFFF;
1688 /* If we are requesting an address that hasn't yet been assigned
1689 to us, use the DHCP Requested Address option. */
1690 if (ip->client->state == S_REQUESTING) {
1691 /* Send back the server identifier... */
1692 i = DHO_DHCP_SERVER_IDENTIFIER;
1693 options[i] = &option_elements[i];
1694 options[i]->value = lease->options[i].data;
1695 options[i]->len = lease->options[i].len;
1696 options[i]->buf_size = lease->options[i].len;
1697 options[i]->timeout = 0xFFFFFFFF;
1699 if (ip->client->state == S_REQUESTING ||
1700 ip->client->state == S_REBOOTING) {
1701 ip->client->requested_address = lease->address;
1702 i = DHO_DHCP_REQUESTED_ADDRESS;
1703 options[i] = &option_elements[i];
1704 options[i]->value = lease->address.iabuf;
1705 options[i]->len = lease->address.len;
1706 options[i]->buf_size = lease->address.len;
1707 options[i]->timeout = 0xFFFFFFFF;
1709 ip->client->requested_address.len = 0;
1711 /* Send any options requested in the config file. */
1712 for (i = 0; i < 256; i++)
1714 ip->client->config->send_options[i].data) {
1715 options[i] = &option_elements[i];
1717 ip->client->config->send_options[i].data;
1719 ip->client->config->send_options[i].len;
1720 options[i]->buf_size =
1721 ip->client->config->send_options[i].len;
1722 options[i]->timeout = 0xFFFFFFFF;
1725 /* send host name if not set via config file. */
1726 if (!options[DHO_HOST_NAME]) {
1727 if (hostname[0] != '\0') {
1729 char* posDot = strchr(hostname, '.');
1731 len = posDot - hostname;
1733 len = strlen(hostname);
1734 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1735 options[DHO_HOST_NAME]->value = hostname;
1736 options[DHO_HOST_NAME]->len = len;
1737 options[DHO_HOST_NAME]->buf_size = len;
1738 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1742 /* set unique client identifier */
1743 char client_ident[sizeof(struct hardware)];
1744 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1745 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1746 ip->hw_address.hlen : sizeof(client_ident)-1;
1747 client_ident[0] = ip->hw_address.htype;
1748 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1749 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1750 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1751 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1752 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1753 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1756 /* Set up the option buffer... */
1757 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1758 options, 0, 0, 0, NULL, 0);
1759 if (ip->client->packet_length < BOOTP_MIN_LEN)
1760 ip->client->packet_length = BOOTP_MIN_LEN;
1762 ip->client->packet.op = BOOTREQUEST;
1763 ip->client->packet.htype = ip->hw_address.htype;
1764 ip->client->packet.hlen = ip->hw_address.hlen;
1765 ip->client->packet.hops = 0;
1766 ip->client->packet.xid = ip->client->xid;
1767 ip->client->packet.secs = 0; /* Filled in by send_request. */
1769 /* If we own the address we're requesting, put it in ciaddr;
1770 otherwise set ciaddr to zero. */
1771 if (ip->client->state == S_BOUND ||
1772 ip->client->state == S_RENEWING ||
1773 ip->client->state == S_REBINDING) {
1774 memcpy(&ip->client->packet.ciaddr,
1775 lease->address.iabuf, lease->address.len);
1776 ip->client->packet.flags = 0;
1778 memset(&ip->client->packet.ciaddr, 0,
1779 sizeof(ip->client->packet.ciaddr));
1780 ip->client->packet.flags = 0;
1783 memset(&ip->client->packet.yiaddr, 0,
1784 sizeof(ip->client->packet.yiaddr));
1785 memset(&ip->client->packet.siaddr, 0,
1786 sizeof(ip->client->packet.siaddr));
1787 memset(&ip->client->packet.giaddr, 0,
1788 sizeof(ip->client->packet.giaddr));
1789 memcpy(ip->client->packet.chaddr,
1790 ip->hw_address.haddr, ip->hw_address.hlen);
1794 make_decline(struct interface_info *ip, struct client_lease *lease)
1796 struct tree_cache *options[256], message_type_tree;
1797 struct tree_cache requested_address_tree;
1798 struct tree_cache server_id_tree, client_id_tree;
1799 unsigned char decline = DHCPDECLINE;
1802 memset(options, 0, sizeof(options));
1803 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1805 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1806 i = DHO_DHCP_MESSAGE_TYPE;
1807 options[i] = &message_type_tree;
1808 options[i]->value = &decline;
1809 options[i]->len = sizeof(decline);
1810 options[i]->buf_size = sizeof(decline);
1811 options[i]->timeout = 0xFFFFFFFF;
1813 /* Send back the server identifier... */
1814 i = DHO_DHCP_SERVER_IDENTIFIER;
1815 options[i] = &server_id_tree;
1816 options[i]->value = lease->options[i].data;
1817 options[i]->len = lease->options[i].len;
1818 options[i]->buf_size = lease->options[i].len;
1819 options[i]->timeout = 0xFFFFFFFF;
1821 /* Send back the address we're declining. */
1822 i = DHO_DHCP_REQUESTED_ADDRESS;
1823 options[i] = &requested_address_tree;
1824 options[i]->value = lease->address.iabuf;
1825 options[i]->len = lease->address.len;
1826 options[i]->buf_size = lease->address.len;
1827 options[i]->timeout = 0xFFFFFFFF;
1829 /* Send the uid if the user supplied one. */
1830 i = DHO_DHCP_CLIENT_IDENTIFIER;
1831 if (ip->client->config->send_options[i].len) {
1832 options[i] = &client_id_tree;
1833 options[i]->value = ip->client->config->send_options[i].data;
1834 options[i]->len = ip->client->config->send_options[i].len;
1835 options[i]->buf_size = ip->client->config->send_options[i].len;
1836 options[i]->timeout = 0xFFFFFFFF;
1840 /* Set up the option buffer... */
1841 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1842 options, 0, 0, 0, NULL, 0);
1843 if (ip->client->packet_length < BOOTP_MIN_LEN)
1844 ip->client->packet_length = BOOTP_MIN_LEN;
1846 ip->client->packet.op = BOOTREQUEST;
1847 ip->client->packet.htype = ip->hw_address.htype;
1848 ip->client->packet.hlen = ip->hw_address.hlen;
1849 ip->client->packet.hops = 0;
1850 ip->client->packet.xid = ip->client->xid;
1851 ip->client->packet.secs = 0; /* Filled in by send_request. */
1852 ip->client->packet.flags = 0;
1854 /* ciaddr must always be zero. */
1855 memset(&ip->client->packet.ciaddr, 0,
1856 sizeof(ip->client->packet.ciaddr));
1857 memset(&ip->client->packet.yiaddr, 0,
1858 sizeof(ip->client->packet.yiaddr));
1859 memset(&ip->client->packet.siaddr, 0,
1860 sizeof(ip->client->packet.siaddr));
1861 memset(&ip->client->packet.giaddr, 0,
1862 sizeof(ip->client->packet.giaddr));
1863 memcpy(ip->client->packet.chaddr,
1864 ip->hw_address.haddr, ip->hw_address.hlen);
1868 free_client_lease(struct client_lease *lease)
1872 if (lease->server_name)
1873 free(lease->server_name);
1874 if (lease->filename)
1875 free(lease->filename);
1876 for (i = 0; i < 256; i++) {
1877 if (lease->options[i].len)
1878 free(lease->options[i].data);
1886 rewrite_client_leases(void)
1888 struct client_lease *lp;
1889 cap_rights_t rights;
1892 leaseFile = fopen(path_dhclient_db, "w");
1894 error("can't create %s: %m", path_dhclient_db);
1895 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1896 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1897 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1899 error("can't limit lease descriptor: %m");
1901 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1903 error("can't limit lease descriptor fcntls: %m");
1910 for (lp = ifi->client->leases; lp; lp = lp->next)
1911 write_client_lease(ifi, lp, 1);
1912 if (ifi->client->active)
1913 write_client_lease(ifi, ifi->client->active, 1);
1916 ftruncate(fileno(leaseFile), ftello(leaseFile));
1917 fsync(fileno(leaseFile));
1921 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1924 static int leases_written;
1929 if (leases_written++ > 20) {
1930 rewrite_client_leases();
1935 /* If the lease came from the config file, we don't need to stash
1936 a copy in the lease database. */
1937 if (lease->is_static)
1940 if (!leaseFile) { /* XXX */
1941 leaseFile = fopen(path_dhclient_db, "w");
1943 error("can't create %s: %m", path_dhclient_db);
1946 fprintf(leaseFile, "lease {\n");
1947 if (lease->is_bootp)
1948 fprintf(leaseFile, " bootp;\n");
1949 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1950 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1951 if (lease->nextserver.len == sizeof(inaddr_any) &&
1952 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1953 sizeof(inaddr_any)))
1954 fprintf(leaseFile, " next-server %s;\n",
1955 piaddr(lease->nextserver));
1956 if (lease->filename)
1957 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1958 if (lease->server_name)
1959 fprintf(leaseFile, " server-name \"%s\";\n",
1960 lease->server_name);
1962 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1963 for (i = 0; i < 256; i++)
1964 if (lease->options[i].len)
1965 fprintf(leaseFile, " option %s %s;\n",
1966 dhcp_options[i].name,
1967 pretty_print_option(i, lease->options[i].data,
1968 lease->options[i].len, 1, 1));
1970 t = gmtime(&lease->renewal);
1971 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1972 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1973 t->tm_hour, t->tm_min, t->tm_sec);
1974 t = gmtime(&lease->rebind);
1975 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1976 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1977 t->tm_hour, t->tm_min, t->tm_sec);
1978 t = gmtime(&lease->expiry);
1979 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1980 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1981 t->tm_hour, t->tm_min, t->tm_sec);
1982 fprintf(leaseFile, "}\n");
1987 script_init(const char *reason, struct string_list *medium)
1989 size_t len, mediumlen = 0;
1990 struct imsg_hdr hdr;
1994 if (medium != NULL && medium->string != NULL)
1995 mediumlen = strlen(medium->string);
1997 hdr.code = IMSG_SCRIPT_INIT;
1998 hdr.len = sizeof(struct imsg_hdr) +
1999 sizeof(size_t) + mediumlen +
2000 sizeof(size_t) + strlen(reason);
2002 if ((buf = buf_open(hdr.len)) == NULL)
2003 error("buf_open: %m");
2006 errs += buf_add(buf, &hdr, sizeof(hdr));
2007 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
2009 errs += buf_add(buf, medium->string, mediumlen);
2010 len = strlen(reason);
2011 errs += buf_add(buf, &len, sizeof(len));
2012 errs += buf_add(buf, reason, len);
2015 error("buf_add: %m");
2017 if (buf_close(privfd, buf) == -1)
2018 error("buf_close: %m");
2022 priv_script_init(const char *reason, char *medium)
2024 struct interface_info *ip = ifi;
2027 ip->client->scriptEnvsize = 100;
2028 if (ip->client->scriptEnv == NULL)
2029 ip->client->scriptEnv =
2030 malloc(ip->client->scriptEnvsize * sizeof(char *));
2031 if (ip->client->scriptEnv == NULL)
2032 error("script_init: no memory for environment");
2034 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2035 if (ip->client->scriptEnv[0] == NULL)
2036 error("script_init: no memory for environment");
2038 ip->client->scriptEnv[1] = NULL;
2040 script_set_env(ip->client, "", "interface", ip->name);
2043 script_set_env(ip->client, "", "medium", medium);
2045 script_set_env(ip->client, "", "reason", reason);
2050 priv_script_write_params(const char *prefix, struct client_lease *lease)
2052 struct interface_info *ip = ifi;
2053 u_int8_t dbuf[1500], *dp = NULL;
2058 script_set_env(ip->client, prefix, "ip_address",
2059 piaddr(lease->address));
2061 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2063 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2064 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2066 dp = lease->options[DHO_SUBNET_MASK].data;
2067 len = lease->options[DHO_SUBNET_MASK].len;
2069 if (len && (len < sizeof(lease->address.iabuf))) {
2070 struct iaddr netmask, subnet, broadcast;
2072 memcpy(netmask.iabuf, dp, len);
2074 subnet = subnet_number(lease->address, netmask);
2076 script_set_env(ip->client, prefix, "network_number",
2078 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2079 broadcast = broadcast_addr(subnet, netmask);
2081 script_set_env(ip->client, prefix,
2082 "broadcast_address",
2088 if (lease->filename)
2089 script_set_env(ip->client, prefix, "filename", lease->filename);
2090 if (lease->server_name)
2091 script_set_env(ip->client, prefix, "server_name",
2092 lease->server_name);
2093 for (i = 0; i < 256; i++) {
2096 if (ip->client->config->defaults[i].len) {
2097 if (lease->options[i].len) {
2099 ip->client->config->default_actions[i]) {
2100 case ACTION_DEFAULT:
2101 dp = lease->options[i].data;
2102 len = lease->options[i].len;
2104 case ACTION_SUPERSEDE:
2107 config->defaults[i].data;
2109 config->defaults[i].len;
2111 case ACTION_PREPEND:
2113 config->defaults[i].len +
2114 lease->options[i].len;
2115 if (len >= sizeof(dbuf)) {
2116 warning("no space to %s %s",
2118 dhcp_options[i].name);
2124 config->defaults[i].data,
2126 config->defaults[i].len);
2127 memcpy(dp + ip->client->
2128 config->defaults[i].len,
2129 lease->options[i].data,
2130 lease->options[i].len);
2135 * When we append, we assume that we're
2136 * appending to text. Some MS servers
2137 * include a NUL byte at the end of
2138 * the search string provided.
2141 config->defaults[i].len +
2142 lease->options[i].len;
2143 if (len >= sizeof(dbuf)) {
2144 warning("no space to %s %s",
2146 dhcp_options[i].name);
2150 lease->options[i].data,
2151 lease->options[i].len);
2152 for (dp = dbuf + lease->options[i].len;
2153 dp > dbuf; dp--, len--)
2158 config->defaults[i].data,
2160 config->defaults[i].len);
2166 config->defaults[i].data;
2168 config->defaults[i].len;
2170 } else if (lease->options[i].len) {
2171 len = lease->options[i].len;
2172 dp = lease->options[i].data;
2179 if (dhcp_option_ev_name(name, sizeof(name),
2181 script_set_env(ip->client, prefix, name,
2182 pretty_print_option(i, dp, len, 0, 0));
2185 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2186 script_set_env(ip->client, prefix, "expiry", tbuf);
2190 script_write_params(const char *prefix, struct client_lease *lease)
2192 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2193 struct imsg_hdr hdr;
2197 if (lease->filename != NULL)
2198 fn_len = strlen(lease->filename);
2199 if (lease->server_name != NULL)
2200 sn_len = strlen(lease->server_name);
2202 pr_len = strlen(prefix);
2204 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2205 hdr.len = sizeof(hdr) + sizeof(*lease) +
2206 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2207 sizeof(pr_len) + pr_len;
2209 for (i = 0; i < 256; i++) {
2210 hdr.len += sizeof(lease->options[i].len);
2211 hdr.len += lease->options[i].len;
2214 scripttime = time(NULL);
2216 if ((buf = buf_open(hdr.len)) == NULL)
2217 error("buf_open: %m");
2220 errs += buf_add(buf, &hdr, sizeof(hdr));
2221 errs += buf_add(buf, lease, sizeof(*lease));
2222 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2223 errs += buf_add(buf, lease->filename, fn_len);
2224 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2225 errs += buf_add(buf, lease->server_name, sn_len);
2226 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2227 errs += buf_add(buf, prefix, pr_len);
2229 for (i = 0; i < 256; i++) {
2230 errs += buf_add(buf, &lease->options[i].len,
2231 sizeof(lease->options[i].len));
2232 errs += buf_add(buf, lease->options[i].data,
2233 lease->options[i].len);
2237 error("buf_add: %m");
2239 if (buf_close(privfd, buf) == -1)
2240 error("buf_close: %m");
2246 struct imsg_hdr hdr;
2250 hdr.code = IMSG_SCRIPT_GO;
2251 hdr.len = sizeof(struct imsg_hdr);
2253 if ((buf = buf_open(hdr.len)) == NULL)
2254 error("buf_open: %m");
2256 if (buf_add(buf, &hdr, sizeof(hdr)))
2257 error("buf_add: %m");
2259 if (buf_close(privfd, buf) == -1)
2260 error("buf_close: %m");
2262 bzero(&hdr, sizeof(hdr));
2263 buf_read(privfd, &hdr, sizeof(hdr));
2264 if (hdr.code != IMSG_SCRIPT_GO_RET)
2265 error("unexpected msg type %u", hdr.code);
2266 if (hdr.len != sizeof(hdr) + sizeof(int))
2267 error("received corrupted message");
2268 buf_read(privfd, &ret, sizeof(ret));
2270 scripttime = time(NULL);
2276 priv_script_go(void)
2278 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2279 static char client_path[] = CLIENT_PATH;
2280 struct interface_info *ip = ifi;
2281 int pid, wpid, wstatus;
2283 scripttime = time(NULL);
2286 scriptName = ip->client->config->script_name;
2287 envp = ip->client->scriptEnv;
2289 scriptName = top_level_config.script_name;
2291 epp[1] = client_path;
2296 argv[0] = scriptName;
2305 wpid = wait(&wstatus);
2306 } while (wpid != pid && wpid > 0);
2312 execve(scriptName, argv, envp);
2313 error("execve (%s, ...): %m", scriptName);
2317 script_flush_env(ip->client);
2319 return (wstatus & 0xff);
2323 script_set_env(struct client_state *client, const char *prefix,
2324 const char *name, const char *value)
2329 /* No `` or $() command substitution allowed in environment values! */
2330 for (j=0; j < strlen(value); j++)
2334 warning("illegal character (%c) in value '%s'",
2336 /* Ignore this option */
2340 namelen = strlen(name);
2342 for (i = 0; client->scriptEnv[i]; i++)
2343 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2344 client->scriptEnv[i][namelen] == '=')
2347 if (client->scriptEnv[i])
2348 /* Reuse the slot. */
2349 free(client->scriptEnv[i]);
2351 /* New variable. Expand if necessary. */
2352 if (i >= client->scriptEnvsize - 1) {
2353 char **newscriptEnv;
2354 int newscriptEnvsize = client->scriptEnvsize + 50;
2356 newscriptEnv = realloc(client->scriptEnv,
2358 if (newscriptEnv == NULL) {
2359 free(client->scriptEnv);
2360 client->scriptEnv = NULL;
2361 client->scriptEnvsize = 0;
2362 error("script_set_env: no memory for variable");
2364 client->scriptEnv = newscriptEnv;
2365 client->scriptEnvsize = newscriptEnvsize;
2367 /* need to set the NULL pointer at end of array beyond
2369 client->scriptEnv[i + 1] = NULL;
2371 /* Allocate space and format the variable in the appropriate slot. */
2372 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2374 if (client->scriptEnv[i] == NULL)
2375 error("script_set_env: no memory for variable assignment");
2376 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2377 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2381 script_flush_env(struct client_state *client)
2385 for (i = 0; client->scriptEnv[i]; i++) {
2386 free(client->scriptEnv[i]);
2387 client->scriptEnv[i] = NULL;
2389 client->scriptEnvsize = 0;
2393 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2397 for (i = 0; option->name[i]; i++) {
2398 if (i + 1 == buflen)
2400 if (option->name[i] == '-')
2403 buf[i] = option->name[i];
2413 static int state = 0;
2414 cap_rights_t rights;
2416 if (no_daemon || state)
2421 /* Stop logging to stderr... */
2424 if (daemon(1, 0) == -1)
2427 cap_rights_init(&rights);
2429 if (pidfile != NULL) {
2430 pidfile_write(pidfile);
2431 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2433 error("can't limit pidfile descriptor: %m");
2437 /* we are chrooted, daemon(3) fails to open /dev/null */
2439 dup2(nullfd, STDIN_FILENO);
2440 dup2(nullfd, STDOUT_FILENO);
2441 dup2(nullfd, STDERR_FILENO);
2446 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2447 error("can't limit stdin: %m");
2448 cap_rights_init(&rights, CAP_WRITE);
2449 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2450 error("can't limit stdout: %m");
2451 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2452 error("can't limit stderr: %m");
2456 check_option(struct client_lease *l, int option)
2461 /* we use this, since this is what gets passed to dhclient-script */
2463 opbuf = pretty_print_option(option, l->options[option].data,
2464 l->options[option].len, 0, 0);
2466 sbuf = option_as_string(option, l->options[option].data,
2467 l->options[option].len);
2470 case DHO_SUBNET_MASK:
2471 case DHO_TIME_SERVERS:
2472 case DHO_NAME_SERVERS:
2474 case DHO_DOMAIN_NAME_SERVERS:
2475 case DHO_LOG_SERVERS:
2476 case DHO_COOKIE_SERVERS:
2477 case DHO_LPR_SERVERS:
2478 case DHO_IMPRESS_SERVERS:
2479 case DHO_RESOURCE_LOCATION_SERVERS:
2480 case DHO_SWAP_SERVER:
2481 case DHO_BROADCAST_ADDRESS:
2482 case DHO_NIS_SERVERS:
2483 case DHO_NTP_SERVERS:
2484 case DHO_NETBIOS_NAME_SERVERS:
2485 case DHO_NETBIOS_DD_SERVER:
2486 case DHO_FONT_SERVERS:
2487 case DHO_DHCP_SERVER_IDENTIFIER:
2488 case DHO_NISPLUS_SERVERS:
2489 case DHO_MOBILE_IP_HOME_AGENT:
2490 case DHO_SMTP_SERVER:
2491 case DHO_POP_SERVER:
2492 case DHO_NNTP_SERVER:
2493 case DHO_WWW_SERVER:
2494 case DHO_FINGER_SERVER:
2495 case DHO_IRC_SERVER:
2496 case DHO_STREETTALK_SERVER:
2497 case DHO_STREETTALK_DA_SERVER:
2498 if (!ipv4addrs(opbuf)) {
2499 warning("Invalid IP address in option: %s", opbuf);
2504 case DHO_NIS_DOMAIN:
2505 case DHO_NISPLUS_DOMAIN:
2506 case DHO_TFTP_SERVER_NAME:
2507 if (!res_hnok(sbuf)) {
2508 warning("Bogus Host Name option %d: %s (%s)", option,
2510 l->options[option].len = 0;
2511 free(l->options[option].data);
2514 case DHO_DOMAIN_NAME:
2515 case DHO_DOMAIN_SEARCH:
2516 if (!res_hnok(sbuf)) {
2517 if (!check_search(sbuf)) {
2518 warning("Bogus domain search list %d: %s (%s)",
2519 option, sbuf, opbuf);
2520 l->options[option].len = 0;
2521 free(l->options[option].data);
2526 case DHO_TIME_OFFSET:
2528 case DHO_MERIT_DUMP:
2530 case DHO_EXTENSIONS_PATH:
2531 case DHO_IP_FORWARDING:
2532 case DHO_NON_LOCAL_SOURCE_ROUTING:
2533 case DHO_POLICY_FILTER:
2534 case DHO_MAX_DGRAM_REASSEMBLY:
2535 case DHO_DEFAULT_IP_TTL:
2536 case DHO_PATH_MTU_AGING_TIMEOUT:
2537 case DHO_PATH_MTU_PLATEAU_TABLE:
2538 case DHO_INTERFACE_MTU:
2539 case DHO_ALL_SUBNETS_LOCAL:
2540 case DHO_PERFORM_MASK_DISCOVERY:
2541 case DHO_MASK_SUPPLIER:
2542 case DHO_ROUTER_DISCOVERY:
2543 case DHO_ROUTER_SOLICITATION_ADDRESS:
2544 case DHO_STATIC_ROUTES:
2545 case DHO_TRAILER_ENCAPSULATION:
2546 case DHO_ARP_CACHE_TIMEOUT:
2547 case DHO_IEEE802_3_ENCAPSULATION:
2548 case DHO_DEFAULT_TCP_TTL:
2549 case DHO_TCP_KEEPALIVE_INTERVAL:
2550 case DHO_TCP_KEEPALIVE_GARBAGE:
2551 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2552 case DHO_NETBIOS_NODE_TYPE:
2553 case DHO_NETBIOS_SCOPE:
2554 case DHO_X_DISPLAY_MANAGER:
2555 case DHO_DHCP_REQUESTED_ADDRESS:
2556 case DHO_DHCP_LEASE_TIME:
2557 case DHO_DHCP_OPTION_OVERLOAD:
2558 case DHO_DHCP_MESSAGE_TYPE:
2559 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2560 case DHO_DHCP_MESSAGE:
2561 case DHO_DHCP_MAX_MESSAGE_SIZE:
2562 case DHO_DHCP_RENEWAL_TIME:
2563 case DHO_DHCP_REBINDING_TIME:
2564 case DHO_DHCP_CLASS_IDENTIFIER:
2565 case DHO_DHCP_CLIENT_IDENTIFIER:
2566 case DHO_BOOTFILE_NAME:
2567 case DHO_DHCP_USER_CLASS_ID:
2570 case DHO_CLASSLESS_ROUTES:
2571 return (check_classless_option(l->options[option].data,
2572 l->options[option].len));
2574 warning("unknown dhcp option value 0x%x", option);
2575 return (unknown_ok);
2579 /* RFC 3442 The Classless Static Routes option checks */
2581 check_classless_option(unsigned char *data, int len)
2584 unsigned char width;
2585 in_addr_t addr, mask;
2588 warning("Too small length: %d", len);
2596 } else if (width < 9) {
2597 addr = (in_addr_t)(data[i] << 24);
2599 } else if (width < 17) {
2600 addr = (in_addr_t)(data[i] << 24) +
2601 (in_addr_t)(data[i + 1] << 16);
2603 } else if (width < 25) {
2604 addr = (in_addr_t)(data[i] << 24) +
2605 (in_addr_t)(data[i + 1] << 16) +
2606 (in_addr_t)(data[i + 2] << 8);
2608 } else if (width < 33) {
2609 addr = (in_addr_t)(data[i] << 24) +
2610 (in_addr_t)(data[i + 1] << 16) +
2611 (in_addr_t)(data[i + 2] << 8) +
2615 warning("Incorrect subnet width: %d", width);
2618 mask = (in_addr_t)(~0) << (32 - width);
2624 * ... After deriving a subnet number and subnet mask
2625 * from each destination descriptor, the DHCP client
2626 * MUST zero any bits in the subnet number where the
2627 * corresponding bit in the mask is zero...
2629 if ((addr & mask) != addr) {
2631 data[i - 1] = (unsigned char)(
2632 (addr >> (((32 - width)/8)*8)) & 0xFF);
2637 warning("Incorrect data length: %d (must be %d)", len, i);
2644 res_hnok(const char *dn)
2646 int pch = PERIOD, ch = *dn++;
2648 while (ch != '\0') {
2651 if (periodchar(ch)) {
2653 } else if (periodchar(pch)) {
2654 if (!borderchar(ch))
2656 } else if (periodchar(nch) || nch == '\0') {
2657 if (!borderchar(ch))
2660 if (!middlechar(ch))
2669 check_search(const char *srch)
2671 int pch = PERIOD, ch = *srch++;
2674 /* 256 char limit re resolv.conf(5) */
2675 if (strlen(srch) > 256)
2678 while (whitechar(ch))
2681 while (ch != '\0') {
2684 if (periodchar(ch) || whitechar(ch)) {
2686 } else if (periodchar(pch)) {
2687 if (!borderchar(ch))
2689 } else if (periodchar(nch) || nch == '\0') {
2690 if (!borderchar(ch))
2693 if (!middlechar(ch))
2696 if (!whitechar(ch)) {
2699 while (whitechar(nch)) {
2708 /* 6 domain limit re resolv.conf(5) */
2714 /* Does buf consist only of dotted decimal ipv4 addrs?
2715 * return how many if so,
2716 * otherwise, return 0
2719 ipv4addrs(const char * buf)
2724 while (inet_aton(buf, &jnk) == 1){
2726 while (periodchar(*buf) || digitchar(*buf))
2738 option_as_string(unsigned int code, unsigned char *data, int len)
2740 static char optbuf[32768]; /* XXX */
2742 int opleft = sizeof(optbuf);
2743 unsigned char *dp = data;
2746 error("option_as_string: bad code %d", code);
2748 for (; dp < data + len; dp++) {
2749 if (!isascii(*dp) || !isprint(*dp)) {
2750 if (dp + 1 != data + len || *dp != 0) {
2751 snprintf(op, opleft, "\\%03o", *dp);
2755 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2756 *dp == '`' || *dp == '\\') {
2770 warning("dhcp option too large");
2775 fork_privchld(int fd, int fd2)
2777 struct pollfd pfd[1];
2782 error("cannot fork");
2789 setproctitle("%s [priv]", ifi->name);
2792 dup2(nullfd, STDIN_FILENO);
2793 dup2(nullfd, STDOUT_FILENO);
2794 dup2(nullfd, STDERR_FILENO);
2802 pfd[0].events = POLLIN;
2803 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2805 error("poll error");
2807 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2810 dispatch_imsg(ifi, fd);