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 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
;
318 orig_ifname
= argv
[0];
323 snprintf(buf
, sizeof(buf
),
324 "/var/run/dhclient.%s.pid", orig_ifname
);
325 fd
= open(buf
, O_RDWR
, 0644);
326 if (fd
< 0 || killclient(fd
)) {
328 "no dhclient running on %s\n",
332 "stopping dhclient on %s\n",
340 if ((nullfd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) == -1)
341 error("cannot open %s: %m", _PATH_DEVNULL
);
344 * If asked to stay alive forever get our daemon going right now
345 * Then set up to fork/monitor and refork on exit.
347 * When I say 'forever' I really mean it. If there are configuration
348 * problems or missing interfaces or whatever, dhclient will wait
349 * 10 seconds and try again.
359 omask
= sigblock(sigmask(SIGINT
) | sigmask(SIGHUP
));
365 if (pid
== 0) /* child falls out of loop */
368 rpid
= waitpid(pid
, NULL
, 0);
378 ifi
= calloc(1, sizeof(*ifi
));
381 client
= calloc(1, sizeof(*client
));
383 error("client calloc");
384 config
= calloc(1, sizeof(*config
));
386 error("config calloc");
388 get_ifname(ifi
->name
, argv
[0]);
390 if (path_dhclient_db
== NULL
&& asprintf(&path_dhclient_db
, "%s.%s",
391 _PATH_DHCLIENT_DB
, ifi
->name
) == -1)
399 memset(&sockaddr_broadcast
, 0, sizeof(sockaddr_broadcast
));
400 sockaddr_broadcast
.sin_family
= AF_INET
;
401 sockaddr_broadcast
.sin_port
= htons(REMOTE_PORT
);
402 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
403 sockaddr_broadcast
.sin_len
= sizeof(sockaddr_broadcast
);
404 inaddr_any
.s_addr
= INADDR_ANY
;
408 if (interface_status(ifi
->name
) == 0) {
409 interface_link_forceup(ifi
->name
);
410 /* Give it up to 4 seconds of silent grace to find link */
416 while (!(ifi
->linkstat
= interface_status(ifi
->name
))) {
418 fprintf(stderr
, "%s: no link ...", ifi
->name
);
420 fprintf(stderr
, ".");
422 if (++i
> config
->link_timeout
) {
423 fprintf(stderr
, " sleeping\n");
429 fprintf(stderr
, " got link\n");
432 if ((pw
= getpwnam("_dhcp")) == NULL
)
433 error("no such user: _dhcp");
435 if (pipe(pipe_fd
) == -1)
439 fork_privchld(pipe_fd
[0], pipe_fd
[1]);
444 if ((fd
= open(path_dhclient_db
, O_RDONLY
|O_EXLOCK
|O_CREAT
, 0)) == -1)
445 error("can't open and lock %s: %m", path_dhclient_db
);
446 read_client_leases();
447 if ((leaseFile
= fopen(path_dhclient_db
, "w")) == NULL
)
448 error("can't open %s: %m", path_dhclient_db
);
449 rewrite_client_leases();
452 if ((routefd
= socket(PF_ROUTE
, SOCK_RAW
, 0)) == -1)
453 error("socket(PF_ROUTE, SOCK_RAW): %m");
455 /* set up the interface */
456 discover_interface();
458 if (chroot(_PATH_VAREMPTY
) == -1)
460 if (chdir("/") == -1)
461 error("chdir(\"/\")");
463 if (setresgid(pw
->pw_gid
, pw
->pw_gid
, pw
->pw_gid
) == -1)
465 if (setgroups(1, &pw
->pw_gid
) == -1)
467 if (setresuid(pw
->pw_uid
, pw
->pw_uid
, pw
->pw_uid
) == -1)
472 setproctitle("%s", ifi
->name
);
475 client
->state
= S_REBOOTING
;
487 fprintf(stderr
, "usage: %s [-dqu] [-c file] [-l file] interface\n",
495 * Each routine is called from the dhclient_state_machine() in one of
497 * -> entering INIT state
498 * -> recvpacket_flag == 0: timeout in this state
499 * -> otherwise: received a packet in this state
501 * Return conditions as handled by dhclient_state_machine():
502 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
503 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
504 * Returns 0: finish the nap which was interrupted for no good reason.
506 * Several per-interface variables are used to keep track of the process:
507 * active_lease: the lease that is being used on the interface
508 * (null pointer if not configured yet).
509 * offered_leases: leases corresponding to DHCPOFFER messages that have
510 * been sent to us by DHCP servers.
511 * acked_leases: leases corresponding to DHCPACK messages that have been
512 * sent to us by DHCP servers.
513 * sendpacket: DHCP packet we're trying to send.
514 * destination: IP address to send sendpacket to
515 * In addition, there are several relevant per-lease variables.
516 * T1_expiry, T2_expiry, lease_expiry: lease milestones
517 * In the active lease, these control the process of renewing the lease;
518 * In leases on the acked_leases list, this simply determines when we
519 * can no longer legitimately use the lease.
524 /* Cancel all timeouts, since a link state change gets us here
525 and can happen anytime. */
528 /* If we don't remember an active lease, go straight to INIT. */
529 if (!client
->active
|| client
->active
->is_bootp
) {
530 client
->state
= S_INIT
;
535 /* make_request doesn't initialize xid because it normally comes
536 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
537 so pick an xid now. */
538 client
->xid
= arc4random();
540 /* Make a DHCPREQUEST packet, and set appropriate per-interface
542 make_request(client
->active
);
543 client
->destination
= iaddr_broadcast
;
544 client
->first_sending
= time(NULL
);
545 client
->interval
= 0;
551 * Called when a lease has completely expired and we've
552 * been unable to renew it.
557 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
559 make_discover(client
->active
);
560 client
->xid
= client
->packet
.xid
;
561 client
->destination
= iaddr_broadcast
;
562 client
->state
= S_SELECTING
;
563 client
->first_sending
= time(NULL
);
564 client
->interval
= 0;
570 * state_selecting is called when one or more DHCPOFFER packets
571 * have been received and a configurable period of time has passed.
574 state_selecting(void)
576 struct client_lease
*lp
, *next
, *picked
;
579 /* Cancel state_selecting and send_discover timeouts, since either
580 one could have got us here. */
583 /* We have received one or more DHCPOFFER packets. Currently,
584 the only criterion by which we judge leases is whether or
585 not we get a response when we arp for them. */
587 for (lp
= client
->offered_leases
; lp
; lp
= next
) {
595 free_client_lease(lp
);
598 client
->offered_leases
= NULL
;
600 /* If we just tossed all the leases we were offered, go back
603 client
->state
= S_INIT
;
611 /* If it was a BOOTREPLY, we can just take the address right now. */
612 if (!picked
->options
[DHO_DHCP_MESSAGE_TYPE
].len
) {
613 client
->new = picked
;
615 /* Make up some lease expiry times
616 XXX these should be configurable. */
617 client
->new->expiry
= cur_time
+ 12000;
618 client
->new->renewal
+= cur_time
+ 8000;
619 client
->new->rebind
+= cur_time
+ 10000;
621 client
->state
= S_REQUESTING
;
623 /* Bind to the address we received. */
628 /* Go to the REQUESTING state. */
629 client
->destination
= iaddr_broadcast
;
630 client
->state
= S_REQUESTING
;
631 client
->first_sending
= cur_time
;
632 client
->interval
= 0;
634 /* Make a DHCPREQUEST packet from the lease we picked. */
635 make_request(picked
);
636 client
->xid
= client
->packet
.xid
;
638 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
639 free_client_lease(picked
);
645 dhcpack(struct iaddr client_addr
, struct option_data
*options
)
647 struct client_lease
*lease
;
651 if (client
->state
!= S_REBOOTING
&&
652 client
->state
!= S_REQUESTING
&&
653 client
->state
!= S_RENEWING
&&
654 client
->state
!= S_REBINDING
)
658 lease
= packet_to_lease(options
);
660 note("packet_to_lease failed.");
666 /* Stop resending DHCPREQUEST. */
669 /* Figure out the lease time. */
670 if (client
->new->options
[DHO_DHCP_LEASE_TIME
].data
)
671 client
->new->expiry
=
672 getULong(client
->new->options
[DHO_DHCP_LEASE_TIME
].data
);
674 client
->new->expiry
= DEFAULT_LEASE_TIME
;
675 /* A number that looks negative here is really just very large,
676 because the lease expiry offset is unsigned. */
677 if (client
->new->expiry
< 0)
678 client
->new->expiry
= TIME_MAX
;
679 /* XXX should be fixed by resetting the client state */
680 if (client
->new->expiry
< 60)
681 client
->new->expiry
= 60;
683 /* Take the server-provided renewal time if there is one;
684 otherwise figure it out according to the spec. */
685 if (client
->new->options
[DHO_DHCP_RENEWAL_TIME
].len
)
686 client
->new->renewal
=
687 getULong(client
->new->options
[DHO_DHCP_RENEWAL_TIME
].data
);
689 client
->new->renewal
= client
->new->expiry
/ 2;
691 /* Same deal with the rebind time. */
692 if (client
->new->options
[DHO_DHCP_REBINDING_TIME
].len
)
693 client
->new->rebind
=
694 getULong(client
->new->options
[DHO_DHCP_REBINDING_TIME
].data
);
696 client
->new->rebind
= client
->new->renewal
+
697 client
->new->renewal
/ 2 + client
->new->renewal
/ 4;
701 client
->new->expiry
+= cur_time
;
702 /* Lease lengths can never be negative. */
703 if (client
->new->expiry
< cur_time
)
704 client
->new->expiry
= TIME_MAX
;
705 client
->new->renewal
+= cur_time
;
706 if (client
->new->renewal
< cur_time
)
707 client
->new->renewal
= TIME_MAX
;
708 client
->new->rebind
+= cur_time
;
709 if (client
->new->rebind
< cur_time
)
710 client
->new->rebind
= TIME_MAX
;
718 /* Run the client script with the new parameters. */
719 script_init((client
->state
== S_REQUESTING
? "BOUND" :
720 (client
->state
== S_RENEWING
? "RENEW" :
721 (client
->state
== S_REBOOTING
? "REBOOT" : "REBIND"))));
722 if (client
->active
&& client
->state
!= S_REBOOTING
)
723 script_write_params("old_", client
->active
);
724 script_write_params("new_", client
->new);
727 /* Replace the old active lease with the new one. */
729 free_client_lease(client
->active
);
730 client
->active
= client
->new;
733 /* Write out new leases file. */
734 rewrite_client_leases();
736 /* Set timeout to start the renewal process. */
737 set_timeout(client
->active
->renewal
, state_bound
);
739 note("bound to %s -- renewal in %lld seconds.",
740 piaddr(client
->active
->address
),
741 (long long)(client
->active
->renewal
- time(NULL
)));
742 client
->state
= S_BOUND
;
746 * state_bound is called when we've successfully bound to a particular
747 * lease, but the renewal time on that lease has expired. We are
748 * expected to unicast a DHCPREQUEST to the server that gave us our
754 /* T1 has expired. */
755 make_request(client
->active
);
756 client
->xid
= client
->packet
.xid
;
758 if (client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].len
== 4) {
759 memcpy(client
->destination
.iabuf
,
760 client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].data
,
762 client
->destination
.len
= 4;
764 client
->destination
= iaddr_broadcast
;
766 client
->first_sending
= time(NULL
);
767 client
->interval
= 0;
768 client
->state
= S_RENEWING
;
774 dhcpoffer(struct iaddr client_addr
, struct option_data
*options
)
776 struct client_lease
*lease
, *lp
;
778 time_t stop_selecting
;
779 char *name
= options
[DHO_DHCP_MESSAGE_TYPE
].len
? "DHCPOFFER" :
783 if (client
->state
!= S_SELECTING
)
787 /* If this lease doesn't supply the minimum required parameters,
789 for (i
= 0; config
->required_options
[i
]; i
++) {
790 if (!options
[config
->required_options
[i
]].len
) {
791 note("%s isn't satisfactory.", name
);
796 /* If we've already seen this lease, don't record it again. */
797 for (lease
= client
->offered_leases
;
798 lease
; lease
= lease
->next
) {
799 if (lease
->address
.len
== sizeof(client
->packet
.yiaddr
) &&
800 !memcmp(lease
->address
.iabuf
,
801 &client
->packet
.yiaddr
, lease
->address
.len
)) {
803 debug("%s already seen.", name
);
809 lease
= packet_to_lease(options
);
811 note("packet_to_lease failed.");
816 * Reject offers whose subnet is already configured on another
819 if (subnet_exists(lease
))
822 /* If this lease was acquired through a BOOTREPLY, record that
824 if (!options
[DHO_DHCP_MESSAGE_TYPE
].len
)
827 /* Figure out when we're supposed to stop selecting. */
828 stop_selecting
= client
->first_sending
+ config
->select_interval
;
830 /* If this is the lease we asked for, put it at the head of the
831 list, and don't mess with the arp request timeout. */
832 if (addr_eq(lease
->address
, client
->requested_address
)) {
833 lease
->next
= client
->offered_leases
;
834 client
->offered_leases
= lease
;
836 /* Put the lease at the end of the list. */
838 if (!client
->offered_leases
)
839 client
->offered_leases
= lease
;
841 for (lp
= client
->offered_leases
; lp
->next
;
848 /* If the selecting interval has expired, go immediately to
849 state_selecting(). Otherwise, time out into
850 state_selecting at the select interval. */
851 if (stop_selecting
<= time(NULL
))
854 set_timeout(stop_selecting
, state_selecting
);
859 * Allocate a client_lease structure and initialize it from the
860 * parameters in the specified packet.
862 struct client_lease
*
863 packet_to_lease(struct option_data
*options
)
865 struct client_lease
*lease
;
868 lease
= malloc(sizeof(struct client_lease
));
871 warning("dhcpoffer: no memory to record lease.");
875 memset(lease
, 0, sizeof(*lease
));
877 /* Copy the lease options. */
878 for (i
= 0; i
< 256; i
++) {
879 if (options
[i
].len
) {
880 lease
->options
[i
] = options
[i
];
881 options
[i
].data
= NULL
;
883 if (!check_option(lease
, i
)) {
884 warning("Invalid lease option - ignoring offer");
885 free_client_lease(lease
);
891 lease
->address
.len
= sizeof(client
->packet
.yiaddr
);
892 memcpy(lease
->address
.iabuf
, &client
->packet
.yiaddr
,
895 /* If the server name was filled out, copy it. */
896 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
897 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 2)) &&
898 client
->packet
.sname
[0]) {
899 lease
->server_name
= malloc(DHCP_SNAME_LEN
+ 1);
900 if (!lease
->server_name
) {
901 warning("dhcpoffer: no memory for server name.");
902 free_client_lease(lease
);
905 memcpy(lease
->server_name
, client
->packet
.sname
,
907 lease
->server_name
[DHCP_SNAME_LEN
] = '\0';
908 if (!res_hnok(lease
->server_name
)) {
909 warning("Bogus server name %s", lease
->server_name
);
910 free(lease
->server_name
);
911 lease
->server_name
= NULL
;
915 /* Ditto for the filename. */
916 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
917 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 1)) &&
918 client
->packet
.file
[0]) {
919 /* Don't count on the NUL terminator. */
920 lease
->filename
= malloc(DHCP_FILE_LEN
+ 1);
921 if (!lease
->filename
) {
922 warning("dhcpoffer: no memory for filename.");
923 free_client_lease(lease
);
926 memcpy(lease
->filename
, client
->packet
.file
, DHCP_FILE_LEN
);
927 lease
->filename
[DHCP_FILE_LEN
] = '\0';
933 dhcpnak(struct iaddr client_addr
, struct option_data
*options
)
936 if (client
->state
!= S_REBOOTING
&&
937 client
->state
!= S_REQUESTING
&&
938 client
->state
!= S_RENEWING
&&
939 client
->state
!= S_REBINDING
)
943 if (!client
->active
) {
944 note("DHCPNAK with no active lease.");
948 free_client_lease(client
->active
);
949 client
->active
= NULL
;
951 /* Stop sending DHCPREQUEST packets... */
954 client
->state
= S_INIT
;
959 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
960 * one after the right interval has expired. If we don't get an offer by
961 * the time we reach the panic interval, call the panic function.
967 int interval
, increase
= 1;
971 /* Figure out how long it's been since we started transmitting. */
972 interval
= cur_time
- client
->first_sending
;
974 /* If we're past the panic timeout, call the script and tell it
975 we haven't found anything for this interface yet. */
976 if (interval
> config
->timeout
) {
982 * If we're supposed to increase the interval, do so. If it's
983 * currently zero (i.e., we haven't sent any packets yet), set
984 * it to initial_interval; otherwise, add to it a random
985 * number between zero and two times itself. On average, this
986 * means that it will double with every transmission.
989 if (!client
->interval
)
990 client
->interval
= config
->initial_interval
;
992 client
->interval
+= (arc4random() >> 2) %
993 (2 * client
->interval
);
996 /* Don't backoff past cutoff. */
997 if (client
->interval
> config
->backoff_cutoff
)
998 client
->interval
= ((config
->backoff_cutoff
/ 2)
999 + ((arc4random() >> 2) %
1000 config
->backoff_cutoff
));
1001 } else if (!client
->interval
)
1002 client
->interval
= config
->initial_interval
;
1004 /* If the backoff would take us to the panic timeout, just use that
1006 if (cur_time
+ client
->interval
>
1007 client
->first_sending
+ config
->timeout
)
1008 client
->interval
= (client
->first_sending
+
1009 config
->timeout
) - cur_time
+ 1;
1011 /* Record the number of seconds since we started sending. */
1012 if (interval
< 65536)
1013 client
->packet
.secs
= htons(interval
);
1015 client
->packet
.secs
= htons(65535);
1016 client
->secs
= client
->packet
.secs
;
1018 note("DHCPDISCOVER on %s to %s port %d interval %ld",
1019 ifi
->name
, inet_ntoa(sockaddr_broadcast
.sin_addr
),
1020 ntohs(sockaddr_broadcast
.sin_port
), client
->interval
);
1022 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1024 set_timeout_interval(client
->interval
, send_discover
);
1028 * state_panic gets called if we haven't received any offers in a preset
1029 * amount of time. When this happens, we try to use existing leases
1030 * that haven't yet expired, and failing that, we call the client script
1031 * and hope it can do something.
1036 struct client_lease
*loop
= client
->active
;
1037 struct client_lease
*lp
;
1040 note("No DHCPOFFERS received.");
1042 /* We may not have an active lease, but we may have some
1043 predefined leases that we can try. */
1044 if (!client
->active
&& client
->leases
)
1047 /* Run through the list of leases and see if one can be used. */
1049 while (client
->active
) {
1050 if (client
->active
->expiry
> cur_time
) {
1051 note("Trying recorded lease %s",
1052 piaddr(client
->active
->address
));
1053 /* Run the client script with the existing
1055 script_init("TIMEOUT");
1056 script_write_params("new_", client
->active
);
1058 /* If the old lease is still good and doesn't
1059 yet need renewal, go into BOUND state and
1060 timeout at the renewal time. */
1062 if (cur_time
< client
->active
->renewal
) {
1063 client
->state
= S_BOUND
;
1064 note("bound: renewal in %lld seconds.",
1065 (long long)(client
->active
->renewal
1067 set_timeout(client
->active
->renewal
,
1070 client
->state
= S_BOUND
;
1071 note("bound: immediate renewal.");
1078 /* If there are no other leases, give up. */
1079 if (!client
->leases
) {
1080 client
->leases
= client
->active
;
1081 client
->active
= NULL
;
1086 /* Otherwise, put the active lease at the end of the
1087 lease list, and try another lease.. */
1088 for (lp
= client
->leases
; lp
->next
; lp
= lp
->next
)
1090 lp
->next
= client
->active
;
1092 lp
->next
->next
= NULL
;
1093 client
->active
= client
->leases
;
1094 client
->leases
= client
->leases
->next
;
1096 /* If we already tried this lease, we've exhausted the
1097 set of leases, so we might as well give up for
1099 if (client
->active
== loop
)
1102 loop
= client
->active
;
1105 /* No leases were available, or what was available didn't work, so
1106 tell the shell script that we failed to allocate an address,
1107 and try again later. */
1108 note("No working leases in persistent database - sleeping.");
1109 script_init("FAIL");
1111 client
->state
= S_INIT
;
1112 set_timeout_interval(config
->retry_interval
, state_init
);
1118 struct sockaddr_in destination
;
1119 struct in_addr from
;
1125 /* Figure out how long it's been since we started transmitting. */
1126 interval
= (int)(cur_time
- client
->first_sending
);
1128 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1129 past the reboot timeout, go to INIT and see if we can
1130 DISCOVER an address... */
1131 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1132 means either that we're on a network with no DHCP server,
1133 or that our server is down. In the latter case, assuming
1134 that there is a backup DHCP server, DHCPDISCOVER will get
1135 us a new address, but we could also have successfully
1136 reused our old address. In the former case, we're hosed
1137 anyway. This is not a win-prone situation. */
1138 if ((client
->state
== S_REBOOTING
||
1139 client
->state
== S_REQUESTING
) &&
1140 interval
> config
->reboot_timeout
) {
1141 client
->state
= S_INIT
;
1147 /* If the lease has expired, relinquish the address and go back
1148 to the INIT state. */
1149 if (client
->state
!= S_REQUESTING
&&
1150 cur_time
> client
->active
->expiry
) {
1151 /* Run the client script with the new parameters. */
1152 script_init("EXPIRE");
1153 script_write_params("old_", client
->active
);
1156 client
->state
= S_INIT
;
1161 /* Do the exponential backoff... */
1162 if (!client
->interval
)
1163 client
->interval
= config
->initial_interval
;
1165 client
->interval
+= ((arc4random() >> 2) %
1166 (2 * client
->interval
));
1168 /* Don't backoff past cutoff. */
1169 if (client
->interval
> config
->backoff_cutoff
)
1170 client
->interval
= ((config
->backoff_cutoff
/ 2) +
1171 ((arc4random() >> 2) % client
->interval
));
1173 /* If the backoff would take us to the expiry time, just set the
1174 timeout to the expiry time. */
1175 if (client
->state
!= S_REQUESTING
&& cur_time
+ client
->interval
>
1176 client
->active
->expiry
)
1177 client
->interval
= client
->active
->expiry
- cur_time
+ 1;
1179 /* If the lease T2 time has elapsed, or if we're not yet bound,
1180 broadcast the DHCPREQUEST rather than unicasting. */
1181 memset(&destination
, 0, sizeof(destination
));
1182 if (client
->state
== S_REQUESTING
||
1183 client
->state
== S_REBOOTING
||
1184 cur_time
> client
->active
->rebind
)
1185 destination
.sin_addr
.s_addr
= INADDR_BROADCAST
;
1187 memcpy(&destination
.sin_addr
.s_addr
, client
->destination
.iabuf
,
1188 sizeof(destination
.sin_addr
.s_addr
));
1189 destination
.sin_port
= htons(REMOTE_PORT
);
1190 destination
.sin_family
= AF_INET
;
1191 destination
.sin_len
= sizeof(destination
);
1193 if (client
->state
!= S_REQUESTING
)
1194 memcpy(&from
, client
->active
->address
.iabuf
, sizeof(from
));
1196 from
.s_addr
= INADDR_ANY
;
1198 /* Record the number of seconds since we started sending. */
1199 if (client
->state
== S_REQUESTING
)
1200 client
->packet
.secs
= client
->secs
;
1202 if (interval
< 65536)
1203 client
->packet
.secs
= htons(interval
);
1205 client
->packet
.secs
= htons(65535);
1208 note("DHCPREQUEST on %s to %s port %d", ifi
->name
,
1209 inet_ntoa(destination
.sin_addr
), ntohs(destination
.sin_port
));
1211 send_packet(from
, &destination
, NULL
);
1213 set_timeout_interval(client
->interval
, send_request
);
1219 note("DHCPDECLINE on %s to %s port %d", ifi
->name
,
1220 inet_ntoa(sockaddr_broadcast
.sin_addr
),
1221 ntohs(sockaddr_broadcast
.sin_port
));
1223 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1227 make_discover(struct client_lease
*lease
)
1229 unsigned char discover
= DHCPDISCOVER
;
1230 struct option_data options
[256];
1233 memset(options
, 0, sizeof(options
));
1234 memset(&client
->packet
, 0, sizeof(client
->packet
));
1236 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1237 i
= DHO_DHCP_MESSAGE_TYPE
;
1238 options
[i
].data
= &discover
;
1239 options
[i
].len
= sizeof(discover
);
1241 /* Request the options we want */
1242 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1243 options
[i
].data
= config
->requested_options
;
1244 options
[i
].len
= config
->requested_option_count
;
1246 /* If we had an address, try to get it again. */
1248 client
->requested_address
= lease
->address
;
1249 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1250 options
[i
].data
= lease
->address
.iabuf
;
1251 options
[i
].len
= lease
->address
.len
;
1253 client
->requested_address
.len
= 0;
1255 /* Send any options requested in the config file. */
1256 for (i
= 0; i
< 256; i
++)
1257 if (!options
[i
].data
&&
1258 config
->send_options
[i
].data
) {
1259 options
[i
].data
= config
->send_options
[i
].data
;
1260 options
[i
].len
= config
->send_options
[i
].len
;
1263 /* Set up the option buffer to fit in a minimal UDP packet. */
1264 i
= cons_options(options
);
1265 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1266 error("options do not fit in DHCPDISCOVER packet.");
1267 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1268 if (client
->packet_length
< BOOTP_MIN_LEN
)
1269 client
->packet_length
= BOOTP_MIN_LEN
;
1271 client
->packet
.op
= BOOTREQUEST
;
1272 client
->packet
.htype
= ifi
->hw_address
.htype
;
1273 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1274 client
->packet
.hops
= 0;
1275 client
->packet
.xid
= arc4random();
1276 client
->packet
.secs
= 0; /* filled in by send_discover. */
1277 client
->packet
.flags
= 0;
1279 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1280 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1281 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1282 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1283 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1284 ifi
->hw_address
.hlen
);
1288 make_request(struct client_lease
* lease
)
1290 unsigned char request
= DHCPREQUEST
;
1291 struct option_data options
[256];
1294 memset(options
, 0, sizeof(options
));
1295 memset(&client
->packet
, 0, sizeof(client
->packet
));
1297 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1298 i
= DHO_DHCP_MESSAGE_TYPE
;
1299 options
[i
].data
= &request
;
1300 options
[i
].len
= sizeof(request
);
1302 /* Request the options we want */
1303 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1304 options
[i
].data
= config
->requested_options
;
1305 options
[i
].len
= config
->requested_option_count
;
1307 /* If we are requesting an address that hasn't yet been assigned
1308 to us, use the DHCP Requested Address option. */
1309 if (client
->state
== S_REQUESTING
) {
1310 /* Send back the server identifier... */
1311 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1312 options
[i
].data
= lease
->options
[i
].data
;
1313 options
[i
].len
= lease
->options
[i
].len
;
1315 if (client
->state
== S_REQUESTING
||
1316 client
->state
== S_REBOOTING
) {
1317 client
->requested_address
= lease
->address
;
1318 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1319 options
[i
].data
= lease
->address
.iabuf
;
1320 options
[i
].len
= lease
->address
.len
;
1322 client
->requested_address
.len
= 0;
1324 /* Send any options requested in the config file. */
1325 for (i
= 0; i
< 256; i
++)
1326 if (!options
[i
].data
&& config
->send_options
[i
].data
) {
1327 options
[i
].data
= config
->send_options
[i
].data
;
1328 options
[i
].len
= config
->send_options
[i
].len
;
1331 /* Set up the option buffer to fit in a minimal UDP packet. */
1332 i
= cons_options(options
);
1333 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1334 error("options do not fit in DHCPREQUEST packet.");
1335 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1336 if (client
->packet_length
< BOOTP_MIN_LEN
)
1337 client
->packet_length
= BOOTP_MIN_LEN
;
1339 client
->packet
.op
= BOOTREQUEST
;
1340 client
->packet
.htype
= ifi
->hw_address
.htype
;
1341 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1342 client
->packet
.hops
= 0;
1343 client
->packet
.xid
= client
->xid
;
1344 client
->packet
.secs
= 0; /* Filled in by send_request. */
1345 client
->packet
.flags
= 0;
1347 /* If we own the address we're requesting, put it in ciaddr;
1348 otherwise set ciaddr to zero. */
1349 if (client
->state
== S_BOUND
||
1350 client
->state
== S_RENEWING
||
1351 client
->state
== S_REBINDING
) {
1352 memcpy(&client
->packet
.ciaddr
,
1353 lease
->address
.iabuf
, lease
->address
.len
);
1355 memset(&client
->packet
.ciaddr
, 0,
1356 sizeof(client
->packet
.ciaddr
));
1359 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1360 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1361 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1362 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1363 ifi
->hw_address
.hlen
);
1367 make_decline(struct client_lease
*lease
)
1369 struct option_data options
[256];
1370 unsigned char decline
= DHCPDECLINE
;
1373 memset(options
, 0, sizeof(options
));
1374 memset(&client
->packet
, 0, sizeof(client
->packet
));
1376 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1377 i
= DHO_DHCP_MESSAGE_TYPE
;
1378 options
[i
].data
= &decline
;
1379 options
[i
].len
= sizeof(decline
);
1381 /* Send back the server identifier... */
1382 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1383 options
[i
].data
= lease
->options
[i
].data
;
1384 options
[i
].len
= lease
->options
[i
].len
;
1386 /* Send back the address we're declining. */
1387 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1388 options
[i
].data
= lease
->address
.iabuf
;
1389 options
[i
].len
= lease
->address
.len
;
1391 /* Send the uid if the user supplied one. */
1392 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
1393 if (config
->send_options
[i
].len
) {
1394 options
[i
].data
= config
->send_options
[i
].data
;
1395 options
[i
].len
= config
->send_options
[i
].len
;
1398 /* Set up the option buffer to fit in a minimal UDP packet. */
1399 i
= cons_options(options
);
1400 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1401 error("options do not fit in DHCPDECLINE packet.");
1402 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1403 if (client
->packet_length
< BOOTP_MIN_LEN
)
1404 client
->packet_length
= BOOTP_MIN_LEN
;
1406 client
->packet
.op
= BOOTREQUEST
;
1407 client
->packet
.htype
= ifi
->hw_address
.htype
;
1408 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1409 client
->packet
.hops
= 0;
1410 client
->packet
.xid
= client
->xid
;
1411 client
->packet
.secs
= 0; /* Filled in by send_request. */
1412 client
->packet
.flags
= 0;
1414 /* ciaddr must always be zero. */
1415 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1416 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1417 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1418 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1419 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1420 ifi
->hw_address
.hlen
);
1424 free_client_lease(struct client_lease
*lease
)
1428 if (lease
->server_name
)
1429 free(lease
->server_name
);
1430 if (lease
->filename
)
1431 free(lease
->filename
);
1432 for (i
= 0; i
< 256; i
++) {
1433 if (lease
->options
[i
].len
)
1434 free(lease
->options
[i
].data
);
1440 rewrite_client_leases(void)
1442 struct client_lease
*lp
;
1444 if (!leaseFile
) /* XXX */
1445 error("lease file not open");
1450 for (lp
= client
->leases
; lp
; lp
= lp
->next
) {
1451 if (client
->active
&& addr_eq(lp
->address
,
1452 client
->active
->address
))
1454 write_client_lease(lp
);
1458 write_client_lease(client
->active
);
1461 ftruncate(fileno(leaseFile
), ftello(leaseFile
));
1462 fsync(fileno(leaseFile
));
1466 write_client_lease(struct client_lease
*lease
)
1471 /* If the lease came from the config file, we don't need to stash
1472 a copy in the lease database. */
1473 if (lease
->is_static
)
1476 if (!leaseFile
) /* XXX */
1477 error("lease file not open");
1479 fprintf(leaseFile
, "lease {\n");
1480 if (lease
->is_bootp
)
1481 fprintf(leaseFile
, " bootp;\n");
1482 fprintf(leaseFile
, " interface \"%s\";\n", ifi
->name
);
1483 fprintf(leaseFile
, " fixed-address %s;\n", piaddr(lease
->address
));
1484 if (lease
->filename
)
1485 fprintf(leaseFile
, " filename \"%s\";\n", lease
->filename
);
1486 if (lease
->server_name
)
1487 fprintf(leaseFile
, " server-name \"%s\";\n",
1488 lease
->server_name
);
1489 for (i
= 0; i
< 256; i
++)
1490 if (lease
->options
[i
].len
)
1491 fprintf(leaseFile
, " option %s %s;\n",
1492 dhcp_options
[i
].name
,
1493 pretty_print_option(i
, &lease
->options
[i
], 1));
1495 t
= gmtime(&lease
->renewal
);
1496 fprintf(leaseFile
, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1497 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1498 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1499 t
= gmtime(&lease
->rebind
);
1500 fprintf(leaseFile
, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1501 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1502 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1503 t
= gmtime(&lease
->expiry
);
1504 fprintf(leaseFile
, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1505 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1506 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1507 fprintf(leaseFile
, "}\n");
1512 script_init(char *reason
)
1515 struct imsg_hdr hdr
;
1518 hdr
.code
= IMSG_SCRIPT_INIT
;
1519 hdr
.len
= sizeof(struct imsg_hdr
) + sizeof(size_t) + strlen(reason
);
1520 buf
= buf_open(hdr
.len
);
1522 buf_add(buf
, &hdr
, sizeof(hdr
));
1523 len
= strlen(reason
);
1524 buf_add(buf
, &len
, sizeof(len
));
1525 buf_add(buf
, reason
, len
);
1527 buf_close(privfd
, buf
);
1531 priv_script_init(char *reason
)
1533 client
->scriptEnvsize
= 100;
1534 if (client
->scriptEnv
== NULL
)
1536 calloc(client
->scriptEnvsize
, sizeof(char *));
1537 if (client
->scriptEnv
== NULL
)
1538 error("script_init: no memory for environment");
1540 client
->scriptEnv
[0] = strdup(CLIENT_PATH
);
1541 if (client
->scriptEnv
[0] == NULL
)
1542 error("script_init: no memory for environment");
1544 client
->scriptEnv
[1] = NULL
;
1546 script_set_env("", "interface", ifi
->name
);
1548 script_set_env("", "reason", reason
);
1552 priv_script_write_params(char *prefix
, struct client_lease
*lease
)
1555 struct option_data o
;
1558 script_set_env(prefix
, "ip_address", piaddr(lease
->address
));
1560 if (lease
->options
[DHO_SUBNET_MASK
].len
&&
1561 (lease
->options
[DHO_SUBNET_MASK
].len
<
1562 sizeof(lease
->address
.iabuf
))) {
1563 struct iaddr netmask
, subnet
, broadcast
;
1565 memcpy(netmask
.iabuf
, lease
->options
[DHO_SUBNET_MASK
].data
,
1566 lease
->options
[DHO_SUBNET_MASK
].len
);
1567 netmask
.len
= lease
->options
[DHO_SUBNET_MASK
].len
;
1569 subnet
= subnet_number(lease
->address
, netmask
);
1571 script_set_env(prefix
, "network_number",
1573 if (!lease
->options
[DHO_BROADCAST_ADDRESS
].len
) {
1574 broadcast
= broadcast_addr(subnet
, netmask
);
1576 script_set_env(prefix
,
1577 "broadcast_address",
1583 if (lease
->filename
)
1584 script_set_env(prefix
, "filename", lease
->filename
);
1585 if (lease
->server_name
)
1586 script_set_env(prefix
, "server_name",
1587 lease
->server_name
);
1589 for (i
= 0; i
< 256; i
++) {
1590 if (!dhcp_option_ev_name(buf
, sizeof(buf
), &dhcp_options
[i
]))
1593 switch (config
->default_actions
[i
]) {
1597 case ACTION_DEFAULT
:
1598 if (lease
->options
[i
].len
)
1599 script_set_env(prefix
, buf
,
1600 pretty_print_option(i
, &lease
->options
[i
],
1602 else if (config
->defaults
[i
].len
)
1603 script_set_env(prefix
, buf
,
1604 pretty_print_option(i
, &config
->defaults
[i
],
1608 case ACTION_SUPERSEDE
:
1609 if (config
->defaults
[i
].len
)
1610 script_set_env(prefix
, buf
,
1611 pretty_print_option(i
, &config
->defaults
[i
],
1615 case ACTION_PREPEND
:
1616 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1618 o
.data
= calloc(1, o
.len
);
1620 error("no space to prepend '%s' to %s",
1621 config
->defaults
[i
].data
,
1622 dhcp_options
[i
].name
);
1623 memcpy(o
.data
, config
->defaults
[i
].data
,
1624 config
->defaults
[i
].len
);
1625 memcpy(o
.data
+ config
->defaults
[i
].len
,
1626 lease
->options
[i
].data
,
1627 lease
->options
[i
].len
);
1628 script_set_env(prefix
, buf
,
1629 pretty_print_option(i
, &o
, 0));
1635 o
.len
= config
->defaults
[i
].len
+ lease
->options
[i
].len
;
1637 o
.data
= calloc(1, o
.len
);
1639 error("no space to append '%s' to %s",
1640 config
->defaults
[i
].data
,
1641 dhcp_options
[i
].name
);
1642 memcpy(o
.data
, lease
->options
[i
].data
,
1643 lease
->options
[i
].len
);
1644 memcpy(o
.data
+ lease
->options
[i
].len
,
1645 config
->defaults
[i
].data
,
1646 config
->defaults
[i
].len
);
1647 script_set_env(prefix
, buf
,
1648 pretty_print_option(i
, &o
, 0));
1655 snprintf(buf
, sizeof(buf
), "%d", (int)lease
->expiry
);
1656 script_set_env(prefix
, "expiry", buf
);
1660 script_write_params(char *prefix
, struct client_lease
*lease
)
1662 size_t fn_len
= 0, sn_len
= 0, pr_len
= 0;
1663 struct imsg_hdr hdr
;
1667 if (lease
->filename
!= NULL
)
1668 fn_len
= strlen(lease
->filename
);
1669 if (lease
->server_name
!= NULL
)
1670 sn_len
= strlen(lease
->server_name
);
1672 pr_len
= strlen(prefix
);
1674 hdr
.code
= IMSG_SCRIPT_WRITE_PARAMS
;
1675 hdr
.len
= sizeof(hdr
) + sizeof(struct client_lease
) +
1676 sizeof(size_t) + fn_len
+ sizeof(size_t) + sn_len
+
1677 sizeof(size_t) + pr_len
;
1679 for (i
= 0; i
< 256; i
++)
1680 hdr
.len
+= sizeof(int) + lease
->options
[i
].len
;
1682 scripttime
= time(NULL
);
1684 buf
= buf_open(hdr
.len
);
1686 buf_add(buf
, &hdr
, sizeof(hdr
));
1687 buf_add(buf
, lease
, sizeof(struct client_lease
));
1688 buf_add(buf
, &fn_len
, sizeof(fn_len
));
1689 buf_add(buf
, lease
->filename
, fn_len
);
1690 buf_add(buf
, &sn_len
, sizeof(sn_len
));
1691 buf_add(buf
, lease
->server_name
, sn_len
);
1692 buf_add(buf
, &pr_len
, sizeof(pr_len
));
1693 buf_add(buf
, prefix
, pr_len
);
1695 for (i
= 0; i
< 256; i
++) {
1696 buf_add(buf
, &lease
->options
[i
].len
,
1697 sizeof(lease
->options
[i
].len
));
1698 buf_add(buf
, lease
->options
[i
].data
,
1699 lease
->options
[i
].len
);
1702 buf_close(privfd
, buf
);
1708 struct imsg_hdr hdr
;
1712 scripttime
= time(NULL
);
1714 hdr
.code
= IMSG_SCRIPT_GO
;
1715 hdr
.len
= sizeof(struct imsg_hdr
);
1717 buf
= buf_open(hdr
.len
);
1719 buf_add(buf
, &hdr
, sizeof(hdr
));
1720 buf_close(privfd
, buf
);
1722 bzero(&hdr
, sizeof(hdr
));
1723 buf_read(privfd
, &hdr
, sizeof(hdr
));
1724 if (hdr
.code
!= IMSG_SCRIPT_GO_RET
)
1725 error("unexpected msg type %u", hdr
.code
);
1726 if (hdr
.len
!= sizeof(hdr
) + sizeof(int))
1727 error("received corrupted message");
1728 buf_read(privfd
, &ret
, sizeof(ret
));
1734 priv_script_go(void)
1736 char *scriptName
, *argv
[2], **envp
;
1737 int pid
, wpid
, wstatus
;
1739 scripttime
= time(NULL
);
1741 scriptName
= config
->script_name
;
1742 envp
= client
->scriptEnv
;
1744 argv
[0] = scriptName
;
1753 wpid
= wait(&wstatus
);
1754 } while (wpid
!= pid
&& wpid
> 0);
1760 execve(scriptName
, argv
, envp
);
1761 error("execve (%s, ...): %m", scriptName
);
1766 return (WEXITSTATUS(wstatus
));
1770 script_set_env(const char *prefix
, const char *name
, const char *value
)
1774 /* No `` or $() command substitution allowed in environment values! */
1775 for (j
= 0; j
< strlen(value
); j
++)
1779 warning("illegal character (%c) in value '%s'",
1781 /* Ignore this option */
1785 namelen
= strlen(name
);
1787 for (i
= 0; client
->scriptEnv
[i
]; i
++)
1788 if (strncmp(client
->scriptEnv
[i
], name
, namelen
) == 0 &&
1789 client
->scriptEnv
[i
][namelen
] == '=')
1792 if (client
->scriptEnv
[i
])
1793 /* Reuse the slot. */
1794 free(client
->scriptEnv
[i
]);
1796 /* New variable. Expand if necessary. */
1797 if (i
>= client
->scriptEnvsize
- 1) {
1798 char **newscriptEnv
;
1799 int newscriptEnvsize
= client
->scriptEnvsize
+ 50;
1801 newscriptEnv
= realloc(client
->scriptEnv
,
1803 if (newscriptEnv
== NULL
) {
1804 free(client
->scriptEnv
);
1805 client
->scriptEnv
= NULL
;
1806 client
->scriptEnvsize
= 0;
1807 error("script_set_env: no memory for variable");
1809 client
->scriptEnv
= newscriptEnv
;
1810 client
->scriptEnvsize
= newscriptEnvsize
;
1812 /* need to set the NULL pointer at end of array beyond
1814 client
->scriptEnv
[i
+ 1] = NULL
;
1816 /* Allocate space and format the variable in the appropriate slot. */
1817 client
->scriptEnv
[i
] = malloc(strlen(prefix
) + strlen(name
) + 1 +
1819 if (client
->scriptEnv
[i
] == NULL
)
1820 error("script_set_env: no memory for variable assignment");
1821 snprintf(client
->scriptEnv
[i
], strlen(prefix
) + strlen(name
) +
1822 1 + strlen(value
) + 1, "%s%s=%s", prefix
, name
, value
);
1826 script_flush_env(void)
1830 for (i
= 0; client
->scriptEnv
[i
]; i
++) {
1831 free(client
->scriptEnv
[i
]);
1832 client
->scriptEnv
[i
] = NULL
;
1834 client
->scriptEnvsize
= 0;
1838 dhcp_option_ev_name(char *buf
, size_t buflen
, const struct option
*option
)
1842 for (i
= 0; option
->name
[i
]; i
++) {
1843 if (i
+ 1 == buflen
)
1845 if (option
->name
[i
] == '-')
1848 buf
[i
] = option
->name
[i
];
1868 * Setup pidfile, kill any dhclient already running for this
1871 snprintf(buf
, sizeof(buf
), "/var/run/dhclient.%s.pid", orig_ifname
);
1872 fd
= open(buf
, O_RDWR
|O_CREAT
, 0644);
1874 if (killclient(fd
)) {
1876 "starting dhclient on %s\n",
1880 "restarting dhclient on %s\n",
1886 * Daemonize if requested
1888 if (no_daemon
== 0) {
1889 /* Stop logging to stderr... */
1892 if (daemon(1, 0) == -1)
1895 /* we are chrooted, daemon(3) fails to open /dev/null */
1897 dup2(nullfd
, STDIN_FILENO
);
1898 dup2(nullfd
, STDOUT_FILENO
);
1899 dup2(nullfd
, STDERR_FILENO
);
1906 * No further daemonizations, write out pid file and lock.
1910 lseek(fd
, 0L, SEEK_SET
);
1912 snprintf(buf
, sizeof(buf
), "%ld\n", (long)getpid());
1913 write(fd
, buf
, strlen(buf
));
1915 /* leave descriptor open and locked */
1920 check_option(struct client_lease
*l
, int option
)
1925 /* we use this, since this is what gets passed to dhclient-script */
1927 opbuf
= pretty_print_option(option
, &l
->options
[option
], 0);
1929 sbuf
= option_as_string(option
, l
->options
[option
].data
,
1930 l
->options
[option
].len
);
1933 case DHO_SUBNET_MASK
:
1934 case DHO_SWAP_SERVER
:
1935 case DHO_BROADCAST_ADDRESS
:
1936 case DHO_DHCP_SERVER_IDENTIFIER
:
1937 case DHO_ROUTER_SOLICITATION_ADDRESS
:
1938 case DHO_DHCP_REQUESTED_ADDRESS
:
1939 if (ipv4addrs(opbuf
) == 0) {
1940 warning("Invalid IP address in option %s: %s",
1941 dhcp_options
[option
].name
, opbuf
);
1944 if (l
->options
[option
].len
!= 4) { /* RFC 2132 */
1945 warning("warning: Only 1 IP address allowed in "
1946 "%s option; length %d, must be 4",
1947 dhcp_options
[option
].name
,
1948 l
->options
[option
].len
);
1949 l
->options
[option
].len
= 4;
1952 case DHO_TIME_SERVERS
:
1953 case DHO_NAME_SERVERS
:
1955 case DHO_DOMAIN_NAME_SERVERS
:
1956 case DHO_LOG_SERVERS
:
1957 case DHO_COOKIE_SERVERS
:
1958 case DHO_LPR_SERVERS
:
1959 case DHO_IMPRESS_SERVERS
:
1960 case DHO_RESOURCE_LOCATION_SERVERS
:
1961 case DHO_NIS_SERVERS
:
1962 case DHO_NTP_SERVERS
:
1963 case DHO_NETBIOS_NAME_SERVERS
:
1964 case DHO_NETBIOS_DD_SERVER
:
1965 case DHO_FONT_SERVERS
:
1966 if (ipv4addrs(opbuf
) == 0) {
1967 warning("Invalid IP address in option %s: %s",
1968 dhcp_options
[option
].name
, opbuf
);
1973 case DHO_DOMAIN_NAME
:
1974 case DHO_NIS_DOMAIN
:
1975 if (!res_hnok(sbuf
)) {
1976 warning("Bogus Host Name option %d: %s (%s)", option
,
1978 l
->options
[option
].len
= 0;
1979 free(l
->options
[option
].data
);
1983 case DHO_TIME_OFFSET
:
1985 case DHO_MERIT_DUMP
:
1987 case DHO_EXTENSIONS_PATH
:
1988 case DHO_IP_FORWARDING
:
1989 case DHO_NON_LOCAL_SOURCE_ROUTING
:
1990 case DHO_POLICY_FILTER
:
1991 case DHO_MAX_DGRAM_REASSEMBLY
:
1992 case DHO_DEFAULT_IP_TTL
:
1993 case DHO_PATH_MTU_AGING_TIMEOUT
:
1994 case DHO_PATH_MTU_PLATEAU_TABLE
:
1995 case DHO_INTERFACE_MTU
:
1996 case DHO_ALL_SUBNETS_LOCAL
:
1997 case DHO_PERFORM_MASK_DISCOVERY
:
1998 case DHO_MASK_SUPPLIER
:
1999 case DHO_ROUTER_DISCOVERY
:
2000 case DHO_STATIC_ROUTES
:
2001 case DHO_TRAILER_ENCAPSULATION
:
2002 case DHO_ARP_CACHE_TIMEOUT
:
2003 case DHO_IEEE802_3_ENCAPSULATION
:
2004 case DHO_DEFAULT_TCP_TTL
:
2005 case DHO_TCP_KEEPALIVE_INTERVAL
:
2006 case DHO_TCP_KEEPALIVE_GARBAGE
:
2007 case DHO_VENDOR_ENCAPSULATED_OPTIONS
:
2008 case DHO_NETBIOS_NODE_TYPE
:
2009 case DHO_NETBIOS_SCOPE
:
2010 case DHO_X_DISPLAY_MANAGER
:
2011 case DHO_DHCP_LEASE_TIME
:
2012 case DHO_DHCP_OPTION_OVERLOAD
:
2013 case DHO_DHCP_MESSAGE_TYPE
:
2014 case DHO_DHCP_PARAMETER_REQUEST_LIST
:
2015 case DHO_DHCP_MESSAGE
:
2016 case DHO_DHCP_MAX_MESSAGE_SIZE
:
2017 case DHO_DHCP_RENEWAL_TIME
:
2018 case DHO_DHCP_REBINDING_TIME
:
2019 case DHO_DHCP_CLASS_IDENTIFIER
:
2020 case DHO_DHCP_CLIENT_IDENTIFIER
:
2021 case DHO_DHCP_USER_CLASS_ID
:
2022 case DHO_TFTP_SERVER
:
2025 case DHO_CLASSLESS_ROUTES
:
2026 return (check_classless_option(l
->options
[option
].data
,
2027 l
->options
[option
].len
));
2030 warning("unknown dhcp option value 0x%x", option
);
2031 return (unknown_ok
);
2035 /* RFC 3442 The Classless Static Routes option checks */
2037 check_classless_option(unsigned char *data
, int len
)
2040 unsigned char width
;
2041 in_addr_t addr
, mask
;
2044 warning("Too small length: %d", len
);
2052 } else if (width
< 9) {
2053 addr
= (in_addr_t
)(data
[i
] << 24);
2055 } else if (width
< 17) {
2056 addr
= (in_addr_t
)(data
[i
] << 24) +
2057 (in_addr_t
)(data
[i
+ 1] << 16);
2059 } else if (width
< 25) {
2060 addr
= (in_addr_t
)(data
[i
] << 24) +
2061 (in_addr_t
)(data
[i
+ 1] << 16) +
2062 (in_addr_t
)(data
[i
+ 2] << 8);
2064 } else if (width
< 33) {
2065 addr
= (in_addr_t
)(data
[i
] << 24) +
2066 (in_addr_t
)(data
[i
+ 1] << 16) +
2067 (in_addr_t
)(data
[i
+ 2] << 8) +
2071 warning("Incorrect subnet width: %d", width
);
2074 mask
= (in_addr_t
)(~0) << (32 - width
);
2080 * ... After deriving a subnet number and subnet mask
2081 * from each destination descriptor, the DHCP client
2082 * MUST zero any bits in the subnet number where the
2083 * corresponding bit in the mask is zero...
2085 if ((addr
& mask
) != addr
) {
2087 data
[i
- 1] = (unsigned char)(
2088 (addr
>> (((32 - width
)/8)*8)) & 0xFF);
2093 warning("Incorrect data length: %d (must be %d)", len
, i
);
2100 res_hnok(const char *name
)
2102 const char *dn
= name
;
2103 int pch
= '.', ch
= *dn
++;
2106 while (ch
!= '\0') {
2111 } else if (pch
== '.' || nch
== '.' || nch
== '\0') {
2114 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '_')
2116 else if (ch
== '_' && warn
== 0) {
2117 warning("warning: hostname %s contains an "
2118 "underscore which violates RFC 952", name
);
2126 /* Does buf consist only of dotted decimal ipv4 addrs?
2127 * return how many if so,
2128 * otherwise, return 0
2131 ipv4addrs(char * buf
)
2136 while (inet_aton(buf
, &jnk
) == 1){
2138 while (*buf
== '.' || isdigit(*buf
))
2149 option_as_string(unsigned int code
, unsigned char *data
, int len
)
2151 static char optbuf
[32768]; /* XXX */
2153 int opleft
= sizeof(optbuf
);
2154 unsigned char *dp
= data
;
2157 error("option_as_string: bad code %d", code
);
2159 for (; dp
< data
+ len
; dp
++) {
2160 if (!isascii(*dp
) || !isprint(*dp
)) {
2161 if (dp
+ 1 != data
+ len
|| *dp
!= 0) {
2163 snprintf(op
, opleft
, "\\%03o", *dp
);
2168 } else if (*dp
== '"' || *dp
== '\'' || *dp
== '$' ||
2169 *dp
== '`' || *dp
== '\\') {
2183 warning("dhcp option too large");
2188 fork_privchld(int fd
, int fd2
)
2190 struct pollfd pfd
[1];
2191 int nfds
, pfail
= 0;
2195 omask
= sigblock(sigmask(SIGINT
)|sigmask(SIGHUP
));
2203 error("cannot fork");
2211 if (chdir("/") == -1)
2212 error("chdir(\"/\")");
2214 setproctitle("%s [priv]", ifi
->name
);
2216 dup2(nullfd
, STDIN_FILENO
);
2217 dup2(nullfd
, STDOUT_FILENO
);
2218 dup2(nullfd
, STDERR_FILENO
);
2224 pfd
[0].events
= POLLIN
;
2225 if ((nfds
= poll(pfd
, 1, INFTIM
)) == -1)
2227 error("poll error");
2230 * Handle temporary errors, but bail if they persist.
2232 if (nfds
== 0 || !(pfd
[0].revents
& POLLIN
)) {
2233 if (pfail
> POLL_FAILURES
)
2234 error("poll failed > %d times", POLL_FAILURES
);
2235 sleep(pfail
* POLL_FAILURE_WAIT
);
2245 get_ifname(char *ifname
, char *arg
)
2247 struct ifgroupreq ifgr
;
2248 struct ifg_req
*ifg
;
2251 if (!strcmp(arg
, "egress")) {
2252 s
= socket(AF_INET
, SOCK_DGRAM
, 0);
2254 error("socket error");
2255 bzero(&ifgr
, sizeof(ifgr
));
2256 strlcpy(ifgr
.ifgr_name
, "egress", sizeof(ifgr
.ifgr_name
));
2257 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1) {
2258 if (errno
== ENOENT
)
2259 error("no interface in group egress found");
2260 error("ioctl SIOCGIFGMEMB: %m");
2262 len
= ifgr
.ifgr_len
;
2263 if ((ifgr
.ifgr_groups
= calloc(1, len
)) == NULL
)
2264 error("get_ifname");
2265 if (ioctl(s
, SIOCGIFGMEMB
, (caddr_t
)&ifgr
) == -1)
2266 error("ioctl SIOCGIFGMEMB: %m");
2269 for (ifg
= ifgr
.ifgr_groups
;
2270 ifg
&& len
>= sizeof(struct ifg_req
); ifg
++) {
2271 len
-= sizeof(struct ifg_req
);
2273 error("too many interfaces in group egress");
2274 arg
= ifg
->ifgrq_member
;
2277 if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2278 error("Interface name too long: %m");
2280 free(ifgr
.ifgr_groups
);
2282 } else if (strlcpy(ifi
->name
, arg
, IFNAMSIZ
) >= IFNAMSIZ
)
2283 error("Interface name too long");
2288 sig_handle(int signo
)
2290 if (monitor_pid
> 0)
2291 kill(monitor_pid
, signo
);
2292 fprintf(stderr
, "killed by signal\n");
2303 * Kill previously running dhclient
2305 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0) {
2310 lseek(fd
, 0L, SEEK_SET
);
2311 n
= read(fd
, buf
, sizeof(buf
));
2314 pid
= strtol(buf
, NULL
, 10);
2320 if (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)
2322 while (flock(fd
, LOCK_EX
|LOCK_NB
) < 0)