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)) {
831 u_int16_t mtu = be16dec(opt->data);
833 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
835 interface_set_mtu_unpriv(privfd, mtu);
838 /* Write out the new lease. */
839 write_client_lease(ip, ip->client->new, 0);
841 /* Run the client script with the new parameters. */
842 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
843 (ip->client->state == S_RENEWING ? "RENEW" :
844 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
845 ip->client->new->medium);
846 if (ip->client->active && ip->client->state != S_REBOOTING)
847 script_write_params("old_", ip->client->active);
848 script_write_params("new_", ip->client->new);
849 if (ip->client->alias)
850 script_write_params("alias_", ip->client->alias);
853 /* Replace the old active lease with the new one. */
854 if (ip->client->active)
855 free_client_lease(ip->client->active);
856 ip->client->active = ip->client->new;
857 ip->client->new = NULL;
859 /* Set up a timeout to start the renewal process. */
860 add_timeout(ip->client->active->renewal, state_bound, ip);
862 note("bound to %s -- renewal in %d seconds.",
863 piaddr(ip->client->active->address),
864 (int)(ip->client->active->renewal - cur_time));
865 ip->client->state = S_BOUND;
866 reinitialize_interfaces();
871 * state_bound is called when we've successfully bound to a particular
872 * lease, but the renewal time on that lease has expired. We are
873 * expected to unicast a DHCPREQUEST to the server that gave us our
877 state_bound(void *ipp)
879 struct interface_info *ip = ipp;
881 ASSERT_STATE(state, S_BOUND);
883 /* T1 has expired. */
884 make_request(ip, ip->client->active);
885 ip->client->xid = ip->client->packet.xid;
887 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
888 memcpy(ip->client->destination.iabuf, ip->client->active->
889 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
890 ip->client->destination.len = 4;
892 ip->client->destination = iaddr_broadcast;
894 ip->client->first_sending = cur_time;
895 ip->client->interval = ip->client->config->initial_interval;
896 ip->client->state = S_RENEWING;
898 /* Send the first packet immediately. */
903 bootp(struct packet *packet)
905 struct iaddrlist *ap;
907 if (packet->raw->op != BOOTREPLY)
910 /* If there's a reject list, make sure this packet's sender isn't
912 for (ap = packet->interface->client->config->reject_list;
914 if (addr_eq(packet->client_addr, ap->addr)) {
915 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
923 dhcp(struct packet *packet)
925 struct iaddrlist *ap;
926 void (*handler)(struct packet *);
929 switch (packet->packet_type) {
946 /* If there's a reject list, make sure this packet's sender isn't
948 for (ap = packet->interface->client->config->reject_list;
950 if (addr_eq(packet->client_addr, ap->addr)) {
951 note("%s from %s rejected.", type, piaddr(ap->addr));
959 dhcpoffer(struct packet *packet)
961 struct interface_info *ip = packet->interface;
962 struct client_lease *lease, *lp;
964 int arp_timeout_needed, stop_selecting;
965 const char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
966 "DHCPOFFER" : "BOOTREPLY";
968 /* If we're not receptive to an offer right now, or if the offer
969 has an unrecognizable transaction id, then just drop it. */
970 if (ip->client->state != S_SELECTING ||
971 packet->interface->client->xid != packet->raw->xid ||
972 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
973 (memcmp(packet->interface->hw_address.haddr,
974 packet->raw->chaddr, packet->raw->hlen)))
977 note("%s from %s", name, piaddr(packet->client_addr));
980 /* If this lease doesn't supply the minimum required parameters,
982 for (i = 0; ip->client->config->required_options[i]; i++) {
983 if (!packet->options[ip->client->config->
984 required_options[i]].len) {
985 note("%s isn't satisfactory.", name);
990 /* If we've already seen this lease, don't record it again. */
991 for (lease = ip->client->offered_leases;
992 lease; lease = lease->next) {
993 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
994 !memcmp(lease->address.iabuf,
995 &packet->raw->yiaddr, lease->address.len)) {
996 debug("%s already seen.", name);
1001 lease = packet_to_lease(packet);
1003 note("packet_to_lease failed.");
1007 /* If this lease was acquired through a BOOTREPLY, record that
1009 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1010 lease->is_bootp = 1;
1012 /* Record the medium under which this lease was offered. */
1013 lease->medium = ip->client->medium;
1015 /* Send out an ARP Request for the offered IP address. */
1016 script_init("ARPSEND", lease->medium);
1017 script_write_params("check_", lease);
1018 /* If the script can't send an ARP request without waiting,
1019 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1021 arp_timeout_needed = 0;
1023 arp_timeout_needed = 2;
1025 /* Figure out when we're supposed to stop selecting. */
1027 ip->client->first_sending + ip->client->config->select_interval;
1029 /* If this is the lease we asked for, put it at the head of the
1030 list, and don't mess with the arp request timeout. */
1031 if (lease->address.len == ip->client->requested_address.len &&
1032 !memcmp(lease->address.iabuf,
1033 ip->client->requested_address.iabuf,
1034 ip->client->requested_address.len)) {
1035 lease->next = ip->client->offered_leases;
1036 ip->client->offered_leases = lease;
1038 /* If we already have an offer, and arping for this
1039 offer would take us past the selection timeout,
1040 then don't extend the timeout - just hope for the
1042 if (ip->client->offered_leases &&
1043 (cur_time + arp_timeout_needed) > stop_selecting)
1044 arp_timeout_needed = 0;
1046 /* Put the lease at the end of the list. */
1048 if (!ip->client->offered_leases)
1049 ip->client->offered_leases = lease;
1051 for (lp = ip->client->offered_leases; lp->next;
1058 /* If we're supposed to stop selecting before we've had time
1059 to wait for the ARPREPLY, add some delay to wait for
1061 if (stop_selecting - cur_time < arp_timeout_needed)
1062 stop_selecting = cur_time + arp_timeout_needed;
1064 /* If the selecting interval has expired, go immediately to
1065 state_selecting(). Otherwise, time out into
1066 state_selecting at the select interval. */
1067 if (stop_selecting <= 0)
1068 state_selecting(ip);
1070 add_timeout(stop_selecting, state_selecting, ip);
1071 cancel_timeout(send_discover, ip);
1075 /* Allocate a client_lease structure and initialize it from the parameters
1076 in the specified packet. */
1078 struct client_lease *
1079 packet_to_lease(struct packet *packet)
1081 struct client_lease *lease;
1084 lease = malloc(sizeof(struct client_lease));
1087 warning("dhcpoffer: no memory to record lease.");
1091 memset(lease, 0, sizeof(*lease));
1093 /* Copy the lease options. */
1094 for (i = 0; i < 256; i++) {
1095 if (packet->options[i].len) {
1096 lease->options[i].data =
1097 malloc(packet->options[i].len + 1);
1098 if (!lease->options[i].data) {
1099 warning("dhcpoffer: no memory for option %d", i);
1100 free_client_lease(lease);
1103 memcpy(lease->options[i].data,
1104 packet->options[i].data,
1105 packet->options[i].len);
1106 lease->options[i].len =
1107 packet->options[i].len;
1108 lease->options[i].data[lease->options[i].len] =
1111 if (!check_option(lease,i)) {
1112 /* ignore a bogus lease offer */
1113 warning("Invalid lease option - ignoring offer");
1114 free_client_lease(lease);
1120 lease->address.len = sizeof(packet->raw->yiaddr);
1121 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1123 lease->nextserver.len = sizeof(packet->raw->siaddr);
1124 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1126 /* If the server name was filled out, copy it.
1127 Do not attempt to validate the server name as a host name.
1128 RFC 2131 merely states that sname is NUL-terminated (which do
1129 do not assume) and that it is the server's host name. Since
1130 the ISC client and server allow arbitrary characters, we do
1132 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1133 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1134 packet->raw->sname[0]) {
1135 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1136 if (!lease->server_name) {
1137 warning("dhcpoffer: no memory for server name.");
1138 free_client_lease(lease);
1141 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1142 lease->server_name[DHCP_SNAME_LEN]='\0';
1145 /* Ditto for the filename. */
1146 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1147 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1148 packet->raw->file[0]) {
1149 /* Don't count on the NUL terminator. */
1150 lease->filename = malloc(DHCP_FILE_LEN + 1);
1151 if (!lease->filename) {
1152 warning("dhcpoffer: no memory for filename.");
1153 free_client_lease(lease);
1156 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1157 lease->filename[DHCP_FILE_LEN]='\0';
1163 dhcpnak(struct packet *packet)
1165 struct interface_info *ip = packet->interface;
1167 /* If we're not receptive to an offer right now, or if the offer
1168 has an unrecognizable transaction id, then just drop it. */
1169 if (packet->interface->client->xid != packet->raw->xid ||
1170 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1171 (memcmp(packet->interface->hw_address.haddr,
1172 packet->raw->chaddr, packet->raw->hlen)))
1175 if (ip->client->state != S_REBOOTING &&
1176 ip->client->state != S_REQUESTING &&
1177 ip->client->state != S_RENEWING &&
1178 ip->client->state != S_REBINDING)
1181 note("DHCPNAK from %s", piaddr(packet->client_addr));
1183 if (!ip->client->active) {
1184 note("DHCPNAK with no active lease.\n");
1188 free_client_lease(ip->client->active);
1189 ip->client->active = NULL;
1191 /* Stop sending DHCPREQUEST packets... */
1192 cancel_timeout(send_request, ip);
1194 ip->client->state = S_INIT;
1198 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1199 one after the right interval has expired. If we don't get an offer by
1200 the time we reach the panic interval, call the panic function. */
1203 send_discover(void *ipp)
1205 struct interface_info *ip = ipp;
1206 int interval, increase = 1;
1208 /* Figure out how long it's been since we started transmitting. */
1209 interval = cur_time - ip->client->first_sending;
1211 /* If we're past the panic timeout, call the script and tell it
1212 we haven't found anything for this interface yet. */
1213 if (interval > ip->client->config->timeout) {
1218 /* If we're selecting media, try the whole list before doing
1219 the exponential backoff, but if we've already received an
1220 offer, stop looping, because we obviously have it right. */
1221 if (!ip->client->offered_leases &&
1222 ip->client->config->media) {
1225 if (ip->client->medium) {
1226 ip->client->medium = ip->client->medium->next;
1229 if (!ip->client->medium) {
1231 error("No valid media types for %s!", ip->name);
1232 ip->client->medium = ip->client->config->media;
1236 note("Trying medium \"%s\" %d", ip->client->medium->string,
1238 script_init("MEDIUM", ip->client->medium);
1244 * If we're supposed to increase the interval, do so. If it's
1245 * currently zero (i.e., we haven't sent any packets yet), set
1246 * it to one; otherwise, add to it a random number between zero
1247 * and two times itself. On average, this means that it will
1248 * double with every transmission.
1251 if (!ip->client->interval)
1252 ip->client->interval =
1253 ip->client->config->initial_interval;
1255 ip->client->interval += (arc4random() >> 2) %
1256 (2 * ip->client->interval);
1259 /* Don't backoff past cutoff. */
1260 if (ip->client->interval >
1261 ip->client->config->backoff_cutoff)
1262 ip->client->interval =
1263 ((ip->client->config->backoff_cutoff / 2)
1264 + ((arc4random() >> 2) %
1265 ip->client->config->backoff_cutoff));
1266 } else if (!ip->client->interval)
1267 ip->client->interval =
1268 ip->client->config->initial_interval;
1270 /* If the backoff would take us to the panic timeout, just use that
1272 if (cur_time + ip->client->interval >
1273 ip->client->first_sending + ip->client->config->timeout)
1274 ip->client->interval =
1275 (ip->client->first_sending +
1276 ip->client->config->timeout) - cur_time + 1;
1278 /* Record the number of seconds since we started sending. */
1279 if (interval < 65536)
1280 ip->client->packet.secs = htons(interval);
1282 ip->client->packet.secs = htons(65535);
1283 ip->client->secs = ip->client->packet.secs;
1285 note("DHCPDISCOVER on %s to %s port %d interval %d",
1286 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1287 (int)ip->client->interval);
1289 /* Send out a packet. */
1290 send_packet_unpriv(privfd, &ip->client->packet,
1291 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1293 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1297 * state_panic gets called if we haven't received any offers in a preset
1298 * amount of time. When this happens, we try to use existing leases
1299 * that haven't yet expired, and failing that, we call the client script
1300 * and hope it can do something.
1303 state_panic(void *ipp)
1305 struct interface_info *ip = ipp;
1306 struct client_lease *loop = ip->client->active;
1307 struct client_lease *lp;
1309 note("No DHCPOFFERS received.");
1311 /* We may not have an active lease, but we may have some
1312 predefined leases that we can try. */
1313 if (!ip->client->active && ip->client->leases)
1316 /* Run through the list of leases and see if one can be used. */
1317 while (ip->client->active) {
1318 if (ip->client->active->expiry > cur_time) {
1319 note("Trying recorded lease %s",
1320 piaddr(ip->client->active->address));
1321 /* Run the client script with the existing
1323 script_init("TIMEOUT",
1324 ip->client->active->medium);
1325 script_write_params("new_", ip->client->active);
1326 if (ip->client->alias)
1327 script_write_params("alias_",
1330 /* If the old lease is still good and doesn't
1331 yet need renewal, go into BOUND state and
1332 timeout at the renewal time. */
1335 ip->client->active->renewal) {
1336 ip->client->state = S_BOUND;
1337 note("bound: renewal in %d seconds.",
1338 (int)(ip->client->active->renewal -
1341 ip->client->active->renewal,
1344 ip->client->state = S_BOUND;
1345 note("bound: immediate renewal.");
1348 reinitialize_interfaces();
1354 /* If there are no other leases, give up. */
1355 if (!ip->client->leases) {
1356 ip->client->leases = ip->client->active;
1357 ip->client->active = NULL;
1362 /* Otherwise, put the active lease at the end of the
1363 lease list, and try another lease.. */
1364 for (lp = ip->client->leases; lp->next; lp = lp->next)
1366 lp->next = ip->client->active;
1368 lp->next->next = NULL;
1369 ip->client->active = ip->client->leases;
1370 ip->client->leases = ip->client->leases->next;
1372 /* If we already tried this lease, we've exhausted the
1373 set of leases, so we might as well give up for
1375 if (ip->client->active == loop)
1378 loop = ip->client->active;
1381 /* No leases were available, or what was available didn't work, so
1382 tell the shell script that we failed to allocate an address,
1383 and try again later. */
1384 note("No working leases in persistent database - sleeping.\n");
1385 script_init("FAIL", NULL);
1386 if (ip->client->alias)
1387 script_write_params("alias_", ip->client->alias);
1389 ip->client->state = S_INIT;
1390 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1396 send_request(void *ipp)
1398 struct interface_info *ip = ipp;
1399 struct in_addr from, to;
1402 /* Figure out how long it's been since we started transmitting. */
1403 interval = cur_time - ip->client->first_sending;
1405 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1406 past the reboot timeout, go to INIT and see if we can
1407 DISCOVER an address... */
1408 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1409 means either that we're on a network with no DHCP server,
1410 or that our server is down. In the latter case, assuming
1411 that there is a backup DHCP server, DHCPDISCOVER will get
1412 us a new address, but we could also have successfully
1413 reused our old address. In the former case, we're hosed
1414 anyway. This is not a win-prone situation. */
1415 if ((ip->client->state == S_REBOOTING ||
1416 ip->client->state == S_REQUESTING) &&
1417 interval > ip->client->config->reboot_timeout) {
1419 ip->client->state = S_INIT;
1420 cancel_timeout(send_request, ip);
1425 /* If we're in the reboot state, make sure the media is set up
1427 if (ip->client->state == S_REBOOTING &&
1428 !ip->client->medium &&
1429 ip->client->active->medium ) {
1430 script_init("MEDIUM", ip->client->active->medium);
1432 /* If the medium we chose won't fly, go to INIT state. */
1436 /* Record the medium. */
1437 ip->client->medium = ip->client->active->medium;
1440 /* If the lease has expired, relinquish the address and go back
1441 to the INIT state. */
1442 if (ip->client->state != S_REQUESTING &&
1443 cur_time > ip->client->active->expiry) {
1444 /* Run the client script with the new parameters. */
1445 script_init("EXPIRE", NULL);
1446 script_write_params("old_", ip->client->active);
1447 if (ip->client->alias)
1448 script_write_params("alias_", ip->client->alias);
1451 /* Now do a preinit on the interface so that we can
1452 discover a new address. */
1453 script_init("PREINIT", NULL);
1454 if (ip->client->alias)
1455 script_write_params("alias_", ip->client->alias);
1458 ip->client->state = S_INIT;
1463 /* Do the exponential backoff... */
1464 if (!ip->client->interval)
1465 ip->client->interval = ip->client->config->initial_interval;
1467 ip->client->interval += ((arc4random() >> 2) %
1468 (2 * ip->client->interval));
1470 /* Don't backoff past cutoff. */
1471 if (ip->client->interval >
1472 ip->client->config->backoff_cutoff)
1473 ip->client->interval =
1474 ((ip->client->config->backoff_cutoff / 2) +
1475 ((arc4random() >> 2) % ip->client->interval));
1477 /* If the backoff would take us to the expiry time, just set the
1478 timeout to the expiry time. */
1479 if (ip->client->state != S_REQUESTING &&
1480 cur_time + ip->client->interval >
1481 ip->client->active->expiry)
1482 ip->client->interval =
1483 ip->client->active->expiry - cur_time + 1;
1485 /* If the lease T2 time has elapsed, or if we're not yet bound,
1486 broadcast the DHCPREQUEST rather than unicasting. */
1487 if (ip->client->state == S_REQUESTING ||
1488 ip->client->state == S_REBOOTING ||
1489 cur_time > ip->client->active->rebind)
1490 to.s_addr = INADDR_BROADCAST;
1492 memcpy(&to.s_addr, ip->client->destination.iabuf,
1495 if (ip->client->state != S_REQUESTING &&
1496 ip->client->state != S_REBOOTING)
1497 memcpy(&from, ip->client->active->address.iabuf,
1500 from.s_addr = INADDR_ANY;
1502 /* Record the number of seconds since we started sending. */
1503 if (ip->client->state == S_REQUESTING)
1504 ip->client->packet.secs = ip->client->secs;
1506 if (interval < 65536)
1507 ip->client->packet.secs = htons(interval);
1509 ip->client->packet.secs = htons(65535);
1512 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1515 /* Send out a packet. */
1516 send_packet_unpriv(privfd, &ip->client->packet,
1517 ip->client->packet_length, from, to);
1519 add_timeout(cur_time + ip->client->interval, send_request, ip);
1523 send_decline(void *ipp)
1525 struct interface_info *ip = ipp;
1527 note("DHCPDECLINE on %s to %s port %d", ip->name,
1528 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1530 /* Send out a packet. */
1531 send_packet_unpriv(privfd, &ip->client->packet,
1532 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1536 make_discover(struct interface_info *ip, struct client_lease *lease)
1538 unsigned char discover = DHCPDISCOVER;
1539 struct tree_cache *options[256];
1540 struct tree_cache option_elements[256];
1543 memset(option_elements, 0, sizeof(option_elements));
1544 memset(options, 0, sizeof(options));
1545 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1547 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1548 i = DHO_DHCP_MESSAGE_TYPE;
1549 options[i] = &option_elements[i];
1550 options[i]->value = &discover;
1551 options[i]->len = sizeof(discover);
1552 options[i]->buf_size = sizeof(discover);
1553 options[i]->timeout = 0xFFFFFFFF;
1555 /* Request the options we want */
1556 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1557 options[i] = &option_elements[i];
1558 options[i]->value = ip->client->config->requested_options;
1559 options[i]->len = ip->client->config->requested_option_count;
1560 options[i]->buf_size =
1561 ip->client->config->requested_option_count;
1562 options[i]->timeout = 0xFFFFFFFF;
1564 /* If we had an address, try to get it again. */
1566 ip->client->requested_address = lease->address;
1567 i = DHO_DHCP_REQUESTED_ADDRESS;
1568 options[i] = &option_elements[i];
1569 options[i]->value = lease->address.iabuf;
1570 options[i]->len = lease->address.len;
1571 options[i]->buf_size = lease->address.len;
1572 options[i]->timeout = 0xFFFFFFFF;
1574 ip->client->requested_address.len = 0;
1576 /* Send any options requested in the config file. */
1577 for (i = 0; i < 256; i++)
1579 ip->client->config->send_options[i].data) {
1580 options[i] = &option_elements[i];
1582 ip->client->config->send_options[i].data;
1584 ip->client->config->send_options[i].len;
1585 options[i]->buf_size =
1586 ip->client->config->send_options[i].len;
1587 options[i]->timeout = 0xFFFFFFFF;
1590 /* send host name if not set via config file. */
1591 if (!options[DHO_HOST_NAME]) {
1592 if (hostname[0] != '\0') {
1594 char* posDot = strchr(hostname, '.');
1596 len = posDot - hostname;
1598 len = strlen(hostname);
1599 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1600 options[DHO_HOST_NAME]->value = hostname;
1601 options[DHO_HOST_NAME]->len = len;
1602 options[DHO_HOST_NAME]->buf_size = len;
1603 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1607 /* set unique client identifier */
1608 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1609 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1610 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1611 ip->hw_address.hlen : sizeof(client_ident)-1;
1612 client_ident[0] = ip->hw_address.htype;
1613 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1614 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1615 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1616 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1617 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1618 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1621 /* Set up the option buffer... */
1622 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1623 options, 0, 0, 0, NULL, 0);
1624 if (ip->client->packet_length < BOOTP_MIN_LEN)
1625 ip->client->packet_length = BOOTP_MIN_LEN;
1627 ip->client->packet.op = BOOTREQUEST;
1628 ip->client->packet.htype = ip->hw_address.htype;
1629 ip->client->packet.hlen = ip->hw_address.hlen;
1630 ip->client->packet.hops = 0;
1631 ip->client->packet.xid = arc4random();
1632 ip->client->packet.secs = 0; /* filled in by send_discover. */
1633 ip->client->packet.flags = 0;
1635 memset(&(ip->client->packet.ciaddr),
1636 0, sizeof(ip->client->packet.ciaddr));
1637 memset(&(ip->client->packet.yiaddr),
1638 0, sizeof(ip->client->packet.yiaddr));
1639 memset(&(ip->client->packet.siaddr),
1640 0, sizeof(ip->client->packet.siaddr));
1641 memset(&(ip->client->packet.giaddr),
1642 0, sizeof(ip->client->packet.giaddr));
1643 memcpy(ip->client->packet.chaddr,
1644 ip->hw_address.haddr, ip->hw_address.hlen);
1649 make_request(struct interface_info *ip, struct client_lease * lease)
1651 unsigned char request = DHCPREQUEST;
1652 struct tree_cache *options[256];
1653 struct tree_cache option_elements[256];
1656 memset(options, 0, sizeof(options));
1657 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1659 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1660 i = DHO_DHCP_MESSAGE_TYPE;
1661 options[i] = &option_elements[i];
1662 options[i]->value = &request;
1663 options[i]->len = sizeof(request);
1664 options[i]->buf_size = sizeof(request);
1665 options[i]->timeout = 0xFFFFFFFF;
1667 /* Request the options we want */
1668 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1669 options[i] = &option_elements[i];
1670 options[i]->value = ip->client->config->requested_options;
1671 options[i]->len = ip->client->config->requested_option_count;
1672 options[i]->buf_size =
1673 ip->client->config->requested_option_count;
1674 options[i]->timeout = 0xFFFFFFFF;
1676 /* If we are requesting an address that hasn't yet been assigned
1677 to us, use the DHCP Requested Address option. */
1678 if (ip->client->state == S_REQUESTING) {
1679 /* Send back the server identifier... */
1680 i = DHO_DHCP_SERVER_IDENTIFIER;
1681 options[i] = &option_elements[i];
1682 options[i]->value = lease->options[i].data;
1683 options[i]->len = lease->options[i].len;
1684 options[i]->buf_size = lease->options[i].len;
1685 options[i]->timeout = 0xFFFFFFFF;
1687 if (ip->client->state == S_REQUESTING ||
1688 ip->client->state == S_REBOOTING) {
1689 ip->client->requested_address = lease->address;
1690 i = DHO_DHCP_REQUESTED_ADDRESS;
1691 options[i] = &option_elements[i];
1692 options[i]->value = lease->address.iabuf;
1693 options[i]->len = lease->address.len;
1694 options[i]->buf_size = lease->address.len;
1695 options[i]->timeout = 0xFFFFFFFF;
1697 ip->client->requested_address.len = 0;
1699 /* Send any options requested in the config file. */
1700 for (i = 0; i < 256; i++)
1702 ip->client->config->send_options[i].data) {
1703 options[i] = &option_elements[i];
1705 ip->client->config->send_options[i].data;
1707 ip->client->config->send_options[i].len;
1708 options[i]->buf_size =
1709 ip->client->config->send_options[i].len;
1710 options[i]->timeout = 0xFFFFFFFF;
1713 /* send host name if not set via config file. */
1714 if (!options[DHO_HOST_NAME]) {
1715 if (hostname[0] != '\0') {
1717 char* posDot = strchr(hostname, '.');
1719 len = posDot - hostname;
1721 len = strlen(hostname);
1722 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1723 options[DHO_HOST_NAME]->value = hostname;
1724 options[DHO_HOST_NAME]->len = len;
1725 options[DHO_HOST_NAME]->buf_size = len;
1726 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1730 /* set unique client identifier */
1731 char client_ident[sizeof(struct hardware)];
1732 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1733 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1734 ip->hw_address.hlen : sizeof(client_ident)-1;
1735 client_ident[0] = ip->hw_address.htype;
1736 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1737 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1738 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1739 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1740 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1741 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1744 /* Set up the option buffer... */
1745 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1746 options, 0, 0, 0, NULL, 0);
1747 if (ip->client->packet_length < BOOTP_MIN_LEN)
1748 ip->client->packet_length = BOOTP_MIN_LEN;
1750 ip->client->packet.op = BOOTREQUEST;
1751 ip->client->packet.htype = ip->hw_address.htype;
1752 ip->client->packet.hlen = ip->hw_address.hlen;
1753 ip->client->packet.hops = 0;
1754 ip->client->packet.xid = ip->client->xid;
1755 ip->client->packet.secs = 0; /* Filled in by send_request. */
1757 /* If we own the address we're requesting, put it in ciaddr;
1758 otherwise set ciaddr to zero. */
1759 if (ip->client->state == S_BOUND ||
1760 ip->client->state == S_RENEWING ||
1761 ip->client->state == S_REBINDING) {
1762 memcpy(&ip->client->packet.ciaddr,
1763 lease->address.iabuf, lease->address.len);
1764 ip->client->packet.flags = 0;
1766 memset(&ip->client->packet.ciaddr, 0,
1767 sizeof(ip->client->packet.ciaddr));
1768 ip->client->packet.flags = 0;
1771 memset(&ip->client->packet.yiaddr, 0,
1772 sizeof(ip->client->packet.yiaddr));
1773 memset(&ip->client->packet.siaddr, 0,
1774 sizeof(ip->client->packet.siaddr));
1775 memset(&ip->client->packet.giaddr, 0,
1776 sizeof(ip->client->packet.giaddr));
1777 memcpy(ip->client->packet.chaddr,
1778 ip->hw_address.haddr, ip->hw_address.hlen);
1782 make_decline(struct interface_info *ip, struct client_lease *lease)
1784 struct tree_cache *options[256], message_type_tree;
1785 struct tree_cache requested_address_tree;
1786 struct tree_cache server_id_tree, client_id_tree;
1787 unsigned char decline = DHCPDECLINE;
1790 memset(options, 0, sizeof(options));
1791 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1793 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1794 i = DHO_DHCP_MESSAGE_TYPE;
1795 options[i] = &message_type_tree;
1796 options[i]->value = &decline;
1797 options[i]->len = sizeof(decline);
1798 options[i]->buf_size = sizeof(decline);
1799 options[i]->timeout = 0xFFFFFFFF;
1801 /* Send back the server identifier... */
1802 i = DHO_DHCP_SERVER_IDENTIFIER;
1803 options[i] = &server_id_tree;
1804 options[i]->value = lease->options[i].data;
1805 options[i]->len = lease->options[i].len;
1806 options[i]->buf_size = lease->options[i].len;
1807 options[i]->timeout = 0xFFFFFFFF;
1809 /* Send back the address we're declining. */
1810 i = DHO_DHCP_REQUESTED_ADDRESS;
1811 options[i] = &requested_address_tree;
1812 options[i]->value = lease->address.iabuf;
1813 options[i]->len = lease->address.len;
1814 options[i]->buf_size = lease->address.len;
1815 options[i]->timeout = 0xFFFFFFFF;
1817 /* Send the uid if the user supplied one. */
1818 i = DHO_DHCP_CLIENT_IDENTIFIER;
1819 if (ip->client->config->send_options[i].len) {
1820 options[i] = &client_id_tree;
1821 options[i]->value = ip->client->config->send_options[i].data;
1822 options[i]->len = ip->client->config->send_options[i].len;
1823 options[i]->buf_size = ip->client->config->send_options[i].len;
1824 options[i]->timeout = 0xFFFFFFFF;
1828 /* Set up the option buffer... */
1829 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1830 options, 0, 0, 0, NULL, 0);
1831 if (ip->client->packet_length < BOOTP_MIN_LEN)
1832 ip->client->packet_length = BOOTP_MIN_LEN;
1834 ip->client->packet.op = BOOTREQUEST;
1835 ip->client->packet.htype = ip->hw_address.htype;
1836 ip->client->packet.hlen = ip->hw_address.hlen;
1837 ip->client->packet.hops = 0;
1838 ip->client->packet.xid = ip->client->xid;
1839 ip->client->packet.secs = 0; /* Filled in by send_request. */
1840 ip->client->packet.flags = 0;
1842 /* ciaddr must always be zero. */
1843 memset(&ip->client->packet.ciaddr, 0,
1844 sizeof(ip->client->packet.ciaddr));
1845 memset(&ip->client->packet.yiaddr, 0,
1846 sizeof(ip->client->packet.yiaddr));
1847 memset(&ip->client->packet.siaddr, 0,
1848 sizeof(ip->client->packet.siaddr));
1849 memset(&ip->client->packet.giaddr, 0,
1850 sizeof(ip->client->packet.giaddr));
1851 memcpy(ip->client->packet.chaddr,
1852 ip->hw_address.haddr, ip->hw_address.hlen);
1856 free_client_lease(struct client_lease *lease)
1860 if (lease->server_name)
1861 free(lease->server_name);
1862 if (lease->filename)
1863 free(lease->filename);
1864 for (i = 0; i < 256; i++) {
1865 if (lease->options[i].len)
1866 free(lease->options[i].data);
1874 rewrite_client_leases(void)
1876 struct client_lease *lp;
1877 cap_rights_t rights;
1880 leaseFile = fopen(path_dhclient_db, "w");
1882 error("can't create %s: %m", path_dhclient_db);
1883 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1884 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1885 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1887 error("can't limit lease descriptor: %m");
1889 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1891 error("can't limit lease descriptor fcntls: %m");
1898 for (lp = ifi->client->leases; lp; lp = lp->next)
1899 write_client_lease(ifi, lp, 1);
1900 if (ifi->client->active)
1901 write_client_lease(ifi, ifi->client->active, 1);
1904 ftruncate(fileno(leaseFile), ftello(leaseFile));
1905 fsync(fileno(leaseFile));
1909 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1912 static int leases_written;
1917 if (leases_written++ > 20) {
1918 rewrite_client_leases();
1923 /* If the lease came from the config file, we don't need to stash
1924 a copy in the lease database. */
1925 if (lease->is_static)
1928 if (!leaseFile) { /* XXX */
1929 leaseFile = fopen(path_dhclient_db, "w");
1931 error("can't create %s: %m", path_dhclient_db);
1934 fprintf(leaseFile, "lease {\n");
1935 if (lease->is_bootp)
1936 fprintf(leaseFile, " bootp;\n");
1937 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1938 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1939 if (lease->nextserver.len == sizeof(inaddr_any) &&
1940 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1941 sizeof(inaddr_any)))
1942 fprintf(leaseFile, " next-server %s;\n",
1943 piaddr(lease->nextserver));
1944 if (lease->filename)
1945 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1946 if (lease->server_name)
1947 fprintf(leaseFile, " server-name \"%s\";\n",
1948 lease->server_name);
1950 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1951 for (i = 0; i < 256; i++)
1952 if (lease->options[i].len)
1953 fprintf(leaseFile, " option %s %s;\n",
1954 dhcp_options[i].name,
1955 pretty_print_option(i, lease->options[i].data,
1956 lease->options[i].len, 1, 1));
1958 t = gmtime(&lease->renewal);
1959 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1960 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1961 t->tm_hour, t->tm_min, t->tm_sec);
1962 t = gmtime(&lease->rebind);
1963 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1964 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1965 t->tm_hour, t->tm_min, t->tm_sec);
1966 t = gmtime(&lease->expiry);
1967 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1968 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1969 t->tm_hour, t->tm_min, t->tm_sec);
1970 fprintf(leaseFile, "}\n");
1975 script_init(const char *reason, struct string_list *medium)
1977 size_t len, mediumlen = 0;
1978 struct imsg_hdr hdr;
1982 if (medium != NULL && medium->string != NULL)
1983 mediumlen = strlen(medium->string);
1985 hdr.code = IMSG_SCRIPT_INIT;
1986 hdr.len = sizeof(struct imsg_hdr) +
1987 sizeof(size_t) + mediumlen +
1988 sizeof(size_t) + strlen(reason);
1990 if ((buf = buf_open(hdr.len)) == NULL)
1991 error("buf_open: %m");
1994 errs += buf_add(buf, &hdr, sizeof(hdr));
1995 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1997 errs += buf_add(buf, medium->string, mediumlen);
1998 len = strlen(reason);
1999 errs += buf_add(buf, &len, sizeof(len));
2000 errs += buf_add(buf, reason, len);
2003 error("buf_add: %m");
2005 if (buf_close(privfd, buf) == -1)
2006 error("buf_close: %m");
2010 priv_script_init(const char *reason, char *medium)
2012 struct interface_info *ip = ifi;
2015 ip->client->scriptEnvsize = 100;
2016 if (ip->client->scriptEnv == NULL)
2017 ip->client->scriptEnv =
2018 malloc(ip->client->scriptEnvsize * sizeof(char *));
2019 if (ip->client->scriptEnv == NULL)
2020 error("script_init: no memory for environment");
2022 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2023 if (ip->client->scriptEnv[0] == NULL)
2024 error("script_init: no memory for environment");
2026 ip->client->scriptEnv[1] = NULL;
2028 script_set_env(ip->client, "", "interface", ip->name);
2031 script_set_env(ip->client, "", "medium", medium);
2033 script_set_env(ip->client, "", "reason", reason);
2038 priv_script_write_params(const char *prefix, struct client_lease *lease)
2040 struct interface_info *ip = ifi;
2041 u_int8_t dbuf[1500], *dp = NULL;
2046 script_set_env(ip->client, prefix, "ip_address",
2047 piaddr(lease->address));
2049 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2051 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2052 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2054 dp = lease->options[DHO_SUBNET_MASK].data;
2055 len = lease->options[DHO_SUBNET_MASK].len;
2057 if (len && (len < sizeof(lease->address.iabuf))) {
2058 struct iaddr netmask, subnet, broadcast;
2060 memcpy(netmask.iabuf, dp, len);
2062 subnet = subnet_number(lease->address, netmask);
2064 script_set_env(ip->client, prefix, "network_number",
2066 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2067 broadcast = broadcast_addr(subnet, netmask);
2069 script_set_env(ip->client, prefix,
2070 "broadcast_address",
2076 if (lease->filename)
2077 script_set_env(ip->client, prefix, "filename", lease->filename);
2078 if (lease->server_name)
2079 script_set_env(ip->client, prefix, "server_name",
2080 lease->server_name);
2081 for (i = 0; i < 256; i++) {
2084 if (ip->client->config->defaults[i].len) {
2085 if (lease->options[i].len) {
2087 ip->client->config->default_actions[i]) {
2088 case ACTION_DEFAULT:
2089 dp = lease->options[i].data;
2090 len = lease->options[i].len;
2092 case ACTION_SUPERSEDE:
2095 config->defaults[i].data;
2097 config->defaults[i].len;
2099 case ACTION_PREPEND:
2101 config->defaults[i].len +
2102 lease->options[i].len;
2103 if (len >= sizeof(dbuf)) {
2104 warning("no space to %s %s",
2106 dhcp_options[i].name);
2112 config->defaults[i].data,
2114 config->defaults[i].len);
2115 memcpy(dp + ip->client->
2116 config->defaults[i].len,
2117 lease->options[i].data,
2118 lease->options[i].len);
2123 * When we append, we assume that we're
2124 * appending to text. Some MS servers
2125 * include a NUL byte at the end of
2126 * the search string provided.
2129 config->defaults[i].len +
2130 lease->options[i].len;
2131 if (len >= sizeof(dbuf)) {
2132 warning("no space to %s %s",
2134 dhcp_options[i].name);
2138 lease->options[i].data,
2139 lease->options[i].len);
2140 for (dp = dbuf + lease->options[i].len;
2141 dp > dbuf; dp--, len--)
2146 config->defaults[i].data,
2148 config->defaults[i].len);
2154 config->defaults[i].data;
2156 config->defaults[i].len;
2158 } else if (lease->options[i].len) {
2159 len = lease->options[i].len;
2160 dp = lease->options[i].data;
2167 if (dhcp_option_ev_name(name, sizeof(name),
2169 script_set_env(ip->client, prefix, name,
2170 pretty_print_option(i, dp, len, 0, 0));
2173 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2174 script_set_env(ip->client, prefix, "expiry", tbuf);
2178 script_write_params(const char *prefix, struct client_lease *lease)
2180 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2181 struct imsg_hdr hdr;
2185 if (lease->filename != NULL)
2186 fn_len = strlen(lease->filename);
2187 if (lease->server_name != NULL)
2188 sn_len = strlen(lease->server_name);
2190 pr_len = strlen(prefix);
2192 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2193 hdr.len = sizeof(hdr) + sizeof(*lease) +
2194 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2195 sizeof(pr_len) + pr_len;
2197 for (i = 0; i < 256; i++) {
2198 hdr.len += sizeof(lease->options[i].len);
2199 hdr.len += lease->options[i].len;
2202 scripttime = time(NULL);
2204 if ((buf = buf_open(hdr.len)) == NULL)
2205 error("buf_open: %m");
2208 errs += buf_add(buf, &hdr, sizeof(hdr));
2209 errs += buf_add(buf, lease, sizeof(*lease));
2210 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2211 errs += buf_add(buf, lease->filename, fn_len);
2212 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2213 errs += buf_add(buf, lease->server_name, sn_len);
2214 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2215 errs += buf_add(buf, prefix, pr_len);
2217 for (i = 0; i < 256; i++) {
2218 errs += buf_add(buf, &lease->options[i].len,
2219 sizeof(lease->options[i].len));
2220 errs += buf_add(buf, lease->options[i].data,
2221 lease->options[i].len);
2225 error("buf_add: %m");
2227 if (buf_close(privfd, buf) == -1)
2228 error("buf_close: %m");
2234 struct imsg_hdr hdr;
2238 hdr.code = IMSG_SCRIPT_GO;
2239 hdr.len = sizeof(struct imsg_hdr);
2241 if ((buf = buf_open(hdr.len)) == NULL)
2242 error("buf_open: %m");
2244 if (buf_add(buf, &hdr, sizeof(hdr)))
2245 error("buf_add: %m");
2247 if (buf_close(privfd, buf) == -1)
2248 error("buf_close: %m");
2250 bzero(&hdr, sizeof(hdr));
2251 buf_read(privfd, &hdr, sizeof(hdr));
2252 if (hdr.code != IMSG_SCRIPT_GO_RET)
2253 error("unexpected msg type %u", hdr.code);
2254 if (hdr.len != sizeof(hdr) + sizeof(int))
2255 error("received corrupted message");
2256 buf_read(privfd, &ret, sizeof(ret));
2258 scripttime = time(NULL);
2264 priv_script_go(void)
2266 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2267 static char client_path[] = CLIENT_PATH;
2268 struct interface_info *ip = ifi;
2269 int pid, wpid, wstatus;
2271 scripttime = time(NULL);
2274 scriptName = ip->client->config->script_name;
2275 envp = ip->client->scriptEnv;
2277 scriptName = top_level_config.script_name;
2279 epp[1] = client_path;
2284 argv[0] = scriptName;
2293 wpid = wait(&wstatus);
2294 } while (wpid != pid && wpid > 0);
2300 execve(scriptName, argv, envp);
2301 error("execve (%s, ...): %m", scriptName);
2305 script_flush_env(ip->client);
2307 return (wstatus & 0xff);
2311 script_set_env(struct client_state *client, const char *prefix,
2312 const char *name, const char *value)
2317 /* No `` or $() command substitution allowed in environment values! */
2318 for (j=0; j < strlen(value); j++)
2322 warning("illegal character (%c) in value '%s'",
2324 /* Ignore this option */
2328 namelen = strlen(name);
2330 for (i = 0; client->scriptEnv[i]; i++)
2331 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2332 client->scriptEnv[i][namelen] == '=')
2335 if (client->scriptEnv[i])
2336 /* Reuse the slot. */
2337 free(client->scriptEnv[i]);
2339 /* New variable. Expand if necessary. */
2340 if (i >= client->scriptEnvsize - 1) {
2341 char **newscriptEnv;
2342 int newscriptEnvsize = client->scriptEnvsize + 50;
2344 newscriptEnv = realloc(client->scriptEnv,
2346 if (newscriptEnv == NULL) {
2347 free(client->scriptEnv);
2348 client->scriptEnv = NULL;
2349 client->scriptEnvsize = 0;
2350 error("script_set_env: no memory for variable");
2352 client->scriptEnv = newscriptEnv;
2353 client->scriptEnvsize = newscriptEnvsize;
2355 /* need to set the NULL pointer at end of array beyond
2357 client->scriptEnv[i + 1] = NULL;
2359 /* Allocate space and format the variable in the appropriate slot. */
2360 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2362 if (client->scriptEnv[i] == NULL)
2363 error("script_set_env: no memory for variable assignment");
2364 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2365 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2369 script_flush_env(struct client_state *client)
2373 for (i = 0; client->scriptEnv[i]; i++) {
2374 free(client->scriptEnv[i]);
2375 client->scriptEnv[i] = NULL;
2377 client->scriptEnvsize = 0;
2381 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2385 for (i = 0; option->name[i]; i++) {
2386 if (i + 1 == buflen)
2388 if (option->name[i] == '-')
2391 buf[i] = option->name[i];
2401 static int state = 0;
2402 cap_rights_t rights;
2404 if (no_daemon || state)
2409 /* Stop logging to stderr... */
2412 if (daemon(1, 0) == -1)
2415 cap_rights_init(&rights);
2417 if (pidfile != NULL) {
2418 pidfile_write(pidfile);
2419 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2421 error("can't limit pidfile descriptor: %m");
2425 /* we are chrooted, daemon(3) fails to open /dev/null */
2427 dup2(nullfd, STDIN_FILENO);
2428 dup2(nullfd, STDOUT_FILENO);
2429 dup2(nullfd, STDERR_FILENO);
2434 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2435 error("can't limit stdin: %m");
2436 cap_rights_init(&rights, CAP_WRITE);
2437 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2438 error("can't limit stdout: %m");
2439 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2440 error("can't limit stderr: %m");
2444 check_option(struct client_lease *l, int option)
2449 /* we use this, since this is what gets passed to dhclient-script */
2451 opbuf = pretty_print_option(option, l->options[option].data,
2452 l->options[option].len, 0, 0);
2454 sbuf = option_as_string(option, l->options[option].data,
2455 l->options[option].len);
2458 case DHO_SUBNET_MASK:
2459 case DHO_TIME_SERVERS:
2460 case DHO_NAME_SERVERS:
2462 case DHO_DOMAIN_NAME_SERVERS:
2463 case DHO_LOG_SERVERS:
2464 case DHO_COOKIE_SERVERS:
2465 case DHO_LPR_SERVERS:
2466 case DHO_IMPRESS_SERVERS:
2467 case DHO_RESOURCE_LOCATION_SERVERS:
2468 case DHO_SWAP_SERVER:
2469 case DHO_BROADCAST_ADDRESS:
2470 case DHO_NIS_SERVERS:
2471 case DHO_NTP_SERVERS:
2472 case DHO_NETBIOS_NAME_SERVERS:
2473 case DHO_NETBIOS_DD_SERVER:
2474 case DHO_FONT_SERVERS:
2475 case DHO_DHCP_SERVER_IDENTIFIER:
2476 case DHO_NISPLUS_SERVERS:
2477 case DHO_MOBILE_IP_HOME_AGENT:
2478 case DHO_SMTP_SERVER:
2479 case DHO_POP_SERVER:
2480 case DHO_NNTP_SERVER:
2481 case DHO_WWW_SERVER:
2482 case DHO_FINGER_SERVER:
2483 case DHO_IRC_SERVER:
2484 case DHO_STREETTALK_SERVER:
2485 case DHO_STREETTALK_DA_SERVER:
2486 if (!ipv4addrs(opbuf)) {
2487 warning("Invalid IP address in option: %s", opbuf);
2492 case DHO_NIS_DOMAIN:
2493 case DHO_NISPLUS_DOMAIN:
2494 case DHO_TFTP_SERVER_NAME:
2495 if (!res_hnok(sbuf)) {
2496 warning("Bogus Host Name option %d: %s (%s)", option,
2498 l->options[option].len = 0;
2499 free(l->options[option].data);
2502 case DHO_DOMAIN_NAME:
2503 case DHO_DOMAIN_SEARCH:
2504 if (!res_hnok(sbuf)) {
2505 if (!check_search(sbuf)) {
2506 warning("Bogus domain search list %d: %s (%s)",
2507 option, sbuf, opbuf);
2508 l->options[option].len = 0;
2509 free(l->options[option].data);
2514 case DHO_TIME_OFFSET:
2516 case DHO_MERIT_DUMP:
2518 case DHO_EXTENSIONS_PATH:
2519 case DHO_IP_FORWARDING:
2520 case DHO_NON_LOCAL_SOURCE_ROUTING:
2521 case DHO_POLICY_FILTER:
2522 case DHO_MAX_DGRAM_REASSEMBLY:
2523 case DHO_DEFAULT_IP_TTL:
2524 case DHO_PATH_MTU_AGING_TIMEOUT:
2525 case DHO_PATH_MTU_PLATEAU_TABLE:
2526 case DHO_INTERFACE_MTU:
2527 case DHO_ALL_SUBNETS_LOCAL:
2528 case DHO_PERFORM_MASK_DISCOVERY:
2529 case DHO_MASK_SUPPLIER:
2530 case DHO_ROUTER_DISCOVERY:
2531 case DHO_ROUTER_SOLICITATION_ADDRESS:
2532 case DHO_STATIC_ROUTES:
2533 case DHO_TRAILER_ENCAPSULATION:
2534 case DHO_ARP_CACHE_TIMEOUT:
2535 case DHO_IEEE802_3_ENCAPSULATION:
2536 case DHO_DEFAULT_TCP_TTL:
2537 case DHO_TCP_KEEPALIVE_INTERVAL:
2538 case DHO_TCP_KEEPALIVE_GARBAGE:
2539 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2540 case DHO_NETBIOS_NODE_TYPE:
2541 case DHO_NETBIOS_SCOPE:
2542 case DHO_X_DISPLAY_MANAGER:
2543 case DHO_DHCP_REQUESTED_ADDRESS:
2544 case DHO_DHCP_LEASE_TIME:
2545 case DHO_DHCP_OPTION_OVERLOAD:
2546 case DHO_DHCP_MESSAGE_TYPE:
2547 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2548 case DHO_DHCP_MESSAGE:
2549 case DHO_DHCP_MAX_MESSAGE_SIZE:
2550 case DHO_DHCP_RENEWAL_TIME:
2551 case DHO_DHCP_REBINDING_TIME:
2552 case DHO_DHCP_CLASS_IDENTIFIER:
2553 case DHO_DHCP_CLIENT_IDENTIFIER:
2554 case DHO_BOOTFILE_NAME:
2555 case DHO_DHCP_USER_CLASS_ID:
2558 case DHO_CLASSLESS_ROUTES:
2559 return (check_classless_option(l->options[option].data,
2560 l->options[option].len));
2562 warning("unknown dhcp option value 0x%x", option);
2563 return (unknown_ok);
2567 /* RFC 3442 The Classless Static Routes option checks */
2569 check_classless_option(unsigned char *data, int len)
2572 unsigned char width;
2573 in_addr_t addr, mask;
2576 warning("Too small length: %d", len);
2584 } else if (width < 9) {
2585 addr = (in_addr_t)(data[i] << 24);
2587 } else if (width < 17) {
2588 addr = (in_addr_t)(data[i] << 24) +
2589 (in_addr_t)(data[i + 1] << 16);
2591 } else if (width < 25) {
2592 addr = (in_addr_t)(data[i] << 24) +
2593 (in_addr_t)(data[i + 1] << 16) +
2594 (in_addr_t)(data[i + 2] << 8);
2596 } else if (width < 33) {
2597 addr = (in_addr_t)(data[i] << 24) +
2598 (in_addr_t)(data[i + 1] << 16) +
2599 (in_addr_t)(data[i + 2] << 8) +
2603 warning("Incorrect subnet width: %d", width);
2606 mask = (in_addr_t)(~0) << (32 - width);
2612 * ... After deriving a subnet number and subnet mask
2613 * from each destination descriptor, the DHCP client
2614 * MUST zero any bits in the subnet number where the
2615 * corresponding bit in the mask is zero...
2617 if ((addr & mask) != addr) {
2619 data[i - 1] = (unsigned char)(
2620 (addr >> (((32 - width)/8)*8)) & 0xFF);
2625 warning("Incorrect data length: %d (must be %d)", len, i);
2632 res_hnok(const char *dn)
2634 int pch = PERIOD, ch = *dn++;
2636 while (ch != '\0') {
2639 if (periodchar(ch)) {
2641 } else if (periodchar(pch)) {
2642 if (!borderchar(ch))
2644 } else if (periodchar(nch) || nch == '\0') {
2645 if (!borderchar(ch))
2648 if (!middlechar(ch))
2657 check_search(const char *srch)
2659 int pch = PERIOD, ch = *srch++;
2662 /* 256 char limit re resolv.conf(5) */
2663 if (strlen(srch) > 256)
2666 while (whitechar(ch))
2669 while (ch != '\0') {
2672 if (periodchar(ch) || whitechar(ch)) {
2674 } else if (periodchar(pch)) {
2675 if (!borderchar(ch))
2677 } else if (periodchar(nch) || nch == '\0') {
2678 if (!borderchar(ch))
2681 if (!middlechar(ch))
2684 if (!whitechar(ch)) {
2687 while (whitechar(nch)) {
2696 /* 6 domain limit re resolv.conf(5) */
2702 /* Does buf consist only of dotted decimal ipv4 addrs?
2703 * return how many if so,
2704 * otherwise, return 0
2707 ipv4addrs(const char * buf)
2712 while (inet_aton(buf, &jnk) == 1){
2714 while (periodchar(*buf) || digitchar(*buf))
2726 option_as_string(unsigned int code, unsigned char *data, int len)
2728 static char optbuf[32768]; /* XXX */
2730 int opleft = sizeof(optbuf);
2731 unsigned char *dp = data;
2734 error("option_as_string: bad code %d", code);
2736 for (; dp < data + len; dp++) {
2737 if (!isascii(*dp) || !isprint(*dp)) {
2738 if (dp + 1 != data + len || *dp != 0) {
2739 snprintf(op, opleft, "\\%03o", *dp);
2743 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2744 *dp == '`' || *dp == '\\') {
2758 warning("dhcp option too large");
2763 fork_privchld(int fd, int fd2)
2765 struct pollfd pfd[1];
2770 error("cannot fork");
2777 setproctitle("%s [priv]", ifi->name);
2780 dup2(nullfd, STDIN_FILENO);
2781 dup2(nullfd, STDOUT_FILENO);
2782 dup2(nullfd, STDERR_FILENO);
2790 pfd[0].events = POLLIN;
2791 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2793 error("poll error");
2795 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2798 dispatch_imsg(ifi, fd);