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$");
64 #include <sys/capsicum.h>
66 #include <net80211/ieee80211_freebsd.h>
68 #ifndef _PATH_VAREMPTY
69 #define _PATH_VAREMPTY "/var/empty"
73 #define hyphenchar(c) ((c) == 0x2d)
74 #define bslashchar(c) ((c) == 0x5c)
75 #define periodchar(c) ((c) == PERIOD)
76 #define asterchar(c) ((c) == 0x2a)
77 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
78 ((c) >= 0x61 && (c) <= 0x7a))
79 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
80 #define whitechar(c) ((c) == ' ' || (c) == '\t')
82 #define borderchar(c) (alphachar(c) || digitchar(c))
83 #define middlechar(c) (borderchar(c) || hyphenchar(c))
84 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
86 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
89 time_t default_lease_time = 43200; /* 12 hours... */
91 char *path_dhclient_conf = _PATH_DHCLIENT_CONF;
92 char *path_dhclient_db = NULL;
98 char hostname[_POSIX_HOST_NAME_MAX + 1];
100 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
101 struct in_addr inaddr_any, inaddr_broadcast;
103 char *path_dhclient_pidfile;
104 struct pidfh *pidfile;
107 * ASSERT_STATE() does nothing now; it used to be
108 * assert (state_is == state_shouldbe).
110 #define ASSERT_STATE(state_is, state_shouldbe) {}
112 #define TIME_MAX 2147483647
119 struct interface_info *ifi;
121 int findproto(char *, int);
122 struct sockaddr *get_ifa(char *, int);
123 void routehandler(struct protocol *);
125 int check_option(struct client_lease *l, int option);
126 int check_classless_option(unsigned char *data, int len);
127 int ipv4addrs(char * buf);
128 int res_hnok(const char *dn);
129 int check_search(const char *srch);
130 char *option_as_string(unsigned int code, unsigned char *data, int len);
131 int fork_privchld(int, int);
134 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
135 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
137 static time_t scripttime;
140 findproto(char *cp, int n)
147 for (i = 1; i; i <<= 1) {
149 sa = (struct sockaddr *)cp;
155 if (sa->sa_family == AF_INET)
157 if (sa->sa_family == AF_INET6)
170 get_ifa(char *cp, int n)
177 for (i = 1; i; i <<= 1)
179 sa = (struct sockaddr *)cp;
188 struct iaddr defaddr = { 4 };
194 struct interface_info *ifi = arg;
197 * Clear existing state.
199 if (ifi->client->active != NULL) {
200 script_init("EXPIRE", NULL);
201 script_write_params("old_",
202 ifi->client->active);
203 if (ifi->client->alias)
204 script_write_params("alias_",
208 ifi->client->state = S_INIT;
213 routehandler(struct protocol *p)
215 char msg[2048], *addr;
216 struct rt_msghdr *rtm;
217 struct if_msghdr *ifm;
218 struct ifa_msghdr *ifam;
219 struct if_announcemsghdr *ifan;
220 struct ieee80211_join_event *jev;
221 struct client_lease *l;
222 time_t t = time(NULL);
228 n = read(routefd, &msg, sizeof(msg));
229 rtm = (struct rt_msghdr *)msg;
230 if (n < sizeof(rtm->rtm_msglen) || n < rtm->rtm_msglen ||
231 rtm->rtm_version != RTM_VERSION)
234 switch (rtm->rtm_type) {
237 ifam = (struct ifa_msghdr *)rtm;
239 if (ifam->ifam_index != ifi->index)
241 if (findproto((char *)(ifam + 1), ifam->ifam_addrs) != AF_INET)
243 if (scripttime == 0 || t < scripttime + 10)
246 sa = get_ifa((char *)(ifam + 1), ifam->ifam_addrs);
250 if ((a.len = sizeof(struct in_addr)) > sizeof(a.iabuf))
251 error("king bula sez: len mismatch");
252 memcpy(a.iabuf, &((struct sockaddr_in *)sa)->sin_addr, a.len);
253 if (addr_eq(a, defaddr))
256 for (l = ifi->client->active; l != NULL; l = l->next)
257 if (addr_eq(a, l->address))
260 if (l == NULL) /* added/deleted addr is not the one we set */
263 addr = inet_ntoa(((struct sockaddr_in *)sa)->sin_addr);
264 if (rtm->rtm_type == RTM_NEWADDR) {
266 * XXX: If someone other than us adds our address,
267 * should we assume they are taking over from us,
268 * delete the lease record, and exit without modifying
271 warning("My address (%s) was re-added", addr);
273 warning("My address (%s) was deleted, dhclient exiting",
279 ifm = (struct if_msghdr *)rtm;
280 if (ifm->ifm_index != ifi->index)
282 if ((rtm->rtm_flags & RTF_UP) == 0) {
283 warning("Interface %s is down, dhclient exiting",
287 linkstat = interface_link_status(ifi->name);
288 if (linkstat != ifi->linkstat) {
289 debug("%s link state %s -> %s", ifi->name,
290 ifi->linkstat ? "up" : "down",
291 linkstat ? "up" : "down");
292 ifi->linkstat = linkstat;
298 ifan = (struct if_announcemsghdr *)rtm;
299 if (ifan->ifan_what == IFAN_DEPARTURE &&
300 ifan->ifan_index == ifi->index) {
301 warning("Interface %s is gone, dhclient exiting",
307 ifan = (struct if_announcemsghdr *)rtm;
308 if (ifan->ifan_index != ifi->index)
310 switch (ifan->ifan_what) {
311 case RTM_IEEE80211_ASSOC:
312 case RTM_IEEE80211_REASSOC:
314 * Use assoc/reassoc event to kick state machine
315 * in case we roam. Otherwise fall back to the
316 * normal state machine just like a wired network.
318 jev = (struct ieee80211_join_event *) &ifan[1];
319 if (memcmp(curbssid, jev->iev_addr, 6)) {
323 memcpy(curbssid, jev->iev_addr, 6);
333 script_init("FAIL", NULL);
334 if (ifi->client->alias)
335 script_write_params("alias_", ifi->client->alias);
338 pidfile_remove(pidfile);
343 main(int argc, char *argv[])
345 extern char *__progname;
346 int ch, fd, quiet = 0, i = 0;
348 int immediate_daemon = 0;
353 /* Initially, log errors to stderr as well as to syslogd. */
354 openlog(__progname, LOG_PID | LOG_NDELAY, DHCPD_LOG_FACILITY);
355 setlogmask(LOG_UPTO(LOG_DEBUG));
357 while ((ch = getopt(argc, argv, "bc:dl:p:qu")) != -1)
360 immediate_daemon = 1;
363 path_dhclient_conf = optarg;
369 path_dhclient_db = optarg;
372 path_dhclient_pidfile = optarg;
390 if (path_dhclient_pidfile == NULL) {
391 asprintf(&path_dhclient_pidfile,
392 "%sdhclient.%s.pid", _PATH_VARRUN, *argv);
393 if (path_dhclient_pidfile == NULL)
396 pidfile = pidfile_open(path_dhclient_pidfile, 0644, &otherpid);
397 if (pidfile == NULL) {
399 error("dhclient already running, pid: %d.", otherpid);
401 error("dhclient already running.");
402 warning("Cannot open or create pidfile: %m");
405 if ((ifi = calloc(1, sizeof(struct interface_info))) == NULL)
407 if (strlcpy(ifi->name, argv[0], IFNAMSIZ) >= IFNAMSIZ)
408 error("Interface name too long");
409 if (path_dhclient_db == NULL && asprintf(&path_dhclient_db, "%s.%s",
410 _PATH_DHCLIENT_DB, ifi->name) == -1)
419 inaddr_broadcast.s_addr = INADDR_BROADCAST;
420 inaddr_any.s_addr = INADDR_ANY;
424 /* The next bit is potentially very time-consuming, so write out
425 the pidfile right away. We will write it out again with the
426 correct pid after daemonizing. */
428 pidfile_write(pidfile);
430 if (!interface_link_status(ifi->name)) {
431 fprintf(stderr, "%s: no link ...", ifi->name);
434 while (!interface_link_status(ifi->name)) {
435 fprintf(stderr, ".");
438 fprintf(stderr, " giving up\n");
443 fprintf(stderr, " got link\n");
447 if ((nullfd = open(_PATH_DEVNULL, O_RDWR, 0)) == -1)
448 error("cannot open %s: %m", _PATH_DEVNULL);
450 if ((pw = getpwnam("_dhcp")) == NULL) {
451 warning("no such user: _dhcp, falling back to \"nobody\"");
452 if ((pw = getpwnam("nobody")) == NULL)
453 error("no such user: nobody");
457 * Obtain hostname before entering capability mode - it won't be
458 * possible then, as reading kern.hostname is not permitted.
460 if (gethostname(hostname, sizeof(hostname)) < 0)
463 priv_script_init("PREINIT", NULL);
464 if (ifi->client->alias)
465 priv_script_write_params("alias_", ifi->client->alias);
468 /* set up the interface */
469 discover_interfaces(ifi);
471 if (pipe(pipe_fd) == -1)
474 fork_privchld(pipe_fd[0], pipe_fd[1]);
483 cap_rights_init(&rights, CAP_READ, CAP_WRITE);
484 if (cap_rights_limit(privfd, &rights) < 0 && errno != ENOSYS)
485 error("can't limit private descriptor: %m");
487 if ((fd = open(path_dhclient_db, O_RDONLY|O_EXLOCK|O_CREAT, 0)) == -1)
488 error("can't open and lock %s: %m", path_dhclient_db);
489 read_client_leases();
490 rewrite_client_leases();
493 if ((routefd = socket(PF_ROUTE, SOCK_RAW, 0)) != -1)
494 add_protocol("AF_ROUTE", routefd, routehandler, ifi);
495 if (shutdown(routefd, SHUT_WR) < 0)
496 error("can't shutdown route socket: %m");
497 cap_rights_init(&rights, CAP_EVENT, CAP_READ);
498 if (cap_rights_limit(routefd, &rights) < 0 && errno != ENOSYS)
499 error("can't limit route socket: %m");
501 if (chroot(_PATH_VAREMPTY) == -1)
503 if (chdir("/") == -1)
504 error("chdir(\"/\")");
506 if (setgroups(1, &pw->pw_gid) ||
507 setegid(pw->pw_gid) || setgid(pw->pw_gid) ||
508 seteuid(pw->pw_uid) || setuid(pw->pw_uid))
509 error("can't drop privileges: %m");
513 setproctitle("%s", ifi->name);
515 if (cap_enter() < 0 && errno != ENOSYS)
516 error("can't enter capability mode: %m");
518 if (immediate_daemon)
521 ifi->client->state = S_INIT;
524 bootp_packet_handler = do_packet;
535 extern char *__progname;
537 fprintf(stderr, "usage: %s [-bdqu] ", __progname);
538 fprintf(stderr, "[-c conffile] [-l leasefile] interface\n");
545 * Each routine is called from the dhclient_state_machine() in one of
547 * -> entering INIT state
548 * -> recvpacket_flag == 0: timeout in this state
549 * -> otherwise: received a packet in this state
551 * Return conditions as handled by dhclient_state_machine():
552 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
553 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
554 * Returns 0: finish the nap which was interrupted for no good reason.
556 * Several per-interface variables are used to keep track of the process:
557 * active_lease: the lease that is being used on the interface
558 * (null pointer if not configured yet).
559 * offered_leases: leases corresponding to DHCPOFFER messages that have
560 * been sent to us by DHCP servers.
561 * acked_leases: leases corresponding to DHCPACK messages that have been
562 * sent to us by DHCP servers.
563 * sendpacket: DHCP packet we're trying to send.
564 * destination: IP address to send sendpacket to
565 * In addition, there are several relevant per-lease variables.
566 * T1_expiry, T2_expiry, lease_expiry: lease milestones
567 * In the active lease, these control the process of renewing the lease;
568 * In leases on the acked_leases list, this simply determines when we
569 * can no longer legitimately use the lease.
573 state_reboot(void *ipp)
575 struct interface_info *ip = ipp;
577 /* If we don't remember an active lease, go straight to INIT. */
578 if (!ip->client->active || ip->client->active->is_bootp) {
583 /* We are in the rebooting state. */
584 ip->client->state = S_REBOOTING;
586 /* make_request doesn't initialize xid because it normally comes
587 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
588 so pick an xid now. */
589 ip->client->xid = arc4random();
591 /* Make a DHCPREQUEST packet, and set appropriate per-interface
593 make_request(ip, ip->client->active);
594 ip->client->destination = iaddr_broadcast;
595 ip->client->first_sending = cur_time;
596 ip->client->interval = ip->client->config->initial_interval;
598 /* Zap the medium list... */
599 ip->client->medium = NULL;
601 /* Send out the first DHCPREQUEST packet. */
606 * Called when a lease has completely expired and we've
607 * been unable to renew it.
610 state_init(void *ipp)
612 struct interface_info *ip = ipp;
614 ASSERT_STATE(state, S_INIT);
616 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
618 make_discover(ip, ip->client->active);
619 ip->client->xid = ip->client->packet.xid;
620 ip->client->destination = iaddr_broadcast;
621 ip->client->state = S_SELECTING;
622 ip->client->first_sending = cur_time;
623 ip->client->interval = ip->client->config->initial_interval;
625 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
631 * state_selecting is called when one or more DHCPOFFER packets
632 * have been received and a configurable period of time has passed.
635 state_selecting(void *ipp)
637 struct interface_info *ip = ipp;
638 struct client_lease *lp, *next, *picked;
640 ASSERT_STATE(state, S_SELECTING);
642 /* Cancel state_selecting and send_discover timeouts, since either
643 one could have got us here. */
644 cancel_timeout(state_selecting, ip);
645 cancel_timeout(send_discover, ip);
647 /* We have received one or more DHCPOFFER packets. Currently,
648 the only criterion by which we judge leases is whether or
649 not we get a response when we arp for them. */
651 for (lp = ip->client->offered_leases; lp; lp = next) {
654 /* Check to see if we got an ARPREPLY for the address
655 in this particular lease. */
657 script_init("ARPCHECK", lp->medium);
658 script_write_params("check_", lp);
660 /* If the ARPCHECK code detects another
661 machine using the offered address, it exits
662 nonzero. We need to send a DHCPDECLINE and
665 make_decline(ip, lp);
673 free_client_lease(lp);
676 ip->client->offered_leases = NULL;
678 /* If we just tossed all the leases we were offered, go back
681 ip->client->state = S_INIT;
686 /* If it was a BOOTREPLY, we can just take the address right now. */
687 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
688 ip->client->new = picked;
690 /* Make up some lease expiry times
691 XXX these should be configurable. */
692 ip->client->new->expiry = cur_time + 12000;
693 ip->client->new->renewal += cur_time + 8000;
694 ip->client->new->rebind += cur_time + 10000;
696 ip->client->state = S_REQUESTING;
698 /* Bind to the address we received. */
703 /* Go to the REQUESTING state. */
704 ip->client->destination = iaddr_broadcast;
705 ip->client->state = S_REQUESTING;
706 ip->client->first_sending = cur_time;
707 ip->client->interval = ip->client->config->initial_interval;
709 /* Make a DHCPREQUEST packet from the lease we picked. */
710 make_request(ip, picked);
711 ip->client->xid = ip->client->packet.xid;
713 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
714 free_client_lease(picked);
716 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
720 /* state_requesting is called when we receive a DHCPACK message after
721 having sent out one or more DHCPREQUEST packets. */
724 dhcpack(struct packet *packet)
726 struct interface_info *ip = packet->interface;
727 struct client_lease *lease;
729 /* If we're not receptive to an offer right now, or if the offer
730 has an unrecognizable transaction id, then just drop it. */
731 if (packet->interface->client->xid != packet->raw->xid ||
732 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
733 (memcmp(packet->interface->hw_address.haddr,
734 packet->raw->chaddr, packet->raw->hlen)))
737 if (ip->client->state != S_REBOOTING &&
738 ip->client->state != S_REQUESTING &&
739 ip->client->state != S_RENEWING &&
740 ip->client->state != S_REBINDING)
743 note("DHCPACK from %s", piaddr(packet->client_addr));
745 lease = packet_to_lease(packet);
747 note("packet_to_lease failed.");
751 ip->client->new = lease;
753 /* Stop resending DHCPREQUEST. */
754 cancel_timeout(send_request, ip);
756 /* Figure out the lease time. */
757 if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
758 ip->client->new->expiry = getULong(
759 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
761 ip->client->new->expiry = default_lease_time;
762 /* A number that looks negative here is really just very large,
763 because the lease expiry offset is unsigned. */
764 if (ip->client->new->expiry < 0)
765 ip->client->new->expiry = TIME_MAX;
766 /* XXX should be fixed by resetting the client state */
767 if (ip->client->new->expiry < 60)
768 ip->client->new->expiry = 60;
770 /* Take the server-provided renewal time if there is one;
771 otherwise figure it out according to the spec. */
772 if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
773 ip->client->new->renewal = getULong(
774 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
776 ip->client->new->renewal = ip->client->new->expiry / 2;
778 /* Same deal with the rebind time. */
779 if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
780 ip->client->new->rebind = getULong(
781 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
783 ip->client->new->rebind = ip->client->new->renewal +
784 ip->client->new->renewal / 2 + ip->client->new->renewal / 4;
786 ip->client->new->expiry += cur_time;
787 /* Lease lengths can never be negative. */
788 if (ip->client->new->expiry < cur_time)
789 ip->client->new->expiry = TIME_MAX;
790 ip->client->new->renewal += cur_time;
791 if (ip->client->new->renewal < cur_time)
792 ip->client->new->renewal = TIME_MAX;
793 ip->client->new->rebind += cur_time;
794 if (ip->client->new->rebind < cur_time)
795 ip->client->new->rebind = TIME_MAX;
801 bind_lease(struct interface_info *ip)
803 /* Remember the medium. */
804 ip->client->new->medium = ip->client->medium;
806 /* Write out the new lease. */
807 write_client_lease(ip, ip->client->new, 0);
809 /* Run the client script with the new parameters. */
810 script_init((ip->client->state == S_REQUESTING ? "BOUND" :
811 (ip->client->state == S_RENEWING ? "RENEW" :
812 (ip->client->state == S_REBOOTING ? "REBOOT" : "REBIND"))),
813 ip->client->new->medium);
814 if (ip->client->active && ip->client->state != S_REBOOTING)
815 script_write_params("old_", ip->client->active);
816 script_write_params("new_", ip->client->new);
817 if (ip->client->alias)
818 script_write_params("alias_", ip->client->alias);
821 /* Replace the old active lease with the new one. */
822 if (ip->client->active)
823 free_client_lease(ip->client->active);
824 ip->client->active = ip->client->new;
825 ip->client->new = NULL;
827 /* Set up a timeout to start the renewal process. */
828 add_timeout(ip->client->active->renewal, state_bound, ip);
830 note("bound to %s -- renewal in %d seconds.",
831 piaddr(ip->client->active->address),
832 (int)(ip->client->active->renewal - cur_time));
833 ip->client->state = S_BOUND;
834 reinitialize_interfaces();
839 * state_bound is called when we've successfully bound to a particular
840 * lease, but the renewal time on that lease has expired. We are
841 * expected to unicast a DHCPREQUEST to the server that gave us our
845 state_bound(void *ipp)
847 struct interface_info *ip = ipp;
849 ASSERT_STATE(state, S_BOUND);
851 /* T1 has expired. */
852 make_request(ip, ip->client->active);
853 ip->client->xid = ip->client->packet.xid;
855 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
856 memcpy(ip->client->destination.iabuf, ip->client->active->
857 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4);
858 ip->client->destination.len = 4;
860 ip->client->destination = iaddr_broadcast;
862 ip->client->first_sending = cur_time;
863 ip->client->interval = ip->client->config->initial_interval;
864 ip->client->state = S_RENEWING;
866 /* Send the first packet immediately. */
871 bootp(struct packet *packet)
873 struct iaddrlist *ap;
875 if (packet->raw->op != BOOTREPLY)
878 /* If there's a reject list, make sure this packet's sender isn't
880 for (ap = packet->interface->client->config->reject_list;
882 if (addr_eq(packet->client_addr, ap->addr)) {
883 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
891 dhcp(struct packet *packet)
893 struct iaddrlist *ap;
894 void (*handler)(struct packet *);
897 switch (packet->packet_type) {
914 /* If there's a reject list, make sure this packet's sender isn't
916 for (ap = packet->interface->client->config->reject_list;
918 if (addr_eq(packet->client_addr, ap->addr)) {
919 note("%s from %s rejected.", type, piaddr(ap->addr));
927 dhcpoffer(struct packet *packet)
929 struct interface_info *ip = packet->interface;
930 struct client_lease *lease, *lp;
932 int arp_timeout_needed, stop_selecting;
933 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ?
934 "DHCPOFFER" : "BOOTREPLY";
936 /* If we're not receptive to an offer right now, or if the offer
937 has an unrecognizable transaction id, then just drop it. */
938 if (ip->client->state != S_SELECTING ||
939 packet->interface->client->xid != packet->raw->xid ||
940 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
941 (memcmp(packet->interface->hw_address.haddr,
942 packet->raw->chaddr, packet->raw->hlen)))
945 note("%s from %s", name, piaddr(packet->client_addr));
948 /* If this lease doesn't supply the minimum required parameters,
950 for (i = 0; ip->client->config->required_options[i]; i++) {
951 if (!packet->options[ip->client->config->
952 required_options[i]].len) {
953 note("%s isn't satisfactory.", name);
958 /* If we've already seen this lease, don't record it again. */
959 for (lease = ip->client->offered_leases;
960 lease; lease = lease->next) {
961 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
962 !memcmp(lease->address.iabuf,
963 &packet->raw->yiaddr, lease->address.len)) {
964 debug("%s already seen.", name);
969 lease = packet_to_lease(packet);
971 note("packet_to_lease failed.");
975 /* If this lease was acquired through a BOOTREPLY, record that
977 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len)
980 /* Record the medium under which this lease was offered. */
981 lease->medium = ip->client->medium;
983 /* Send out an ARP Request for the offered IP address. */
984 script_init("ARPSEND", lease->medium);
985 script_write_params("check_", lease);
986 /* If the script can't send an ARP request without waiting,
987 we'll be waiting when we do the ARPCHECK, so don't wait now. */
989 arp_timeout_needed = 0;
991 arp_timeout_needed = 2;
993 /* Figure out when we're supposed to stop selecting. */
995 ip->client->first_sending + ip->client->config->select_interval;
997 /* If this is the lease we asked for, put it at the head of the
998 list, and don't mess with the arp request timeout. */
999 if (lease->address.len == ip->client->requested_address.len &&
1000 !memcmp(lease->address.iabuf,
1001 ip->client->requested_address.iabuf,
1002 ip->client->requested_address.len)) {
1003 lease->next = ip->client->offered_leases;
1004 ip->client->offered_leases = lease;
1006 /* If we already have an offer, and arping for this
1007 offer would take us past the selection timeout,
1008 then don't extend the timeout - just hope for the
1010 if (ip->client->offered_leases &&
1011 (cur_time + arp_timeout_needed) > stop_selecting)
1012 arp_timeout_needed = 0;
1014 /* Put the lease at the end of the list. */
1016 if (!ip->client->offered_leases)
1017 ip->client->offered_leases = lease;
1019 for (lp = ip->client->offered_leases; lp->next;
1026 /* If we're supposed to stop selecting before we've had time
1027 to wait for the ARPREPLY, add some delay to wait for
1029 if (stop_selecting - cur_time < arp_timeout_needed)
1030 stop_selecting = cur_time + arp_timeout_needed;
1032 /* If the selecting interval has expired, go immediately to
1033 state_selecting(). Otherwise, time out into
1034 state_selecting at the select interval. */
1035 if (stop_selecting <= 0)
1036 state_selecting(ip);
1038 add_timeout(stop_selecting, state_selecting, ip);
1039 cancel_timeout(send_discover, ip);
1043 /* Allocate a client_lease structure and initialize it from the parameters
1044 in the specified packet. */
1046 struct client_lease *
1047 packet_to_lease(struct packet *packet)
1049 struct client_lease *lease;
1052 lease = malloc(sizeof(struct client_lease));
1055 warning("dhcpoffer: no memory to record lease.");
1059 memset(lease, 0, sizeof(*lease));
1061 /* Copy the lease options. */
1062 for (i = 0; i < 256; i++) {
1063 if (packet->options[i].len) {
1064 lease->options[i].data =
1065 malloc(packet->options[i].len + 1);
1066 if (!lease->options[i].data) {
1067 warning("dhcpoffer: no memory for option %d", i);
1068 free_client_lease(lease);
1071 memcpy(lease->options[i].data,
1072 packet->options[i].data,
1073 packet->options[i].len);
1074 lease->options[i].len =
1075 packet->options[i].len;
1076 lease->options[i].data[lease->options[i].len] =
1079 if (!check_option(lease,i)) {
1080 /* ignore a bogus lease offer */
1081 warning("Invalid lease option - ignoring offer");
1082 free_client_lease(lease);
1088 lease->address.len = sizeof(packet->raw->yiaddr);
1089 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
1091 lease->nextserver.len = sizeof(packet->raw->siaddr);
1092 memcpy(lease->nextserver.iabuf, &packet->raw->siaddr, lease->nextserver.len);
1094 /* If the server name was filled out, copy it.
1095 Do not attempt to validate the server name as a host name.
1096 RFC 2131 merely states that sname is NUL-terminated (which do
1097 do not assume) and that it is the server's host name. Since
1098 the ISC client and server allow arbitrary characters, we do
1100 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1101 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
1102 packet->raw->sname[0]) {
1103 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
1104 if (!lease->server_name) {
1105 warning("dhcpoffer: no memory for server name.");
1106 free_client_lease(lease);
1109 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
1110 lease->server_name[DHCP_SNAME_LEN]='\0';
1113 /* Ditto for the filename. */
1114 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len ||
1115 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
1116 packet->raw->file[0]) {
1117 /* Don't count on the NUL terminator. */
1118 lease->filename = malloc(DHCP_FILE_LEN + 1);
1119 if (!lease->filename) {
1120 warning("dhcpoffer: no memory for filename.");
1121 free_client_lease(lease);
1124 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
1125 lease->filename[DHCP_FILE_LEN]='\0';
1131 dhcpnak(struct packet *packet)
1133 struct interface_info *ip = packet->interface;
1135 /* If we're not receptive to an offer right now, or if the offer
1136 has an unrecognizable transaction id, then just drop it. */
1137 if (packet->interface->client->xid != packet->raw->xid ||
1138 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
1139 (memcmp(packet->interface->hw_address.haddr,
1140 packet->raw->chaddr, packet->raw->hlen)))
1143 if (ip->client->state != S_REBOOTING &&
1144 ip->client->state != S_REQUESTING &&
1145 ip->client->state != S_RENEWING &&
1146 ip->client->state != S_REBINDING)
1149 note("DHCPNAK from %s", piaddr(packet->client_addr));
1151 if (!ip->client->active) {
1152 note("DHCPNAK with no active lease.\n");
1156 free_client_lease(ip->client->active);
1157 ip->client->active = NULL;
1159 /* Stop sending DHCPREQUEST packets... */
1160 cancel_timeout(send_request, ip);
1162 ip->client->state = S_INIT;
1166 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another
1167 one after the right interval has expired. If we don't get an offer by
1168 the time we reach the panic interval, call the panic function. */
1171 send_discover(void *ipp)
1173 struct interface_info *ip = ipp;
1174 int interval, increase = 1;
1176 /* Figure out how long it's been since we started transmitting. */
1177 interval = cur_time - ip->client->first_sending;
1179 /* If we're past the panic timeout, call the script and tell it
1180 we haven't found anything for this interface yet. */
1181 if (interval > ip->client->config->timeout) {
1186 /* If we're selecting media, try the whole list before doing
1187 the exponential backoff, but if we've already received an
1188 offer, stop looping, because we obviously have it right. */
1189 if (!ip->client->offered_leases &&
1190 ip->client->config->media) {
1193 if (ip->client->medium) {
1194 ip->client->medium = ip->client->medium->next;
1197 if (!ip->client->medium) {
1199 error("No valid media types for %s!", ip->name);
1200 ip->client->medium = ip->client->config->media;
1204 note("Trying medium \"%s\" %d", ip->client->medium->string,
1206 script_init("MEDIUM", ip->client->medium);
1212 * If we're supposed to increase the interval, do so. If it's
1213 * currently zero (i.e., we haven't sent any packets yet), set
1214 * it to one; otherwise, add to it a random number between zero
1215 * and two times itself. On average, this means that it will
1216 * double with every transmission.
1219 if (!ip->client->interval)
1220 ip->client->interval =
1221 ip->client->config->initial_interval;
1223 ip->client->interval += (arc4random() >> 2) %
1224 (2 * ip->client->interval);
1227 /* Don't backoff past cutoff. */
1228 if (ip->client->interval >
1229 ip->client->config->backoff_cutoff)
1230 ip->client->interval =
1231 ((ip->client->config->backoff_cutoff / 2)
1232 + ((arc4random() >> 2) %
1233 ip->client->config->backoff_cutoff));
1234 } else if (!ip->client->interval)
1235 ip->client->interval =
1236 ip->client->config->initial_interval;
1238 /* If the backoff would take us to the panic timeout, just use that
1240 if (cur_time + ip->client->interval >
1241 ip->client->first_sending + ip->client->config->timeout)
1242 ip->client->interval =
1243 (ip->client->first_sending +
1244 ip->client->config->timeout) - cur_time + 1;
1246 /* Record the number of seconds since we started sending. */
1247 if (interval < 65536)
1248 ip->client->packet.secs = htons(interval);
1250 ip->client->packet.secs = htons(65535);
1251 ip->client->secs = ip->client->packet.secs;
1253 note("DHCPDISCOVER on %s to %s port %d interval %d",
1254 ip->name, inet_ntoa(inaddr_broadcast), REMOTE_PORT,
1255 (int)ip->client->interval);
1257 /* Send out a packet. */
1258 send_packet_unpriv(privfd, &ip->client->packet,
1259 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1261 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1265 * state_panic gets called if we haven't received any offers in a preset
1266 * amount of time. When this happens, we try to use existing leases
1267 * that haven't yet expired, and failing that, we call the client script
1268 * and hope it can do something.
1271 state_panic(void *ipp)
1273 struct interface_info *ip = ipp;
1274 struct client_lease *loop = ip->client->active;
1275 struct client_lease *lp;
1277 note("No DHCPOFFERS received.");
1279 /* We may not have an active lease, but we may have some
1280 predefined leases that we can try. */
1281 if (!ip->client->active && ip->client->leases)
1284 /* Run through the list of leases and see if one can be used. */
1285 while (ip->client->active) {
1286 if (ip->client->active->expiry > cur_time) {
1287 note("Trying recorded lease %s",
1288 piaddr(ip->client->active->address));
1289 /* Run the client script with the existing
1291 script_init("TIMEOUT",
1292 ip->client->active->medium);
1293 script_write_params("new_", ip->client->active);
1294 if (ip->client->alias)
1295 script_write_params("alias_",
1298 /* If the old lease is still good and doesn't
1299 yet need renewal, go into BOUND state and
1300 timeout at the renewal time. */
1303 ip->client->active->renewal) {
1304 ip->client->state = S_BOUND;
1305 note("bound: renewal in %d seconds.",
1306 (int)(ip->client->active->renewal -
1309 ip->client->active->renewal,
1312 ip->client->state = S_BOUND;
1313 note("bound: immediate renewal.");
1316 reinitialize_interfaces();
1322 /* If there are no other leases, give up. */
1323 if (!ip->client->leases) {
1324 ip->client->leases = ip->client->active;
1325 ip->client->active = NULL;
1330 /* Otherwise, put the active lease at the end of the
1331 lease list, and try another lease.. */
1332 for (lp = ip->client->leases; lp->next; lp = lp->next)
1334 lp->next = ip->client->active;
1336 lp->next->next = NULL;
1337 ip->client->active = ip->client->leases;
1338 ip->client->leases = ip->client->leases->next;
1340 /* If we already tried this lease, we've exhausted the
1341 set of leases, so we might as well give up for
1343 if (ip->client->active == loop)
1346 loop = ip->client->active;
1349 /* No leases were available, or what was available didn't work, so
1350 tell the shell script that we failed to allocate an address,
1351 and try again later. */
1352 note("No working leases in persistent database - sleeping.\n");
1353 script_init("FAIL", NULL);
1354 if (ip->client->alias)
1355 script_write_params("alias_", ip->client->alias);
1357 ip->client->state = S_INIT;
1358 add_timeout(cur_time + ip->client->config->retry_interval, state_init,
1364 send_request(void *ipp)
1366 struct interface_info *ip = ipp;
1367 struct in_addr from, to;
1370 /* Figure out how long it's been since we started transmitting. */
1371 interval = cur_time - ip->client->first_sending;
1373 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1374 past the reboot timeout, go to INIT and see if we can
1375 DISCOVER an address... */
1376 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1377 means either that we're on a network with no DHCP server,
1378 or that our server is down. In the latter case, assuming
1379 that there is a backup DHCP server, DHCPDISCOVER will get
1380 us a new address, but we could also have successfully
1381 reused our old address. In the former case, we're hosed
1382 anyway. This is not a win-prone situation. */
1383 if ((ip->client->state == S_REBOOTING ||
1384 ip->client->state == S_REQUESTING) &&
1385 interval > ip->client->config->reboot_timeout) {
1387 ip->client->state = S_INIT;
1388 cancel_timeout(send_request, ip);
1393 /* If we're in the reboot state, make sure the media is set up
1395 if (ip->client->state == S_REBOOTING &&
1396 !ip->client->medium &&
1397 ip->client->active->medium ) {
1398 script_init("MEDIUM", ip->client->active->medium);
1400 /* If the medium we chose won't fly, go to INIT state. */
1404 /* Record the medium. */
1405 ip->client->medium = ip->client->active->medium;
1408 /* If the lease has expired, relinquish the address and go back
1409 to the INIT state. */
1410 if (ip->client->state != S_REQUESTING &&
1411 cur_time > ip->client->active->expiry) {
1412 /* Run the client script with the new parameters. */
1413 script_init("EXPIRE", NULL);
1414 script_write_params("old_", ip->client->active);
1415 if (ip->client->alias)
1416 script_write_params("alias_", ip->client->alias);
1419 /* Now do a preinit on the interface so that we can
1420 discover a new address. */
1421 script_init("PREINIT", NULL);
1422 if (ip->client->alias)
1423 script_write_params("alias_", ip->client->alias);
1426 ip->client->state = S_INIT;
1431 /* Do the exponential backoff... */
1432 if (!ip->client->interval)
1433 ip->client->interval = ip->client->config->initial_interval;
1435 ip->client->interval += ((arc4random() >> 2) %
1436 (2 * ip->client->interval));
1438 /* Don't backoff past cutoff. */
1439 if (ip->client->interval >
1440 ip->client->config->backoff_cutoff)
1441 ip->client->interval =
1442 ((ip->client->config->backoff_cutoff / 2) +
1443 ((arc4random() >> 2) % ip->client->interval));
1445 /* If the backoff would take us to the expiry time, just set the
1446 timeout to the expiry time. */
1447 if (ip->client->state != S_REQUESTING &&
1448 cur_time + ip->client->interval >
1449 ip->client->active->expiry)
1450 ip->client->interval =
1451 ip->client->active->expiry - cur_time + 1;
1453 /* If the lease T2 time has elapsed, or if we're not yet bound,
1454 broadcast the DHCPREQUEST rather than unicasting. */
1455 if (ip->client->state == S_REQUESTING ||
1456 ip->client->state == S_REBOOTING ||
1457 cur_time > ip->client->active->rebind)
1458 to.s_addr = INADDR_BROADCAST;
1460 memcpy(&to.s_addr, ip->client->destination.iabuf,
1463 if (ip->client->state != S_REQUESTING)
1464 memcpy(&from, ip->client->active->address.iabuf,
1467 from.s_addr = INADDR_ANY;
1469 /* Record the number of seconds since we started sending. */
1470 if (ip->client->state == S_REQUESTING)
1471 ip->client->packet.secs = ip->client->secs;
1473 if (interval < 65536)
1474 ip->client->packet.secs = htons(interval);
1476 ip->client->packet.secs = htons(65535);
1479 note("DHCPREQUEST on %s to %s port %d", ip->name, inet_ntoa(to),
1482 /* Send out a packet. */
1483 send_packet_unpriv(privfd, &ip->client->packet,
1484 ip->client->packet_length, from, to);
1486 add_timeout(cur_time + ip->client->interval, send_request, ip);
1490 send_decline(void *ipp)
1492 struct interface_info *ip = ipp;
1494 note("DHCPDECLINE on %s to %s port %d", ip->name,
1495 inet_ntoa(inaddr_broadcast), REMOTE_PORT);
1497 /* Send out a packet. */
1498 send_packet_unpriv(privfd, &ip->client->packet,
1499 ip->client->packet_length, inaddr_any, inaddr_broadcast);
1503 make_discover(struct interface_info *ip, struct client_lease *lease)
1505 unsigned char discover = DHCPDISCOVER;
1506 struct tree_cache *options[256];
1507 struct tree_cache option_elements[256];
1510 memset(option_elements, 0, sizeof(option_elements));
1511 memset(options, 0, sizeof(options));
1512 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1514 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1515 i = DHO_DHCP_MESSAGE_TYPE;
1516 options[i] = &option_elements[i];
1517 options[i]->value = &discover;
1518 options[i]->len = sizeof(discover);
1519 options[i]->buf_size = sizeof(discover);
1520 options[i]->timeout = 0xFFFFFFFF;
1522 /* Request the options we want */
1523 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1524 options[i] = &option_elements[i];
1525 options[i]->value = ip->client->config->requested_options;
1526 options[i]->len = ip->client->config->requested_option_count;
1527 options[i]->buf_size =
1528 ip->client->config->requested_option_count;
1529 options[i]->timeout = 0xFFFFFFFF;
1531 /* If we had an address, try to get it again. */
1533 ip->client->requested_address = lease->address;
1534 i = DHO_DHCP_REQUESTED_ADDRESS;
1535 options[i] = &option_elements[i];
1536 options[i]->value = lease->address.iabuf;
1537 options[i]->len = lease->address.len;
1538 options[i]->buf_size = lease->address.len;
1539 options[i]->timeout = 0xFFFFFFFF;
1541 ip->client->requested_address.len = 0;
1543 /* Send any options requested in the config file. */
1544 for (i = 0; i < 256; i++)
1546 ip->client->config->send_options[i].data) {
1547 options[i] = &option_elements[i];
1549 ip->client->config->send_options[i].data;
1551 ip->client->config->send_options[i].len;
1552 options[i]->buf_size =
1553 ip->client->config->send_options[i].len;
1554 options[i]->timeout = 0xFFFFFFFF;
1557 /* send host name if not set via config file. */
1558 if (!options[DHO_HOST_NAME]) {
1559 if (hostname[0] != '\0') {
1561 char* posDot = strchr(hostname, '.');
1563 len = posDot - hostname;
1565 len = strlen(hostname);
1566 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1567 options[DHO_HOST_NAME]->value = hostname;
1568 options[DHO_HOST_NAME]->len = len;
1569 options[DHO_HOST_NAME]->buf_size = len;
1570 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1574 /* set unique client identifier */
1575 struct hardware client_ident;
1576 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1577 size_t hwlen = MIN(ip->hw_address.hlen,
1578 sizeof(client_ident.haddr));
1579 client_ident.htype = ip->hw_address.htype;
1580 client_ident.hlen = hwlen;
1581 memcpy(client_ident.haddr, ip->hw_address.haddr, hwlen);
1582 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1583 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = (void *)&client_ident;
1584 hwlen += offsetof(struct hardware, haddr);
1585 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen;
1586 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen;
1587 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1590 /* Set up the option buffer... */
1591 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1592 options, 0, 0, 0, NULL, 0);
1593 if (ip->client->packet_length < BOOTP_MIN_LEN)
1594 ip->client->packet_length = BOOTP_MIN_LEN;
1596 ip->client->packet.op = BOOTREQUEST;
1597 ip->client->packet.htype = ip->hw_address.htype;
1598 ip->client->packet.hlen = ip->hw_address.hlen;
1599 ip->client->packet.hops = 0;
1600 ip->client->packet.xid = arc4random();
1601 ip->client->packet.secs = 0; /* filled in by send_discover. */
1602 ip->client->packet.flags = 0;
1604 memset(&(ip->client->packet.ciaddr),
1605 0, sizeof(ip->client->packet.ciaddr));
1606 memset(&(ip->client->packet.yiaddr),
1607 0, sizeof(ip->client->packet.yiaddr));
1608 memset(&(ip->client->packet.siaddr),
1609 0, sizeof(ip->client->packet.siaddr));
1610 memset(&(ip->client->packet.giaddr),
1611 0, sizeof(ip->client->packet.giaddr));
1612 memcpy(ip->client->packet.chaddr, ip->hw_address.haddr,
1613 MIN(ip->hw_address.hlen, sizeof(ip->client->packet.chaddr)));
1618 make_request(struct interface_info *ip, struct client_lease * lease)
1620 unsigned char request = DHCPREQUEST;
1621 struct tree_cache *options[256];
1622 struct tree_cache option_elements[256];
1625 memset(options, 0, sizeof(options));
1626 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1628 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1629 i = DHO_DHCP_MESSAGE_TYPE;
1630 options[i] = &option_elements[i];
1631 options[i]->value = &request;
1632 options[i]->len = sizeof(request);
1633 options[i]->buf_size = sizeof(request);
1634 options[i]->timeout = 0xFFFFFFFF;
1636 /* Request the options we want */
1637 i = DHO_DHCP_PARAMETER_REQUEST_LIST;
1638 options[i] = &option_elements[i];
1639 options[i]->value = ip->client->config->requested_options;
1640 options[i]->len = ip->client->config->requested_option_count;
1641 options[i]->buf_size =
1642 ip->client->config->requested_option_count;
1643 options[i]->timeout = 0xFFFFFFFF;
1645 /* If we are requesting an address that hasn't yet been assigned
1646 to us, use the DHCP Requested Address option. */
1647 if (ip->client->state == S_REQUESTING) {
1648 /* Send back the server identifier... */
1649 i = DHO_DHCP_SERVER_IDENTIFIER;
1650 options[i] = &option_elements[i];
1651 options[i]->value = lease->options[i].data;
1652 options[i]->len = lease->options[i].len;
1653 options[i]->buf_size = lease->options[i].len;
1654 options[i]->timeout = 0xFFFFFFFF;
1656 if (ip->client->state == S_REQUESTING ||
1657 ip->client->state == S_REBOOTING) {
1658 ip->client->requested_address = lease->address;
1659 i = DHO_DHCP_REQUESTED_ADDRESS;
1660 options[i] = &option_elements[i];
1661 options[i]->value = lease->address.iabuf;
1662 options[i]->len = lease->address.len;
1663 options[i]->buf_size = lease->address.len;
1664 options[i]->timeout = 0xFFFFFFFF;
1666 ip->client->requested_address.len = 0;
1668 /* Send any options requested in the config file. */
1669 for (i = 0; i < 256; i++)
1671 ip->client->config->send_options[i].data) {
1672 options[i] = &option_elements[i];
1674 ip->client->config->send_options[i].data;
1676 ip->client->config->send_options[i].len;
1677 options[i]->buf_size =
1678 ip->client->config->send_options[i].len;
1679 options[i]->timeout = 0xFFFFFFFF;
1682 /* send host name if not set via config file. */
1683 if (!options[DHO_HOST_NAME]) {
1684 if (hostname[0] != '\0') {
1686 char* posDot = strchr(hostname, '.');
1688 len = posDot - hostname;
1690 len = strlen(hostname);
1691 options[DHO_HOST_NAME] = &option_elements[DHO_HOST_NAME];
1692 options[DHO_HOST_NAME]->value = hostname;
1693 options[DHO_HOST_NAME]->len = len;
1694 options[DHO_HOST_NAME]->buf_size = len;
1695 options[DHO_HOST_NAME]->timeout = 0xFFFFFFFF;
1699 /* set unique client identifier */
1700 char client_ident[sizeof(struct hardware)];
1701 if (!options[DHO_DHCP_CLIENT_IDENTIFIER]) {
1702 int hwlen = (ip->hw_address.hlen < sizeof(client_ident)-1) ?
1703 ip->hw_address.hlen : sizeof(client_ident)-1;
1704 client_ident[0] = ip->hw_address.htype;
1705 memcpy(&client_ident[1], ip->hw_address.haddr, hwlen);
1706 options[DHO_DHCP_CLIENT_IDENTIFIER] = &option_elements[DHO_DHCP_CLIENT_IDENTIFIER];
1707 options[DHO_DHCP_CLIENT_IDENTIFIER]->value = client_ident;
1708 options[DHO_DHCP_CLIENT_IDENTIFIER]->len = hwlen+1;
1709 options[DHO_DHCP_CLIENT_IDENTIFIER]->buf_size = hwlen+1;
1710 options[DHO_DHCP_CLIENT_IDENTIFIER]->timeout = 0xFFFFFFFF;
1713 /* Set up the option buffer... */
1714 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1715 options, 0, 0, 0, NULL, 0);
1716 if (ip->client->packet_length < BOOTP_MIN_LEN)
1717 ip->client->packet_length = BOOTP_MIN_LEN;
1719 ip->client->packet.op = BOOTREQUEST;
1720 ip->client->packet.htype = ip->hw_address.htype;
1721 ip->client->packet.hlen = ip->hw_address.hlen;
1722 ip->client->packet.hops = 0;
1723 ip->client->packet.xid = ip->client->xid;
1724 ip->client->packet.secs = 0; /* Filled in by send_request. */
1726 /* If we own the address we're requesting, put it in ciaddr;
1727 otherwise set ciaddr to zero. */
1728 if (ip->client->state == S_BOUND ||
1729 ip->client->state == S_RENEWING ||
1730 ip->client->state == S_REBINDING) {
1731 memcpy(&ip->client->packet.ciaddr,
1732 lease->address.iabuf, lease->address.len);
1733 ip->client->packet.flags = 0;
1735 memset(&ip->client->packet.ciaddr, 0,
1736 sizeof(ip->client->packet.ciaddr));
1737 ip->client->packet.flags = 0;
1740 memset(&ip->client->packet.yiaddr, 0,
1741 sizeof(ip->client->packet.yiaddr));
1742 memset(&ip->client->packet.siaddr, 0,
1743 sizeof(ip->client->packet.siaddr));
1744 memset(&ip->client->packet.giaddr, 0,
1745 sizeof(ip->client->packet.giaddr));
1746 memcpy(ip->client->packet.chaddr,
1747 ip->hw_address.haddr, ip->hw_address.hlen);
1751 make_decline(struct interface_info *ip, struct client_lease *lease)
1753 struct tree_cache *options[256], message_type_tree;
1754 struct tree_cache requested_address_tree;
1755 struct tree_cache server_id_tree, client_id_tree;
1756 unsigned char decline = DHCPDECLINE;
1759 memset(options, 0, sizeof(options));
1760 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1762 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1763 i = DHO_DHCP_MESSAGE_TYPE;
1764 options[i] = &message_type_tree;
1765 options[i]->value = &decline;
1766 options[i]->len = sizeof(decline);
1767 options[i]->buf_size = sizeof(decline);
1768 options[i]->timeout = 0xFFFFFFFF;
1770 /* Send back the server identifier... */
1771 i = DHO_DHCP_SERVER_IDENTIFIER;
1772 options[i] = &server_id_tree;
1773 options[i]->value = lease->options[i].data;
1774 options[i]->len = lease->options[i].len;
1775 options[i]->buf_size = lease->options[i].len;
1776 options[i]->timeout = 0xFFFFFFFF;
1778 /* Send back the address we're declining. */
1779 i = DHO_DHCP_REQUESTED_ADDRESS;
1780 options[i] = &requested_address_tree;
1781 options[i]->value = lease->address.iabuf;
1782 options[i]->len = lease->address.len;
1783 options[i]->buf_size = lease->address.len;
1784 options[i]->timeout = 0xFFFFFFFF;
1786 /* Send the uid if the user supplied one. */
1787 i = DHO_DHCP_CLIENT_IDENTIFIER;
1788 if (ip->client->config->send_options[i].len) {
1789 options[i] = &client_id_tree;
1790 options[i]->value = ip->client->config->send_options[i].data;
1791 options[i]->len = ip->client->config->send_options[i].len;
1792 options[i]->buf_size = ip->client->config->send_options[i].len;
1793 options[i]->timeout = 0xFFFFFFFF;
1797 /* Set up the option buffer... */
1798 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1799 options, 0, 0, 0, NULL, 0);
1800 if (ip->client->packet_length < BOOTP_MIN_LEN)
1801 ip->client->packet_length = BOOTP_MIN_LEN;
1803 ip->client->packet.op = BOOTREQUEST;
1804 ip->client->packet.htype = ip->hw_address.htype;
1805 ip->client->packet.hlen = ip->hw_address.hlen;
1806 ip->client->packet.hops = 0;
1807 ip->client->packet.xid = ip->client->xid;
1808 ip->client->packet.secs = 0; /* Filled in by send_request. */
1809 ip->client->packet.flags = 0;
1811 /* ciaddr must always be zero. */
1812 memset(&ip->client->packet.ciaddr, 0,
1813 sizeof(ip->client->packet.ciaddr));
1814 memset(&ip->client->packet.yiaddr, 0,
1815 sizeof(ip->client->packet.yiaddr));
1816 memset(&ip->client->packet.siaddr, 0,
1817 sizeof(ip->client->packet.siaddr));
1818 memset(&ip->client->packet.giaddr, 0,
1819 sizeof(ip->client->packet.giaddr));
1820 memcpy(ip->client->packet.chaddr,
1821 ip->hw_address.haddr, ip->hw_address.hlen);
1825 free_client_lease(struct client_lease *lease)
1829 if (lease->server_name)
1830 free(lease->server_name);
1831 if (lease->filename)
1832 free(lease->filename);
1833 for (i = 0; i < 256; i++) {
1834 if (lease->options[i].len)
1835 free(lease->options[i].data);
1843 rewrite_client_leases(void)
1845 struct client_lease *lp;
1846 cap_rights_t rights;
1849 leaseFile = fopen(path_dhclient_db, "w");
1851 error("can't create %s: %m", path_dhclient_db);
1852 cap_rights_init(&rights, CAP_FCNTL, CAP_FSTAT, CAP_FSYNC,
1853 CAP_FTRUNCATE, CAP_SEEK, CAP_WRITE);
1854 if (cap_rights_limit(fileno(leaseFile), &rights) < 0 &&
1856 error("can't limit lease descriptor: %m");
1858 if (cap_fcntls_limit(fileno(leaseFile), CAP_FCNTL_GETFL) < 0 &&
1860 error("can't limit lease descriptor fcntls: %m");
1867 for (lp = ifi->client->leases; lp; lp = lp->next)
1868 write_client_lease(ifi, lp, 1);
1869 if (ifi->client->active)
1870 write_client_lease(ifi, ifi->client->active, 1);
1873 ftruncate(fileno(leaseFile), ftello(leaseFile));
1874 fsync(fileno(leaseFile));
1878 write_client_lease(struct interface_info *ip, struct client_lease *lease,
1881 static int leases_written;
1886 if (leases_written++ > 20) {
1887 rewrite_client_leases();
1892 /* If the lease came from the config file, we don't need to stash
1893 a copy in the lease database. */
1894 if (lease->is_static)
1897 if (!leaseFile) { /* XXX */
1898 leaseFile = fopen(path_dhclient_db, "w");
1900 error("can't create %s: %m", path_dhclient_db);
1903 fprintf(leaseFile, "lease {\n");
1904 if (lease->is_bootp)
1905 fprintf(leaseFile, " bootp;\n");
1906 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1907 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1908 if (lease->nextserver.len == sizeof(inaddr_any) &&
1909 0 != memcmp(lease->nextserver.iabuf, &inaddr_any,
1910 sizeof(inaddr_any)))
1911 fprintf(leaseFile, " next-server %s;\n",
1912 piaddr(lease->nextserver));
1913 if (lease->filename)
1914 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1915 if (lease->server_name)
1916 fprintf(leaseFile, " server-name \"%s\";\n",
1917 lease->server_name);
1919 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1920 for (i = 0; i < 256; i++)
1921 if (lease->options[i].len)
1922 fprintf(leaseFile, " option %s %s;\n",
1923 dhcp_options[i].name,
1924 pretty_print_option(i, lease->options[i].data,
1925 lease->options[i].len, 1, 1));
1927 t = gmtime(&lease->renewal);
1928 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1929 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1930 t->tm_hour, t->tm_min, t->tm_sec);
1931 t = gmtime(&lease->rebind);
1932 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1933 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1934 t->tm_hour, t->tm_min, t->tm_sec);
1935 t = gmtime(&lease->expiry);
1936 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1937 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1938 t->tm_hour, t->tm_min, t->tm_sec);
1939 fprintf(leaseFile, "}\n");
1944 script_init(char *reason, struct string_list *medium)
1946 size_t len, mediumlen = 0;
1947 struct imsg_hdr hdr;
1951 if (medium != NULL && medium->string != NULL)
1952 mediumlen = strlen(medium->string);
1954 hdr.code = IMSG_SCRIPT_INIT;
1955 hdr.len = sizeof(struct imsg_hdr) +
1956 sizeof(size_t) + mediumlen +
1957 sizeof(size_t) + strlen(reason);
1959 if ((buf = buf_open(hdr.len)) == NULL)
1960 error("buf_open: %m");
1963 errs += buf_add(buf, &hdr, sizeof(hdr));
1964 errs += buf_add(buf, &mediumlen, sizeof(mediumlen));
1966 errs += buf_add(buf, medium->string, mediumlen);
1967 len = strlen(reason);
1968 errs += buf_add(buf, &len, sizeof(len));
1969 errs += buf_add(buf, reason, len);
1972 error("buf_add: %m");
1974 if (buf_close(privfd, buf) == -1)
1975 error("buf_close: %m");
1979 priv_script_init(char *reason, char *medium)
1981 struct interface_info *ip = ifi;
1984 ip->client->scriptEnvsize = 100;
1985 if (ip->client->scriptEnv == NULL)
1986 ip->client->scriptEnv =
1987 malloc(ip->client->scriptEnvsize * sizeof(char *));
1988 if (ip->client->scriptEnv == NULL)
1989 error("script_init: no memory for environment");
1991 ip->client->scriptEnv[0] = strdup(CLIENT_PATH);
1992 if (ip->client->scriptEnv[0] == NULL)
1993 error("script_init: no memory for environment");
1995 ip->client->scriptEnv[1] = NULL;
1997 script_set_env(ip->client, "", "interface", ip->name);
2000 script_set_env(ip->client, "", "medium", medium);
2002 script_set_env(ip->client, "", "reason", reason);
2007 priv_script_write_params(char *prefix, struct client_lease *lease)
2009 struct interface_info *ip = ifi;
2010 u_int8_t dbuf[1500], *dp = NULL;
2014 script_set_env(ip->client, prefix, "ip_address",
2015 piaddr(lease->address));
2017 if (ip->client->config->default_actions[DHO_SUBNET_MASK] ==
2019 dp = ip->client->config->defaults[DHO_SUBNET_MASK].data;
2020 len = ip->client->config->defaults[DHO_SUBNET_MASK].len;
2022 dp = lease->options[DHO_SUBNET_MASK].data;
2023 len = lease->options[DHO_SUBNET_MASK].len;
2025 if (len && (len < sizeof(lease->address.iabuf))) {
2026 struct iaddr netmask, subnet, broadcast;
2028 memcpy(netmask.iabuf, dp, len);
2030 subnet = subnet_number(lease->address, netmask);
2032 script_set_env(ip->client, prefix, "network_number",
2034 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
2035 broadcast = broadcast_addr(subnet, netmask);
2037 script_set_env(ip->client, prefix,
2038 "broadcast_address",
2044 if (lease->filename)
2045 script_set_env(ip->client, prefix, "filename", lease->filename);
2046 if (lease->server_name)
2047 script_set_env(ip->client, prefix, "server_name",
2048 lease->server_name);
2049 for (i = 0; i < 256; i++) {
2052 if (ip->client->config->defaults[i].len) {
2053 if (lease->options[i].len) {
2055 ip->client->config->default_actions[i]) {
2056 case ACTION_DEFAULT:
2057 dp = lease->options[i].data;
2058 len = lease->options[i].len;
2060 case ACTION_SUPERSEDE:
2063 config->defaults[i].data;
2065 config->defaults[i].len;
2067 case ACTION_PREPEND:
2069 config->defaults[i].len +
2070 lease->options[i].len;
2071 if (len >= sizeof(dbuf)) {
2072 warning("no space to %s %s",
2074 dhcp_options[i].name);
2080 config->defaults[i].data,
2082 config->defaults[i].len);
2083 memcpy(dp + ip->client->
2084 config->defaults[i].len,
2085 lease->options[i].data,
2086 lease->options[i].len);
2091 * When we append, we assume that we're
2092 * appending to text. Some MS servers
2093 * include a NUL byte at the end of
2094 * the search string provided.
2097 config->defaults[i].len +
2098 lease->options[i].len;
2099 if (len >= sizeof(dbuf)) {
2100 warning("no space to %s %s",
2102 dhcp_options[i].name);
2106 lease->options[i].data,
2107 lease->options[i].len);
2108 for (dp = dbuf + lease->options[i].len;
2109 dp > dbuf; dp--, len--)
2114 config->defaults[i].data,
2116 config->defaults[i].len);
2122 config->defaults[i].data;
2124 config->defaults[i].len;
2126 } else if (lease->options[i].len) {
2127 len = lease->options[i].len;
2128 dp = lease->options[i].data;
2135 if (dhcp_option_ev_name(name, sizeof(name),
2137 script_set_env(ip->client, prefix, name,
2138 pretty_print_option(i, dp, len, 0, 0));
2141 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
2142 script_set_env(ip->client, prefix, "expiry", tbuf);
2146 script_write_params(char *prefix, struct client_lease *lease)
2148 size_t fn_len = 0, sn_len = 0, pr_len = 0;
2149 struct imsg_hdr hdr;
2153 if (lease->filename != NULL)
2154 fn_len = strlen(lease->filename);
2155 if (lease->server_name != NULL)
2156 sn_len = strlen(lease->server_name);
2158 pr_len = strlen(prefix);
2160 hdr.code = IMSG_SCRIPT_WRITE_PARAMS;
2161 hdr.len = sizeof(hdr) + sizeof(struct client_lease) +
2162 sizeof(size_t) + fn_len + sizeof(size_t) + sn_len +
2163 sizeof(size_t) + pr_len;
2165 for (i = 0; i < 256; i++)
2166 hdr.len += sizeof(int) + lease->options[i].len;
2168 scripttime = time(NULL);
2170 if ((buf = buf_open(hdr.len)) == NULL)
2171 error("buf_open: %m");
2174 errs += buf_add(buf, &hdr, sizeof(hdr));
2175 errs += buf_add(buf, lease, sizeof(struct client_lease));
2176 errs += buf_add(buf, &fn_len, sizeof(fn_len));
2177 errs += buf_add(buf, lease->filename, fn_len);
2178 errs += buf_add(buf, &sn_len, sizeof(sn_len));
2179 errs += buf_add(buf, lease->server_name, sn_len);
2180 errs += buf_add(buf, &pr_len, sizeof(pr_len));
2181 errs += buf_add(buf, prefix, pr_len);
2183 for (i = 0; i < 256; i++) {
2184 errs += buf_add(buf, &lease->options[i].len,
2185 sizeof(lease->options[i].len));
2186 errs += buf_add(buf, lease->options[i].data,
2187 lease->options[i].len);
2191 error("buf_add: %m");
2193 if (buf_close(privfd, buf) == -1)
2194 error("buf_close: %m");
2200 struct imsg_hdr hdr;
2204 hdr.code = IMSG_SCRIPT_GO;
2205 hdr.len = sizeof(struct imsg_hdr);
2207 if ((buf = buf_open(hdr.len)) == NULL)
2208 error("buf_open: %m");
2210 if (buf_add(buf, &hdr, sizeof(hdr)))
2211 error("buf_add: %m");
2213 if (buf_close(privfd, buf) == -1)
2214 error("buf_close: %m");
2216 bzero(&hdr, sizeof(hdr));
2217 buf_read(privfd, &hdr, sizeof(hdr));
2218 if (hdr.code != IMSG_SCRIPT_GO_RET)
2219 error("unexpected msg type %u", hdr.code);
2220 if (hdr.len != sizeof(hdr) + sizeof(int))
2221 error("received corrupted message");
2222 buf_read(privfd, &ret, sizeof(ret));
2224 scripttime = time(NULL);
2230 priv_script_go(void)
2232 char *scriptName, *argv[2], **envp, *epp[3], reason[] = "REASON=NBI";
2233 static char client_path[] = CLIENT_PATH;
2234 struct interface_info *ip = ifi;
2235 int pid, wpid, wstatus;
2237 scripttime = time(NULL);
2240 scriptName = ip->client->config->script_name;
2241 envp = ip->client->scriptEnv;
2243 scriptName = top_level_config.script_name;
2245 epp[1] = client_path;
2250 argv[0] = scriptName;
2259 wpid = wait(&wstatus);
2260 } while (wpid != pid && wpid > 0);
2266 execve(scriptName, argv, envp);
2267 error("execve (%s, ...): %m", scriptName);
2271 script_flush_env(ip->client);
2273 return (wstatus & 0xff);
2277 script_set_env(struct client_state *client, const char *prefix,
2278 const char *name, const char *value)
2282 /* No `` or $() command substitution allowed in environment values! */
2283 for (j=0; j < strlen(value); j++)
2287 warning("illegal character (%c) in value '%s'",
2289 /* Ignore this option */
2293 namelen = strlen(name);
2295 for (i = 0; client->scriptEnv[i]; i++)
2296 if (strncmp(client->scriptEnv[i], name, namelen) == 0 &&
2297 client->scriptEnv[i][namelen] == '=')
2300 if (client->scriptEnv[i])
2301 /* Reuse the slot. */
2302 free(client->scriptEnv[i]);
2304 /* New variable. Expand if necessary. */
2305 if (i >= client->scriptEnvsize - 1) {
2306 char **newscriptEnv;
2307 int newscriptEnvsize = client->scriptEnvsize + 50;
2309 newscriptEnv = realloc(client->scriptEnv,
2311 if (newscriptEnv == NULL) {
2312 free(client->scriptEnv);
2313 client->scriptEnv = NULL;
2314 client->scriptEnvsize = 0;
2315 error("script_set_env: no memory for variable");
2317 client->scriptEnv = newscriptEnv;
2318 client->scriptEnvsize = newscriptEnvsize;
2320 /* need to set the NULL pointer at end of array beyond
2322 client->scriptEnv[i + 1] = NULL;
2324 /* Allocate space and format the variable in the appropriate slot. */
2325 client->scriptEnv[i] = malloc(strlen(prefix) + strlen(name) + 1 +
2327 if (client->scriptEnv[i] == NULL)
2328 error("script_set_env: no memory for variable assignment");
2329 snprintf(client->scriptEnv[i], strlen(prefix) + strlen(name) +
2330 1 + strlen(value) + 1, "%s%s=%s", prefix, name, value);
2334 script_flush_env(struct client_state *client)
2338 for (i = 0; client->scriptEnv[i]; i++) {
2339 free(client->scriptEnv[i]);
2340 client->scriptEnv[i] = NULL;
2342 client->scriptEnvsize = 0;
2346 dhcp_option_ev_name(char *buf, size_t buflen, struct option *option)
2350 for (i = 0; option->name[i]; i++) {
2351 if (i + 1 == buflen)
2353 if (option->name[i] == '-')
2356 buf[i] = option->name[i];
2366 static int state = 0;
2367 cap_rights_t rights;
2369 if (no_daemon || state)
2374 /* Stop logging to stderr... */
2377 if (daemon(1, 0) == -1)
2380 cap_rights_init(&rights);
2382 if (pidfile != NULL) {
2383 pidfile_write(pidfile);
2384 if (cap_rights_limit(pidfile_fileno(pidfile), &rights) < 0 &&
2386 error("can't limit pidfile descriptor: %m");
2390 /* we are chrooted, daemon(3) fails to open /dev/null */
2392 dup2(nullfd, STDIN_FILENO);
2393 dup2(nullfd, STDOUT_FILENO);
2394 dup2(nullfd, STDERR_FILENO);
2399 if (cap_rights_limit(STDIN_FILENO, &rights) < 0 && errno != ENOSYS)
2400 error("can't limit stdin: %m");
2401 cap_rights_init(&rights, CAP_WRITE);
2402 if (cap_rights_limit(STDOUT_FILENO, &rights) < 0 && errno != ENOSYS)
2403 error("can't limit stdout: %m");
2404 if (cap_rights_limit(STDERR_FILENO, &rights) < 0 && errno != ENOSYS)
2405 error("can't limit stderr: %m");
2409 check_option(struct client_lease *l, int option)
2414 /* we use this, since this is what gets passed to dhclient-script */
2416 opbuf = pretty_print_option(option, l->options[option].data,
2417 l->options[option].len, 0, 0);
2419 sbuf = option_as_string(option, l->options[option].data,
2420 l->options[option].len);
2423 case DHO_SUBNET_MASK:
2424 case DHO_TIME_SERVERS:
2425 case DHO_NAME_SERVERS:
2427 case DHO_DOMAIN_NAME_SERVERS:
2428 case DHO_LOG_SERVERS:
2429 case DHO_COOKIE_SERVERS:
2430 case DHO_LPR_SERVERS:
2431 case DHO_IMPRESS_SERVERS:
2432 case DHO_RESOURCE_LOCATION_SERVERS:
2433 case DHO_SWAP_SERVER:
2434 case DHO_BROADCAST_ADDRESS:
2435 case DHO_NIS_SERVERS:
2436 case DHO_NTP_SERVERS:
2437 case DHO_NETBIOS_NAME_SERVERS:
2438 case DHO_NETBIOS_DD_SERVER:
2439 case DHO_FONT_SERVERS:
2440 case DHO_DHCP_SERVER_IDENTIFIER:
2441 case DHO_NISPLUS_SERVERS:
2442 case DHO_MOBILE_IP_HOME_AGENT:
2443 case DHO_SMTP_SERVER:
2444 case DHO_POP_SERVER:
2445 case DHO_NNTP_SERVER:
2446 case DHO_WWW_SERVER:
2447 case DHO_FINGER_SERVER:
2448 case DHO_IRC_SERVER:
2449 case DHO_STREETTALK_SERVER:
2450 case DHO_STREETTALK_DA_SERVER:
2451 if (!ipv4addrs(opbuf)) {
2452 warning("Invalid IP address in option: %s", opbuf);
2457 case DHO_NIS_DOMAIN:
2458 case DHO_NISPLUS_DOMAIN:
2459 case DHO_TFTP_SERVER_NAME:
2460 if (!res_hnok(sbuf)) {
2461 warning("Bogus Host Name option %d: %s (%s)", option,
2463 l->options[option].len = 0;
2464 free(l->options[option].data);
2467 case DHO_DOMAIN_NAME:
2468 case DHO_DOMAIN_SEARCH:
2469 if (!res_hnok(sbuf)) {
2470 if (!check_search(sbuf)) {
2471 warning("Bogus domain search list %d: %s (%s)",
2472 option, sbuf, opbuf);
2473 l->options[option].len = 0;
2474 free(l->options[option].data);
2479 case DHO_TIME_OFFSET:
2481 case DHO_MERIT_DUMP:
2483 case DHO_EXTENSIONS_PATH:
2484 case DHO_IP_FORWARDING:
2485 case DHO_NON_LOCAL_SOURCE_ROUTING:
2486 case DHO_POLICY_FILTER:
2487 case DHO_MAX_DGRAM_REASSEMBLY:
2488 case DHO_DEFAULT_IP_TTL:
2489 case DHO_PATH_MTU_AGING_TIMEOUT:
2490 case DHO_PATH_MTU_PLATEAU_TABLE:
2491 case DHO_INTERFACE_MTU:
2492 case DHO_ALL_SUBNETS_LOCAL:
2493 case DHO_PERFORM_MASK_DISCOVERY:
2494 case DHO_MASK_SUPPLIER:
2495 case DHO_ROUTER_DISCOVERY:
2496 case DHO_ROUTER_SOLICITATION_ADDRESS:
2497 case DHO_STATIC_ROUTES:
2498 case DHO_TRAILER_ENCAPSULATION:
2499 case DHO_ARP_CACHE_TIMEOUT:
2500 case DHO_IEEE802_3_ENCAPSULATION:
2501 case DHO_DEFAULT_TCP_TTL:
2502 case DHO_TCP_KEEPALIVE_INTERVAL:
2503 case DHO_TCP_KEEPALIVE_GARBAGE:
2504 case DHO_VENDOR_ENCAPSULATED_OPTIONS:
2505 case DHO_NETBIOS_NODE_TYPE:
2506 case DHO_NETBIOS_SCOPE:
2507 case DHO_X_DISPLAY_MANAGER:
2508 case DHO_DHCP_REQUESTED_ADDRESS:
2509 case DHO_DHCP_LEASE_TIME:
2510 case DHO_DHCP_OPTION_OVERLOAD:
2511 case DHO_DHCP_MESSAGE_TYPE:
2512 case DHO_DHCP_PARAMETER_REQUEST_LIST:
2513 case DHO_DHCP_MESSAGE:
2514 case DHO_DHCP_MAX_MESSAGE_SIZE:
2515 case DHO_DHCP_RENEWAL_TIME:
2516 case DHO_DHCP_REBINDING_TIME:
2517 case DHO_DHCP_CLASS_IDENTIFIER:
2518 case DHO_DHCP_CLIENT_IDENTIFIER:
2519 case DHO_BOOTFILE_NAME:
2520 case DHO_DHCP_USER_CLASS_ID:
2523 case DHO_CLASSLESS_ROUTES:
2524 return (check_classless_option(l->options[option].data,
2525 l->options[option].len));
2527 warning("unknown dhcp option value 0x%x", option);
2528 return (unknown_ok);
2532 /* RFC 3442 The Classless Static Routes option checks */
2534 check_classless_option(unsigned char *data, int len)
2537 unsigned char width;
2538 in_addr_t addr, mask;
2541 warning("Too small length: %d", len);
2549 } else if (width < 9) {
2550 addr = (in_addr_t)(data[i] << 24);
2552 } else if (width < 17) {
2553 addr = (in_addr_t)(data[i] << 24) +
2554 (in_addr_t)(data[i + 1] << 16);
2556 } else if (width < 25) {
2557 addr = (in_addr_t)(data[i] << 24) +
2558 (in_addr_t)(data[i + 1] << 16) +
2559 (in_addr_t)(data[i + 2] << 8);
2561 } else if (width < 33) {
2562 addr = (in_addr_t)(data[i] << 24) +
2563 (in_addr_t)(data[i + 1] << 16) +
2564 (in_addr_t)(data[i + 2] << 8) +
2568 warning("Incorrect subnet width: %d", width);
2571 mask = (in_addr_t)(~0) << (32 - width);
2577 * ... After deriving a subnet number and subnet mask
2578 * from each destination descriptor, the DHCP client
2579 * MUST zero any bits in the subnet number where the
2580 * corresponding bit in the mask is zero...
2582 if ((addr & mask) != addr) {
2584 data[i - 1] = (unsigned char)(
2585 (addr >> (((32 - width)/8)*8)) & 0xFF);
2590 warning("Incorrect data length: %d (must be %d)", len, i);
2597 res_hnok(const char *dn)
2599 int pch = PERIOD, ch = *dn++;
2601 while (ch != '\0') {
2604 if (periodchar(ch)) {
2606 } else if (periodchar(pch)) {
2607 if (!borderchar(ch))
2609 } else if (periodchar(nch) || nch == '\0') {
2610 if (!borderchar(ch))
2613 if (!middlechar(ch))
2622 check_search(const char *srch)
2624 int pch = PERIOD, ch = *srch++;
2627 /* 256 char limit re resolv.conf(5) */
2628 if (strlen(srch) > 256)
2631 while (whitechar(ch))
2634 while (ch != '\0') {
2637 if (periodchar(ch) || whitechar(ch)) {
2639 } else if (periodchar(pch)) {
2640 if (!borderchar(ch))
2642 } else if (periodchar(nch) || nch == '\0') {
2643 if (!borderchar(ch))
2646 if (!middlechar(ch))
2649 if (!whitechar(ch)) {
2652 while (whitechar(nch)) {
2661 /* 6 domain limit re resolv.conf(5) */
2667 /* Does buf consist only of dotted decimal ipv4 addrs?
2668 * return how many if so,
2669 * otherwise, return 0
2672 ipv4addrs(char * buf)
2677 while (inet_aton(buf, &jnk) == 1){
2679 while (periodchar(*buf) || digitchar(*buf))
2691 option_as_string(unsigned int code, unsigned char *data, int len)
2693 static char optbuf[32768]; /* XXX */
2695 int opleft = sizeof(optbuf);
2696 unsigned char *dp = data;
2699 error("option_as_string: bad code %d", code);
2701 for (; dp < data + len; dp++) {
2702 if (!isascii(*dp) || !isprint(*dp)) {
2703 if (dp + 1 != data + len || *dp != 0) {
2704 snprintf(op, opleft, "\\%03o", *dp);
2708 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
2709 *dp == '`' || *dp == '\\') {
2723 warning("dhcp option too large");
2728 fork_privchld(int fd, int fd2)
2730 struct pollfd pfd[1];
2735 error("cannot fork");
2742 setproctitle("%s [priv]", ifi->name);
2745 dup2(nullfd, STDIN_FILENO);
2746 dup2(nullfd, STDOUT_FILENO);
2747 dup2(nullfd, STDERR_FILENO);
2755 pfd[0].events = POLLIN;
2756 if ((nfds = poll(pfd, 1, INFTIM)) == -1)
2758 error("poll error");
2760 if (nfds == 0 || !(pfd[0].revents & POLLIN))
2763 dispatch_imsg(ifi, fd);