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 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(char * buf);
131 int res_hnok(const char *dn);
132 int check_search(const char *srch);
133 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_",
214 ifi->client->state = S_INIT;
219 routehandler(struct protocol *p)
221 char msg[2048], *addr;
222 struct rt_msghdr *rtm;
223 struct if_msghdr *ifm;
224 struct ifa_msghdr *ifam;
225 struct if_announcemsghdr *ifan;
226 struct ieee80211_join_event *jev;
227 struct client_lease *l;
228 time_t t = time(NULL);
234 n = read(routefd, &msg, sizeof(msg));
235 rtm = (struct rt_msghdr *)msg;
236 if (n < (ssize_t)sizeof(rtm->rtm_msglen) ||
237 n < (ssize_t)rtm->rtm_msglen ||
238 rtm->rtm_version != RTM_VERSION)
241 switch (rtm->rtm_type) {
244 ifam = (struct ifa_msghdr *)rtm;
246 if (ifam->ifam_index != ifi->index)
248 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
250 if (scripttime == 0 || t < scripttime + 10)
253 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
257 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
258 error("king bula sez: len mismatch");
259 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
260 if (addr_eq(a, defaddr))
263 for (l = ifi->client->active; l != NULL; l = l->next)
264 if (addr_eq(a, l->address))
267 if (l == NULL) /* added/deleted addr is not the one we set */
270 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
271 if (rtm->rtm_type == RTM_NEWADDR) {
273 * XXX: If someone other than us adds our address,
274 * should we assume they are taking over from us,
275 * delete the lease record, and exit without modifying
278 warning("My address (%s) was re-added", addr);
280 warning("My address (%s) was deleted, dhclient exiting",
286 ifm = (struct if_msghdr *)rtm;
287 if (ifm->ifm_index != ifi->index)
289 if ((rtm->rtm_flags & RTF_UP) == 0) {
290 warning("Interface %s is down, dhclient exiting",
294 linkstat = interface_link_status(ifi->name);
295 if (linkstat != ifi->linkstat) {
296 debug("%s link state %s -> %s", ifi->name,
297 ifi->linkstat ? "up" : "down",
298 linkstat ? "up" : "down");
299 ifi->linkstat = linkstat;
305 ifan = (struct if_announcemsghdr *)rtm;
306 if (ifan->ifan_what == IFAN_DEPARTURE &&
307 ifan->ifan_index == ifi->index) {
308 warning("Interface %s is gone, dhclient exiting",
314 ifan = (struct if_announcemsghdr *)rtm;
315 if (ifan->ifan_index != ifi->index)
317 switch (ifan->ifan_what) {
318 case RTM_IEEE80211_ASSOC:
319 case RTM_IEEE80211_REASSOC:
321 * Use assoc/reassoc event to kick state machine
322 * in case we roam. Otherwise fall back to the
323 * normal state machine just like a wired network.
325 jev = (struct ieee80211_join_event *) &ifan[1];
326 if (memcmp(curbssid, jev->iev_addr, 6)) {
330 memcpy(curbssid, jev->iev_addr, 6);
340 script_init("FAIL", NULL);
341 if (ifi->client->alias)
342 script_write_params("alias_", ifi->client->alias);
345 pidfile_remove(pidfile);
350 main(int argc, char *argv[])
352 extern char *__progname;
353 int ch, fd, quiet = 0, i = 0;
355 int immediate_daemon = 0;
360 /* Initially, log errors to stderr as well as to syslogd. */
361 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
362 setlogmask(LOG_UPTO(LOG_DEBUG));
364 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
367 immediate_daemon = 1;
370 path_dhclient_conf = optarg;
376 path_dhclient_db = optarg;
379 path_dhclient_pidfile = optarg;
397 if (path_dhclient_pidfile == NULL) {
398 asprintf(&path_dhclient_pidfile,
399 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
400 if (path_dhclient_pidfile == NULL)
403 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
404 if (pidfile == NULL) {
406 error("dhclient already running, pid: %d.", otherpid);
408 error("dhclient already running.");
409 warning("Cannot open or create pidfile: %m");
412 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
414 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
415 error("Interface name too long");
416 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
417 _PATH_DHCLIENT_DB, ifi->name) == -1)
426 inaddr_broadcast.s_addr = INADDR_BROADCAST;
427 inaddr_any.s_addr = INADDR_ANY;
431 /* The next bit is potentially very time-consuming, so write out
432 the pidfile right away. We will write it out again with the
433 correct pid after daemonizing. */
435 pidfile_write(pidfile);
437 if (!interface_link_status(ifi->name)) {
438 fprintf(stderr, "%s: no link ...", ifi->name);
441 while (!interface_link_status(ifi->name)) {
442 fprintf(stderr, ".");
445 fprintf(stderr, " giving up\n");
450 fprintf(stderr, " got link\n");
454 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
455 error("cannot open %s: %m", _PATH_DEVNULL);
457 if ((pw = getpwnam("_dhcp")) == NULL) {
458 warning("no such user: _dhcp, falling back to \"nobody\"");
459 if ((pw = getpwnam("nobody")) == NULL)
460 error("no such user: nobody");
464 * Obtain hostname before entering capability mode - it won't be
465 * possible then, as reading kern.hostname is not permitted.
467 if (gethostname(hostname, sizeof(hostname)) < 0)
470 priv_script_init("PREINIT", NULL);
471 if (ifi->client->alias)
472 priv_script_write_params("alias_", ifi->client->alias);
475 /* set up the interface */
476 discover_interfaces(ifi);
478 if (pipe(pipe_fd) == -1)
481 fork_privchld(pipe_fd[0], pipe_fd[1]);
490 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
491 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
492 error("can't limit private descriptor: %m");
494 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
495 error("can't open and lock %s: %m", path_dhclient_db);
496 read_client_leases();
497 rewrite_client_leases();
500 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
501 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
502 if (shutdown(routefd, SHUT_WR) < 0)
503 error("can't shutdown route socket: %m");
504 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
505 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
506 error("can't limit route socket: %m");
508 if (chroot(_PATH_VAREMPTY) == -1)
510 if (chdir("/") == -1)
511 error("chdir(\"/\")");
513 if (setgroups(1, &pw->pw_gid) ||
514 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
515 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
516 error("can't drop privileges: %m");
520 setproctitle("%s", ifi->name);
522 if (cap_enter() < 0 && errno != ENOSYS)
523 error("can't enter capability mode: %m");
525 if (immediate_daemon)
528 ifi->client->state = S_INIT;
531 bootp_packet_handler = do_packet;
542 extern char *__progname;
544 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
545 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
552 * Each routine is called from the dhclient_state_machine() in one of
554 * -> entering INIT state
555 * -> recvpacket_flag == 0: timeout in this state
556 * -> otherwise: received a packet in this state
558 * Return conditions as handled by dhclient_state_machine():
559 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
560 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
561 * Returns 0: finish the nap which was interrupted for no good reason.
563 * Several per-interface variables are used to keep track of the process:
564 * active_lease: the lease that is being used on the interface
565 * (null pointer if not configured yet).
566 * offered_leases: leases corresponding to DHCPOFFER messages that have
567 * been sent to us by DHCP servers.
568 * acked_leases: leases corresponding to DHCPACK messages that have been
569 * sent to us by DHCP servers.
570 * sendpacket: DHCP packet we're trying to send.
571 * destination: IP address to send sendpacket to
572 * In addition, there are several relevant per-lease variables.
573 * T1_expiry, T2_expiry, lease_expiry: lease milestones
574 * In the active lease, these control the process of renewing the lease;
575 * In leases on the acked_leases list, this simply determines when we
576 * can no longer legitimately use the lease.
580 state_reboot(void *ipp)
582 struct interface_info *ip = ipp;
584 /* If we don't remember an active lease, go straight to INIT. */
585 if (!ip->client->active || ip->client->active->is_bootp) {
590 /* We are in the rebooting state. */
591 ip->client->state = S_REBOOTING;
593 /* make_request doesn't initialize xid because it normally comes
594 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
595 so pick an xid now. */
596 ip->client->xid = arc4random();
598 /* Make a DHCPREQUEST packet, and set appropriate per-interface
600 make_request(ip, ip->client->active);
601 ip->client->destination = iaddr_broadcast;
602 ip->client->first_sending = cur_time;
603 ip->client->interval = ip->client->config->initial_interval;
605 /* Zap the medium list... */
606 ip->client->medium = NULL;
608 /* Send out the first DHCPREQUEST packet. */
613 * Called when a lease has completely expired and we've
614 * been unable to renew it.
617 state_init(void *ipp)
619 struct interface_info *ip = ipp;
621 ASSERT_STATE(state, S_INIT);
623 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
625 make_discover(ip, ip->client->active);
626 ip->client->xid = ip->client->packet.xid;
627 ip->client->destination = iaddr_broadcast;
628 ip->client->state = S_SELECTING;
629 ip->client->first_sending = cur_time;
630 ip->client->interval = ip->client->config->initial_interval;
632 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
638 * state_selecting is called when one or more DHCPOFFER packets
639 * have been received and a configurable period of time has passed.
642 state_selecting(void *ipp)
644 struct interface_info *ip = ipp;
645 struct client_lease *lp, *next, *picked;
647 ASSERT_STATE(state, S_SELECTING);
649 /* Cancel state_selecting and send_discover timeouts, since either
650 one could have got us here. */
651 cancel_timeout(state_selecting, ip);
652 cancel_timeout(send_discover, ip);
654 /* We have received one or more DHCPOFFER packets. Currently,
655 the only criterion by which we judge leases is whether or
656 not we get a response when we arp for them. */
658 for (lp = ip->client->offered_leases; lp; lp = next) {
661 /* Check to see if we got an ARPREPLY for the address
662 in this particular lease. */
664 script_init("ARPCHECK", lp->medium);
665 script_write_params("check_", lp);
667 /* If the ARPCHECK code detects another
668 machine using the offered address, it exits
669 nonzero. We need to send a DHCPDECLINE and
672 make_decline(ip, lp);
680 free_client_lease(lp);
683 ip->client->offered_leases = NULL;
685 /* If we just tossed all the leases we were offered, go back
688 ip->client->state = S_INIT;
693 /* If it was a BOOTREPLY, we can just take the address right now. */
694 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
695 ip->client->new = picked;
697 /* Make up some lease expiry times
698 XXX these should be configurable. */
699 ip->client->new->expiry = cur_time + 12000;
700 ip->client->new->renewal += cur_time + 8000;
701 ip->client->new->rebind += cur_time + 10000;
703 ip->client->state = S_REQUESTING;
705 /* Bind to the address we received. */
710 /* Go to the REQUESTING state. */
711 ip->client->destination = iaddr_broadcast;
712 ip->client->state = S_REQUESTING;
713 ip->client->first_sending = cur_time;
714 ip->client->interval = ip->client->config->initial_interval;
716 /* Make a DHCPREQUEST packet from the lease we picked. */
717 make_request(ip, picked);
718 ip->client->xid = ip->client->packet.xid;
720 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
721 free_client_lease(picked);
723 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
727 /* state_requesting is called when we receive a DHCPACK message after
728 having sent out one or more DHCPREQUEST packets. */
731 dhcpack(struct packet *packet)
733 struct interface_info *ip = packet->interface;
734 struct client_lease *lease;
736 /* If we're not receptive to an offer right now, or if the offer
737 has an unrecognizable transaction id, then just drop it. */
738 if (packet->interface->client->xid != packet->raw->xid ||
739 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
740 (memcmp(packet->interface->hw_address.haddr,
741 packet->raw->chaddr, packet->raw->hlen)))
744 if (ip->client->state != S_REBOOTING &&
745 ip->client->state != S_REQUESTING &&
746 ip->client->state != S_RENEWING &&
747 ip->client->state != S_REBINDING)
750 note("DHCPACK from %s", piaddr(packet->client_addr));
752 lease = packet_to_lease(packet);
754 note("packet_to_lease failed.");
758 ip->client->new = lease;
760 /* Stop resending DHCPREQUEST. */
761 cancel_timeout(send_request, ip);
763 /* Figure out the lease time. */
764 if (ip->client->config->default_actions[DHO_DHCP_LEASE_TIME] ==
766 ip->client->new->expiry = getULong(
767 ip->client->config->defaults[DHO_DHCP_LEASE_TIME].data);
768 else if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
769 ip->client->new->expiry = getULong(
770 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
772 ip->client->new->expiry = default_lease_time;
773 /* A number that looks negative here is really just very large,
774 because the lease expiry offset is unsigned. Also make sure that
775 the addition of cur_time below does not overflow (a 32 bit) time_t. */
776 if (ip->client->new->expiry < 0 ||
777 ip->client->new->expiry > TIME_MAX - cur_time)
778 ip->client->new->expiry = TIME_MAX - cur_time;
779 /* XXX should be fixed by resetting the client state */
780 if (ip->client->new->expiry < 60)
781 ip->client->new->expiry = 60;
783 /* Unless overridden in the config, take the server-provided renewal
784 * time if there is one. Otherwise figure it out according to the spec.
785 * Also make sure the renewal time does not exceed the expiry time.
787 if (ip->client->config->default_actions[DHO_DHCP_RENEWAL_TIME] ==
789 ip->client->new->renewal = getULong(
790 ip->client->config->defaults[DHO_DHCP_RENEWAL_TIME].data);
791 else if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
792 ip->client->new->renewal = getULong(
793 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
795 ip->client->new->renewal = ip->client->new->expiry / 2;
796 if (ip->client->new->renewal < 0 ||
797 ip->client->new->renewal > ip->client->new->expiry / 2)
798 ip->client->new->renewal = ip->client->new->expiry / 2;
800 /* Same deal with the rebind time. */
801 if (ip->client->config->default_actions[DHO_DHCP_REBINDING_TIME] ==
803 ip->client->new->rebind = getULong(
804 ip->client->config->defaults[DHO_DHCP_REBINDING_TIME].data);
805 else if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
806 ip->client->new->rebind = getULong(
807 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
809 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
810 if (ip->client->new->rebind < 0 ||
811 ip->client->new->rebind > ip->client->new->renewal / 4 * 7)
812 ip->client->new->rebind = ip->client->new->renewal / 4 * 7;
814 /* Convert the time offsets into seconds-since-the-epoch */
815 ip->client->new->expiry += cur_time;
816 ip->client->new->renewal += cur_time;
817 ip->client->new->rebind += cur_time;
823 bind_lease(struct interface_info *ip)
825 struct option_data *opt;
827 /* Remember the medium. */
828 ip->client->new->medium = ip->client->medium;
830 opt = &ip->client->new->options[DHO_INTERFACE_MTU];
831 if (opt->len == sizeof(u_int16_t)) {
832 u_int16_t mtu = be16dec(opt->data);
834 warning("mtu size %u < %d: ignored", (unsigned)mtu, MIN_MTU);
836 interface_set_mtu_unpriv(privfd, mtu);
839 /* Write out the new lease. */
840 write_client_lease(ip, ip->client->new, 0);
842 /* Run the client script with the new parameters. */
843 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
844 (ip->client->state == S_RENEWING ? "RENEW" :
845 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
846 ip->client->new->medium);
847 if (ip->client->active && ip->client->state != S_REBOOTING)
848 script_write_params("old_", ip->client->active);
849 script_write_params("new_", ip->client->new);
850 if (ip->client->alias)
851 script_write_params("alias_", ip->client->alias);
854 /* Replace the old active lease with the new one. */
855 if (ip->client->active)
856 free_client_lease(ip->client->active);
857 ip->client->active = ip->client->new;
858 ip->client->new = NULL;
860 /* Set up a timeout to start the renewal process. */
861 add_timeout(ip->client->active->renewal, state_bound, ip);
863 note("bound to %s -- renewal in %d seconds.",
864 piaddr(ip->client->active->address),
865 (int)(ip->client->active->renewal - cur_time));
866 ip->client->state = S_BOUND;
867 reinitialize_interfaces();
872 * state_bound is called when we've successfully bound to a particular
873 * lease, but the renewal time on that lease has expired. We are
874 * expected to unicast a DHCPREQUEST to the server that gave us our
878 state_bound(void *ipp)
880 struct interface_info *ip = ipp;
882 ASSERT_STATE(state, S_BOUND);
884 /* T1 has expired. */
885 make_request(ip, ip->client->active);
886 ip->client->xid = ip->client->packet.xid;
888 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
889 memcpy(ip->client->destination.iabuf, ip->client->active->
890 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
891 ip->client->destination.len = 4;
893 ip->client->destination = iaddr_broadcast;
895 ip->client->first_sending = cur_time;
896 ip->client->interval = ip->client->config->initial_interval;
897 ip->client->state = S_RENEWING;
899 /* Send the first packet immediately. */
904 bootp(struct packet *packet)
906 struct iaddrlist *ap;
908 if (packet->raw->op != BOOTREPLY)
911 /* If there's a reject list, make sure this packet's sender isn't
913 for (ap = packet->interface->client->config->reject_list;
915 if (addr_eq(packet->client_addr, ap->addr)) {
916 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
924 dhcp(struct packet *packet)
926 struct iaddrlist *ap;
927 void (*handler)(struct packet *);
930 switch (packet->packet_type) {
947 /* If there's a reject list, make sure this packet's sender isn't
949 for (ap = packet->interface->client->config->reject_list;
951 if (addr_eq(packet->client_addr, ap->addr)) {
952 note("%s from %s rejected.", type, piaddr(ap->addr));
960 dhcpoffer(struct packet *packet)
962 struct interface_info *ip = packet->interface;
963 struct client_lease *lease, *lp;
965 int arp_timeout_needed, stop_selecting;
966 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
967 "DHCPOFFER" : "BOOTREPLY";
969 /* If we're not receptive to an offer right now, or if the offer
970 has an unrecognizable transaction id, then just drop it. */
971 if (ip->client->state != S_SELECTING ||
972 packet->interface->client->xid != packet->raw->xid ||
973 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
974 (memcmp(packet->interface->hw_address.haddr,
975 packet->raw->chaddr, packet->raw->hlen)))
978 note("%s from %s", name, piaddr(packet->client_addr));
981 /* If this lease doesn't supply the minimum required parameters,
983 for (i = 0; ip->client->config->required_options[i]; i++) {
984 if (!packet->options[ip->client->config->
985 required_options[i]].len) {
986 note("%s isn't satisfactory.", name);
991 /* If we've already seen this lease, don't record it again. */
992 for (lease = ip->client->offered_leases;
993 lease; lease = lease->next) {
994 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
995 !memcmp(lease->address.iabuf,
996 &packet->raw->yiaddr, lease->address.len)) {
997 debug("%s already seen.", name);
1002 lease = packet_to_lease(packet);
1004 note("packet_to_lease failed.");
1008 /* If this lease was acquired through a BOOTREPLY, record that
1010 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
1011 lease->is_bootp = 1;
1013 /* Record the medium under which this lease was offered. */
1014 lease->medium = ip->client->medium;
1016 /* Send out an ARP Request for the offered IP address. */
1017 script_init("ARPSEND", lease->medium);
1018 script_write_params("check_", lease);
1019 /* If the script can't send an ARP request without waiting,
1020 we'll be waiting when we do the ARPCHECK, so don't wait now. */
1022 arp_timeout_needed = 0;
1024 arp_timeout_needed = 2;
1026 /* Figure out when we're supposed to stop selecting. */
1028 ip->client->first_sending + ip->client->config->select_interval;
1030 /* If this is the lease we asked for, put it at the head of the
1031 list, and don't mess with the arp request timeout. */
1032 if (lease->address.len == ip->client->requested_address.len &&
1033 !memcmp(lease->address.iabuf,
1034 ip->client->requested_address.iabuf,
1035 ip->client->requested_address.len)) {
1036 lease->next = ip->client->offered_leases;
1037 ip->client->offered_leases = lease;
1039 /* If we already have an offer, and arping for this
1040 offer would take us past the selection timeout,
1041 then don't extend the timeout - just hope for the
1043 if (ip->client->offered_leases &&
1044 (cur_time + arp_timeout_needed) > stop_selecting)
1045 arp_timeout_needed = 0;
1047 /* Put the lease at the end of the list. */
1049 if (!ip->client->offered_leases)
1050 ip->client->offered_leases = lease;
1052 for (lp = ip->client->offered_leases; lp->next;
1059 /* If we're supposed to stop selecting before we've had time
1060 to wait for the ARPREPLY, add some delay to wait for
1062 if (stop_selecting - cur_time < arp_timeout_needed)
1063 stop_selecting = cur_time + arp_timeout_needed;
1065 /* If the selecting interval has expired, go immediately to
1066 state_selecting(). Otherwise, time out into
1067 state_selecting at the select interval. */
1068 if (stop_selecting <= 0)
1069 state_selecting(ip);
1071 add_timeout(stop_selecting, state_selecting, ip);
1072 cancel_timeout(send_discover, ip);
1076 /* Allocate a client_lease structure and initialize it from the parameters
1077 in the specified packet. */
1079 struct client_lease *
1080 packet_to_lease(struct packet *packet)
1082 struct client_lease *lease;
1085 lease = malloc(sizeof(struct client_lease));
1088 warning("dhcpoffer: no memory to record lease.");
1092 memset(lease, 0, sizeof(*lease));
1094 /* Copy the lease options. */
1095 for (i = 0; i < 256; i++) {
1096 if (packet->options[i].len) {
1097 lease->options[i].data =
1098 malloc(packet->options[i].len + 1);
1099 if (!lease->options[i].data) {
1100 warning("dhcpoffer: no memory for option %d", i);
1101 free_client_lease(lease);
1104 memcpy(lease->options[i].data,
1105 packet->options[i].data,
1106 packet->options[i].len);
1107 lease->options[i].len =
1108 packet->options[i].len;
1109 lease->options[i].data[lease->options[i].len] =
1112 if (!check_option(lease,i)) {
1113 /* ignore a bogus lease offer */
1114 warning("Invalid lease option - ignoring offer");
1115 free_client_lease(lease);
1121 lease->address.len = sizeof(packet->raw->yiaddr);
1122 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1124 lease->nextserver.len = sizeof(packet->raw->siaddr);
1125 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1127 /* If the server name was filled out, copy it.
1128 Do not attempt to validate the server name as a host name.
1129 RFC 2131 merely states that sname is NUL-terminated (which do
1130 do not assume) and that it is the server's host name. Since
1131 the ISC client and server allow arbitrary characters, we do
1133 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1134 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1135 packet->raw->sname[0]) {
1136 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1137 if (!lease->server_name) {
1138 warning("dhcpoffer: no memory for server name.");
1139 free_client_lease(lease);
1142 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1143 lease->server_name[DHCP_SNAME_LEN]='\0';
1146 /* Ditto for the filename. */
1147 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1148 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1149 packet->raw->file[0]) {
1150 /* Don't count on the NUL terminator. */
1151 lease->filename = malloc(DHCP_FILE_LEN + 1);
1152 if (!lease->filename) {
1153 warning("dhcpoffer: no memory for filename.");
1154 free_client_lease(lease);
1157 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1158 lease->filename[DHCP_FILE_LEN]='\0';
1164 dhcpnak(struct packet *packet)
1166 struct interface_info *ip = packet->interface;
1168 /* If we're not receptive to an offer right now, or if the offer
1169 has an unrecognizable transaction id, then just drop it. */
1170 if (packet->interface->client->xid != packet->raw->xid ||
1171 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1172 (memcmp(packet->interface->hw_address.haddr,
1173 packet->raw->chaddr, packet->raw->hlen)))
1176 if (ip->client->state != S_REBOOTING &&
1177 ip->client->state != S_REQUESTING &&
1178 ip->client->state != S_RENEWING &&
1179 ip->client->state != S_REBINDING)
1182 note("DHCPNAK from %s", piaddr(packet->client_addr));
1184 if (!ip->client->active) {
1185 note("DHCPNAK with no active lease.\n");
1189 free_client_lease(ip->client->active);
1190 ip->client->active = NULL;
1192 /* Stop sending DHCPREQUEST packets... */
1193 cancel_timeout(send_request, ip);
1195 ip->client->state = S_INIT;
1199 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1200 one after the right interval has expired. If we don't get an offer by
1201 the time we reach the panic interval, call the panic function. */
1204 send_discover(void *ipp)
1206 struct interface_info *ip = ipp;
1207 int interval, increase = 1;
1209 /* Figure out how long it's been since we started transmitting. */
1210 interval = cur_time - ip->client->first_sending;
1212 /* If we're past the panic timeout, call the script and tell it
1213 we haven't found anything for this interface yet. */
1214 if (interval > ip->client->config->timeout) {
1219 /* If we're selecting media, try the whole list before doing
1220 the exponential backoff, but if we've already received an
1221 offer, stop looping, because we obviously have it right. */
1222 if (!ip->client->offered_leases &&
1223 ip->client->config->media) {
1226 if (ip->client->medium) {
1227 ip->client->medium = ip->client->medium->next;
1230 if (!ip->client->medium) {
1232 error("No valid media types for %s!", ip->name);
1233 ip->client->medium = ip->client->config->media;
1237 note("Trying medium \"%s\" %d", ip->client->medium->string,
1239 script_init("MEDIUM", ip->client->medium);
1245 * If we're supposed to increase the interval, do so. If it's
1246 * currently zero (i.e., we haven't sent any packets yet), set
1247 * it to one; otherwise, add to it a random number between zero
1248 * and two times itself. On average, this means that it will
1249 * double with every transmission.
1252 if (!ip->client->interval)
1253 ip->client->interval =
1254 ip->client->config->initial_interval;
1256 ip->client->interval += (arc4random() >> 2) %
1257 (2 * ip->client->interval);
1260 /* Don't backoff past cutoff. */
1261 if (ip->client->interval >
1262 ip->client->config->backoff_cutoff)
1263 ip->client->interval =
1264 ((ip->client->config->backoff_cutoff / 2)
1265 + ((arc4random() >> 2) %
1266 ip->client->config->backoff_cutoff));
1267 } else if (!ip->client->interval)
1268 ip->client->interval =
1269 ip->client->config->initial_interval;
1271 /* If the backoff would take us to the panic timeout, just use that
1273 if (cur_time + ip->client->interval >
1274 ip->client->first_sending + ip->client->config->timeout)
1275 ip->client->interval =
1276 (ip->client->first_sending +
1277 ip->client->config->timeout) - cur_time + 1;
1279 /* Record the number of seconds since we started sending. */
1280 if (interval < 65536)
1281 ip->client->packet.secs = htons(interval);
1283 ip->client->packet.secs = htons(65535);
1284 ip->client->secs = ip->client->packet.secs;
1286 note("DHCPDISCOVER on %s to %s port %d interval %d",
1287 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1288 (int)ip->client->interval);
1290 /* Send out a packet. */
1291 send_packet_unpriv(privfd, &ip->client->packet,
1292 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1294 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1298 * state_panic gets called if we haven't received any offers in a preset
1299 * amount of time. When this happens, we try to use existing leases
1300 * that haven't yet expired, and failing that, we call the client script
1301 * and hope it can do something.
1304 state_panic(void *ipp)
1306 struct interface_info *ip = ipp;
1307 struct client_lease *loop = ip->client->active;
1308 struct client_lease *lp;
1310 note("No DHCPOFFERS received.");
1312 /* We may not have an active lease, but we may have some
1313 predefined leases that we can try. */
1314 if (!ip->client->active && ip->client->leases)
1317 /* Run through the list of leases and see if one can be used. */
1318 while (ip->client->active) {
1319 if (ip->client->active->expiry > cur_time) {
1320 note("Trying recorded lease %s",
1321 piaddr(ip->client->active->address));
1322 /* Run the client script with the existing
1324 script_init("TIMEOUT",
1325 ip->client->active->medium);
1326 script_write_params("new_", ip->client->active);
1327 if (ip->client->alias)
1328 script_write_params("alias_",
1331 /* If the old lease is still good and doesn't
1332 yet need renewal, go into BOUND state and
1333 timeout at the renewal time. */
1336 ip->client->active->renewal) {
1337 ip->client->state = S_BOUND;
1338 note("bound: renewal in %d seconds.",
1339 (int)(ip->client->active->renewal -
1342 ip->client->active->renewal,
1345 ip->client->state = S_BOUND;
1346 note("bound: immediate renewal.");
1349 reinitialize_interfaces();
1355 /* If there are no other leases, give up. */
1356 if (!ip->client->leases) {
1357 ip->client->leases = ip->client->active;
1358 ip->client->active = NULL;
1363 /* Otherwise, put the active lease at the end of the
1364 lease list, and try another lease.. */
1365 for (lp = ip->client->leases; lp->next; lp = lp->next)
1367 lp->next = ip->client->active;
1369 lp->next->next = NULL;
1370 ip->client->active = ip->client->leases;
1371 ip->client->leases = ip->client->leases->next;
1373 /* If we already tried this lease, we've exhausted the
1374 set of leases, so we might as well give up for
1376 if (ip->client->active == loop)
1379 loop = ip->client->active;
1382 /* No leases were available, or what was available didn't work, so
1383 tell the shell script that we failed to allocate an address,
1384 and try again later. */
1385 note("No working leases in persistent database - sleeping.\n");
1386 script_init("FAIL", NULL);
1387 if (ip->client->alias)
1388 script_write_params("alias_", ip->client->alias);
1390 ip->client->state = S_INIT;
1391 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1397 send_request(void *ipp)
1399 struct interface_info *ip = ipp;
1400 struct in_addr from, to;
1403 /* Figure out how long it's been since we started transmitting. */
1404 interval = cur_time - ip->client->first_sending;
1406 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1407 past the reboot timeout, go to INIT and see if we can
1408 DISCOVER an address... */
1409 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1410 means either that we're on a network with no DHCP server,
1411 or that our server is down. In the latter case, assuming
1412 that there is a backup DHCP server, DHCPDISCOVER will get
1413 us a new address, but we could also have successfully
1414 reused our old address. In the former case, we're hosed
1415 anyway. This is not a win-prone situation. */
1416 if ((ip->client->state == S_REBOOTING ||
1417 ip->client->state == S_REQUESTING) &&
1418 interval > ip->client->config->reboot_timeout) {
1420 ip->client->state = S_INIT;
1421 cancel_timeout(send_request, ip);
1426 /* If we're in the reboot state, make sure the media is set up
1428 if (ip->client->state == S_REBOOTING &&
1429 !ip->client->medium &&
1430 ip->client->active->medium ) {
1431 script_init("MEDIUM", ip->client->active->medium);
1433 /* If the medium we chose won't fly, go to INIT state. */
1437 /* Record the medium. */
1438 ip->client->medium = ip->client->active->medium;
1441 /* If the lease has expired, relinquish the address and go back
1442 to the INIT state. */
1443 if (ip->client->state != S_REQUESTING &&
1444 cur_time > ip->client->active->expiry) {
1445 /* Run the client script with the new parameters. */
1446 script_init("EXPIRE", NULL);
1447 script_write_params("old_", ip->client->active);
1448 if (ip->client->alias)
1449 script_write_params("alias_", ip->client->alias);
1452 /* Now do a preinit on the interface so that we can
1453 discover a new address. */
1454 script_init("PREINIT", NULL);
1455 if (ip->client->alias)
1456 script_write_params("alias_", ip->client->alias);
1459 ip->client->state = S_INIT;
1464 /* Do the exponential backoff... */
1465 if (!ip->client->interval)
1466 ip->client->interval = ip->client->config->initial_interval;
1468 ip->client->interval += ((arc4random() >> 2) %
1469 (2 * ip->client->interval));
1471 /* Don't backoff past cutoff. */
1472 if (ip->client->interval >
1473 ip->client->config->backoff_cutoff)
1474 ip->client->interval =
1475 ((ip->client->config->backoff_cutoff / 2) +
1476 ((arc4random() >> 2) % ip->client->interval));
1478 /* If the backoff would take us to the expiry time, just set the
1479 timeout to the expiry time. */
1480 if (ip->client->state != S_REQUESTING &&
1481 cur_time + ip->client->interval >
1482 ip->client->active->expiry)
1483 ip->client->interval =
1484 ip->client->active->expiry - cur_time + 1;
1486 /* If the lease T2 time has elapsed, or if we're not yet bound,
1487 broadcast the DHCPREQUEST rather than unicasting. */
1488 if (ip->client->state == S_REQUESTING ||
1489 ip->client->state == S_REBOOTING ||
1490 cur_time > ip->client->active->rebind)
1491 to.s_addr = INADDR_BROADCAST;
1493 memcpy(&to.s_addr, ip->client->destination.iabuf,
1496 if (ip->client->state != S_REQUESTING &&
1497 ip->client->state != S_REBOOTING)
1498 memcpy(&from, ip->client->active->address.iabuf,
1501 from.s_addr = INADDR_ANY;
1503 /* Record the number of seconds since we started sending. */
1504 if (ip->client->state == S_REQUESTING)
1505 ip->client->packet.secs = ip->client->secs;
1507 if (interval < 65536)
1508 ip->client->packet.secs = htons(interval);
1510 ip->client->packet.secs = htons(65535);
1513 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1516 /* Send out a packet. */
1517 send_packet_unpriv(privfd, &ip->client->packet,
1518 ip->client->packet_length, from, to);
1520 add_timeout(cur_time + ip->client->interval, send_request, ip);
1524 send_decline(void *ipp)
1526 struct interface_info *ip = ipp;
1528 note("DHCPDECLINE on %s to %s port %d", ip->name,
1529 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1531 /* Send out a packet. */
1532 send_packet_unpriv(privfd, &ip->client->packet,
1533 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1537 make_discover(struct interface_info *ip, struct client_lease *lease)
1539 unsigned char discover = DHCPDISCOVER;
1540 struct tree_cache *options[256];
1541 struct tree_cache option_elements[256];
1544 memset(option_elements, 0, sizeof(option_elements));
1545 memset(options, 0, sizeof(options));
1546 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1548 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1549 i = DHO_DHCP_MESSAGE_TYPE;
1550 options[i] = &option_elements[i];
1551 options[i]->value = &discover;
1552 options[i]->len = sizeof(discover);
1553 options[i]->buf_size = sizeof(discover);
1554 options[i]->timeout = 0xFFFFFFFF;
1556 /* Request the options we want */
1557 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1558 options[i] = &option_elements[i];
1559 options[i]->value = ip->client->config->requested_options;
1560 options[i]->len = ip->client->config->requested_option_count;
1561 options[i]->buf_size =
1562 ip->client->config->requested_option_count;
1563 options[i]->timeout = 0xFFFFFFFF;
1565 /* If we had an address, try to get it again. */
1567 ip->client->requested_address = lease->address;
1568 i = DHO_DHCP_REQUESTED_ADDRESS;
1569 options[i] = &option_elements[i];
1570 options[i]->value = lease->address.iabuf;
1571 options[i]->len = lease->address.len;
1572 options[i]->buf_size = lease->address.len;
1573 options[i]->timeout = 0xFFFFFFFF;
1575 ip->client->requested_address.len = 0;
1577 /* Send any options requested in the config file. */
1578 for (i = 0; i < 256; i++)
1580 ip->client->config->send_options[i].data) {
1581 options[i] = &option_elements[i];
1583 ip->client->config->send_options[i].data;
1585 ip->client->config->send_options[i].len;
1586 options[i]->buf_size =
1587 ip->client->config->send_options[i].len;
1588 options[i]->timeout = 0xFFFFFFFF;
1591 /* send host name if not set via config file. */
1592 if (!options[DHO_HOST_NAME]) {
1593 if (hostname[0] != '\0') {
1595 char* posDot = strchr(hostname, '.');
1597 len = posDot - hostname;
1599 len = strlen(hostname);
1600 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1601 options[DHO_HOST_NAME]->value = hostname;
1602 options[DHO_HOST_NAME]->len = len;
1603 options[DHO_HOST_NAME]->buf_size = len;
1604 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1608 /* set unique client identifier */
1609 char client_ident[sizeof(ip->hw_address.haddr) + 1];
1610 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1611 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1612 ip->hw_address.hlen : sizeof(client_ident)-1;
1613 client_ident[0] = ip->hw_address.htype;
1614 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1615 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1616 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1617 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1618 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1619 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1622 /* Set up the option buffer... */
1623 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1624 options, 0, 0, 0, NULL, 0);
1625 if (ip->client->packet_length < BOOTP_MIN_LEN)
1626 ip->client->packet_length = BOOTP_MIN_LEN;
1628 ip->client->packet.op = BOOTREQUEST;
1629 ip->client->packet.htype = ip->hw_address.htype;
1630 ip->client->packet.hlen = ip->hw_address.hlen;
1631 ip->client->packet.hops = 0;
1632 ip->client->packet.xid = arc4random();
1633 ip->client->packet.secs = 0; /* filled in by send_discover. */
1634 ip->client->packet.flags = 0;
1636 memset(&(ip->client->packet.ciaddr),
1637 0, sizeof(ip->client->packet.ciaddr));
1638 memset(&(ip->client->packet.yiaddr),
1639 0, sizeof(ip->client->packet.yiaddr));
1640 memset(&(ip->client->packet.siaddr),
1641 0, sizeof(ip->client->packet.siaddr));
1642 memset(&(ip->client->packet.giaddr),
1643 0, sizeof(ip->client->packet.giaddr));
1644 memcpy(ip->client->packet.chaddr,
1645 ip->hw_address.haddr, ip->hw_address.hlen);
1650 make_request(struct interface_info *ip, struct client_lease * lease)
1652 unsigned char request = DHCPREQUEST;
1653 struct tree_cache *options[256];
1654 struct tree_cache option_elements[256];
1657 memset(options, 0, sizeof(options));
1658 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1660 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1661 i = DHO_DHCP_MESSAGE_TYPE;
1662 options[i] = &option_elements[i];
1663 options[i]->value = &request;
1664 options[i]->len = sizeof(request);
1665 options[i]->buf_size = sizeof(request);
1666 options[i]->timeout = 0xFFFFFFFF;
1668 /* Request the options we want */
1669 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1670 options[i] = &option_elements[i];
1671 options[i]->value = ip->client->config->requested_options;
1672 options[i]->len = ip->client->config->requested_option_count;
1673 options[i]->buf_size =
1674 ip->client->config->requested_option_count;
1675 options[i]->timeout = 0xFFFFFFFF;
1677 /* If we are requesting an address that hasn't yet been assigned
1678 to us, use the DHCP Requested Address option. */
1679 if (ip->client->state == S_REQUESTING) {
1680 /* Send back the server identifier... */
1681 i = DHO_DHCP_SERVER_IDENTIFIER;
1682 options[i] = &option_elements[i];
1683 options[i]->value = lease->options[i].data;
1684 options[i]->len = lease->options[i].len;
1685 options[i]->buf_size = lease->options[i].len;
1686 options[i]->timeout = 0xFFFFFFFF;
1688 if (ip->client->state == S_REQUESTING ||
1689 ip->client->state == S_REBOOTING) {
1690 ip->client->requested_address = lease->address;
1691 i = DHO_DHCP_REQUESTED_ADDRESS;
1692 options[i] = &option_elements[i];
1693 options[i]->value = lease->address.iabuf;
1694 options[i]->len = lease->address.len;
1695 options[i]->buf_size = lease->address.len;
1696 options[i]->timeout = 0xFFFFFFFF;
1698 ip->client->requested_address.len = 0;
1700 /* Send any options requested in the config file. */
1701 for (i = 0; i < 256; i++)
1703 ip->client->config->send_options[i].data) {
1704 options[i] = &option_elements[i];
1706 ip->client->config->send_options[i].data;
1708 ip->client->config->send_options[i].len;
1709 options[i]->buf_size =
1710 ip->client->config->send_options[i].len;
1711 options[i]->timeout = 0xFFFFFFFF;
1714 /* send host name if not set via config file. */
1715 if (!options[DHO_HOST_NAME]) {
1716 if (hostname[0] != '\0') {
1718 char* posDot = strchr(hostname, '.');
1720 len = posDot - hostname;
1722 len = strlen(hostname);
1723 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1724 options[DHO_HOST_NAME]->value = hostname;
1725 options[DHO_HOST_NAME]->len = len;
1726 options[DHO_HOST_NAME]->buf_size = len;
1727 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1731 /* set unique client identifier */
1732 char client_ident[sizeof(struct hardware)];
1733 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1734 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1735 ip->hw_address.hlen : sizeof(client_ident)-1;
1736 client_ident[0] = ip->hw_address.htype;
1737 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1738 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1739 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1740 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1741 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1742 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1745 /* Set up the option buffer... */
1746 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1747 options, 0, 0, 0, NULL, 0);
1748 if (ip->client->packet_length < BOOTP_MIN_LEN)
1749 ip->client->packet_length = BOOTP_MIN_LEN;
1751 ip->client->packet.op = BOOTREQUEST;
1752 ip->client->packet.htype = ip->hw_address.htype;
1753 ip->client->packet.hlen = ip->hw_address.hlen;
1754 ip->client->packet.hops = 0;
1755 ip->client->packet.xid = ip->client->xid;
1756 ip->client->packet.secs = 0; /* Filled in by send_request. */
1758 /* If we own the address we're requesting, put it in ciaddr;
1759 otherwise set ciaddr to zero. */
1760 if (ip->client->state == S_BOUND ||
1761 ip->client->state == S_RENEWING ||
1762 ip->client->state == S_REBINDING) {
1763 memcpy(&ip->client->packet.ciaddr,
1764 lease->address.iabuf, lease->address.len);
1765 ip->client->packet.flags = 0;
1767 memset(&ip->client->packet.ciaddr, 0,
1768 sizeof(ip->client->packet.ciaddr));
1769 ip->client->packet.flags = 0;
1772 memset(&ip->client->packet.yiaddr, 0,
1773 sizeof(ip->client->packet.yiaddr));
1774 memset(&ip->client->packet.siaddr, 0,
1775 sizeof(ip->client->packet.siaddr));
1776 memset(&ip->client->packet.giaddr, 0,
1777 sizeof(ip->client->packet.giaddr));
1778 memcpy(ip->client->packet.chaddr,
1779 ip->hw_address.haddr, ip->hw_address.hlen);
1783 make_decline(struct interface_info *ip, struct client_lease *lease)
1785 struct tree_cache *options[256], message_type_tree;
1786 struct tree_cache requested_address_tree;
1787 struct tree_cache server_id_tree, client_id_tree;
1788 unsigned char decline = DHCPDECLINE;
1791 memset(options, 0, sizeof(options));
1792 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1794 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1795 i = DHO_DHCP_MESSAGE_TYPE;
1796 options[i] = &message_type_tree;
1797 options[i]->value = &decline;
1798 options[i]->len = sizeof(decline);
1799 options[i]->buf_size = sizeof(decline);
1800 options[i]->timeout = 0xFFFFFFFF;
1802 /* Send back the server identifier... */
1803 i = DHO_DHCP_SERVER_IDENTIFIER;
1804 options[i] = &server_id_tree;
1805 options[i]->value = lease->options[i].data;
1806 options[i]->len = lease->options[i].len;
1807 options[i]->buf_size = lease->options[i].len;
1808 options[i]->timeout = 0xFFFFFFFF;
1810 /* Send back the address we're declining. */
1811 i = DHO_DHCP_REQUESTED_ADDRESS;
1812 options[i] = &requested_address_tree;
1813 options[i]->value = lease->address.iabuf;
1814 options[i]->len = lease->address.len;
1815 options[i]->buf_size = lease->address.len;
1816 options[i]->timeout = 0xFFFFFFFF;
1818 /* Send the uid if the user supplied one. */
1819 i = DHO_DHCP_CLIENT_IDENTIFIER;
1820 if (ip->client->config->send_options[i].len) {
1821 options[i] = &client_id_tree;
1822 options[i]->value = ip->client->config->send_options[i].data;
1823 options[i]->len = ip->client->config->send_options[i].len;
1824 options[i]->buf_size = ip->client->config->send_options[i].len;
1825 options[i]->timeout = 0xFFFFFFFF;
1829 /* Set up the option buffer... */
1830 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1831 options, 0, 0, 0, NULL, 0);
1832 if (ip->client->packet_length < BOOTP_MIN_LEN)
1833 ip->client->packet_length = BOOTP_MIN_LEN;
1835 ip->client->packet.op = BOOTREQUEST;
1836 ip->client->packet.htype = ip->hw_address.htype;
1837 ip->client->packet.hlen = ip->hw_address.hlen;
1838 ip->client->packet.hops = 0;
1839 ip->client->packet.xid = ip->client->xid;
1840 ip->client->packet.secs = 0; /* Filled in by send_request. */
1841 ip->client->packet.flags = 0;
1843 /* ciaddr must always be zero. */
1844 memset(&ip->client->packet.ciaddr, 0,
1845 sizeof(ip->client->packet.ciaddr));
1846 memset(&ip->client->packet.yiaddr, 0,
1847 sizeof(ip->client->packet.yiaddr));
1848 memset(&ip->client->packet.siaddr, 0,
1849 sizeof(ip->client->packet.siaddr));
1850 memset(&ip->client->packet.giaddr, 0,
1851 sizeof(ip->client->packet.giaddr));
1852 memcpy(ip->client->packet.chaddr,
1853 ip->hw_address.haddr, ip->hw_address.hlen);
1857 free_client_lease(struct client_lease *lease)
1861 if (lease->server_name)
1862 free(lease->server_name);
1863 if (lease->filename)
1864 free(lease->filename);
1865 for (i = 0; i < 256; i++) {
1866 if (lease->options[i].len)
1867 free(lease->options[i].data);
1875 rewrite_client_leases(void)
1877 struct client_lease *lp;
1878 cap_rights_t rights;
1881 leaseFile = fopen(path_dhclient_db, "w");
1883 error("can't create %s: %m", path_dhclient_db);
1884 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1885 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1886 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1888 error("can't limit lease descriptor: %m");
1890 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1892 error("can't limit lease descriptor fcntls: %m");
1899 for (lp = ifi->client->leases; lp; lp = lp->next)
1900 write_client_lease(ifi, lp, 1);
1901 if (ifi->client->active)
1902 write_client_lease(ifi, ifi->client->active, 1);
1905 ftruncate(fileno(leaseFile), ftello(leaseFile));
1906 fsync(fileno(leaseFile));
1910 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1913 static int leases_written;
1918 if (leases_written++ > 20) {
1919 rewrite_client_leases();
1924 /* If the lease came from the config file, we don't need to stash
1925 a copy in the lease database. */
1926 if (lease->is_static)
1929 if (!leaseFile) { /* XXX */
1930 leaseFile = fopen(path_dhclient_db, "w");
1932 error("can't create %s: %m", path_dhclient_db);
1935 fprintf(leaseFile, "lease {\n");
1936 if (lease->is_bootp)
1937 fprintf(leaseFile, " bootp;\n");
1938 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1939 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1940 if (lease->nextserver.len == sizeof(inaddr_any) &&
1941 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1942 sizeof(inaddr_any)))
1943 fprintf(leaseFile, " next-server %s;\n",
1944 piaddr(lease->nextserver));
1945 if (lease->filename)
1946 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1947 if (lease->server_name)
1948 fprintf(leaseFile, " server-name \"%s\";\n",
1949 lease->server_name);
1951 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1952 for (i = 0; i < 256; i++)
1953 if (lease->options[i].len)
1954 fprintf(leaseFile, " option %s %s;\n",
1955 dhcp_options[i].name,
1956 pretty_print_option(i, lease->options[i].data,
1957 lease->options[i].len, 1, 1));
1959 t = gmtime(&lease->renewal);
1960 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1961 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1962 t->tm_hour, t->tm_min, t->tm_sec);
1963 t = gmtime(&lease->rebind);
1964 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1965 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1966 t->tm_hour, t->tm_min, t->tm_sec);
1967 t = gmtime(&lease->expiry);
1968 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1969 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1970 t->tm_hour, t->tm_min, t->tm_sec);
1971 fprintf(leaseFile, "}\n");
1976 script_init(char *reason, struct string_list *medium)
1978 size_t len, mediumlen = 0;
1979 struct imsg_hdr hdr;
1983 if (medium != NULL && medium->string != NULL)
1984 mediumlen = strlen(medium->string);
1986 hdr.code = IMSG_SCRIPT_INIT;
1987 hdr.len = sizeof(struct imsg_hdr) +
1988 sizeof(size_t) + mediumlen +
1989 sizeof(size_t) + strlen(reason);
1991 if ((buf = buf_open(hdr.len)) == NULL)
1992 error("buf_open: %m");
1995 errs += buf_add(buf, &hdr, sizeof(hdr));
1996 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1998 errs += buf_add(buf, medium->string, mediumlen);
1999 len = strlen(reason);
2000 errs += buf_add(buf, &len, sizeof(len));
2001 errs += buf_add(buf, reason, len);
2004 error("buf_add: %m");
2006 if (buf_close(privfd, buf) == -1)
2007 error("buf_close: %m");
2011 priv_script_init(char *reason, char *medium)
2013 struct interface_info *ip = ifi;
2016 ip->client->scriptEnvsize = 100;
2017 if (ip->client->scriptEnv == NULL)
2018 ip->client->scriptEnv =
2019 malloc(ip->client->scriptEnvsize * sizeof(char *));
2020 if (ip->client->scriptEnv == NULL)
2021 error("script_init: no memory for environment");
2023 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
2024 if (ip->client->scriptEnv[0] == NULL)
2025 error("script_init: no memory for environment");
2027 ip->client->scriptEnv[1] = NULL;
2029 script_set_env(ip->client, "", "interface", ip->name);
2032 script_set_env(ip->client, "", "medium", medium);
2034 script_set_env(ip->client, "", "reason", reason);
2039 priv_script_write_params(char *prefix, struct client_lease *lease)
2041 struct interface_info *ip = ifi;
2042 u_int8_t dbuf[1500], *dp = NULL;
2047 script_set_env(ip->client, prefix, "ip_address",
2048 piaddr(lease->address));
2050 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2052 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2053 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2055 dp = lease->options[DHO_SUBNET_MASK].data;
2056 len = lease->options[DHO_SUBNET_MASK].len;
2058 if (len && (len < sizeof(lease->address.iabuf))) {
2059 struct iaddr netmask, subnet, broadcast;
2061 memcpy(netmask.iabuf, dp, len);
2063 subnet = subnet_number(lease->address, netmask);
2065 script_set_env(ip->client, prefix, "network_number",
2067 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2068 broadcast = broadcast_addr(subnet, netmask);
2070 script_set_env(ip->client, prefix,
2071 "broadcast_address",
2077 if (lease->filename)
2078 script_set_env(ip->client, prefix, "filename", lease->filename);
2079 if (lease->server_name)
2080 script_set_env(ip->client, prefix, "server_name",
2081 lease->server_name);
2082 for (i = 0; i < 256; i++) {
2085 if (ip->client->config->defaults[i].len) {
2086 if (lease->options[i].len) {
2088 ip->client->config->default_actions[i]) {
2089 case ACTION_DEFAULT:
2090 dp = lease->options[i].data;
2091 len = lease->options[i].len;
2093 case ACTION_SUPERSEDE:
2096 config->defaults[i].data;
2098 config->defaults[i].len;
2100 case ACTION_PREPEND:
2102 config->defaults[i].len +
2103 lease->options[i].len;
2104 if (len >= sizeof(dbuf)) {
2105 warning("no space to %s %s",
2107 dhcp_options[i].name);
2113 config->defaults[i].data,
2115 config->defaults[i].len);
2116 memcpy(dp + ip->client->
2117 config->defaults[i].len,
2118 lease->options[i].data,
2119 lease->options[i].len);
2124 * When we append, we assume that we're
2125 * appending to text. Some MS servers
2126 * include a NUL byte at the end of
2127 * the search string provided.
2130 config->defaults[i].len +
2131 lease->options[i].len;
2132 if (len >= sizeof(dbuf)) {
2133 warning("no space to %s %s",
2135 dhcp_options[i].name);
2139 lease->options[i].data,
2140 lease->options[i].len);
2141 for (dp = dbuf + lease->options[i].len;
2142 dp > dbuf; dp--, len--)
2147 config->defaults[i].data,
2149 config->defaults[i].len);
2155 config->defaults[i].data;
2157 config->defaults[i].len;
2159 } else if (lease->options[i].len) {
2160 len = lease->options[i].len;
2161 dp = lease->options[i].data;
2168 if (dhcp_option_ev_name(name, sizeof(name),
2170 script_set_env(ip->client, prefix, name,
2171 pretty_print_option(i, dp, len, 0, 0));
2174 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2175 script_set_env(ip->client, prefix, "expiry", tbuf);
2179 script_write_params(char *prefix, struct client_lease *lease)
2181 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2182 struct imsg_hdr hdr;
2186 if (lease->filename != NULL)
2187 fn_len = strlen(lease->filename);
2188 if (lease->server_name != NULL)
2189 sn_len = strlen(lease->server_name);
2191 pr_len = strlen(prefix);
2193 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2194 hdr.len = sizeof(hdr) + sizeof(*lease) +
2195 sizeof(fn_len) + fn_len + sizeof(sn_len) + sn_len +
2196 sizeof(pr_len) + pr_len;
2198 for (i = 0; i < 256; i++) {
2199 hdr.len += sizeof(lease->options[i].len);
2200 hdr.len += lease->options[i].len;
2203 scripttime = time(NULL);
2205 if ((buf = buf_open(hdr.len)) == NULL)
2206 error("buf_open: %m");
2209 errs += buf_add(buf, &hdr, sizeof(hdr));
2210 errs += buf_add(buf, lease, sizeof(*lease));
2211 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2212 errs += buf_add(buf, lease->filename, fn_len);
2213 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2214 errs += buf_add(buf, lease->server_name, sn_len);
2215 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2216 errs += buf_add(buf, prefix, pr_len);
2218 for (i = 0; i < 256; i++) {
2219 errs += buf_add(buf, &lease->options[i].len,
2220 sizeof(lease->options[i].len));
2221 errs += buf_add(buf, lease->options[i].data,
2222 lease->options[i].len);
2226 error("buf_add: %m");
2228 if (buf_close(privfd, buf) == -1)
2229 error("buf_close: %m");
2235 struct imsg_hdr hdr;
2239 hdr.code = IMSG_SCRIPT_GO;
2240 hdr.len = sizeof(struct imsg_hdr);
2242 if ((buf = buf_open(hdr.len)) == NULL)
2243 error("buf_open: %m");
2245 if (buf_add(buf, &hdr, sizeof(hdr)))
2246 error("buf_add: %m");
2248 if (buf_close(privfd, buf) == -1)
2249 error("buf_close: %m");
2251 bzero(&hdr, sizeof(hdr));
2252 buf_read(privfd, &hdr, sizeof(hdr));
2253 if (hdr.code != IMSG_SCRIPT_GO_RET)
2254 error("unexpected msg type %u", hdr.code);
2255 if (hdr.len != sizeof(hdr) + sizeof(int))
2256 error("received corrupted message");
2257 buf_read(privfd, &ret, sizeof(ret));
2259 scripttime = time(NULL);
2265 priv_script_go(void)
2267 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2268 static char client_path[] = CLIENT_PATH;
2269 struct interface_info *ip = ifi;
2270 int pid, wpid, wstatus;
2272 scripttime = time(NULL);
2275 scriptName = ip->client->config->script_name;
2276 envp = ip->client->scriptEnv;
2278 scriptName = top_level_config.script_name;
2280 epp[1] = client_path;
2285 argv[0] = scriptName;
2294 wpid = wait(&wstatus);
2295 } while (wpid != pid && wpid > 0);
2301 execve(scriptName, argv, envp);
2302 error("execve (%s, ...): %m", scriptName);
2306 script_flush_env(ip->client);
2308 return (wstatus & 0xff);
2312 script_set_env(struct client_state *client, const char *prefix,
2313 const char *name, const char *value)
2318 /* No `` or $() command substitution allowed in environment values! */
2319 for (j=0; j < strlen(value); j++)
2323 warning("illegal character (%c) in value '%s'",
2325 /* Ignore this option */
2329 namelen = strlen(name);
2331 for (i = 0; client->scriptEnv[i]; i++)
2332 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2333 client->scriptEnv[i][namelen] == '=')
2336 if (client->scriptEnv[i])
2337 /* Reuse the slot. */
2338 free(client->scriptEnv[i]);
2340 /* New variable. Expand if necessary. */
2341 if (i >= client->scriptEnvsize - 1) {
2342 char **newscriptEnv;
2343 int newscriptEnvsize = client->scriptEnvsize + 50;
2345 newscriptEnv = realloc(client->scriptEnv,
2347 if (newscriptEnv == NULL) {
2348 free(client->scriptEnv);
2349 client->scriptEnv = NULL;
2350 client->scriptEnvsize = 0;
2351 error("script_set_env: no memory for variable");
2353 client->scriptEnv = newscriptEnv;
2354 client->scriptEnvsize = newscriptEnvsize;
2356 /* need to set the NULL pointer at end of array beyond
2358 client->scriptEnv[i + 1] = NULL;
2360 /* Allocate space and format the variable in the appropriate slot. */
2361 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2363 if (client->scriptEnv[i] == NULL)
2364 error("script_set_env: no memory for variable assignment");
2365 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2366 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2370 script_flush_env(struct client_state *client)
2374 for (i = 0; client->scriptEnv[i]; i++) {
2375 free(client->scriptEnv[i]);
2376 client->scriptEnv[i] = NULL;
2378 client->scriptEnvsize = 0;
2382 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2386 for (i = 0; option->name[i]; i++) {
2387 if (i + 1 == buflen)
2389 if (option->name[i] == '-')
2392 buf[i] = option->name[i];
2402 static int state = 0;
2403 cap_rights_t rights;
2405 if (no_daemon || state)
2410 /* Stop logging to stderr... */
2413 if (daemon(1, 0) == -1)
2416 cap_rights_init(&rights);
2418 if (pidfile != NULL) {
2419 pidfile_write(pidfile);
2420 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2422 error("can't limit pidfile descriptor: %m");
2426 /* we are chrooted, daemon(3) fails to open /dev/null */
2428 dup2(nullfd, STDIN_FILENO);
2429 dup2(nullfd, STDOUT_FILENO);
2430 dup2(nullfd, STDERR_FILENO);
2435 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2436 error("can't limit stdin: %m");
2437 cap_rights_init(&rights, CAP_WRITE);
2438 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2439 error("can't limit stdout: %m");
2440 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2441 error("can't limit stderr: %m");
2445 check_option(struct client_lease *l, int option)
2450 /* we use this, since this is what gets passed to dhclient-script */
2452 opbuf = pretty_print_option(option, l->options[option].data,
2453 l->options[option].len, 0, 0);
2455 sbuf = option_as_string(option, l->options[option].data,
2456 l->options[option].len);
2459 case DHO_SUBNET_MASK:
2460 case DHO_TIME_SERVERS:
2461 case DHO_NAME_SERVERS:
2463 case DHO_DOMAIN_NAME_SERVERS:
2464 case DHO_LOG_SERVERS:
2465 case DHO_COOKIE_SERVERS:
2466 case DHO_LPR_SERVERS:
2467 case DHO_IMPRESS_SERVERS:
2468 case DHO_RESOURCE_LOCATION_SERVERS:
2469 case DHO_SWAP_SERVER:
2470 case DHO_BROADCAST_ADDRESS:
2471 case DHO_NIS_SERVERS:
2472 case DHO_NTP_SERVERS:
2473 case DHO_NETBIOS_NAME_SERVERS:
2474 case DHO_NETBIOS_DD_SERVER:
2475 case DHO_FONT_SERVERS:
2476 case DHO_DHCP_SERVER_IDENTIFIER:
2477 case DHO_NISPLUS_SERVERS:
2478 case DHO_MOBILE_IP_HOME_AGENT:
2479 case DHO_SMTP_SERVER:
2480 case DHO_POP_SERVER:
2481 case DHO_NNTP_SERVER:
2482 case DHO_WWW_SERVER:
2483 case DHO_FINGER_SERVER:
2484 case DHO_IRC_SERVER:
2485 case DHO_STREETTALK_SERVER:
2486 case DHO_STREETTALK_DA_SERVER:
2487 if (!ipv4addrs(opbuf)) {
2488 warning("Invalid IP address in option: %s", opbuf);
2493 case DHO_NIS_DOMAIN:
2494 case DHO_NISPLUS_DOMAIN:
2495 case DHO_TFTP_SERVER_NAME:
2496 if (!res_hnok(sbuf)) {
2497 warning("Bogus Host Name option %d: %s (%s)", option,
2499 l->options[option].len = 0;
2500 free(l->options[option].data);
2503 case DHO_DOMAIN_NAME:
2504 case DHO_DOMAIN_SEARCH:
2505 if (!res_hnok(sbuf)) {
2506 if (!check_search(sbuf)) {
2507 warning("Bogus domain search list %d: %s (%s)",
2508 option, sbuf, opbuf);
2509 l->options[option].len = 0;
2510 free(l->options[option].data);
2515 case DHO_TIME_OFFSET:
2517 case DHO_MERIT_DUMP:
2519 case DHO_EXTENSIONS_PATH:
2520 case DHO_IP_FORWARDING:
2521 case DHO_NON_LOCAL_SOURCE_ROUTING:
2522 case DHO_POLICY_FILTER:
2523 case DHO_MAX_DGRAM_REASSEMBLY:
2524 case DHO_DEFAULT_IP_TTL:
2525 case DHO_PATH_MTU_AGING_TIMEOUT:
2526 case DHO_PATH_MTU_PLATEAU_TABLE:
2527 case DHO_INTERFACE_MTU:
2528 case DHO_ALL_SUBNETS_LOCAL:
2529 case DHO_PERFORM_MASK_DISCOVERY:
2530 case DHO_MASK_SUPPLIER:
2531 case DHO_ROUTER_DISCOVERY:
2532 case DHO_ROUTER_SOLICITATION_ADDRESS:
2533 case DHO_STATIC_ROUTES:
2534 case DHO_TRAILER_ENCAPSULATION:
2535 case DHO_ARP_CACHE_TIMEOUT:
2536 case DHO_IEEE802_3_ENCAPSULATION:
2537 case DHO_DEFAULT_TCP_TTL:
2538 case DHO_TCP_KEEPALIVE_INTERVAL:
2539 case DHO_TCP_KEEPALIVE_GARBAGE:
2540 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2541 case DHO_NETBIOS_NODE_TYPE:
2542 case DHO_NETBIOS_SCOPE:
2543 case DHO_X_DISPLAY_MANAGER:
2544 case DHO_DHCP_REQUESTED_ADDRESS:
2545 case DHO_DHCP_LEASE_TIME:
2546 case DHO_DHCP_OPTION_OVERLOAD:
2547 case DHO_DHCP_MESSAGE_TYPE:
2548 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2549 case DHO_DHCP_MESSAGE:
2550 case DHO_DHCP_MAX_MESSAGE_SIZE:
2551 case DHO_DHCP_RENEWAL_TIME:
2552 case DHO_DHCP_REBINDING_TIME:
2553 case DHO_DHCP_CLASS_IDENTIFIER:
2554 case DHO_DHCP_CLIENT_IDENTIFIER:
2555 case DHO_BOOTFILE_NAME:
2556 case DHO_DHCP_USER_CLASS_ID:
2559 case DHO_CLASSLESS_ROUTES:
2560 return (check_classless_option(l->options[option].data,
2561 l->options[option].len));
2563 warning("unknown dhcp option value 0x%x", option);
2564 return (unknown_ok);
2568 /* RFC 3442 The Classless Static Routes option checks */
2570 check_classless_option(unsigned char *data, int len)
2573 unsigned char width;
2574 in_addr_t addr, mask;
2577 warning("Too small length: %d", len);
2585 } else if (width < 9) {
2586 addr = (in_addr_t)(data[i] << 24);
2588 } else if (width < 17) {
2589 addr = (in_addr_t)(data[i] << 24) +
2590 (in_addr_t)(data[i + 1] << 16);
2592 } else if (width < 25) {
2593 addr = (in_addr_t)(data[i] << 24) +
2594 (in_addr_t)(data[i + 1] << 16) +
2595 (in_addr_t)(data[i + 2] << 8);
2597 } else if (width < 33) {
2598 addr = (in_addr_t)(data[i] << 24) +
2599 (in_addr_t)(data[i + 1] << 16) +
2600 (in_addr_t)(data[i + 2] << 8) +
2604 warning("Incorrect subnet width: %d", width);
2607 mask = (in_addr_t)(~0) << (32 - width);
2613 * ... After deriving a subnet number and subnet mask
2614 * from each destination descriptor, the DHCP client
2615 * MUST zero any bits in the subnet number where the
2616 * corresponding bit in the mask is zero...
2618 if ((addr & mask) != addr) {
2620 data[i - 1] = (unsigned char)(
2621 (addr >> (((32 - width)/8)*8)) & 0xFF);
2626 warning("Incorrect data length: %d (must be %d)", len, i);
2633 res_hnok(const char *dn)
2635 int pch = PERIOD, ch = *dn++;
2637 while (ch != '\0') {
2640 if (periodchar(ch)) {
2642 } else if (periodchar(pch)) {
2643 if (!borderchar(ch))
2645 } else if (periodchar(nch) || nch == '\0') {
2646 if (!borderchar(ch))
2649 if (!middlechar(ch))
2658 check_search(const char *srch)
2660 int pch = PERIOD, ch = *srch++;
2663 /* 256 char limit re resolv.conf(5) */
2664 if (strlen(srch) > 256)
2667 while (whitechar(ch))
2670 while (ch != '\0') {
2673 if (periodchar(ch) || whitechar(ch)) {
2675 } else if (periodchar(pch)) {
2676 if (!borderchar(ch))
2678 } else if (periodchar(nch) || nch == '\0') {
2679 if (!borderchar(ch))
2682 if (!middlechar(ch))
2685 if (!whitechar(ch)) {
2688 while (whitechar(nch)) {
2697 /* 6 domain limit re resolv.conf(5) */
2703 /* Does buf consist only of dotted decimal ipv4 addrs?
2704 * return how many if so,
2705 * otherwise, return 0
2708 ipv4addrs(char * buf)
2713 while (inet_aton(buf, &jnk) == 1){
2715 while (periodchar(*buf) || digitchar(*buf))
2727 option_as_string(unsigned int code, unsigned char *data, int len)
2729 static char optbuf[32768]; /* XXX */
2731 int opleft = sizeof(optbuf);
2732 unsigned char *dp = data;
2735 error("option_as_string: bad code %d", code);
2737 for (; dp < data + len; dp++) {
2738 if (!isascii(*dp) || !isprint(*dp)) {
2739 if (dp + 1 != data + len || *dp != 0) {
2740 snprintf(op, opleft, "\\%03o", *dp);
2744 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2745 *dp == '`' || *dp == '\\') {
2759 warning("dhcp option too large");
2764 fork_privchld(int fd, int fd2)
2766 struct pollfd pfd[1];
2771 error("cannot fork");
2778 setproctitle("%s [priv]", ifi->name);
2781 dup2(nullfd, STDIN_FILENO);
2782 dup2(nullfd, STDOUT_FILENO);
2783 dup2(nullfd, STDERR_FILENO);
2791 pfd[0].events = POLLIN;
2792 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2794 error("poll error");
2796 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2799 dispatch_imsg(ifi, fd);