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);
94 int check_option(struct client_lease
*l
, int option
);
95 int ipv4addrs(char * buf
);
96 int res_hnok(const char *dn
);
97 char *option_as_string(unsigned int code
, unsigned char *data
, int len
);
98 int fork_privchld(int, int);
99 void get_ifname(char *, char *);
100 static void sig_handle(int sig
);
101 static int killclient(int fd
);
104 static FILE *leaseFile
;
107 findproto(char *cp
, int n
)
114 for (i
= 1; i
; i
<<= 1) {
116 sa
= (struct sockaddr
*)cp
;
122 if (sa
->sa_family
== AF_INET
)
124 if (sa
->sa_family
== AF_INET6
)
137 get_ifa(char *cp
, int n
)
144 for (i
= 1; i
; i
<<= 1)
146 sa
= (struct sockaddr
*)cp
;
154 struct iaddr defaddr
= { .len
= 4 }; /* NULL is for silence warnings */
161 struct rt_msghdr
*rtm
;
162 struct if_msghdr
*ifm
;
163 struct ifa_msghdr
*ifam
;
164 struct if_announcemsghdr
*ifan
;
165 struct client_lease
*l
;
169 char *errmsg
, buf
[64];
172 n
= read(routefd
, &msg
, sizeof(msg
));
173 } while (n
== -1 && errno
== EINTR
);
175 rtm
= (struct rt_msghdr
*)msg
;
176 if (n
< sizeof(rtm
->rtm_msglen
) || n
< rtm
->rtm_msglen
||
177 rtm
->rtm_version
!= RTM_VERSION
)
180 switch (rtm
->rtm_type
) {
182 ifam
= (struct ifa_msghdr
*)rtm
;
183 if (ifam
->ifam_index
!= ifi
->index
)
185 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
187 sa
= get_ifa((char *)(ifam
+ 1), ifam
->ifam_addrs
);
189 errmsg
= "sa == NULL";
193 if ((a
.len
= sizeof(struct in_addr
)) > sizeof(a
.iabuf
))
194 error("king bula sez: len mismatch");
195 memcpy(a
.iabuf
, &((struct sockaddr_in
*)sa
)->sin_addr
, a
.len
);
196 if (addr_eq(a
, defaddr
))
199 /* state_panic() can try unexpired existing leases */
200 if (client
->active
&& addr_eq(a
, client
->active
->address
))
202 for (l
= client
->leases
; l
!= NULL
; l
= l
->next
)
203 if (addr_eq(a
, l
->address
))
207 /* new addr is the one we set */
209 snprintf(buf
, sizeof(buf
), "%s: %s",
210 "new address not one we set", piaddr(a
));
214 ifam
= (struct ifa_msghdr
*)rtm
;
215 if (ifam
->ifam_index
!= ifi
->index
)
217 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
219 /* XXX check addrs like RTM_NEWADDR instead of this? */
220 if (scripttime
== 0 || time(NULL
) < scripttime
+ 10)
222 errmsg
= "interface address deleted";
225 ifm
= (struct if_msghdr
*)rtm
;
226 if (ifm
->ifm_index
!= ifi
->index
)
228 if ((rtm
->rtm_flags
& RTF_UP
) == 0) {
229 errmsg
= "interface down";
234 LINK_STATE_IS_UP(ifm
->ifm_data
.ifi_link_state
) ? 1 : 0;
235 if (linkstat
!= ifi
->linkstat
) {
237 debug("link state %s -> %s",
238 ifi
->linkstat
? "up" : "down",
239 linkstat
? "up" : "down");
241 ifi
->linkstat
= interface_status(ifi
->name
);
243 client
->state
= S_REBOOTING
;
249 ifan
= (struct if_announcemsghdr
*)rtm
;
250 if (ifan
->ifan_what
== IFAN_DEPARTURE
&&
251 ifan
->ifan_index
== ifi
->index
) {
252 errmsg
= "interface departure";
264 error("routehandler: %s", errmsg
);
268 main(int argc
, char *argv
[])
273 int dokillclient
= 0;
277 /* Initially, log errors to stderr as well as to syslogd. */
278 openlog(getprogname(), LOG_PID
| LOG_NDELAY
, DHCPD_LOG_FACILITY
);
279 setlogmask(LOG_UPTO(LOG_INFO
));
281 signal(SIGINT
, sig_handle
);
282 signal(SIGHUP
, sig_handle
);
284 while ((ch
= getopt(argc
, argv
, "c:dl:quwx")) != -1) {
287 path_dhclient_conf
= optarg
;
293 path_dhclient_db
= optarg
;
317 orig_ifname
= argv
[0];
322 snprintf(buf
, sizeof(buf
),
323 "/var/run/dhclient.%s.pid", orig_ifname
);
324 fd
= open(buf
, O_RDWR
, 0644);
325 if (fd
< 0 || killclient(fd
)) {
327 "no dhclient running on %s\n",
331 "stopping dhclient on %s\n",
339 if ((nullfd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) == -1)
340 error("cannot open %s: %m", _PATH_DEVNULL
);
343 * If asked to stay alive forever get our daemon going right now
344 * Then set up to fork/monitor and refork on exit.
346 * When I say 'forever' I really mean it. If there are configuration
347 * problems or missing interfaces or whatever, dhclient will wait
348 * 10 seconds and try again.
358 omask
= sigblock(sigmask(SIGINT
) | sigmask(SIGHUP
));
364 if (pid
== 0) /* child falls out of loop */
367 rpid
= waitpid(pid
, NULL
, 0);
377 ifi
= calloc(1, sizeof(*ifi
));
380 client
= calloc(1, sizeof(*client
));
382 error("client calloc");
383 config
= calloc(1, sizeof(*config
));
385 error("config calloc");
387 get_ifname(ifi
->name
, argv
[0]);
389 if (path_dhclient_db
== NULL
&& asprintf(&path_dhclient_db
, "%s.%s",
390 _PATH_DHCLIENT_DB
, ifi
->name
) == -1)
398 memset(&sockaddr_broadcast
, 0, sizeof(sockaddr_broadcast
));
399 sockaddr_broadcast
.sin_family
= AF_INET
;
400 sockaddr_broadcast
.sin_port
= htons(REMOTE_PORT
);
401 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
402 sockaddr_broadcast
.sin_len
= sizeof(sockaddr_broadcast
);
403 inaddr_any
.s_addr
= INADDR_ANY
;
407 if (interface_status(ifi
->name
) == 0) {
408 interface_link_forceup(ifi
->name
);
409 /* Give it up to 4 seconds of silent grace to find link */
415 while (!(ifi
->linkstat
= interface_status(ifi
->name
))) {
417 fprintf(stderr
, "%s: no link ...", ifi
->name
);
419 fprintf(stderr
, ".");
421 if (++i
> config
->link_timeout
) {
422 fprintf(stderr
, " sleeping\n");
428 fprintf(stderr
, " got link\n");
431 if ((pw
= getpwnam("_dhcp")) == NULL
)
432 error("no such user: _dhcp");
434 if (pipe(pipe_fd
) == -1)
438 fork_privchld(pipe_fd
[0], pipe_fd
[1]);
443 if ((fd
= open(path_dhclient_db
, O_RDONLY
|O_EXLOCK
|O_CREAT
, 0)) == -1)
444 error("can't open and lock %s: %m", path_dhclient_db
);
445 read_client_leases();
446 if ((leaseFile
= fopen(path_dhclient_db
, "w")) == NULL
)
447 error("can't open %s: %m", path_dhclient_db
);
448 rewrite_client_leases();
451 if ((routefd
= socket(PF_ROUTE
, SOCK_RAW
, 0)) == -1)
452 error("socket(PF_ROUTE, SOCK_RAW): %m");
454 /* set up the interface */
455 discover_interface();
457 if (chroot(_PATH_VAREMPTY
) == -1)
459 if (chdir("/") == -1)
460 error("chdir(\"/\")");
462 if (setresgid(pw
->pw_gid
, pw
->pw_gid
, pw
->pw_gid
) == -1)
464 if (setgroups(1, &pw
->pw_gid
) == -1)
466 if (setresuid(pw
->pw_uid
, pw
->pw_uid
, pw
->pw_uid
) == -1)
471 setproctitle("%s", ifi
->name
);
474 client
->state
= S_REBOOTING
;
486 fprintf(stderr
, "usage: %s [-dqu] [-c file] [-l file] interface\n",
494 * Each routine is called from the dhclient_state_machine() in one of
496 * -> entering INIT state
497 * -> recvpacket_flag == 0: timeout in this state
498 * -> otherwise: received a packet in this state
500 * Return conditions as handled by dhclient_state_machine():
501 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
502 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
503 * Returns 0: finish the nap which was interrupted for no good reason.
505 * Several per-interface variables are used to keep track of the process:
506 * active_lease: the lease that is being used on the interface
507 * (null pointer if not configured yet).
508 * offered_leases: leases corresponding to DHCPOFFER messages that have
509 * been sent to us by DHCP servers.
510 * acked_leases: leases corresponding to DHCPACK messages that have been
511 * sent to us by DHCP servers.
512 * sendpacket: DHCP packet we're trying to send.
513 * destination: IP address to send sendpacket to
514 * In addition, there are several relevant per-lease variables.
515 * T1_expiry, T2_expiry, lease_expiry: lease milestones
516 * In the active lease, these control the process of renewing the lease;
517 * In leases on the acked_leases list, this simply determines when we
518 * can no longer legitimately use the lease.
523 /* Cancel all timeouts, since a link state change gets us here
524 and can happen anytime. */
527 /* If we don't remember an active lease, go straight to INIT. */
528 if (!client
->active
|| client
->active
->is_bootp
) {
529 client
->state
= S_INIT
;
534 /* make_request doesn't initialize xid because it normally comes
535 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
536 so pick an xid now. */
537 client
->xid
= arc4random();
539 /* Make a DHCPREQUEST packet, and set appropriate per-interface
541 make_request(client
->active
);
542 client
->destination
= iaddr_broadcast
;
543 client
->first_sending
= time(NULL
);
544 client
->interval
= 0;
550 * Called when a lease has completely expired and we've
551 * been unable to renew it.
556 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
558 make_discover(client
->active
);
559 client
->xid
= client
->packet
.xid
;
560 client
->destination
= iaddr_broadcast
;
561 client
->state
= S_SELECTING
;
562 client
->first_sending
= time(NULL
);
563 client
->interval
= 0;
569 * state_selecting is called when one or more DHCPOFFER packets
570 * have been received and a configurable period of time has passed.
573 state_selecting(void)
575 struct client_lease
*lp
, *next
, *picked
;
578 /* Cancel state_selecting and send_discover timeouts, since either
579 one could have got us here. */
582 /* We have received one or more DHCPOFFER packets. Currently,
583 the only criterion by which we judge leases is whether or
584 not we get a response when we arp for them. */
586 for (lp
= client
->offered_leases
; lp
; lp
= next
) {
594 free_client_lease(lp
);
597 client
->offered_leases
= NULL
;
599 /* If we just tossed all the leases we were offered, go back
602 client
->state
= S_INIT
;
610 /* If it was a BOOTREPLY, we can just take the address right now. */
611 if (!picked
->options
[DHO_DHCP_MESSAGE_TYPE
].len
) {
612 client
->new = picked
;
614 /* Make up some lease expiry times
615 XXX these should be configurable. */
616 client
->new->expiry
= cur_time
+ 12000;
617 client
->new->renewal
+= cur_time
+ 8000;
618 client
->new->rebind
+= cur_time
+ 10000;
620 client
->state
= S_REQUESTING
;
622 /* Bind to the address we received. */
627 /* Go to the REQUESTING state. */
628 client
->destination
= iaddr_broadcast
;
629 client
->state
= S_REQUESTING
;
630 client
->first_sending
= cur_time
;
631 client
->interval
= 0;
633 /* Make a DHCPREQUEST packet from the lease we picked. */
634 make_request(picked
);
635 client
->xid
= client
->packet
.xid
;
637 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
638 free_client_lease(picked
);
644 dhcpack(struct iaddr client_addr
, struct option_data
*options
)
646 struct client_lease
*lease
;
650 if (client
->state
!= S_REBOOTING
&&
651 client
->state
!= S_REQUESTING
&&
652 client
->state
!= S_RENEWING
&&
653 client
->state
!= S_REBINDING
)
657 lease
= packet_to_lease(options
);
659 note("packet_to_lease failed.");
665 /* Stop resending DHCPREQUEST. */
668 /* Figure out the lease time. */
669 if (client
->new->options
[DHO_DHCP_LEASE_TIME
].data
)
670 client
->new->expiry
=
671 getULong(client
->new->options
[DHO_DHCP_LEASE_TIME
].data
);
673 client
->new->expiry
= DEFAULT_LEASE_TIME
;
674 /* A number that looks negative here is really just very large,
675 because the lease expiry offset is unsigned. */
676 if (client
->new->expiry
< 0)
677 client
->new->expiry
= TIME_MAX
;
678 /* XXX should be fixed by resetting the client state */
679 if (client
->new->expiry
< 60)
680 client
->new->expiry
= 60;
682 /* Take the server-provided renewal time if there is one;
683 otherwise figure it out according to the spec. */
684 if (client
->new->options
[DHO_DHCP_RENEWAL_TIME
].len
)
685 client
->new->renewal
=
686 getULong(client
->new->options
[DHO_DHCP_RENEWAL_TIME
].data
);
688 client
->new->renewal
= client
->new->expiry
/ 2;
690 /* Same deal with the rebind time. */
691 if (client
->new->options
[DHO_DHCP_REBINDING_TIME
].len
)
692 client
->new->rebind
=
693 getULong(client
->new->options
[DHO_DHCP_REBINDING_TIME
].data
);
695 client
->new->rebind
= client
->new->renewal
+
696 client
->new->renewal
/ 2 + client
->new->renewal
/ 4;
700 client
->new->expiry
+= cur_time
;
701 /* Lease lengths can never be negative. */
702 if (client
->new->expiry
< cur_time
)
703 client
->new->expiry
= TIME_MAX
;
704 client
->new->renewal
+= cur_time
;
705 if (client
->new->renewal
< cur_time
)
706 client
->new->renewal
= TIME_MAX
;
707 client
->new->rebind
+= cur_time
;
708 if (client
->new->rebind
< cur_time
)
709 client
->new->rebind
= TIME_MAX
;
717 /* Run the client script with the new parameters. */
718 script_init((client
->state
== S_REQUESTING
? "BOUND" :
719 (client
->state
== S_RENEWING
? "RENEW" :
720 (client
->state
== S_REBOOTING
? "REBOOT" : "REBIND"))));
721 if (client
->active
&& client
->state
!= S_REBOOTING
)
722 script_write_params("old_", client
->active
);
723 script_write_params("new_", client
->new);
726 /* Replace the old active lease with the new one. */
728 free_client_lease(client
->active
);
729 client
->active
= client
->new;
732 /* Write out new leases file. */
733 rewrite_client_leases();
735 /* Set timeout to start the renewal process. */
736 set_timeout(client
->active
->renewal
, state_bound
);
738 note("bound to %s -- renewal in %lld seconds.",
739 piaddr(client
->active
->address
),
740 (long long)(client
->active
->renewal
- time(NULL
)));
741 client
->state
= S_BOUND
;
745 * state_bound is called when we've successfully bound to a particular
746 * lease, but the renewal time on that lease has expired. We are
747 * expected to unicast a DHCPREQUEST to the server that gave us our
753 /* T1 has expired. */
754 make_request(client
->active
);
755 client
->xid
= client
->packet
.xid
;
757 if (client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].len
== 4) {
758 memcpy(client
->destination
.iabuf
,
759 client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].data
,
761 client
->destination
.len
= 4;
763 client
->destination
= iaddr_broadcast
;
765 client
->first_sending
= time(NULL
);
766 client
->interval
= 0;
767 client
->state
= S_RENEWING
;
773 dhcpoffer(struct iaddr client_addr
, struct option_data
*options
)
775 struct client_lease
*lease
, *lp
;
777 time_t stop_selecting
;
778 char *name
= options
[DHO_DHCP_MESSAGE_TYPE
].len
? "DHCPOFFER" :
782 if (client
->state
!= S_SELECTING
)
786 /* If this lease doesn't supply the minimum required parameters,
788 for (i
= 0; config
->required_options
[i
]; i
++) {
789 if (!options
[config
->required_options
[i
]].len
) {
790 note("%s isn't satisfactory.", name
);
795 /* If we've already seen this lease, don't record it again. */
796 for (lease
= client
->offered_leases
;
797 lease
; lease
= lease
->next
) {
798 if (lease
->address
.len
== sizeof(client
->packet
.yiaddr
) &&
799 !memcmp(lease
->address
.iabuf
,
800 &client
->packet
.yiaddr
, lease
->address
.len
)) {
802 debug("%s already seen.", name
);
808 lease
= packet_to_lease(options
);
810 note("packet_to_lease failed.");
815 * Reject offers whose subnet is already configured on another
818 if (subnet_exists(lease
))
821 /* If this lease was acquired through a BOOTREPLY, record that
823 if (!options
[DHO_DHCP_MESSAGE_TYPE
].len
)
826 /* Figure out when we're supposed to stop selecting. */
827 stop_selecting
= client
->first_sending
+ config
->select_interval
;
829 /* If this is the lease we asked for, put it at the head of the
830 list, and don't mess with the arp request timeout. */
831 if (addr_eq(lease
->address
, client
->requested_address
)) {
832 lease
->next
= client
->offered_leases
;
833 client
->offered_leases
= lease
;
835 /* Put the lease at the end of the list. */
837 if (!client
->offered_leases
)
838 client
->offered_leases
= lease
;
840 for (lp
= client
->offered_leases
; lp
->next
;
847 /* If the selecting interval has expired, go immediately to
848 state_selecting(). Otherwise, time out into
849 state_selecting at the select interval. */
850 if (stop_selecting
<= time(NULL
))
853 set_timeout(stop_selecting
, state_selecting
);
858 * Allocate a client_lease structure and initialize it from the
859 * parameters in the specified packet.
861 struct client_lease
*
862 packet_to_lease(struct option_data
*options
)
864 struct client_lease
*lease
;
867 lease
= malloc(sizeof(struct client_lease
));
870 warning("dhcpoffer: no memory to record lease.");
874 memset(lease
, 0, sizeof(*lease
));
876 /* Copy the lease options. */
877 for (i
= 0; i
< 256; i
++) {
878 if (options
[i
].len
) {
879 lease
->options
[i
] = options
[i
];
880 options
[i
].data
= NULL
;
882 if (!check_option(lease
, i
)) {
883 warning("Invalid lease option - ignoring offer");
884 free_client_lease(lease
);
890 lease
->address
.len
= sizeof(client
->packet
.yiaddr
);
891 memcpy(lease
->address
.iabuf
, &client
->packet
.yiaddr
,
894 /* If the server name was filled out, copy it. */
895 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
896 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 2)) &&
897 client
->packet
.sname
[0]) {
898 lease
->server_name
= malloc(DHCP_SNAME_LEN
+ 1);
899 if (!lease
->server_name
) {
900 warning("dhcpoffer: no memory for server name.");
901 free_client_lease(lease
);
904 memcpy(lease
->server_name
, client
->packet
.sname
,
906 lease
->server_name
[DHCP_SNAME_LEN
] = '\0';
907 if (!res_hnok(lease
->server_name
)) {
908 warning("Bogus server name %s", lease
->server_name
);
909 free(lease
->server_name
);
910 lease
->server_name
= NULL
;
914 /* Ditto for the filename. */
915 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
916 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 1)) &&
917 client
->packet
.file
[0]) {
918 /* Don't count on the NUL terminator. */
919 lease
->filename
= malloc(DHCP_FILE_LEN
+ 1);
920 if (!lease
->filename
) {
921 warning("dhcpoffer: no memory for filename.");
922 free_client_lease(lease
);
925 memcpy(lease
->filename
, client
->packet
.file
, DHCP_FILE_LEN
);
926 lease
->filename
[DHCP_FILE_LEN
] = '\0';
932 dhcpnak(struct iaddr client_addr
, struct option_data
*options
)
935 if (client
->state
!= S_REBOOTING
&&
936 client
->state
!= S_REQUESTING
&&
937 client
->state
!= S_RENEWING
&&
938 client
->state
!= S_REBINDING
)
942 if (!client
->active
) {
943 note("DHCPNAK with no active lease.");
947 free_client_lease(client
->active
);
948 client
->active
= NULL
;
950 /* Stop sending DHCPREQUEST packets... */
953 client
->state
= S_INIT
;
958 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
959 * one after the right interval has expired. If we don't get an offer by
960 * the time we reach the panic interval, call the panic function.
966 int interval
, increase
= 1;
970 /* Figure out how long it's been since we started transmitting. */
971 interval
= cur_time
- client
->first_sending
;
973 /* If we're past the panic timeout, call the script and tell it
974 we haven't found anything for this interface yet. */
975 if (interval
> config
->timeout
) {
981 * If we're supposed to increase the interval, do so. If it's
982 * currently zero (i.e., we haven't sent any packets yet), set
983 * it to initial_interval; otherwise, add to it a random
984 * number between zero and two times itself. On average, this
985 * means that it will double with every transmission.
988 if (!client
->interval
)
989 client
->interval
= config
->initial_interval
;
991 client
->interval
+= (arc4random() >> 2) %
992 (2 * client
->interval
);
995 /* Don't backoff past cutoff. */
996 if (client
->interval
> config
->backoff_cutoff
)
997 client
->interval
= ((config
->backoff_cutoff
/ 2)
998 + ((arc4random() >> 2) %
999 config
->backoff_cutoff
));
1000 } else if (!client
->interval
)
1001 client
->interval
= config
->initial_interval
;
1003 /* If the backoff would take us to the panic timeout, just use that
1005 if (cur_time
+ client
->interval
>
1006 client
->first_sending
+ config
->timeout
)
1007 client
->interval
= (client
->first_sending
+
1008 config
->timeout
) - cur_time
+ 1;
1010 /* Record the number of seconds since we started sending. */
1011 if (interval
< 65536)
1012 client
->packet
.secs
= htons(interval
);
1014 client
->packet
.secs
= htons(65535);
1015 client
->secs
= client
->packet
.secs
;
1017 note("DHCPDISCOVER on %s to %s port %d interval %ld",
1018 ifi
->name
, inet_ntoa(sockaddr_broadcast
.sin_addr
),
1019 ntohs(sockaddr_broadcast
.sin_port
), client
->interval
);
1021 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1023 set_timeout_interval(client
->interval
, send_discover
);
1027 * state_panic gets called if we haven't received any offers in a preset
1028 * amount of time. When this happens, we try to use existing leases
1029 * that haven't yet expired, and failing that, we call the client script
1030 * and hope it can do something.
1035 struct client_lease
*loop
= client
->active
;
1036 struct client_lease
*lp
;
1039 note("No DHCPOFFERS received.");
1041 /* We may not have an active lease, but we may have some
1042 predefined leases that we can try. */
1043 if (!client
->active
&& client
->leases
)
1046 /* Run through the list of leases and see if one can be used. */
1048 while (client
->active
) {
1049 if (client
->active
->expiry
> cur_time
) {
1050 note("Trying recorded lease %s",
1051 piaddr(client
->active
->address
));
1052 /* Run the client script with the existing
1054 script_init("TIMEOUT");
1055 script_write_params("new_", client
->active
);
1057 /* If the old lease is still good and doesn't
1058 yet need renewal, go into BOUND state and
1059 timeout at the renewal time. */
1061 if (cur_time
< client
->active
->renewal
) {
1062 client
->state
= S_BOUND
;
1063 note("bound: renewal in %lld seconds.",
1064 (long long)(client
->active
->renewal
1066 set_timeout(client
->active
->renewal
,
1069 client
->state
= S_BOUND
;
1070 note("bound: immediate renewal.");
1077 /* If there are no other leases, give up. */
1078 if (!client
->leases
) {
1079 client
->leases
= client
->active
;
1080 client
->active
= NULL
;
1085 /* Otherwise, put the active lease at the end of the
1086 lease list, and try another lease.. */
1087 for (lp
= client
->leases
; lp
->next
; lp
= lp
->next
)
1089 lp
->next
= client
->active
;
1091 lp
->next
->next
= NULL
;
1092 client
->active
= client
->leases
;
1093 client
->leases
= client
->leases
->next
;
1095 /* If we already tried this lease, we've exhausted the
1096 set of leases, so we might as well give up for
1098 if (client
->active
== loop
)
1101 loop
= client
->active
;
1104 /* No leases were available, or what was available didn't work, so
1105 tell the shell script that we failed to allocate an address,
1106 and try again later. */
1107 note("No working leases in persistent database - sleeping.");
1108 script_init("FAIL");
1110 client
->state
= S_INIT
;
1111 set_timeout_interval(config
->retry_interval
, state_init
);
1117 struct sockaddr_in destination
;
1118 struct in_addr from
;
1124 /* Figure out how long it's been since we started transmitting. */
1125 interval
= (int)(cur_time
- client
->first_sending
);
1127 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1128 past the reboot timeout, go to INIT and see if we can
1129 DISCOVER an address... */
1130 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1131 means either that we're on a network with no DHCP server,
1132 or that our server is down. In the latter case, assuming
1133 that there is a backup DHCP server, DHCPDISCOVER will get
1134 us a new address, but we could also have successfully
1135 reused our old address. In the former case, we're hosed
1136 anyway. This is not a win-prone situation. */
1137 if ((client
->state
== S_REBOOTING
||
1138 client
->state
== S_REQUESTING
) &&
1139 interval
> config
->reboot_timeout
) {
1140 client
->state
= S_INIT
;
1146 /* If the lease has expired, relinquish the address and go back
1147 to the INIT state. */
1148 if (client
->state
!= S_REQUESTING
&&
1149 cur_time
> client
->active
->expiry
) {
1150 /* Run the client script with the new parameters. */
1151 script_init("EXPIRE");
1152 script_write_params("old_", client
->active
);
1155 client
->state
= S_INIT
;
1160 /* Do the exponential backoff... */
1161 if (!client
->interval
)
1162 client
->interval
= config
->initial_interval
;
1164 client
->interval
+= ((arc4random() >> 2) %
1165 (2 * client
->interval
));
1167 /* Don't backoff past cutoff. */
1168 if (client
->interval
> config
->backoff_cutoff
)
1169 client
->interval
= ((config
->backoff_cutoff
/ 2) +
1170 ((arc4random() >> 2) % client
->interval
));
1172 /* If the backoff would take us to the expiry time, just set the
1173 timeout to the expiry time. */
1174 if (client
->state
!= S_REQUESTING
&& cur_time
+ client
->interval
>
1175 client
->active
->expiry
)
1176 client
->interval
= client
->active
->expiry
- cur_time
+ 1;
1178 /* If the lease T2 time has elapsed, or if we're not yet bound,
1179 broadcast the DHCPREQUEST rather than unicasting. */
1180 memset(&destination
, 0, sizeof(destination
));
1181 if (client
->state
== S_REQUESTING
||
1182 client
->state
== S_REBOOTING
||
1183 cur_time
> client
->active
->rebind
)
1184 destination
.sin_addr
.s_addr
= INADDR_BROADCAST
;
1186 memcpy(&destination
.sin_addr
.s_addr
, client
->destination
.iabuf
,
1187 sizeof(destination
.sin_addr
.s_addr
));
1188 destination
.sin_port
= htons(REMOTE_PORT
);
1189 destination
.sin_family
= AF_INET
;
1190 destination
.sin_len
= sizeof(destination
);
1192 if (client
->state
!= S_REQUESTING
)
1193 memcpy(&from
, client
->active
->address
.iabuf
, sizeof(from
));
1195 from
.s_addr
= INADDR_ANY
;
1197 /* Record the number of seconds since we started sending. */
1198 if (client
->state
== S_REQUESTING
)
1199 client
->packet
.secs
= client
->secs
;
1201 if (interval
< 65536)
1202 client
->packet
.secs
= htons(interval
);
1204 client
->packet
.secs
= htons(65535);
1207 note("DHCPREQUEST on %s to %s port %d", ifi
->name
,
1208 inet_ntoa(destination
.sin_addr
), ntohs(destination
.sin_port
));
1210 send_packet(from
, &destination
, NULL
);
1212 set_timeout_interval(client
->interval
, send_request
);
1218 note("DHCPDECLINE on %s to %s port %d", ifi
->name
,
1219 inet_ntoa(sockaddr_broadcast
.sin_addr
),
1220 ntohs(sockaddr_broadcast
.sin_port
));
1222 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1226 make_discover(struct client_lease
*lease
)
1228 unsigned char discover
= DHCPDISCOVER
;
1229 struct option_data options
[256];
1232 memset(options
, 0, sizeof(options
));
1233 memset(&client
->packet
, 0, sizeof(client
->packet
));
1235 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1236 i
= DHO_DHCP_MESSAGE_TYPE
;
1237 options
[i
].data
= &discover
;
1238 options
[i
].len
= sizeof(discover
);
1240 /* Request the options we want */
1241 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1242 options
[i
].data
= config
->requested_options
;
1243 options
[i
].len
= config
->requested_option_count
;
1245 /* If we had an address, try to get it again. */
1247 client
->requested_address
= lease
->address
;
1248 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1249 options
[i
].data
= lease
->address
.iabuf
;
1250 options
[i
].len
= lease
->address
.len
;
1252 client
->requested_address
.len
= 0;
1254 /* Send any options requested in the config file. */
1255 for (i
= 0; i
< 256; i
++)
1256 if (!options
[i
].data
&&
1257 config
->send_options
[i
].data
) {
1258 options
[i
].data
= config
->send_options
[i
].data
;
1259 options
[i
].len
= config
->send_options
[i
].len
;
1262 /* Set up the option buffer to fit in a minimal UDP packet. */
1263 i
= cons_options(options
);
1264 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1265 error("options do not fit in DHCPDISCOVER packet.");
1266 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1267 if (client
->packet_length
< BOOTP_MIN_LEN
)
1268 client
->packet_length
= BOOTP_MIN_LEN
;
1270 client
->packet
.op
= BOOTREQUEST
;
1271 client
->packet
.htype
= ifi
->hw_address
.htype
;
1272 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1273 client
->packet
.hops
= 0;
1274 client
->packet
.xid
= arc4random();
1275 client
->packet
.secs
= 0; /* filled in by send_discover. */
1276 client
->packet
.flags
= 0;
1278 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1279 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1280 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1281 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1282 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1283 ifi
->hw_address
.hlen
);
1287 make_request(struct client_lease
* lease
)
1289 unsigned char request
= DHCPREQUEST
;
1290 struct option_data options
[256];
1293 memset(options
, 0, sizeof(options
));
1294 memset(&client
->packet
, 0, sizeof(client
->packet
));
1296 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1297 i
= DHO_DHCP_MESSAGE_TYPE
;
1298 options
[i
].data
= &request
;
1299 options
[i
].len
= sizeof(request
);
1301 /* Request the options we want */
1302 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1303 options
[i
].data
= config
->requested_options
;
1304 options
[i
].len
= config
->requested_option_count
;
1306 /* If we are requesting an address that hasn't yet been assigned
1307 to us, use the DHCP Requested Address option. */
1308 if (client
->state
== S_REQUESTING
) {
1309 /* Send back the server identifier... */
1310 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1311 options
[i
].data
= lease
->options
[i
].data
;
1312 options
[i
].len
= lease
->options
[i
].len
;
1314 if (client
->state
== S_REQUESTING
||
1315 client
->state
== S_REBOOTING
) {
1316 client
->requested_address
= lease
->address
;
1317 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1318 options
[i
].data
= lease
->address
.iabuf
;
1319 options
[i
].len
= lease
->address
.len
;
1321 client
->requested_address
.len
= 0;
1323 /* Send any options requested in the config file. */
1324 for (i
= 0; i
< 256; i
++)
1325 if (!options
[i
].data
&& config
->send_options
[i
].data
) {
1326 options
[i
].data
= config
->send_options
[i
].data
;
1327 options
[i
].len
= config
->send_options
[i
].len
;
1330 /* Set up the option buffer to fit in a minimal UDP packet. */
1331 i
= cons_options(options
);
1332 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1333 error("options do not fit in DHCPREQUEST packet.");
1334 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1335 if (client
->packet_length
< BOOTP_MIN_LEN
)
1336 client
->packet_length
= BOOTP_MIN_LEN
;
1338 client
->packet
.op
= BOOTREQUEST
;
1339 client
->packet
.htype
= ifi
->hw_address
.htype
;
1340 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1341 client
->packet
.hops
= 0;
1342 client
->packet
.xid
= client
->xid
;
1343 client
->packet
.secs
= 0; /* Filled in by send_request. */
1344 client
->packet
.flags
= 0;
1346 /* If we own the address we're requesting, put it in ciaddr;
1347 otherwise set ciaddr to zero. */
1348 if (client
->state
== S_BOUND
||
1349 client
->state
== S_RENEWING
||
1350 client
->state
== S_REBINDING
) {
1351 memcpy(&client
->packet
.ciaddr
,
1352 lease
->address
.iabuf
, lease
->address
.len
);
1354 memset(&client
->packet
.ciaddr
, 0,
1355 sizeof(client
->packet
.ciaddr
));
1358 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1359 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1360 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1361 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1362 ifi
->hw_address
.hlen
);
1366 make_decline(struct client_lease
*lease
)
1368 struct option_data options
[256];
1369 unsigned char decline
= DHCPDECLINE
;
1372 memset(options
, 0, sizeof(options
));
1373 memset(&client
->packet
, 0, sizeof(client
->packet
));
1375 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1376 i
= DHO_DHCP_MESSAGE_TYPE
;
1377 options
[i
].data
= &decline
;
1378 options
[i
].len
= sizeof(decline
);
1380 /* Send back the server identifier... */
1381 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1382 options
[i
].data
= lease
->options
[i
].data
;
1383 options
[i
].len
= lease
->options
[i
].len
;
1385 /* Send back the address we're declining. */
1386 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1387 options
[i
].data
= lease
->address
.iabuf
;
1388 options
[i
].len
= lease
->address
.len
;
1390 /* Send the uid if the user supplied one. */
1391 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
1392 if (config
->send_options
[i
].len
) {
1393 options
[i
].data
= config
->send_options
[i
].data
;
1394 options
[i
].len
= config
->send_options
[i
].len
;
1397 /* Set up the option buffer to fit in a minimal UDP packet. */
1398 i
= cons_options(options
);
1399 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1400 error("options do not fit in DHCPDECLINE packet.");
1401 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1402 if (client
->packet_length
< BOOTP_MIN_LEN
)
1403 client
->packet_length
= BOOTP_MIN_LEN
;
1405 client
->packet
.op
= BOOTREQUEST
;
1406 client
->packet
.htype
= ifi
->hw_address
.htype
;
1407 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1408 client
->packet
.hops
= 0;
1409 client
->packet
.xid
= client
->xid
;
1410 client
->packet
.secs
= 0; /* Filled in by send_request. */
1411 client
->packet
.flags
= 0;
1413 /* ciaddr must always be zero. */
1414 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1415 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1416 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1417 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1418 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1419 ifi
->hw_address
.hlen
);
1423 free_client_lease(struct client_lease
*lease
)
1427 if (lease
->server_name
)
1428 free(lease
->server_name
);
1429 if (lease
->filename
)
1430 free(lease
->filename
);
1431 for (i
= 0; i
< 256; i
++) {
1432 if (lease
->options
[i
].len
)
1433 free(lease
->options
[i
].data
);
1439 rewrite_client_leases(void)
1441 struct client_lease
*lp
;
1443 if (!leaseFile
) /* XXX */
1444 error("lease file not open");
1449 for (lp
= client
->leases
; lp
; lp
= lp
->next
) {
1450 if (client
->active
&& addr_eq(lp
->address
,
1451 client
->active
->address
))
1453 write_client_lease(lp
);
1457 write_client_lease(client
->active
);
1460 ftruncate(fileno(leaseFile
), ftello(leaseFile
));
1461 fsync(fileno(leaseFile
));
1465 write_client_lease(struct client_lease
*lease
)
1470 /* If the lease came from the config file, we don't need to stash
1471 a copy in the lease database. */
1472 if (lease
->is_static
)
1475 if (!leaseFile
) /* XXX */
1476 error("lease file not open");
1478 fprintf(leaseFile
, "lease {\n");
1479 if (lease
->is_bootp
)
1480 fprintf(leaseFile
, " bootp;\n");
1481 fprintf(leaseFile
, " interface \"%s\";\n", ifi
->name
);
1482 fprintf(leaseFile
, " fixed-address %s;\n", piaddr(lease
->address
));
1483 if (lease
->filename
)
1484 fprintf(leaseFile
, " filename \"%s\";\n", lease
->filename
);
1485 if (lease
->server_name
)
1486 fprintf(leaseFile
, " server-name \"%s\";\n",
1487 lease
->server_name
);
1488 for (i
= 0; i
< 256; i
++)
1489 if (lease
->options
[i
].len
)
1490 fprintf(leaseFile
, " option %s %s;\n",
1491 dhcp_options
[i
].name
,
1492 pretty_print_option(i
, &lease
->options
[i
], 1));
1494 t
= gmtime(&lease
->renewal
);
1495 fprintf(leaseFile
, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1496 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1497 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1498 t
= gmtime(&lease
->rebind
);
1499 fprintf(leaseFile
, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1500 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1501 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1502 t
= gmtime(&lease
->expiry
);
1503 fprintf(leaseFile
, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1504 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1505 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1506 fprintf(leaseFile
, "}\n");
1511 script_init(char *reason
)
1514 struct imsg_hdr hdr
;
1517 hdr
.code
= IMSG_SCRIPT_INIT
;
1518 hdr
.len
= sizeof(struct imsg_hdr
) + sizeof(size_t) + strlen(reason
);
1519 buf
= buf_open(hdr
.len
);
1521 buf_add(buf
, &hdr
, sizeof(hdr
));
1522 len
= strlen(reason
);
1523 buf_add(buf
, &len
, sizeof(len
));
1524 buf_add(buf
, reason
, len
);
1526 buf_close(privfd
, buf
);
1530 priv_script_init(char *reason
)
1532 client
->scriptEnvsize
= 100;
1533 if (client
->scriptEnv
== NULL
)
1535 calloc(client
->scriptEnvsize
, sizeof(char *));
1536 if (client
->scriptEnv
== NULL
)
1537 error("script_init: no memory for environment");
1539 client
->scriptEnv
[0] = strdup(CLIENT_PATH
);
1540 if (client
->scriptEnv
[0] == NULL
)
1541 error("script_init: no memory for environment");
1543 client
->scriptEnv
[1] = NULL
;
1545 script_set_env("", "interface", ifi
->name
);
1547 script_set_env("", "reason", reason
);
1551 priv_script_write_params(char *prefix
, struct client_lease
*lease
)
1554 struct option_data o
;
1557 script_set_env(prefix
, "ip_address", piaddr(lease
->address
));
1559 if (lease
->options
[DHO_SUBNET_MASK
].len
&&
1560 (lease
->options
[DHO_SUBNET_MASK
].len
<
1561 sizeof(lease
->address
.iabuf
))) {
1562 struct iaddr netmask
, subnet
, broadcast
;
1564 memcpy(netmask
.iabuf
, lease
->options
[DHO_SUBNET_MASK
].data
,
1565 lease
->options
[DHO_SUBNET_MASK
].len
);
1566 netmask
.len
= lease
->options
[DHO_SUBNET_MASK
].len
;
1568 subnet
= subnet_number(lease
->address
, netmask
);
1570 script_set_env(prefix
, "network_number",
1572 if (!lease
->options
[DHO_BROADCAST_ADDRESS
].len
) {
1573 broadcast
= broadcast_addr(subnet
, netmask
);
1575 script_set_env(prefix
,
1576 "broadcast_address",
1582 if (lease
->filename
)
1583 script_set_env(prefix
, "filename", lease
->filename
);
1584 if (lease
->server_name
)
1585 script_set_env(prefix
, "server_name",
1586 lease
->server_name
);
1588 for (i
= 0; i
< 256; i
++) {
1589 if (!dhcp_option_ev_name(buf
, sizeof(buf
), &dhcp_options
[i
]))
1592 switch (config
->default_actions
[i
]) {
1596 case ACTION_DEFAULT
:
1597 if (lease
->options
[i
].len
)
1598 script_set_env(prefix
, buf
,
1599 pretty_print_option(i
, &lease
->options
[i
],
1601 else if (config
->defaults
[i
].len
)
1602 script_set_env(prefix
, buf
,
1603 pretty_print_option(i
, &config
->defaults
[i
],
1607 case ACTION_SUPERSEDE
:
1608 if (config
->defaults
[i
].len
)
1609 script_set_env(prefix
, buf
,
1610 pretty_print_option(i
, &config
->defaults
[i
],
1614 case ACTION_PREPEND
:
1615 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1617 o
.data
= calloc(1, o
.len
);
1619 error("no space to prepend '%s' to %s",
1620 config
->defaults
[i
].data
,
1621 dhcp_options
[i
].name
);
1622 memcpy(o
.data
, config
->defaults
[i
].data
,
1623 config
->defaults
[i
].len
);
1624 memcpy(o
.data
+ config
->defaults
[i
].len
,
1625 lease
->options
[i
].data
,
1626 lease
->options
[i
].len
);
1627 script_set_env(prefix
, buf
,
1628 pretty_print_option(i
, &o
, 0));
1634 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1636 o
.data
= calloc(1, o
.len
);
1638 error("no space to append '%s' to %s",
1639 config
->defaults
[i
].data
,
1640 dhcp_options
[i
].name
);
1641 memcpy(o
.data
, lease
->options
[i
].data
,
1642 lease
->options
[i
].len
);
1643 memcpy(o
.data
+ lease
->options
[i
].len
,
1644 config
->defaults
[i
].data
,
1645 config
->defaults
[i
].len
);
1646 script_set_env(prefix
, buf
,
1647 pretty_print_option(i
, &o
, 0));
1654 snprintf(buf
, sizeof(buf
), "%d", (int)lease
->expiry
);
1655 script_set_env(prefix
, "expiry", buf
);
1659 script_write_params(char *prefix
, struct client_lease
*lease
)
1661 size_t fn_len
= 0, sn_len
= 0, pr_len
= 0;
1662 struct imsg_hdr hdr
;
1666 if (lease
->filename
!= NULL
)
1667 fn_len
= strlen(lease
->filename
);
1668 if (lease
->server_name
!= NULL
)
1669 sn_len
= strlen(lease
->server_name
);
1671 pr_len
= strlen(prefix
);
1673 hdr
.code
= IMSG_SCRIPT_WRITE_PARAMS
;
1674 hdr
.len
= sizeof(hdr
) + sizeof(struct client_lease
) +
1675 sizeof(size_t) + fn_len
+ sizeof(size_t) + sn_len
+
1676 sizeof(size_t) + pr_len
;
1678 for (i
= 0; i
< 256; i
++)
1679 hdr
.len
+= sizeof(int) + lease
->options
[i
].len
;
1681 scripttime
= time(NULL
);
1683 buf
= buf_open(hdr
.len
);
1685 buf_add(buf
, &hdr
, sizeof(hdr
));
1686 buf_add(buf
, lease
, sizeof(struct client_lease
));
1687 buf_add(buf
, &fn_len
, sizeof(fn_len
));
1688 buf_add(buf
, lease
->filename
, fn_len
);
1689 buf_add(buf
, &sn_len
, sizeof(sn_len
));
1690 buf_add(buf
, lease
->server_name
, sn_len
);
1691 buf_add(buf
, &pr_len
, sizeof(pr_len
));
1692 buf_add(buf
, prefix
, pr_len
);
1694 for (i
= 0; i
< 256; i
++) {
1695 buf_add(buf
, &lease
->options
[i
].len
,
1696 sizeof(lease
->options
[i
].len
));
1697 buf_add(buf
, lease
->options
[i
].data
,
1698 lease
->options
[i
].len
);
1701 buf_close(privfd
, buf
);
1707 struct imsg_hdr hdr
;
1711 scripttime
= time(NULL
);
1713 hdr
.code
= IMSG_SCRIPT_GO
;
1714 hdr
.len
= sizeof(struct imsg_hdr
);
1716 buf
= buf_open(hdr
.len
);
1718 buf_add(buf
, &hdr
, sizeof(hdr
));
1719 buf_close(privfd
, buf
);
1721 bzero(&hdr
, sizeof(hdr
));
1722 buf_read(privfd
, &hdr
, sizeof(hdr
));
1723 if (hdr
.code
!= IMSG_SCRIPT_GO_RET
)
1724 error("unexpected msg type %u", hdr
.code
);
1725 if (hdr
.len
!= sizeof(hdr
) + sizeof(int))
1726 error("received corrupted message");
1727 buf_read(privfd
, &ret
, sizeof(ret
));
1733 priv_script_go(void)
1735 char *scriptName
, *argv
[2], **envp
;
1736 int pid
, wpid
, wstatus
;
1738 scripttime
= time(NULL
);
1740 scriptName
= config
->script_name
;
1741 envp
= client
->scriptEnv
;
1743 argv
[0] = scriptName
;
1752 wpid
= wait(&wstatus
);
1753 } while (wpid
!= pid
&& wpid
> 0);
1759 execve(scriptName
, argv
, envp
);
1760 error("execve (%s, ...): %m", scriptName
);
1765 return (WEXITSTATUS(wstatus
));
1769 script_set_env(const char *prefix
, const char *name
, const char *value
)
1773 /* No `` or $() command substitution allowed in environment values! */
1774 for (j
= 0; j
< strlen(value
); j
++)
1778 warning("illegal character (%c) in value '%s'",
1780 /* Ignore this option */
1784 namelen
= strlen(name
);
1786 for (i
= 0; client
->scriptEnv
[i
]; i
++)
1787 if (strncmp(client
->scriptEnv
[i
], name
, namelen
) == 0 &&
1788 client
->scriptEnv
[i
][namelen
] == '=')
1791 if (client
->scriptEnv
[i
])
1792 /* Reuse the slot. */
1793 free(client
->scriptEnv
[i
]);
1795 /* New variable. Expand if necessary. */
1796 if (i
>= client
->scriptEnvsize
- 1) {
1797 char **newscriptEnv
;
1798 int newscriptEnvsize
= client
->scriptEnvsize
+ 50;
1800 newscriptEnv
= realloc(client
->scriptEnv
,
1802 if (newscriptEnv
== NULL
) {
1803 free(client
->scriptEnv
);
1804 client
->scriptEnv
= NULL
;
1805 client
->scriptEnvsize
= 0;
1806 error("script_set_env: no memory for variable");
1808 client
->scriptEnv
= newscriptEnv
;
1809 client
->scriptEnvsize
= newscriptEnvsize
;
1811 /* need to set the NULL pointer at end of array beyond
1813 client
->scriptEnv
[i
+ 1] = NULL
;
1815 /* Allocate space and format the variable in the appropriate slot. */
1816 client
->scriptEnv
[i
] = malloc(strlen(prefix
) + strlen(name
) + 1 +
1818 if (client
->scriptEnv
[i
] == NULL
)
1819 error("script_set_env: no memory for variable assignment");
1820 snprintf(client
->scriptEnv
[i
], strlen(prefix
) + strlen(name
) +
1821 1 + strlen(value
) + 1, "%s%s=%s", prefix
, name
, value
);
1825 script_flush_env(void)
1829 for (i
= 0; client
->scriptEnv
[i
]; i
++) {
1830 free(client
->scriptEnv
[i
]);
1831 client
->scriptEnv
[i
] = NULL
;
1833 client
->scriptEnvsize
= 0;
1837 dhcp_option_ev_name(char *buf
, size_t buflen
, const struct option
*option
)
1841 for (i
= 0; option
->name
[i
]; i
++) {
1842 if (i
+ 1 == buflen
)
1844 if (option
->name
[i
] == '-')
1847 buf
[i
] = option
->name
[i
];
1867 * Setup pidfile, kill any dhclient already running for this
1870 snprintf(buf
, sizeof(buf
), "/var/run/dhclient.%s.pid", orig_ifname
);
1871 fd
= open(buf
, O_RDWR
|O_CREAT
, 0644);
1873 if (killclient(fd
)) {
1875 "starting dhclient on %s\n",
1879 "restarting dhclient on %s\n",
1885 * Daemonize if requested
1887 if (no_daemon
== 0) {
1888 /* Stop logging to stderr... */
1891 if (daemon(1, 0) == -1)
1894 /* we are chrooted, daemon(3) fails to open /dev/null */
1896 dup2(nullfd
, STDIN_FILENO
);
1897 dup2(nullfd
, STDOUT_FILENO
);
1898 dup2(nullfd
, STDERR_FILENO
);
1905 * No further daemonizations, write out pid file and lock.
1909 lseek(fd
, 0L, SEEK_SET
);
1911 snprintf(buf
, sizeof(buf
), "%ld\n", (long)getpid());
1912 write(fd
, buf
, strlen(buf
));
1914 /* leave descriptor open and locked */
1919 check_option(struct client_lease
*l
, int option
)
1924 /* we use this, since this is what gets passed to dhclient-script */
1926 opbuf
= pretty_print_option(option
, &l
->options
[option
], 0);
1928 sbuf
= option_as_string(option
, l
->options
[option
].data
,
1929 l
->options
[option
].len
);
1932 case DHO_SUBNET_MASK
:
1933 case DHO_SWAP_SERVER
:
1934 case DHO_BROADCAST_ADDRESS
:
1935 case DHO_DHCP_SERVER_IDENTIFIER
:
1936 case DHO_ROUTER_SOLICITATION_ADDRESS
:
1937 case DHO_DHCP_REQUESTED_ADDRESS
:
1938 if (ipv4addrs(opbuf
) == 0) {
1939 warning("Invalid IP address in option %s: %s",
1940 dhcp_options
[option
].name
, opbuf
);
1943 if (l
->options
[option
].len
!= 4) { /* RFC 2132 */
1944 warning("warning: Only 1 IP address allowed in "
1945 "%s option; length %d, must be 4",
1946 dhcp_options
[option
].name
,
1947 l
->options
[option
].len
);
1948 l
->options
[option
].len
= 4;
1951 case DHO_TIME_SERVERS
:
1952 case DHO_NAME_SERVERS
:
1954 case DHO_DOMAIN_NAME_SERVERS
:
1955 case DHO_LOG_SERVERS
:
1956 case DHO_COOKIE_SERVERS
:
1957 case DHO_LPR_SERVERS
:
1958 case DHO_IMPRESS_SERVERS
:
1959 case DHO_RESOURCE_LOCATION_SERVERS
:
1960 case DHO_NIS_SERVERS
:
1961 case DHO_NTP_SERVERS
:
1962 case DHO_NETBIOS_NAME_SERVERS
:
1963 case DHO_NETBIOS_DD_SERVER
:
1964 case DHO_FONT_SERVERS
:
1965 if (ipv4addrs(opbuf
) == 0) {
1966 warning("Invalid IP address in option %s: %s",
1967 dhcp_options
[option
].name
, opbuf
);
1972 case DHO_DOMAIN_NAME
:
1973 case DHO_NIS_DOMAIN
:
1974 if (!res_hnok(sbuf
)) {
1975 warning("Bogus Host Name option %d: %s (%s)", option
,
1977 l
->options
[option
].len
= 0;
1978 free(l
->options
[option
].data
);
1982 case DHO_TIME_OFFSET
:
1984 case DHO_MERIT_DUMP
:
1986 case DHO_EXTENSIONS_PATH
:
1987 case DHO_IP_FORWARDING
:
1988 case DHO_NON_LOCAL_SOURCE_ROUTING
:
1989 case DHO_POLICY_FILTER
:
1990 case DHO_MAX_DGRAM_REASSEMBLY
:
1991 case DHO_DEFAULT_IP_TTL
:
1992 case DHO_PATH_MTU_AGING_TIMEOUT
:
1993 case DHO_PATH_MTU_PLATEAU_TABLE
:
1994 case DHO_INTERFACE_MTU
:
1995 case DHO_ALL_SUBNETS_LOCAL
:
1996 case DHO_PERFORM_MASK_DISCOVERY
:
1997 case DHO_MASK_SUPPLIER
:
1998 case DHO_ROUTER_DISCOVERY
:
1999 case DHO_STATIC_ROUTES
:
2000 case DHO_TRAILER_ENCAPSULATION
:
2001 case DHO_ARP_CACHE_TIMEOUT
:
2002 case DHO_IEEE802_3_ENCAPSULATION
:
2003 case DHO_DEFAULT_TCP_TTL
:
2004 case DHO_TCP_KEEPALIVE_INTERVAL
:
2005 case DHO_TCP_KEEPALIVE_GARBAGE
:
2006 case DHO_VENDOR_ENCAPSULATED_OPTIONS
:
2007 case DHO_NETBIOS_NODE_TYPE
:
2008 case DHO_NETBIOS_SCOPE
:
2009 case DHO_X_DISPLAY_MANAGER
:
2010 case DHO_DHCP_LEASE_TIME
:
2011 case DHO_DHCP_OPTION_OVERLOAD
:
2012 case DHO_DHCP_MESSAGE_TYPE
:
2013 case DHO_DHCP_PARAMETER_REQUEST_LIST
:
2014 case DHO_DHCP_MESSAGE
:
2015 case DHO_DHCP_MAX_MESSAGE_SIZE
:
2016 case DHO_DHCP_RENEWAL_TIME
:
2017 case DHO_DHCP_REBINDING_TIME
:
2018 case DHO_DHCP_CLASS_IDENTIFIER
:
2019 case DHO_DHCP_CLIENT_IDENTIFIER
:
2020 case DHO_DHCP_USER_CLASS_ID
:
2021 case DHO_TFTP_SERVER
:
2026 warning("unknown dhcp option value 0x%x", option
);
2027 return (unknown_ok
);
2032 res_hnok(const char *name
)
2034 const char *dn
= name
;
2035 int pch
= '.', ch
= *dn
++;
2038 while (ch
!= '\0') {
2043 } else if (pch
== '.' || nch
== '.' || nch
== '\0') {
2046 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '_')
2048 else if (ch
== '_' && warn
== 0) {
2049 warning("warning: hostname %s contains an "
2050 "underscore which violates RFC 952", name
);
2058 /* Does buf consist only of dotted decimal ipv4 addrs?
2059 * return how many if so,
2060 * otherwise, return 0
2063 ipv4addrs(char * buf
)
2068 while (inet_aton(buf
, &jnk
) == 1){
2070 while (*buf
== '.' || isdigit(*buf
))
2081 option_as_string(unsigned int code
, unsigned char *data
, int len
)
2083 static char optbuf
[32768]; /* XXX */
2085 int opleft
= sizeof(optbuf
);
2086 unsigned char *dp
= data
;
2089 error("option_as_string: bad code %d", code
);
2091 for (; dp
< data
+ len
; dp
++) {
2092 if (!isascii(*dp
) || !isprint(*dp
)) {
2093 if (dp
+ 1 != data
+ len
|| *dp
!= 0) {
2095 snprintf(op
, opleft
, "\\%03o", *dp
);
2100 } else if (*dp
== '"' || *dp
== '\'' || *dp
== '$' ||
2101 *dp
== '`' || *dp
== '\\') {
2115 warning("dhcp option too large");
2120 fork_privchld(int fd
, int fd2
)
2122 struct pollfd pfd
[1];
2123 int nfds
, pfail
= 0;
2127 omask
= sigblock(sigmask(SIGINT
)|sigmask(SIGHUP
));
2135 error("cannot fork");
2143 if (chdir("/") == -1)
2144 error("chdir(\"/\")");
2146 setproctitle("%s [priv]", ifi
->name
);
2148 dup2(nullfd
, STDIN_FILENO
);
2149 dup2(nullfd
, STDOUT_FILENO
);
2150 dup2(nullfd
, STDERR_FILENO
);
2156 pfd
[0].events
= POLLIN
;
2157 if ((nfds
= poll(pfd
, 1, INFTIM
)) == -1)
2159 error("poll error");
2162 * Handle temporary errors, but bail if they persist.
2164 if (nfds
== 0 || !(pfd
[0].revents
& POLLIN
)) {
2165 if (pfail
> POLL_FAILURES
)
2166 error("poll failed > %d times", POLL_FAILURES
);
2167 sleep(pfail
* POLL_FAILURE_WAIT
);
2177 get_ifname(char *ifname
, char *arg
)
2179 struct ifgroupreq ifgr
;
2180 struct ifg_req
*ifg
;
2183 if (!strcmp(arg
, "egress")) {
2184 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
2186 error("socket error");
2187 bzero(&ifgr
, sizeof(ifgr
));
2188 strlcpy(ifgr
.ifgr_name
, "egress", sizeof(ifgr
.ifgr_name
));
2189 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
2190 if (errno
== ENOENT
)
2191 error("no interface in group egress found");
2192 error("ioctl SIOCGIFGMEMB: %m");
2194 len
= ifgr
.ifgr_len
;
2195 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
2196 error("get_ifname");
2197 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
2198 error("ioctl SIOCGIFGMEMB: %m");
2201 for (ifg
= ifgr
.ifgr_groups
;
2202 ifg
&& len
>= sizeof(struct ifg_req
); ifg
++) {
2203 len
-= sizeof(struct ifg_req
);
2205 error("too many interfaces in group egress");
2206 arg
= ifg
->ifgrq_member
;
2209 if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2210 error("Interface name too long: %m");
2212 free(ifgr
.ifgr_groups
);
2214 } else if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2215 error("Interface name too long");
2220 sig_handle(int signo
)
2222 if (monitor_pid
> 0)
2223 kill(monitor_pid
, signo
);
2224 fprintf(stderr
, "killed by signal\n");
2235 * Kill previously running dhclient
2237 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0) {
2242 lseek(fd
, 0L, SEEK_SET
);
2243 n
= read(fd
, buf
, sizeof(buf
));
2246 pid
= strtol(buf
, NULL
, 10);
2252 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)
2254 while (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)