2 * Copyright 2004 Henning Brauer <henning@openbsd.org>
3 * Copyright (c) 1995, 1996, 1997, 1998, 1999
4 * The Internet Software Consortium. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of The Internet Software Consortium nor the names
16 * of its contributors may be used to endorse or promote products derived
17 * from this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
20 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
21 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * This software has been written for the Internet Software Consortium
34 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
35 * Enterprises. To learn more about the Internet Software Consortium,
36 * see ``http://www.vix.com/isc''. To learn more about Vixie
37 * Enterprises, see ``http://www.vix.com''.
39 * This client was substantially modified and enhanced by Elliot Poger
40 * for use on Linux while he was working on the MosquitoNet project at
43 * The current version owes much to Elliot's Linux enhancements, but
44 * was substantially reorganized and partially rewritten by Ted Lemon
45 * so as to use the same networking framework that the Internet Software
46 * Consortium DHCP server uses. Much system-specific configuration code
47 * was moved into a shell script so that as support for more operating
48 * systems is added, it will not be necessary to port and maintain
49 * system-specific configuration code to these operating systems - instead,
50 * the shell script can invoke the native tools to accomplish the same
53 #include <sys/ioctl.h>
64 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
65 #define DEFAULT_LEASE_TIME 43200 /* 12 hours... */
66 #define TIME_MAX 2147483647
67 #define POLL_FAILURES 10
68 #define POLL_FAILURE_WAIT 1 /* Back off multiplier (seconds) */
70 char *path_dhclient_conf
= _PATH_DHCLIENT_CONF
;
71 char *path_dhclient_db
= NULL
;
83 struct iaddr iaddr_broadcast
= { 4, { 255, 255, 255, 255 } };
84 struct in_addr inaddr_any
;
85 struct sockaddr_in sockaddr_broadcast
;
87 struct interface_info
*ifi
;
88 struct client_state
*client
;
89 struct client_config
*config
;
91 int findproto(char *, int);
92 struct sockaddr
*get_ifa(char *, int);
93 void usage(void) __dead2
;
94 int check_option(struct client_lease
*l
, int option
);
95 int check_classless_option(unsigned char *data
, int len
);
96 int ipv4addrs(char * buf
);
97 int res_hnok(const char *dn
);
98 char *option_as_string(unsigned int code
, unsigned char *data
, int len
);
99 int fork_privchld(int, int);
100 void get_ifname(char *, char *);
101 static void sig_handle(int sig
);
102 static int killclient(int fd
);
105 static FILE *leaseFile
;
108 findproto(char *cp
, int n
)
115 for (i
= 1; i
; i
<<= 1) {
117 sa
= (struct sockaddr
*)cp
;
123 if (sa
->sa_family
== AF_INET
)
125 if (sa
->sa_family
== AF_INET6
)
138 get_ifa(char *cp
, int n
)
145 for (i
= 1; i
; i
<<= 1)
147 sa
= (struct sockaddr
*)cp
;
155 struct iaddr defaddr
= { .len
= 4 }; /* NULL is for silence warnings */
162 struct rt_msghdr
*rtm
;
163 struct if_msghdr
*ifm
;
164 struct ifa_msghdr
*ifam
;
165 struct if_announcemsghdr
*ifan
;
166 struct client_lease
*l
;
170 char *errmsg
, buf
[64];
173 n
= read(routefd
, &msg
, sizeof(msg
));
174 } while (n
== -1 && errno
== EINTR
);
176 rtm
= (struct rt_msghdr
*)msg
;
177 if (n
< sizeof(rtm
->rtm_msglen
) || n
< rtm
->rtm_msglen
||
178 rtm
->rtm_version
!= RTM_VERSION
)
181 switch (rtm
->rtm_type
) {
183 ifam
= (struct ifa_msghdr
*)rtm
;
184 if (ifam
->ifam_index
!= ifi
->index
)
186 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
188 sa
= get_ifa((char *)(ifam
+ 1), ifam
->ifam_addrs
);
190 errmsg
= "sa == NULL";
194 if ((a
.len
= sizeof(struct in_addr
)) > sizeof(a
.iabuf
))
195 error("king bula sez: len mismatch");
196 memcpy(a
.iabuf
, &((struct sockaddr_in
*)sa
)->sin_addr
, a
.len
);
197 if (addr_eq(a
, defaddr
))
200 /* state_panic() can try unexpired existing leases */
201 if (client
->active
&& addr_eq(a
, client
->active
->address
))
203 for (l
= client
->leases
; l
!= NULL
; l
= l
->next
)
204 if (addr_eq(a
, l
->address
))
208 /* new addr is the one we set */
210 snprintf(buf
, sizeof(buf
), "%s: %s",
211 "new address not one we set", piaddr(a
));
215 ifam
= (struct ifa_msghdr
*)rtm
;
216 if (ifam
->ifam_index
!= ifi
->index
)
218 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
220 /* XXX check addrs like RTM_NEWADDR instead of this? */
221 if (scripttime
== 0 || time(NULL
) < scripttime
+ 10)
223 errmsg
= "interface address deleted";
226 ifm
= (struct if_msghdr
*)rtm
;
227 if (ifm
->ifm_index
!= ifi
->index
)
229 if ((rtm
->rtm_flags
& RTF_UP
) == 0) {
230 errmsg
= "interface down";
235 LINK_STATE_IS_UP(ifm
->ifm_data
.ifi_link_state
) ? 1 : 0;
236 if (linkstat
!= ifi
->linkstat
) {
238 debug("link state %s -> %s",
239 ifi
->linkstat
? "up" : "down",
240 linkstat
? "up" : "down");
242 ifi
->linkstat
= interface_status(ifi
->name
);
244 client
->state
= S_REBOOTING
;
250 ifan
= (struct if_announcemsghdr
*)rtm
;
251 if (ifan
->ifan_what
== IFAN_DEPARTURE
&&
252 ifan
->ifan_index
== ifi
->index
) {
253 errmsg
= "interface departure";
265 error("routehandler: %s", errmsg
);
269 main(int argc
, char *argv
[])
274 int dokillclient
= 0;
278 /* Initially, log errors to stderr as well as to syslogd. */
279 openlog(getprogname(), LOG_PID
| LOG_NDELAY
, DHCPD_LOG_FACILITY
);
280 setlogmask(LOG_UPTO(LOG_INFO
));
282 signal(SIGINT
, sig_handle
);
283 signal(SIGHUP
, sig_handle
);
285 while ((ch
= getopt(argc
, argv
, "c:dl:quwx")) != -1) {
288 path_dhclient_conf
= optarg
;
294 path_dhclient_db
= optarg
;
317 * dport wpa_supplicant uses 'start ifc' instead of 'ifc', allow
318 * the 'start' keyword.
321 if (strcmp(argv
[0], "start") == 0) {
325 } else if (strcmp(argv
[0], "stop") == 0) {
334 orig_ifname
= argv
[0];
339 snprintf(buf
, sizeof(buf
),
340 "/var/run/dhclient.%s.pid", orig_ifname
);
341 fd
= open(buf
, O_RDWR
, 0644);
342 if (fd
< 0 || killclient(fd
)) {
344 "no dhclient running on %s\n",
348 "stopping dhclient on %s\n",
356 if ((nullfd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) == -1)
357 error("cannot open %s: %m", _PATH_DEVNULL
);
360 * If asked to stay alive forever get our daemon going right now
361 * Then set up to fork/monitor and refork on exit.
363 * When I say 'forever' I really mean it. If there are configuration
364 * problems or missing interfaces or whatever, dhclient will wait
365 * 10 seconds and try again.
375 omask
= sigblock(sigmask(SIGINT
) | sigmask(SIGHUP
));
381 if (pid
== 0) /* child falls out of loop */
384 rpid
= waitpid(pid
, NULL
, 0);
394 ifi
= calloc(1, sizeof(*ifi
));
397 client
= calloc(1, sizeof(*client
));
399 error("client calloc");
400 config
= calloc(1, sizeof(*config
));
402 error("config calloc");
404 get_ifname(ifi
->name
, argv
[0]);
406 if (path_dhclient_db
== NULL
&& asprintf(&path_dhclient_db
, "%s.%s",
407 _PATH_DHCLIENT_DB
, ifi
->name
) == -1)
415 memset(&sockaddr_broadcast
, 0, sizeof(sockaddr_broadcast
));
416 sockaddr_broadcast
.sin_family
= AF_INET
;
417 sockaddr_broadcast
.sin_port
= htons(REMOTE_PORT
);
418 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
419 sockaddr_broadcast
.sin_len
= sizeof(sockaddr_broadcast
);
420 inaddr_any
.s_addr
= INADDR_ANY
;
424 if (interface_status(ifi
->name
) == 0) {
425 interface_link_forceup(ifi
->name
);
426 /* Give it up to 4 seconds of silent grace to find link */
432 while (!(ifi
->linkstat
= interface_status(ifi
->name
))) {
434 fprintf(stderr
, "%s: no link ...", ifi
->name
);
436 fprintf(stderr
, ".");
438 if (++i
> config
->link_timeout
) {
439 fprintf(stderr
, " sleeping\n");
445 fprintf(stderr
, " got link\n");
448 if ((pw
= getpwnam("_dhcp")) == NULL
)
449 error("no such user: _dhcp");
451 if (pipe(pipe_fd
) == -1)
455 fork_privchld(pipe_fd
[0], pipe_fd
[1]);
460 if ((fd
= open(path_dhclient_db
, O_RDONLY
|O_EXLOCK
|O_CREAT
, 0)) == -1)
461 error("can't open and lock %s: %m", path_dhclient_db
);
462 read_client_leases();
463 if ((leaseFile
= fopen(path_dhclient_db
, "w")) == NULL
)
464 error("can't open %s: %m", path_dhclient_db
);
465 rewrite_client_leases();
468 if ((routefd
= socket(PF_ROUTE
, SOCK_RAW
, 0)) == -1)
469 error("socket(PF_ROUTE, SOCK_RAW): %m");
471 /* set up the interface */
472 discover_interface();
474 if (chroot(_PATH_VAREMPTY
) == -1)
476 if (chdir("/") == -1)
477 error("chdir(\"/\")");
479 if (setresgid(pw
->pw_gid
, pw
->pw_gid
, pw
->pw_gid
) == -1)
481 if (setgroups(1, &pw
->pw_gid
) == -1)
483 if (setresuid(pw
->pw_uid
, pw
->pw_uid
, pw
->pw_uid
) == -1)
488 setproctitle("%s", ifi
->name
);
491 client
->state
= S_REBOOTING
;
503 fprintf(stderr
, "usage: %s [-dqu] [-c file] [-l file] interface\n",
511 * Each routine is called from the dhclient_state_machine() in one of
513 * -> entering INIT state
514 * -> recvpacket_flag == 0: timeout in this state
515 * -> otherwise: received a packet in this state
517 * Return conditions as handled by dhclient_state_machine():
518 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
519 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
520 * Returns 0: finish the nap which was interrupted for no good reason.
522 * Several per-interface variables are used to keep track of the process:
523 * active_lease: the lease that is being used on the interface
524 * (null pointer if not configured yet).
525 * offered_leases: leases corresponding to DHCPOFFER messages that have
526 * been sent to us by DHCP servers.
527 * acked_leases: leases corresponding to DHCPACK messages that have been
528 * sent to us by DHCP servers.
529 * sendpacket: DHCP packet we're trying to send.
530 * destination: IP address to send sendpacket to
531 * In addition, there are several relevant per-lease variables.
532 * T1_expiry, T2_expiry, lease_expiry: lease milestones
533 * In the active lease, these control the process of renewing the lease;
534 * In leases on the acked_leases list, this simply determines when we
535 * can no longer legitimately use the lease.
540 /* Cancel all timeouts, since a link state change gets us here
541 and can happen anytime. */
544 /* If we don't remember an active lease, go straight to INIT. */
545 if (!client
->active
|| client
->active
->is_bootp
) {
546 client
->state
= S_INIT
;
551 /* make_request doesn't initialize xid because it normally comes
552 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
553 so pick an xid now. */
554 client
->xid
= arc4random();
556 /* Make a DHCPREQUEST packet, and set appropriate per-interface
558 make_request(client
->active
);
559 client
->destination
= iaddr_broadcast
;
560 client
->first_sending
= time(NULL
);
561 client
->interval
= 0;
567 * Called when a lease has completely expired and we've
568 * been unable to renew it.
573 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
575 make_discover(client
->active
);
576 client
->xid
= client
->packet
.xid
;
577 client
->destination
= iaddr_broadcast
;
578 client
->state
= S_SELECTING
;
579 client
->first_sending
= time(NULL
);
580 client
->interval
= 0;
586 * state_selecting is called when one or more DHCPOFFER packets
587 * have been received and a configurable period of time has passed.
590 state_selecting(void)
592 struct client_lease
*lp
, *next
, *picked
;
595 /* Cancel state_selecting and send_discover timeouts, since either
596 one could have got us here. */
599 /* We have received one or more DHCPOFFER packets. Currently,
600 the only criterion by which we judge leases is whether or
601 not we get a response when we arp for them. */
603 for (lp
= client
->offered_leases
; lp
; lp
= next
) {
611 free_client_lease(lp
);
614 client
->offered_leases
= NULL
;
616 /* If we just tossed all the leases we were offered, go back
619 client
->state
= S_INIT
;
627 /* If it was a BOOTREPLY, we can just take the address right now. */
628 if (!picked
->options
[DHO_DHCP_MESSAGE_TYPE
].len
) {
629 client
->new = picked
;
631 /* Make up some lease expiry times
632 XXX these should be configurable. */
633 client
->new->expiry
= cur_time
+ 12000;
634 client
->new->renewal
+= cur_time
+ 8000;
635 client
->new->rebind
+= cur_time
+ 10000;
637 client
->state
= S_REQUESTING
;
639 /* Bind to the address we received. */
644 /* Go to the REQUESTING state. */
645 client
->destination
= iaddr_broadcast
;
646 client
->state
= S_REQUESTING
;
647 client
->first_sending
= cur_time
;
648 client
->interval
= 0;
650 /* Make a DHCPREQUEST packet from the lease we picked. */
651 make_request(picked
);
652 client
->xid
= client
->packet
.xid
;
654 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
655 free_client_lease(picked
);
661 dhcpack(struct iaddr client_addr
, struct option_data
*options
)
663 struct client_lease
*lease
;
667 if (client
->state
!= S_REBOOTING
&&
668 client
->state
!= S_REQUESTING
&&
669 client
->state
!= S_RENEWING
&&
670 client
->state
!= S_REBINDING
)
674 lease
= packet_to_lease(options
);
676 note("packet_to_lease failed.");
682 /* Stop resending DHCPREQUEST. */
685 /* Figure out the lease time. */
686 if (client
->new->options
[DHO_DHCP_LEASE_TIME
].data
)
687 client
->new->expiry
=
688 getULong(client
->new->options
[DHO_DHCP_LEASE_TIME
].data
);
690 client
->new->expiry
= DEFAULT_LEASE_TIME
;
691 /* A number that looks negative here is really just very large,
692 because the lease expiry offset is unsigned. */
693 if (client
->new->expiry
< 0)
694 client
->new->expiry
= TIME_MAX
;
695 /* XXX should be fixed by resetting the client state */
696 if (client
->new->expiry
< 60)
697 client
->new->expiry
= 60;
699 /* Take the server-provided renewal time if there is one;
700 otherwise figure it out according to the spec. */
701 if (client
->new->options
[DHO_DHCP_RENEWAL_TIME
].len
)
702 client
->new->renewal
=
703 getULong(client
->new->options
[DHO_DHCP_RENEWAL_TIME
].data
);
705 client
->new->renewal
= client
->new->expiry
/ 2;
707 /* Same deal with the rebind time. */
708 if (client
->new->options
[DHO_DHCP_REBINDING_TIME
].len
)
709 client
->new->rebind
=
710 getULong(client
->new->options
[DHO_DHCP_REBINDING_TIME
].data
);
712 client
->new->rebind
= client
->new->renewal
+
713 client
->new->renewal
/ 2 + client
->new->renewal
/ 4;
717 client
->new->expiry
+= cur_time
;
718 /* Lease lengths can never be negative. */
719 if (client
->new->expiry
< cur_time
)
720 client
->new->expiry
= TIME_MAX
;
721 client
->new->renewal
+= cur_time
;
722 if (client
->new->renewal
< cur_time
)
723 client
->new->renewal
= TIME_MAX
;
724 client
->new->rebind
+= cur_time
;
725 if (client
->new->rebind
< cur_time
)
726 client
->new->rebind
= TIME_MAX
;
734 /* Run the client script with the new parameters. */
735 script_init((client
->state
== S_REQUESTING
? "BOUND" :
736 (client
->state
== S_RENEWING
? "RENEW" :
737 (client
->state
== S_REBOOTING
? "REBOOT" : "REBIND"))));
738 if (client
->active
&& client
->state
!= S_REBOOTING
)
739 script_write_params("old_", client
->active
);
740 script_write_params("new_", client
->new);
743 /* Replace the old active lease with the new one. */
745 free_client_lease(client
->active
);
746 client
->active
= client
->new;
749 /* Write out new leases file. */
750 rewrite_client_leases();
752 /* Set timeout to start the renewal process. */
753 set_timeout(client
->active
->renewal
, state_bound
);
755 note("bound to %s -- renewal in %lld seconds.",
756 piaddr(client
->active
->address
),
757 (long long)(client
->active
->renewal
- time(NULL
)));
758 client
->state
= S_BOUND
;
762 * state_bound is called when we've successfully bound to a particular
763 * lease, but the renewal time on that lease has expired. We are
764 * expected to unicast a DHCPREQUEST to the server that gave us our
770 /* T1 has expired. */
771 make_request(client
->active
);
772 client
->xid
= client
->packet
.xid
;
774 if (client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].len
== 4) {
775 memcpy(client
->destination
.iabuf
,
776 client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].data
,
778 client
->destination
.len
= 4;
780 client
->destination
= iaddr_broadcast
;
782 client
->first_sending
= time(NULL
);
783 client
->interval
= 0;
784 client
->state
= S_RENEWING
;
790 dhcpoffer(struct iaddr client_addr
, struct option_data
*options
)
792 struct client_lease
*lease
, *lp
;
794 time_t stop_selecting
;
795 char *name
= options
[DHO_DHCP_MESSAGE_TYPE
].len
? "DHCPOFFER" :
799 if (client
->state
!= S_SELECTING
)
803 /* If this lease doesn't supply the minimum required parameters,
805 for (i
= 0; config
->required_options
[i
]; i
++) {
806 if (!options
[config
->required_options
[i
]].len
) {
807 note("%s isn't satisfactory.", name
);
812 /* If we've already seen this lease, don't record it again. */
813 for (lease
= client
->offered_leases
;
814 lease
; lease
= lease
->next
) {
815 if (lease
->address
.len
== sizeof(client
->packet
.yiaddr
) &&
816 !memcmp(lease
->address
.iabuf
,
817 &client
->packet
.yiaddr
, lease
->address
.len
)) {
819 debug("%s already seen.", name
);
825 lease
= packet_to_lease(options
);
827 note("packet_to_lease failed.");
832 * Reject offers whose subnet is already configured on another
835 if (subnet_exists(lease
))
838 /* If this lease was acquired through a BOOTREPLY, record that
840 if (!options
[DHO_DHCP_MESSAGE_TYPE
].len
)
843 /* Figure out when we're supposed to stop selecting. */
844 stop_selecting
= client
->first_sending
+ config
->select_interval
;
846 /* If this is the lease we asked for, put it at the head of the
847 list, and don't mess with the arp request timeout. */
848 if (addr_eq(lease
->address
, client
->requested_address
)) {
849 lease
->next
= client
->offered_leases
;
850 client
->offered_leases
= lease
;
852 /* Put the lease at the end of the list. */
854 if (!client
->offered_leases
)
855 client
->offered_leases
= lease
;
857 for (lp
= client
->offered_leases
; lp
->next
;
864 /* If the selecting interval has expired, go immediately to
865 state_selecting(). Otherwise, time out into
866 state_selecting at the select interval. */
867 if (stop_selecting
<= time(NULL
))
870 set_timeout(stop_selecting
, state_selecting
);
875 * Allocate a client_lease structure and initialize it from the
876 * parameters in the specified packet.
878 struct client_lease
*
879 packet_to_lease(struct option_data
*options
)
881 struct client_lease
*lease
;
884 lease
= malloc(sizeof(struct client_lease
));
887 warning("dhcpoffer: no memory to record lease.");
891 memset(lease
, 0, sizeof(*lease
));
893 /* Copy the lease options. */
894 for (i
= 0; i
< 256; i
++) {
895 if (options
[i
].len
) {
896 lease
->options
[i
] = options
[i
];
897 options
[i
].data
= NULL
;
899 if (!check_option(lease
, i
)) {
900 warning("Invalid lease option - ignoring offer");
901 free_client_lease(lease
);
907 lease
->address
.len
= sizeof(client
->packet
.yiaddr
);
908 memcpy(lease
->address
.iabuf
, &client
->packet
.yiaddr
,
911 /* If the server name was filled out, copy it. */
912 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
913 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 2)) &&
914 client
->packet
.sname
[0]) {
915 lease
->server_name
= malloc(DHCP_SNAME_LEN
+ 1);
916 if (!lease
->server_name
) {
917 warning("dhcpoffer: no memory for server name.");
918 free_client_lease(lease
);
921 memcpy(lease
->server_name
, client
->packet
.sname
,
923 lease
->server_name
[DHCP_SNAME_LEN
] = '\0';
924 if (!res_hnok(lease
->server_name
)) {
925 warning("Bogus server name %s", lease
->server_name
);
926 free(lease
->server_name
);
927 lease
->server_name
= NULL
;
931 /* Ditto for the filename. */
932 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
933 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 1)) &&
934 client
->packet
.file
[0]) {
935 /* Don't count on the NUL terminator. */
936 lease
->filename
= malloc(DHCP_FILE_LEN
+ 1);
937 if (!lease
->filename
) {
938 warning("dhcpoffer: no memory for filename.");
939 free_client_lease(lease
);
942 memcpy(lease
->filename
, client
->packet
.file
, DHCP_FILE_LEN
);
943 lease
->filename
[DHCP_FILE_LEN
] = '\0';
949 dhcpnak(struct iaddr client_addr
, struct option_data
*options
)
952 if (client
->state
!= S_REBOOTING
&&
953 client
->state
!= S_REQUESTING
&&
954 client
->state
!= S_RENEWING
&&
955 client
->state
!= S_REBINDING
)
959 if (!client
->active
) {
960 note("DHCPNAK with no active lease.");
964 free_client_lease(client
->active
);
965 client
->active
= NULL
;
967 /* Stop sending DHCPREQUEST packets... */
970 client
->state
= S_INIT
;
975 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
976 * one after the right interval has expired. If we don't get an offer by
977 * the time we reach the panic interval, call the panic function.
983 int interval
, increase
= 1;
987 /* Figure out how long it's been since we started transmitting. */
988 interval
= cur_time
- client
->first_sending
;
990 /* If we're past the panic timeout, call the script and tell it
991 we haven't found anything for this interface yet. */
992 if (interval
> config
->timeout
) {
998 * If we're supposed to increase the interval, do so. If it's
999 * currently zero (i.e., we haven't sent any packets yet), set
1000 * it to initial_interval; otherwise, add to it a random
1001 * number between zero and two times itself. On average, this
1002 * means that it will double with every transmission.
1005 if (!client
->interval
)
1006 client
->interval
= config
->initial_interval
;
1008 client
->interval
+= (arc4random() >> 2) %
1009 (2 * client
->interval
);
1012 /* Don't backoff past cutoff. */
1013 if (client
->interval
> config
->backoff_cutoff
)
1014 client
->interval
= ((config
->backoff_cutoff
/ 2)
1015 + ((arc4random() >> 2) %
1016 config
->backoff_cutoff
));
1017 } else if (!client
->interval
)
1018 client
->interval
= config
->initial_interval
;
1020 /* If the backoff would take us to the panic timeout, just use that
1022 if (cur_time
+ client
->interval
>
1023 client
->first_sending
+ config
->timeout
)
1024 client
->interval
= (client
->first_sending
+
1025 config
->timeout
) - cur_time
+ 1;
1027 /* Record the number of seconds since we started sending. */
1028 if (interval
< 65536)
1029 client
->packet
.secs
= htons(interval
);
1031 client
->packet
.secs
= htons(65535);
1032 client
->secs
= client
->packet
.secs
;
1034 note("DHCPDISCOVER on %s to %s port %d interval %ld",
1035 ifi
->name
, inet_ntoa(sockaddr_broadcast
.sin_addr
),
1036 ntohs(sockaddr_broadcast
.sin_port
), client
->interval
);
1038 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1040 set_timeout_interval(client
->interval
, send_discover
);
1044 * state_panic gets called if we haven't received any offers in a preset
1045 * amount of time. When this happens, we try to use existing leases
1046 * that haven't yet expired, and failing that, we call the client script
1047 * and hope it can do something.
1052 struct client_lease
*loop
= client
->active
;
1053 struct client_lease
*lp
;
1056 note("No DHCPOFFERS received.");
1058 /* We may not have an active lease, but we may have some
1059 predefined leases that we can try. */
1060 if (!client
->active
&& client
->leases
)
1063 /* Run through the list of leases and see if one can be used. */
1065 while (client
->active
) {
1066 if (client
->active
->expiry
> cur_time
) {
1067 note("Trying recorded lease %s",
1068 piaddr(client
->active
->address
));
1069 /* Run the client script with the existing
1071 script_init("TIMEOUT");
1072 script_write_params("new_", client
->active
);
1074 /* If the old lease is still good and doesn't
1075 yet need renewal, go into BOUND state and
1076 timeout at the renewal time. */
1078 if (cur_time
< client
->active
->renewal
) {
1079 client
->state
= S_BOUND
;
1080 note("bound: renewal in %lld seconds.",
1081 (long long)(client
->active
->renewal
1083 set_timeout(client
->active
->renewal
,
1086 client
->state
= S_BOUND
;
1087 note("bound: immediate renewal.");
1094 /* If there are no other leases, give up. */
1095 if (!client
->leases
) {
1096 client
->leases
= client
->active
;
1097 client
->active
= NULL
;
1102 /* Otherwise, put the active lease at the end of the
1103 lease list, and try another lease.. */
1104 for (lp
= client
->leases
; lp
->next
; lp
= lp
->next
)
1106 lp
->next
= client
->active
;
1108 lp
->next
->next
= NULL
;
1109 client
->active
= client
->leases
;
1110 client
->leases
= client
->leases
->next
;
1112 /* If we already tried this lease, we've exhausted the
1113 set of leases, so we might as well give up for
1115 if (client
->active
== loop
)
1118 loop
= client
->active
;
1121 /* No leases were available, or what was available didn't work, so
1122 tell the shell script that we failed to allocate an address,
1123 and try again later. */
1124 note("No working leases in persistent database - sleeping.");
1125 script_init("FAIL");
1127 client
->state
= S_INIT
;
1128 set_timeout_interval(config
->retry_interval
, state_init
);
1134 struct sockaddr_in destination
;
1135 struct in_addr from
;
1141 /* Figure out how long it's been since we started transmitting. */
1142 interval
= (int)(cur_time
- client
->first_sending
);
1144 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1145 past the reboot timeout, go to INIT and see if we can
1146 DISCOVER an address... */
1147 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1148 means either that we're on a network with no DHCP server,
1149 or that our server is down. In the latter case, assuming
1150 that there is a backup DHCP server, DHCPDISCOVER will get
1151 us a new address, but we could also have successfully
1152 reused our old address. In the former case, we're hosed
1153 anyway. This is not a win-prone situation. */
1154 if ((client
->state
== S_REBOOTING
||
1155 client
->state
== S_REQUESTING
) &&
1156 interval
> config
->reboot_timeout
) {
1157 client
->state
= S_INIT
;
1163 /* If the lease has expired, relinquish the address and go back
1164 to the INIT state. */
1165 if (client
->state
!= S_REQUESTING
&&
1166 cur_time
> client
->active
->expiry
) {
1167 /* Run the client script with the new parameters. */
1168 script_init("EXPIRE");
1169 script_write_params("old_", client
->active
);
1172 client
->state
= S_INIT
;
1177 /* Do the exponential backoff... */
1178 if (!client
->interval
)
1179 client
->interval
= config
->initial_interval
;
1181 client
->interval
+= ((arc4random() >> 2) %
1182 (2 * client
->interval
));
1184 /* Don't backoff past cutoff. */
1185 if (client
->interval
> config
->backoff_cutoff
)
1186 client
->interval
= ((config
->backoff_cutoff
/ 2) +
1187 ((arc4random() >> 2) % client
->interval
));
1189 /* If the backoff would take us to the expiry time, just set the
1190 timeout to the expiry time. */
1191 if (client
->state
!= S_REQUESTING
&& cur_time
+ client
->interval
>
1192 client
->active
->expiry
)
1193 client
->interval
= client
->active
->expiry
- cur_time
+ 1;
1195 /* If the lease T2 time has elapsed, or if we're not yet bound,
1196 broadcast the DHCPREQUEST rather than unicasting. */
1197 memset(&destination
, 0, sizeof(destination
));
1198 if (client
->state
== S_REQUESTING
||
1199 client
->state
== S_REBOOTING
||
1200 cur_time
> client
->active
->rebind
)
1201 destination
.sin_addr
.s_addr
= INADDR_BROADCAST
;
1203 memcpy(&destination
.sin_addr
.s_addr
, client
->destination
.iabuf
,
1204 sizeof(destination
.sin_addr
.s_addr
));
1205 destination
.sin_port
= htons(REMOTE_PORT
);
1206 destination
.sin_family
= AF_INET
;
1207 destination
.sin_len
= sizeof(destination
);
1209 if (client
->state
!= S_REQUESTING
)
1210 memcpy(&from
, client
->active
->address
.iabuf
, sizeof(from
));
1212 from
.s_addr
= INADDR_ANY
;
1214 /* Record the number of seconds since we started sending. */
1215 if (client
->state
== S_REQUESTING
)
1216 client
->packet
.secs
= client
->secs
;
1218 if (interval
< 65536)
1219 client
->packet
.secs
= htons(interval
);
1221 client
->packet
.secs
= htons(65535);
1224 note("DHCPREQUEST on %s to %s port %d", ifi
->name
,
1225 inet_ntoa(destination
.sin_addr
), ntohs(destination
.sin_port
));
1227 send_packet(from
, &destination
, NULL
);
1229 set_timeout_interval(client
->interval
, send_request
);
1235 note("DHCPDECLINE on %s to %s port %d", ifi
->name
,
1236 inet_ntoa(sockaddr_broadcast
.sin_addr
),
1237 ntohs(sockaddr_broadcast
.sin_port
));
1239 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1243 make_discover(struct client_lease
*lease
)
1245 unsigned char discover
= DHCPDISCOVER
;
1246 struct option_data options
[256];
1249 memset(options
, 0, sizeof(options
));
1250 memset(&client
->packet
, 0, sizeof(client
->packet
));
1252 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1253 i
= DHO_DHCP_MESSAGE_TYPE
;
1254 options
[i
].data
= &discover
;
1255 options
[i
].len
= sizeof(discover
);
1257 /* Request the options we want */
1258 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1259 options
[i
].data
= config
->requested_options
;
1260 options
[i
].len
= config
->requested_option_count
;
1262 /* If we had an address, try to get it again. */
1264 client
->requested_address
= lease
->address
;
1265 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1266 options
[i
].data
= lease
->address
.iabuf
;
1267 options
[i
].len
= lease
->address
.len
;
1269 client
->requested_address
.len
= 0;
1271 /* Send any options requested in the config file. */
1272 for (i
= 0; i
< 256; i
++)
1273 if (!options
[i
].data
&&
1274 config
->send_options
[i
].data
) {
1275 options
[i
].data
= config
->send_options
[i
].data
;
1276 options
[i
].len
= config
->send_options
[i
].len
;
1279 /* Set up the option buffer to fit in a minimal UDP packet. */
1280 i
= cons_options(options
);
1281 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1282 error("options do not fit in DHCPDISCOVER packet.");
1283 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1284 if (client
->packet_length
< BOOTP_MIN_LEN
)
1285 client
->packet_length
= BOOTP_MIN_LEN
;
1287 client
->packet
.op
= BOOTREQUEST
;
1288 client
->packet
.htype
= ifi
->hw_address
.htype
;
1289 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1290 client
->packet
.hops
= 0;
1291 client
->packet
.xid
= arc4random();
1292 client
->packet
.secs
= 0; /* filled in by send_discover. */
1293 client
->packet
.flags
= 0;
1295 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1296 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1297 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1298 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1299 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1300 ifi
->hw_address
.hlen
);
1304 make_request(struct client_lease
* lease
)
1306 unsigned char request
= DHCPREQUEST
;
1307 struct option_data options
[256];
1310 memset(options
, 0, sizeof(options
));
1311 memset(&client
->packet
, 0, sizeof(client
->packet
));
1313 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1314 i
= DHO_DHCP_MESSAGE_TYPE
;
1315 options
[i
].data
= &request
;
1316 options
[i
].len
= sizeof(request
);
1318 /* Request the options we want */
1319 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1320 options
[i
].data
= config
->requested_options
;
1321 options
[i
].len
= config
->requested_option_count
;
1323 /* If we are requesting an address that hasn't yet been assigned
1324 to us, use the DHCP Requested Address option. */
1325 if (client
->state
== S_REQUESTING
) {
1326 /* Send back the server identifier... */
1327 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1328 options
[i
].data
= lease
->options
[i
].data
;
1329 options
[i
].len
= lease
->options
[i
].len
;
1331 if (client
->state
== S_REQUESTING
||
1332 client
->state
== S_REBOOTING
) {
1333 client
->requested_address
= lease
->address
;
1334 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1335 options
[i
].data
= lease
->address
.iabuf
;
1336 options
[i
].len
= lease
->address
.len
;
1338 client
->requested_address
.len
= 0;
1340 /* Send any options requested in the config file. */
1341 for (i
= 0; i
< 256; i
++)
1342 if (!options
[i
].data
&& config
->send_options
[i
].data
) {
1343 options
[i
].data
= config
->send_options
[i
].data
;
1344 options
[i
].len
= config
->send_options
[i
].len
;
1347 /* Set up the option buffer to fit in a minimal UDP packet. */
1348 i
= cons_options(options
);
1349 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1350 error("options do not fit in DHCPREQUEST packet.");
1351 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1352 if (client
->packet_length
< BOOTP_MIN_LEN
)
1353 client
->packet_length
= BOOTP_MIN_LEN
;
1355 client
->packet
.op
= BOOTREQUEST
;
1356 client
->packet
.htype
= ifi
->hw_address
.htype
;
1357 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1358 client
->packet
.hops
= 0;
1359 client
->packet
.xid
= client
->xid
;
1360 client
->packet
.secs
= 0; /* Filled in by send_request. */
1361 client
->packet
.flags
= 0;
1363 /* If we own the address we're requesting, put it in ciaddr;
1364 otherwise set ciaddr to zero. */
1365 if (client
->state
== S_BOUND
||
1366 client
->state
== S_RENEWING
||
1367 client
->state
== S_REBINDING
) {
1368 memcpy(&client
->packet
.ciaddr
,
1369 lease
->address
.iabuf
, lease
->address
.len
);
1371 memset(&client
->packet
.ciaddr
, 0,
1372 sizeof(client
->packet
.ciaddr
));
1375 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1376 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1377 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1378 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1379 ifi
->hw_address
.hlen
);
1383 make_decline(struct client_lease
*lease
)
1385 struct option_data options
[256];
1386 unsigned char decline
= DHCPDECLINE
;
1389 memset(options
, 0, sizeof(options
));
1390 memset(&client
->packet
, 0, sizeof(client
->packet
));
1392 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1393 i
= DHO_DHCP_MESSAGE_TYPE
;
1394 options
[i
].data
= &decline
;
1395 options
[i
].len
= sizeof(decline
);
1397 /* Send back the server identifier... */
1398 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1399 options
[i
].data
= lease
->options
[i
].data
;
1400 options
[i
].len
= lease
->options
[i
].len
;
1402 /* Send back the address we're declining. */
1403 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1404 options
[i
].data
= lease
->address
.iabuf
;
1405 options
[i
].len
= lease
->address
.len
;
1407 /* Send the uid if the user supplied one. */
1408 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
1409 if (config
->send_options
[i
].len
) {
1410 options
[i
].data
= config
->send_options
[i
].data
;
1411 options
[i
].len
= config
->send_options
[i
].len
;
1414 /* Set up the option buffer to fit in a minimal UDP packet. */
1415 i
= cons_options(options
);
1416 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1417 error("options do not fit in DHCPDECLINE packet.");
1418 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1419 if (client
->packet_length
< BOOTP_MIN_LEN
)
1420 client
->packet_length
= BOOTP_MIN_LEN
;
1422 client
->packet
.op
= BOOTREQUEST
;
1423 client
->packet
.htype
= ifi
->hw_address
.htype
;
1424 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1425 client
->packet
.hops
= 0;
1426 client
->packet
.xid
= client
->xid
;
1427 client
->packet
.secs
= 0; /* Filled in by send_request. */
1428 client
->packet
.flags
= 0;
1430 /* ciaddr must always be zero. */
1431 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1432 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1433 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1434 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1435 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1436 ifi
->hw_address
.hlen
);
1440 free_client_lease(struct client_lease
*lease
)
1444 if (lease
->server_name
)
1445 free(lease
->server_name
);
1446 if (lease
->filename
)
1447 free(lease
->filename
);
1448 for (i
= 0; i
< 256; i
++) {
1449 if (lease
->options
[i
].len
)
1450 free(lease
->options
[i
].data
);
1456 rewrite_client_leases(void)
1458 struct client_lease
*lp
;
1460 if (!leaseFile
) /* XXX */
1461 error("lease file not open");
1466 for (lp
= client
->leases
; lp
; lp
= lp
->next
) {
1467 if (client
->active
&& addr_eq(lp
->address
,
1468 client
->active
->address
))
1470 write_client_lease(lp
);
1474 write_client_lease(client
->active
);
1477 ftruncate(fileno(leaseFile
), ftello(leaseFile
));
1478 fsync(fileno(leaseFile
));
1482 write_client_lease(struct client_lease
*lease
)
1487 /* If the lease came from the config file, we don't need to stash
1488 a copy in the lease database. */
1489 if (lease
->is_static
)
1492 if (!leaseFile
) /* XXX */
1493 error("lease file not open");
1495 fprintf(leaseFile
, "lease {\n");
1496 if (lease
->is_bootp
)
1497 fprintf(leaseFile
, " bootp;\n");
1498 fprintf(leaseFile
, " interface \"%s\";\n", ifi
->name
);
1499 fprintf(leaseFile
, " fixed-address %s;\n", piaddr(lease
->address
));
1500 if (lease
->filename
)
1501 fprintf(leaseFile
, " filename \"%s\";\n", lease
->filename
);
1502 if (lease
->server_name
)
1503 fprintf(leaseFile
, " server-name \"%s\";\n",
1504 lease
->server_name
);
1505 for (i
= 0; i
< 256; i
++)
1506 if (lease
->options
[i
].len
)
1507 fprintf(leaseFile
, " option %s %s;\n",
1508 dhcp_options
[i
].name
,
1509 pretty_print_option(i
, &lease
->options
[i
], 1));
1511 t
= gmtime(&lease
->renewal
);
1512 fprintf(leaseFile
, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1513 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1514 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1515 t
= gmtime(&lease
->rebind
);
1516 fprintf(leaseFile
, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1517 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1518 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1519 t
= gmtime(&lease
->expiry
);
1520 fprintf(leaseFile
, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1521 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1522 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1523 fprintf(leaseFile
, "}\n");
1528 script_init(char *reason
)
1531 struct imsg_hdr hdr
;
1534 hdr
.code
= IMSG_SCRIPT_INIT
;
1535 hdr
.len
= sizeof(struct imsg_hdr
) + sizeof(size_t) + strlen(reason
);
1536 buf
= buf_open(hdr
.len
);
1538 buf_add(buf
, &hdr
, sizeof(hdr
));
1539 len
= strlen(reason
);
1540 buf_add(buf
, &len
, sizeof(len
));
1541 buf_add(buf
, reason
, len
);
1543 buf_close(privfd
, buf
);
1547 priv_script_init(char *reason
)
1549 client
->scriptEnvsize
= 100;
1550 if (client
->scriptEnv
== NULL
)
1552 calloc(client
->scriptEnvsize
, sizeof(char *));
1553 if (client
->scriptEnv
== NULL
)
1554 error("script_init: no memory for environment");
1556 client
->scriptEnv
[0] = strdup(CLIENT_PATH
);
1557 if (client
->scriptEnv
[0] == NULL
)
1558 error("script_init: no memory for environment");
1560 client
->scriptEnv
[1] = NULL
;
1562 script_set_env("", "interface", ifi
->name
);
1564 script_set_env("", "reason", reason
);
1568 priv_script_write_params(char *prefix
, struct client_lease
*lease
)
1571 struct option_data o
;
1574 script_set_env(prefix
, "ip_address", piaddr(lease
->address
));
1576 if (lease
->options
[DHO_SUBNET_MASK
].len
&&
1577 (lease
->options
[DHO_SUBNET_MASK
].len
<
1578 sizeof(lease
->address
.iabuf
))) {
1579 struct iaddr netmask
, subnet
, broadcast
;
1581 memcpy(netmask
.iabuf
, lease
->options
[DHO_SUBNET_MASK
].data
,
1582 lease
->options
[DHO_SUBNET_MASK
].len
);
1583 netmask
.len
= lease
->options
[DHO_SUBNET_MASK
].len
;
1585 subnet
= subnet_number(lease
->address
, netmask
);
1587 script_set_env(prefix
, "network_number",
1589 if (!lease
->options
[DHO_BROADCAST_ADDRESS
].len
) {
1590 broadcast
= broadcast_addr(subnet
, netmask
);
1592 script_set_env(prefix
,
1593 "broadcast_address",
1599 if (lease
->filename
)
1600 script_set_env(prefix
, "filename", lease
->filename
);
1601 if (lease
->server_name
)
1602 script_set_env(prefix
, "server_name",
1603 lease
->server_name
);
1605 for (i
= 0; i
< 256; i
++) {
1606 if (!dhcp_option_ev_name(buf
, sizeof(buf
), &dhcp_options
[i
]))
1609 switch (config
->default_actions
[i
]) {
1613 case ACTION_DEFAULT
:
1614 if (lease
->options
[i
].len
)
1615 script_set_env(prefix
, buf
,
1616 pretty_print_option(i
, &lease
->options
[i
],
1618 else if (config
->defaults
[i
].len
)
1619 script_set_env(prefix
, buf
,
1620 pretty_print_option(i
, &config
->defaults
[i
],
1624 case ACTION_SUPERSEDE
:
1625 if (config
->defaults
[i
].len
)
1626 script_set_env(prefix
, buf
,
1627 pretty_print_option(i
, &config
->defaults
[i
],
1631 case ACTION_PREPEND
:
1632 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1634 o
.data
= calloc(1, o
.len
);
1636 error("no space to prepend '%s' to %s",
1637 config
->defaults
[i
].data
,
1638 dhcp_options
[i
].name
);
1639 memcpy(o
.data
, config
->defaults
[i
].data
,
1640 config
->defaults
[i
].len
);
1641 memcpy(o
.data
+ config
->defaults
[i
].len
,
1642 lease
->options
[i
].data
,
1643 lease
->options
[i
].len
);
1644 script_set_env(prefix
, buf
,
1645 pretty_print_option(i
, &o
, 0));
1651 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1653 o
.data
= calloc(1, o
.len
);
1655 error("no space to append '%s' to %s",
1656 config
->defaults
[i
].data
,
1657 dhcp_options
[i
].name
);
1658 memcpy(o
.data
, lease
->options
[i
].data
,
1659 lease
->options
[i
].len
);
1660 memcpy(o
.data
+ lease
->options
[i
].len
,
1661 config
->defaults
[i
].data
,
1662 config
->defaults
[i
].len
);
1663 script_set_env(prefix
, buf
,
1664 pretty_print_option(i
, &o
, 0));
1671 snprintf(buf
, sizeof(buf
), "%d", (int)lease
->expiry
);
1672 script_set_env(prefix
, "expiry", buf
);
1676 script_write_params(char *prefix
, struct client_lease
*lease
)
1678 size_t fn_len
= 0, sn_len
= 0, pr_len
= 0;
1679 struct imsg_hdr hdr
;
1683 if (lease
->filename
!= NULL
)
1684 fn_len
= strlen(lease
->filename
);
1685 if (lease
->server_name
!= NULL
)
1686 sn_len
= strlen(lease
->server_name
);
1688 pr_len
= strlen(prefix
);
1690 hdr
.code
= IMSG_SCRIPT_WRITE_PARAMS
;
1691 hdr
.len
= sizeof(hdr
) + sizeof(struct client_lease
) +
1692 sizeof(size_t) + fn_len
+ sizeof(size_t) + sn_len
+
1693 sizeof(size_t) + pr_len
;
1695 for (i
= 0; i
< 256; i
++)
1696 hdr
.len
+= sizeof(int) + lease
->options
[i
].len
;
1698 scripttime
= time(NULL
);
1700 buf
= buf_open(hdr
.len
);
1702 buf_add(buf
, &hdr
, sizeof(hdr
));
1703 buf_add(buf
, lease
, sizeof(struct client_lease
));
1704 buf_add(buf
, &fn_len
, sizeof(fn_len
));
1705 buf_add(buf
, lease
->filename
, fn_len
);
1706 buf_add(buf
, &sn_len
, sizeof(sn_len
));
1707 buf_add(buf
, lease
->server_name
, sn_len
);
1708 buf_add(buf
, &pr_len
, sizeof(pr_len
));
1709 buf_add(buf
, prefix
, pr_len
);
1711 for (i
= 0; i
< 256; i
++) {
1712 buf_add(buf
, &lease
->options
[i
].len
,
1713 sizeof(lease
->options
[i
].len
));
1714 buf_add(buf
, lease
->options
[i
].data
,
1715 lease
->options
[i
].len
);
1718 buf_close(privfd
, buf
);
1724 struct imsg_hdr hdr
;
1728 scripttime
= time(NULL
);
1730 hdr
.code
= IMSG_SCRIPT_GO
;
1731 hdr
.len
= sizeof(struct imsg_hdr
);
1733 buf
= buf_open(hdr
.len
);
1735 buf_add(buf
, &hdr
, sizeof(hdr
));
1736 buf_close(privfd
, buf
);
1738 bzero(&hdr
, sizeof(hdr
));
1739 buf_read(privfd
, &hdr
, sizeof(hdr
));
1740 if (hdr
.code
!= IMSG_SCRIPT_GO_RET
)
1741 error("unexpected msg type %u", hdr
.code
);
1742 if (hdr
.len
!= sizeof(hdr
) + sizeof(int))
1743 error("received corrupted message");
1744 buf_read(privfd
, &ret
, sizeof(ret
));
1750 priv_script_go(void)
1752 char *scriptName
, *argv
[2], **envp
;
1753 int pid
, wpid
, wstatus
;
1755 scripttime
= time(NULL
);
1757 scriptName
= config
->script_name
;
1758 envp
= client
->scriptEnv
;
1760 argv
[0] = scriptName
;
1768 wpid
= wait(&wstatus
);
1769 } while (wpid
!= pid
&& wpid
> 0);
1774 execve(scriptName
, argv
, envp
);
1775 error("execve (%s, ...): %m", scriptName
);
1780 return (WEXITSTATUS(wstatus
));
1784 script_set_env(const char *prefix
, const char *name
, const char *value
)
1788 /* No `` or $() command substitution allowed in environment values! */
1789 for (j
= 0; j
< strlen(value
); j
++)
1793 warning("illegal character (%c) in value '%s'",
1795 /* Ignore this option */
1799 namelen
= strlen(name
);
1801 for (i
= 0; client
->scriptEnv
[i
]; i
++)
1802 if (strncmp(client
->scriptEnv
[i
], name
, namelen
) == 0 &&
1803 client
->scriptEnv
[i
][namelen
] == '=')
1806 if (client
->scriptEnv
[i
])
1807 /* Reuse the slot. */
1808 free(client
->scriptEnv
[i
]);
1810 /* New variable. Expand if necessary. */
1811 if (i
>= client
->scriptEnvsize
- 1) {
1812 char **newscriptEnv
;
1813 int newscriptEnvsize
= client
->scriptEnvsize
+ 50;
1815 newscriptEnv
= realloc(client
->scriptEnv
,
1817 if (newscriptEnv
== NULL
) {
1818 free(client
->scriptEnv
);
1819 client
->scriptEnv
= NULL
;
1820 client
->scriptEnvsize
= 0;
1821 error("script_set_env: no memory for variable");
1823 client
->scriptEnv
= newscriptEnv
;
1824 client
->scriptEnvsize
= newscriptEnvsize
;
1826 /* need to set the NULL pointer at end of array beyond
1828 client
->scriptEnv
[i
+ 1] = NULL
;
1830 /* Allocate space and format the variable in the appropriate slot. */
1831 client
->scriptEnv
[i
] = malloc(strlen(prefix
) + strlen(name
) + 1 +
1833 if (client
->scriptEnv
[i
] == NULL
)
1834 error("script_set_env: no memory for variable assignment");
1835 snprintf(client
->scriptEnv
[i
], strlen(prefix
) + strlen(name
) +
1836 1 + strlen(value
) + 1, "%s%s=%s", prefix
, name
, value
);
1840 script_flush_env(void)
1844 for (i
= 0; client
->scriptEnv
[i
]; i
++) {
1845 free(client
->scriptEnv
[i
]);
1846 client
->scriptEnv
[i
] = NULL
;
1848 client
->scriptEnvsize
= 0;
1852 dhcp_option_ev_name(char *buf
, size_t buflen
, const struct option
*option
)
1856 for (i
= 0; option
->name
[i
]; i
++) {
1857 if (i
+ 1 == buflen
)
1859 if (option
->name
[i
] == '-')
1862 buf
[i
] = option
->name
[i
];
1882 * Setup pidfile, kill any dhclient already running for this
1885 snprintf(buf
, sizeof(buf
), "/var/run/dhclient.%s.pid", orig_ifname
);
1886 fd
= open(buf
, O_RDWR
|O_CREAT
, 0644);
1888 if (killclient(fd
)) {
1890 "starting dhclient on %s\n",
1894 "restarting dhclient on %s\n",
1900 * Daemonize if requested
1902 if (no_daemon
== 0) {
1903 /* Stop logging to stderr... */
1906 if (daemon(1, 0) == -1)
1909 /* we are chrooted, daemon(3) fails to open /dev/null */
1911 dup2(nullfd
, STDIN_FILENO
);
1912 dup2(nullfd
, STDOUT_FILENO
);
1913 dup2(nullfd
, STDERR_FILENO
);
1920 * No further daemonizations, write out pid file and lock.
1924 lseek(fd
, 0L, SEEK_SET
);
1926 snprintf(buf
, sizeof(buf
), "%ld\n", (long)getpid());
1927 write(fd
, buf
, strlen(buf
));
1929 /* leave descriptor open and locked */
1934 check_option(struct client_lease
*l
, int option
)
1939 /* we use this, since this is what gets passed to dhclient-script */
1941 opbuf
= pretty_print_option(option
, &l
->options
[option
], 0);
1943 sbuf
= option_as_string(option
, l
->options
[option
].data
,
1944 l
->options
[option
].len
);
1947 case DHO_SUBNET_MASK
:
1948 case DHO_SWAP_SERVER
:
1949 case DHO_BROADCAST_ADDRESS
:
1950 case DHO_DHCP_SERVER_IDENTIFIER
:
1951 case DHO_ROUTER_SOLICITATION_ADDRESS
:
1952 case DHO_DHCP_REQUESTED_ADDRESS
:
1953 if (ipv4addrs(opbuf
) == 0) {
1954 warning("Invalid IP address in option %s: %s",
1955 dhcp_options
[option
].name
, opbuf
);
1958 if (l
->options
[option
].len
!= 4) { /* RFC 2132 */
1959 warning("warning: Only 1 IP address allowed in "
1960 "%s option; length %d, must be 4",
1961 dhcp_options
[option
].name
,
1962 l
->options
[option
].len
);
1963 l
->options
[option
].len
= 4;
1966 case DHO_TIME_SERVERS
:
1967 case DHO_NAME_SERVERS
:
1969 case DHO_DOMAIN_NAME_SERVERS
:
1970 case DHO_LOG_SERVERS
:
1971 case DHO_COOKIE_SERVERS
:
1972 case DHO_LPR_SERVERS
:
1973 case DHO_IMPRESS_SERVERS
:
1974 case DHO_RESOURCE_LOCATION_SERVERS
:
1975 case DHO_NIS_SERVERS
:
1976 case DHO_NTP_SERVERS
:
1977 case DHO_NETBIOS_NAME_SERVERS
:
1978 case DHO_NETBIOS_DD_SERVER
:
1979 case DHO_FONT_SERVERS
:
1980 if (ipv4addrs(opbuf
) == 0) {
1981 warning("Invalid IP address in option %s: %s",
1982 dhcp_options
[option
].name
, opbuf
);
1987 case DHO_DOMAIN_NAME
:
1988 case DHO_NIS_DOMAIN
:
1989 if (!res_hnok(sbuf
)) {
1990 warning("Bogus Host Name option %d: %s (%s)", option
,
1992 l
->options
[option
].len
= 0;
1993 free(l
->options
[option
].data
);
1997 case DHO_TIME_OFFSET
:
1999 case DHO_MERIT_DUMP
:
2001 case DHO_EXTENSIONS_PATH
:
2002 case DHO_IP_FORWARDING
:
2003 case DHO_NON_LOCAL_SOURCE_ROUTING
:
2004 case DHO_POLICY_FILTER
:
2005 case DHO_MAX_DGRAM_REASSEMBLY
:
2006 case DHO_DEFAULT_IP_TTL
:
2007 case DHO_PATH_MTU_AGING_TIMEOUT
:
2008 case DHO_PATH_MTU_PLATEAU_TABLE
:
2009 case DHO_INTERFACE_MTU
:
2010 case DHO_ALL_SUBNETS_LOCAL
:
2011 case DHO_PERFORM_MASK_DISCOVERY
:
2012 case DHO_MASK_SUPPLIER
:
2013 case DHO_ROUTER_DISCOVERY
:
2014 case DHO_STATIC_ROUTES
:
2015 case DHO_TRAILER_ENCAPSULATION
:
2016 case DHO_ARP_CACHE_TIMEOUT
:
2017 case DHO_IEEE802_3_ENCAPSULATION
:
2018 case DHO_DEFAULT_TCP_TTL
:
2019 case DHO_TCP_KEEPALIVE_INTERVAL
:
2020 case DHO_TCP_KEEPALIVE_GARBAGE
:
2021 case DHO_VENDOR_ENCAPSULATED_OPTIONS
:
2022 case DHO_NETBIOS_NODE_TYPE
:
2023 case DHO_NETBIOS_SCOPE
:
2024 case DHO_X_DISPLAY_MANAGER
:
2025 case DHO_DHCP_LEASE_TIME
:
2026 case DHO_DHCP_OPTION_OVERLOAD
:
2027 case DHO_DHCP_MESSAGE_TYPE
:
2028 case DHO_DHCP_PARAMETER_REQUEST_LIST
:
2029 case DHO_DHCP_MESSAGE
:
2030 case DHO_DHCP_MAX_MESSAGE_SIZE
:
2031 case DHO_DHCP_RENEWAL_TIME
:
2032 case DHO_DHCP_REBINDING_TIME
:
2033 case DHO_DHCP_CLASS_IDENTIFIER
:
2034 case DHO_DHCP_CLIENT_IDENTIFIER
:
2035 case DHO_DHCP_USER_CLASS_ID
:
2036 case DHO_TFTP_SERVER
:
2039 case DHO_CLASSLESS_ROUTES
:
2040 return (check_classless_option(l
->options
[option
].data
,
2041 l
->options
[option
].len
));
2044 warning("unknown dhcp option value 0x%x", option
);
2045 return (unknown_ok
);
2049 /* RFC 3442 The Classless Static Routes option checks */
2051 check_classless_option(unsigned char *data
, int len
)
2054 unsigned char width
;
2055 in_addr_t addr
, mask
;
2058 warning("Too small length: %d", len
);
2066 } else if (width
< 9) {
2067 addr
= (in_addr_t
)(data
[i
] << 24);
2069 } else if (width
< 17) {
2070 addr
= (in_addr_t
)(data
[i
] << 24) +
2071 (in_addr_t
)(data
[i
+ 1] << 16);
2073 } else if (width
< 25) {
2074 addr
= (in_addr_t
)(data
[i
] << 24) +
2075 (in_addr_t
)(data
[i
+ 1] << 16) +
2076 (in_addr_t
)(data
[i
+ 2] << 8);
2078 } else if (width
< 33) {
2079 addr
= (in_addr_t
)(data
[i
] << 24) +
2080 (in_addr_t
)(data
[i
+ 1] << 16) +
2081 (in_addr_t
)(data
[i
+ 2] << 8) +
2085 warning("Incorrect subnet width: %d", width
);
2088 mask
= (in_addr_t
)(~0) << (32 - width
);
2094 * ... After deriving a subnet number and subnet mask
2095 * from each destination descriptor, the DHCP client
2096 * MUST zero any bits in the subnet number where the
2097 * corresponding bit in the mask is zero...
2099 if ((addr
& mask
) != addr
) {
2101 data
[i
- 1] = (unsigned char)(
2102 (addr
>> rounddown(32 - width
, 8)) & 0xFF);
2107 warning("Incorrect data length: %d (must be %d)", len
, i
);
2114 res_hnok(const char *name
)
2116 const char *dn
= name
;
2117 int pch
= '.', ch
= *dn
++;
2120 while (ch
!= '\0') {
2125 } else if (pch
== '.' || nch
== '.' || nch
== '\0') {
2128 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '_')
2130 else if (ch
== '_' && warn
== 0) {
2131 warning("warning: hostname %s contains an "
2132 "underscore which violates RFC 952", name
);
2140 /* Does buf consist only of dotted decimal ipv4 addrs?
2141 * return how many if so,
2142 * otherwise, return 0
2145 ipv4addrs(char * buf
)
2150 while (inet_aton(buf
, &jnk
) == 1){
2152 while (*buf
== '.' || isdigit(*buf
))
2163 option_as_string(unsigned int code
, unsigned char *data
, int len
)
2165 static char optbuf
[32768]; /* XXX */
2167 int opleft
= sizeof(optbuf
);
2168 unsigned char *dp
= data
;
2171 error("option_as_string: bad code %d", code
);
2173 for (; dp
< data
+ len
; dp
++) {
2174 if (!isascii(*dp
) || !isprint(*dp
)) {
2175 if (dp
+ 1 != data
+ len
|| *dp
!= 0) {
2177 snprintf(op
, opleft
, "\\%03o", *dp
);
2182 } else if (*dp
== '"' || *dp
== '\'' || *dp
== '$' ||
2183 *dp
== '`' || *dp
== '\\') {
2197 warning("dhcp option too large");
2202 fork_privchld(int fd
, int fd2
)
2204 struct pollfd pfd
[1];
2205 int nfds
, pfail
= 0;
2209 omask
= sigblock(sigmask(SIGINT
)|sigmask(SIGHUP
));
2217 error("cannot fork");
2225 if (chdir("/") == -1)
2226 error("chdir(\"/\")");
2228 setproctitle("%s [priv]", ifi
->name
);
2230 dup2(nullfd
, STDIN_FILENO
);
2231 dup2(nullfd
, STDOUT_FILENO
);
2232 dup2(nullfd
, STDERR_FILENO
);
2238 pfd
[0].events
= POLLIN
;
2239 if ((nfds
= poll(pfd
, 1, INFTIM
)) == -1)
2241 error("poll error");
2244 * Handle temporary errors, but bail if they persist.
2246 if (nfds
== 0 || !(pfd
[0].revents
& POLLIN
)) {
2247 if (pfail
> POLL_FAILURES
)
2248 error("poll failed > %d times", POLL_FAILURES
);
2249 sleep(pfail
* POLL_FAILURE_WAIT
);
2259 get_ifname(char *ifname
, char *arg
)
2261 struct ifgroupreq ifgr
;
2262 struct ifg_req
*ifg
;
2265 if (!strcmp(arg
, "egress")) {
2266 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
2268 error("socket error");
2269 bzero(&ifgr
, sizeof(ifgr
));
2270 strlcpy(ifgr
.ifgr_name
, "egress", sizeof(ifgr
.ifgr_name
));
2271 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
2272 if (errno
== ENOENT
)
2273 error("no interface in group egress found");
2274 error("ioctl SIOCGIFGMEMB: %m");
2276 len
= ifgr
.ifgr_len
;
2277 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
2278 error("get_ifname");
2279 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
2280 error("ioctl SIOCGIFGMEMB: %m");
2283 for (ifg
= ifgr
.ifgr_groups
;
2284 ifg
&& len
>= sizeof(struct ifg_req
); ifg
++) {
2285 len
-= sizeof(struct ifg_req
);
2287 error("too many interfaces in group egress");
2288 arg
= ifg
->ifgrq_member
;
2291 if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2292 error("Interface name too long: %m");
2294 free(ifgr
.ifgr_groups
);
2296 } else if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2297 error("Interface name too long");
2302 sig_handle(int signo
)
2304 if (monitor_pid
> 0)
2305 kill(monitor_pid
, signo
);
2306 fprintf(stderr
, "killed by signal\n");
2317 * Kill previously running dhclient
2319 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0) {
2324 lseek(fd
, 0L, SEEK_SET
);
2325 n
= read(fd
, buf
, sizeof(buf
));
2328 pid
= strtol(buf
, NULL
, 10);
2334 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)
2336 while (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)