1 /* $OpenBSD: dhclient.c,v 1.118 2008/05/09 05:19:14 reyk Exp $ */
2 /* $DragonFly: src/sbin/dhclient/dhclient.c,v 1.2 2008/09/10 10:01:18 matthias Exp $ */
5 * Copyright 2004 Henning Brauer <henning@openbsd.org>
6 * Copyright (c) 1995, 1996, 1997, 1998, 1999
7 * The Internet Software Consortium. All rights reserved.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. Neither the name of The Internet Software Consortium nor the names
19 * of its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
22 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
23 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
24 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
25 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
27 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
28 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
29 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
30 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
31 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * This software has been written for the Internet Software Consortium
37 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
38 * Enterprises. To learn more about the Internet Software Consortium,
39 * see ``http://www.vix.com/isc''. To learn more about Vixie
40 * Enterprises, see ``http://www.vix.com''.
42 * This client was substantially modified and enhanced by Elliot Poger
43 * for use on Linux while he was working on the MosquitoNet project at
46 * The current version owes much to Elliot's Linux enhancements, but
47 * was substantially reorganized and partially rewritten by Ted Lemon
48 * so as to use the same networking framework that the Internet Software
49 * Consortium DHCP server uses. Much system-specific configuration code
50 * was moved into a shell script so that as support for more operating
51 * systems is added, it will not be necessary to port and maintain
52 * system-specific configuration code to these operating systems - instead,
53 * the shell script can invoke the native tools to accomplish the same
64 #define CLIENT_PATH "PATH=/usr/bin:/usr/sbin:/bin:/sbin"
65 #define DEFAULT_LEASE_TIME 43200 /* 12 hours... */
66 #define TIME_MAX 2147483647
70 char *path_dhclient_conf
= _PATH_DHCLIENT_CONF
;
71 char *path_dhclient_db
= NULL
;
80 struct iaddr iaddr_broadcast
= { 4, { 255, 255, 255, 255 } };
81 struct in_addr inaddr_any
;
82 struct sockaddr_in sockaddr_broadcast
;
84 struct interface_info
*ifi
;
85 struct client_state
*client
;
86 struct client_config
*config
;
88 int findproto(char *, int);
89 struct sockaddr
*get_ifa(char *, int);
91 int check_option(struct client_lease
*l
, int option
);
92 int ipv4addrs(char * buf
);
93 int res_hnok(const char *dn
);
94 char *option_as_string(unsigned int code
, unsigned char *data
, int len
);
95 int fork_privchld(int, int);
98 ((a) > 0 ? (1 + (((a) - 1) | (sizeof(long) - 1))) : sizeof(long))
99 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
102 static FILE *leaseFile
;
105 findproto(char *cp
, int n
)
112 for (i
= 1; i
; i
<<= 1) {
114 sa
= (struct sockaddr
*)cp
;
120 if (sa
->sa_family
== AF_INET
)
122 if (sa
->sa_family
== AF_INET6
)
135 get_ifa(char *cp
, int n
)
142 for (i
= 1; i
; i
<<= 1)
144 sa
= (struct sockaddr
*)cp
;
152 struct iaddr defaddr
= { 4, {NULL
} }; /* NULL is for silence warnings */
160 struct rt_msghdr
*rtm
;
161 struct if_msghdr
*ifm
;
162 struct ifa_msghdr
*ifam
;
163 struct if_announcemsghdr
*ifan
;
164 struct client_lease
*l
;
165 time_t t
= time(NULL
);
171 n
= read(routefd
, &msg
, sizeof(msg
));
172 } while (n
== -1 && errno
== EINTR
);
174 rtm
= (struct rt_msghdr
*)msg
;
175 if (n
< sizeof(rtm
->rtm_msglen
) || n
< rtm
->rtm_msglen
||
176 rtm
->rtm_version
!= RTM_VERSION
)
179 switch (rtm
->rtm_type
) {
181 ifam
= (struct ifa_msghdr
*)rtm
;
182 if (ifam
->ifam_index
!= ifi
->index
)
184 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
186 sa
= get_ifa((char *)(ifam
+ 1), ifam
->ifam_addrs
);
190 if ((a
.len
= sizeof(struct in_addr
)) > sizeof(a
.iabuf
))
191 error("king bula sez: len mismatch");
192 memcpy(a
.iabuf
, &((struct sockaddr_in
*)sa
)->sin_addr
, a
.len
);
193 if (addr_eq(a
, defaddr
))
196 for (l
= client
->active
; l
!= NULL
; l
= l
->next
)
197 if (addr_eq(a
, l
->address
))
200 if (l
!= NULL
|| (client
->alias
&&
201 addr_eq(a
, client
->alias
->address
)))
202 /* new addr is the one we set */
207 ifam
= (struct ifa_msghdr
*)rtm
;
208 if (ifam
->ifam_index
!= ifi
->index
)
210 if (findproto((char *)(ifam
+ 1), ifam
->ifam_addrs
) != AF_INET
)
212 if (scripttime
== 0 || t
< scripttime
+ 10)
216 ifm
= (struct if_msghdr
*)rtm
;
217 if (ifm
->ifm_index
!= ifi
->index
)
219 if ((rtm
->rtm_flags
& RTF_UP
) == 0)
223 LINK_STATE_IS_UP(ifm
->ifm_data
.ifi_link_state
) ? 1 : 0;
224 if (linkstat
!= ifi
->linkstat
) {
225 debug("link state %s -> %s",
226 ifi
->linkstat
? "up" : "down",
227 linkstat
? "up" : "down");
228 ifi
->linkstat
= interface_link_status(ifi
->name
);
230 client
->state
= S_INIT
;
236 ifan
= (struct if_announcemsghdr
*)rtm
;
237 if (ifan
->ifan_what
== IFAN_DEPARTURE
&&
238 ifan
->ifan_index
== ifi
->index
)
247 script_init("FAIL", NULL
);
249 script_write_params("alias_", client
->alias
);
255 main(int argc
, char *argv
[])
257 int ch
, fd
, quiet
= 0, i
= 0, pipe_fd
[2];
260 /* Initially, log errors to stderr as well as to syslogd. */
261 openlog(getprogname(), LOG_PID
| LOG_NDELAY
, DHCPD_LOG_FACILITY
);
262 setlogmask(LOG_UPTO(LOG_INFO
));
264 while ((ch
= getopt(argc
, argv
, "c:dl:qu")) != -1)
267 path_dhclient_conf
= optarg
;
273 path_dhclient_db
= optarg
;
291 ifi
= calloc(1, sizeof(*ifi
));
294 client
= calloc(1, sizeof(*client
));
296 error("client calloc");
297 config
= calloc(1, sizeof(*config
));
299 error("config calloc");
301 if (strlcpy(ifi
->name
, argv
[0], IFNAMSIZ
) >= IFNAMSIZ
)
302 error("Interface name too long");
303 if (path_dhclient_db
== NULL
&& asprintf(&path_dhclient_db
, "%s.%s",
304 _PATH_DHCLIENT_DB
, ifi
->name
) == -1)
313 memset(&sockaddr_broadcast
, 0, sizeof(sockaddr_broadcast
));
314 sockaddr_broadcast
.sin_family
= AF_INET
;
315 sockaddr_broadcast
.sin_port
= htons(REMOTE_PORT
);
316 sockaddr_broadcast
.sin_addr
.s_addr
= INADDR_BROADCAST
;
317 sockaddr_broadcast
.sin_len
= sizeof(sockaddr_broadcast
);
318 inaddr_any
.s_addr
= INADDR_ANY
;
322 if (interface_status(ifi
->name
) == 0) {
323 interface_link_forceup(ifi
->name
);
324 /* Give it up to 4 seconds of silent grace to find link */
329 while (!(ifi
->linkstat
= interface_link_status(ifi
->name
))) {
331 fprintf(stderr
, "%s: no link ...", ifi
->name
);
333 fprintf(stderr
, ".");
335 if (++i
> config
->link_timeout
) {
336 fprintf(stderr
, " sleeping\n");
342 fprintf(stderr
, " got link\n");
345 if ((nullfd
= open(_PATH_DEVNULL
, O_RDWR
, 0)) == -1)
346 error("cannot open %s: %m", _PATH_DEVNULL
);
348 if ((pw
= getpwnam("_dhcp")) == NULL
) {
349 warning("no such user: _dhcp, falling back to \"nobody\"");
350 if ((pw
= getpwnam("nobody")) == NULL
)
351 error("no such user: nobody");
354 if (pipe(pipe_fd
) == -1)
357 fork_privchld(pipe_fd
[0], pipe_fd
[1]);
362 if ((fd
= open(path_dhclient_db
, O_RDONLY
|O_EXLOCK
|O_CREAT
, 0)) == -1)
363 error("can't open and lock %s: %m", path_dhclient_db
);
364 read_client_leases();
365 if ((leaseFile
= fopen(path_dhclient_db
, "w")) == NULL
)
366 error("can't open %s: %m", path_dhclient_db
);
367 rewrite_client_leases();
370 priv_script_init("PREINIT", NULL
);
372 priv_script_write_params("alias_", client
->alias
);
375 if ((routefd
= socket(PF_ROUTE
, SOCK_RAW
, 0)) == -1)
376 error("socket(PF_ROUTE, SOCK_RAW): %m");
378 /* set up the interface */
379 discover_interface();
381 if (chroot(_PATH_VAREMPTY
) == -1)
383 if (chdir("/") == -1)
384 error("chdir(\"/\")");
386 if (setresgid(pw
->pw_gid
, pw
->pw_gid
, pw
->pw_gid
) == -1)
388 if (setgroups(1, &pw
->pw_gid
) == -1)
390 if (setresuid(pw
->pw_uid
, pw
->pw_uid
, pw
->pw_uid
) == -1)
395 setproctitle("%s", ifi
->name
);
398 client
->state
= S_INIT
;
412 fprintf(stderr
, "usage: %s [-dqu] [-c file] [-l file] interface\n",
420 * Each routine is called from the dhclient_state_machine() in one of
422 * -> entering INIT state
423 * -> recvpacket_flag == 0: timeout in this state
424 * -> otherwise: received a packet in this state
426 * Return conditions as handled by dhclient_state_machine():
427 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
428 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
429 * Returns 0: finish the nap which was interrupted for no good reason.
431 * Several per-interface variables are used to keep track of the process:
432 * active_lease: the lease that is being used on the interface
433 * (null pointer if not configured yet).
434 * offered_leases: leases corresponding to DHCPOFFER messages that have
435 * been sent to us by DHCP servers.
436 * acked_leases: leases corresponding to DHCPACK messages that have been
437 * sent to us by DHCP servers.
438 * sendpacket: DHCP packet we're trying to send.
439 * destination: IP address to send sendpacket to
440 * In addition, there are several relevant per-lease variables.
441 * T1_expiry, T2_expiry, lease_expiry: lease milestones
442 * In the active lease, these control the process of renewing the lease;
443 * In leases on the acked_leases list, this simply determines when we
444 * can no longer legitimately use the lease.
449 /* If we don't remember an active lease, go straight to INIT. */
450 if (!client
->active
|| client
->active
->is_bootp
) {
455 /* We are in the rebooting state. */
456 client
->state
= S_REBOOTING
;
458 /* make_request doesn't initialize xid because it normally comes
459 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
460 so pick an xid now. */
461 client
->xid
= arc4random();
463 /* Make a DHCPREQUEST packet, and set appropriate per-interface
465 make_request(client
->active
);
466 client
->destination
= iaddr_broadcast
;
467 client
->first_sending
= cur_time
;
468 client
->interval
= config
->initial_interval
;
470 /* Zap the medium list... */
471 client
->medium
= NULL
;
473 /* Send out the first DHCPREQUEST packet. */
478 * Called when a lease has completely expired and we've
479 * been unable to renew it.
484 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
486 make_discover(client
->active
);
487 client
->xid
= client
->packet
.xid
;
488 client
->destination
= iaddr_broadcast
;
489 client
->state
= S_SELECTING
;
490 client
->first_sending
= cur_time
;
491 client
->interval
= config
->initial_interval
;
493 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
499 * state_selecting is called when one or more DHCPOFFER packets
500 * have been received and a configurable period of time has passed.
503 state_selecting(void)
505 struct client_lease
*lp
, *next
, *picked
;
507 /* Cancel state_selecting and send_discover timeouts, since either
508 one could have got us here. */
509 cancel_timeout(state_selecting
);
510 cancel_timeout(send_discover
);
512 /* We have received one or more DHCPOFFER packets. Currently,
513 the only criterion by which we judge leases is whether or
514 not we get a response when we arp for them. */
516 for (lp
= client
->offered_leases
; lp
; lp
= next
) {
519 /* Check to see if we got an ARPREPLY for the address
520 in this particular lease. */
522 script_init("ARPCHECK", lp
->medium
);
523 script_write_params("check_", lp
);
525 /* If the ARPCHECK code detects another
526 machine using the offered address, it exits
527 nonzero. We need to send a DHCPDECLINE and
538 free_client_lease(lp
);
541 client
->offered_leases
= NULL
;
543 /* If we just tossed all the leases we were offered, go back
546 client
->state
= S_INIT
;
551 /* If it was a BOOTREPLY, we can just take the address right now. */
552 if (!picked
->options
[DHO_DHCP_MESSAGE_TYPE
].len
) {
553 client
->new = picked
;
555 /* Make up some lease expiry times
556 XXX these should be configurable. */
557 client
->new->expiry
= cur_time
+ 12000;
558 client
->new->renewal
+= cur_time
+ 8000;
559 client
->new->rebind
+= cur_time
+ 10000;
561 client
->state
= S_REQUESTING
;
563 /* Bind to the address we received. */
568 /* Go to the REQUESTING state. */
569 client
->destination
= iaddr_broadcast
;
570 client
->state
= S_REQUESTING
;
571 client
->first_sending
= cur_time
;
572 client
->interval
= config
->initial_interval
;
574 /* Make a DHCPREQUEST packet from the lease we picked. */
575 make_request(picked
);
576 client
->xid
= client
->packet
.xid
;
578 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
579 free_client_lease(picked
);
581 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
586 dhcpack(struct iaddr client_addr
, struct option_data
*options
)
588 struct client_lease
*lease
;
590 if (client
->xid
!= client
->packet
.xid
)
593 if (client
->state
!= S_REBOOTING
&&
594 client
->state
!= S_REQUESTING
&&
595 client
->state
!= S_RENEWING
&&
596 client
->state
!= S_REBINDING
)
599 note("DHCPACK from %s", piaddr(client_addr
));
601 lease
= packet_to_lease(options
);
603 note("packet_to_lease failed.");
609 /* Stop resending DHCPREQUEST. */
610 cancel_timeout(send_request
);
612 /* Figure out the lease time. */
613 if (client
->new->options
[DHO_DHCP_LEASE_TIME
].data
)
614 client
->new->expiry
=
615 getULong(client
->new->options
[DHO_DHCP_LEASE_TIME
].data
);
617 client
->new->expiry
= DEFAULT_LEASE_TIME
;
618 /* A number that looks negative here is really just very large,
619 because the lease expiry offset is unsigned. */
620 if (client
->new->expiry
< 0)
621 client
->new->expiry
= TIME_MAX
;
622 /* XXX should be fixed by resetting the client state */
623 if (client
->new->expiry
< 60)
624 client
->new->expiry
= 60;
626 /* Take the server-provided renewal time if there is one;
627 otherwise figure it out according to the spec. */
628 if (client
->new->options
[DHO_DHCP_RENEWAL_TIME
].len
)
629 client
->new->renewal
=
630 getULong(client
->new->options
[DHO_DHCP_RENEWAL_TIME
].data
);
632 client
->new->renewal
= client
->new->expiry
/ 2;
634 /* Same deal with the rebind time. */
635 if (client
->new->options
[DHO_DHCP_REBINDING_TIME
].len
)
636 client
->new->rebind
=
637 getULong(client
->new->options
[DHO_DHCP_REBINDING_TIME
].data
);
639 client
->new->rebind
= client
->new->renewal
+
640 client
->new->renewal
/ 2 + client
->new->renewal
/ 4;
642 client
->new->expiry
+= cur_time
;
643 /* Lease lengths can never be negative. */
644 if (client
->new->expiry
< cur_time
)
645 client
->new->expiry
= TIME_MAX
;
646 client
->new->renewal
+= cur_time
;
647 if (client
->new->renewal
< cur_time
)
648 client
->new->renewal
= TIME_MAX
;
649 client
->new->rebind
+= cur_time
;
650 if (client
->new->rebind
< cur_time
)
651 client
->new->rebind
= TIME_MAX
;
659 /* Remember the medium. */
660 client
->new->medium
= client
->medium
;
662 /* Write out the new lease. */
663 write_client_lease(client
->new, 0);
665 /* Run the client script with the new parameters. */
666 script_init((client
->state
== S_REQUESTING
? "BOUND" :
667 (client
->state
== S_RENEWING
? "RENEW" :
668 (client
->state
== S_REBOOTING
? "REBOOT" : "REBIND"))),
669 client
->new->medium
);
670 if (client
->active
&& client
->state
!= S_REBOOTING
)
671 script_write_params("old_", client
->active
);
672 script_write_params("new_", client
->new);
674 script_write_params("alias_", client
->alias
);
677 /* Replace the old active lease with the new one. */
679 free_client_lease(client
->active
);
680 client
->active
= client
->new;
683 /* Set up a timeout to start the renewal process. */
684 add_timeout(client
->active
->renewal
, state_bound
);
686 note("bound to %s -- renewal in %ld seconds.",
687 piaddr(client
->active
->address
),
688 client
->active
->renewal
- cur_time
);
689 client
->state
= S_BOUND
;
690 reinitialize_interface();
695 * state_bound is called when we've successfully bound to a particular
696 * lease, but the renewal time on that lease has expired. We are
697 * expected to unicast a DHCPREQUEST to the server that gave us our
703 /* T1 has expired. */
704 make_request(client
->active
);
705 client
->xid
= client
->packet
.xid
;
707 if (client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].len
== 4) {
708 memcpy(client
->destination
.iabuf
,
709 client
->active
->options
[DHO_DHCP_SERVER_IDENTIFIER
].data
,
711 client
->destination
.len
= 4;
713 client
->destination
= iaddr_broadcast
;
715 client
->first_sending
= cur_time
;
716 client
->interval
= config
->initial_interval
;
717 client
->state
= S_RENEWING
;
719 /* Send the first packet immediately. */
724 dhcpoffer(struct iaddr client_addr
, struct option_data
*options
)
726 struct client_lease
*lease
, *lp
;
728 int arp_timeout_needed
, stop_selecting
;
729 char *name
= options
[DHO_DHCP_MESSAGE_TYPE
].len
? "DHCPOFFER" :
732 if (client
->xid
!= client
->packet
.xid
)
735 if (client
->state
!= S_SELECTING
)
738 note("%s from %s", name
, piaddr(client_addr
));
740 /* If this lease doesn't supply the minimum required parameters,
742 for (i
= 0; config
->required_options
[i
]; i
++) {
743 if (!options
[config
->required_options
[i
]].len
) {
744 note("%s isn't satisfactory.", name
);
749 /* If we've already seen this lease, don't record it again. */
750 for (lease
= client
->offered_leases
;
751 lease
; lease
= lease
->next
) {
752 if (lease
->address
.len
== sizeof(client
->packet
.yiaddr
) &&
753 !memcmp(lease
->address
.iabuf
,
754 &client
->packet
.yiaddr
, lease
->address
.len
)) {
755 debug("%s already seen.", name
);
760 lease
= packet_to_lease(options
);
762 note("packet_to_lease failed.");
766 /* If this lease was acquired through a BOOTREPLY, record that
768 if (!options
[DHO_DHCP_MESSAGE_TYPE
].len
)
771 /* Record the medium under which this lease was offered. */
772 lease
->medium
= client
->medium
;
774 /* Send out an ARP Request for the offered IP address. */
775 script_init("ARPSEND", lease
->medium
);
776 script_write_params("check_", lease
);
777 /* If the script can't send an ARP request without waiting,
778 we'll be waiting when we do the ARPCHECK, so don't wait now. */
780 arp_timeout_needed
= 0;
782 arp_timeout_needed
= 2;
784 /* Figure out when we're supposed to stop selecting. */
785 stop_selecting
= client
->first_sending
+ config
->select_interval
;
787 /* If this is the lease we asked for, put it at the head of the
788 list, and don't mess with the arp request timeout. */
789 if (lease
->address
.len
== client
->requested_address
.len
&&
790 !memcmp(lease
->address
.iabuf
,
791 client
->requested_address
.iabuf
,
792 client
->requested_address
.len
)) {
793 lease
->next
= client
->offered_leases
;
794 client
->offered_leases
= lease
;
796 /* If we already have an offer, and arping for this
797 offer would take us past the selection timeout,
798 then don't extend the timeout - just hope for the
800 if (client
->offered_leases
&&
801 (cur_time
+ arp_timeout_needed
) > stop_selecting
)
802 arp_timeout_needed
= 0;
804 /* Put the lease at the end of the list. */
806 if (!client
->offered_leases
)
807 client
->offered_leases
= lease
;
809 for (lp
= client
->offered_leases
; lp
->next
;
816 /* If we're supposed to stop selecting before we've had time
817 to wait for the ARPREPLY, add some delay to wait for
819 if (stop_selecting
- cur_time
< arp_timeout_needed
)
820 stop_selecting
= cur_time
+ arp_timeout_needed
;
822 /* If the selecting interval has expired, go immediately to
823 state_selecting(). Otherwise, time out into
824 state_selecting at the select interval. */
825 if (stop_selecting
<= 0)
828 add_timeout(stop_selecting
, state_selecting
);
829 cancel_timeout(send_discover
);
834 * Allocate a client_lease structure and initialize it from the
835 * parameters in the specified packet.
837 struct client_lease
*
838 packet_to_lease(struct option_data
*options
)
840 struct client_lease
*lease
;
843 lease
= malloc(sizeof(struct client_lease
));
846 warning("dhcpoffer: no memory to record lease.");
850 memset(lease
, 0, sizeof(*lease
));
852 /* Copy the lease options. */
853 for (i
= 0; i
< 256; i
++) {
854 if (options
[i
].len
) {
855 lease
->options
[i
] = options
[i
];
856 options
[i
].data
= NULL
;
858 if (!check_option(lease
, i
)) {
859 warning("Invalid lease option - ignoring offer");
860 free_client_lease(lease
);
866 lease
->address
.len
= sizeof(client
->packet
.yiaddr
);
867 memcpy(lease
->address
.iabuf
, &client
->packet
.yiaddr
,
870 /* If the server name was filled out, copy it. */
871 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
872 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 2)) &&
873 client
->packet
.sname
[0]) {
874 lease
->server_name
= malloc(DHCP_SNAME_LEN
+ 1);
875 if (!lease
->server_name
) {
876 warning("dhcpoffer: no memory for server name.");
877 free_client_lease(lease
);
880 memcpy(lease
->server_name
, client
->packet
.sname
,
882 lease
->server_name
[DHCP_SNAME_LEN
] = '\0';
883 if (!res_hnok(lease
->server_name
)) {
884 warning("Bogus server name %s", lease
->server_name
);
885 free(lease
->server_name
);
886 lease
->server_name
= NULL
;
890 /* Ditto for the filename. */
891 if ((!lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].len
||
892 !(lease
->options
[DHO_DHCP_OPTION_OVERLOAD
].data
[0] & 1)) &&
893 client
->packet
.file
[0]) {
894 /* Don't count on the NUL terminator. */
895 lease
->filename
= malloc(DHCP_FILE_LEN
+ 1);
896 if (!lease
->filename
) {
897 warning("dhcpoffer: no memory for filename.");
898 free_client_lease(lease
);
901 memcpy(lease
->filename
, client
->packet
.file
, DHCP_FILE_LEN
);
902 lease
->filename
[DHCP_FILE_LEN
] = '\0';
908 dhcpnak(struct iaddr client_addr
, struct option_data
*options
)
910 if (client
->xid
!= client
->packet
.xid
)
913 if (client
->state
!= S_REBOOTING
&&
914 client
->state
!= S_REQUESTING
&&
915 client
->state
!= S_RENEWING
&&
916 client
->state
!= S_REBINDING
)
919 note("DHCPNAK from %s", piaddr(client_addr
));
921 if (!client
->active
) {
922 note("DHCPNAK with no active lease.");
926 free_client_lease(client
->active
);
927 client
->active
= NULL
;
929 /* Stop sending DHCPREQUEST packets... */
930 cancel_timeout(send_request
);
932 client
->state
= S_INIT
;
937 * Send out a DHCPDISCOVER packet, and set a timeout to send out another
938 * one after the right interval has expired. If we don't get an offer by
939 * the time we reach the panic interval, call the panic function.
944 int interval
, increase
= 1;
946 /* Figure out how long it's been since we started transmitting. */
947 interval
= cur_time
- client
->first_sending
;
949 /* If we're past the panic timeout, call the script and tell it
950 we haven't found anything for this interface yet. */
951 if (interval
> config
->timeout
) {
956 /* If we're selecting media, try the whole list before doing
957 the exponential backoff, but if we've already received an
958 offer, stop looping, because we obviously have it right. */
959 if (!client
->offered_leases
&& config
->media
) {
962 if (client
->medium
) {
963 client
->medium
= client
->medium
->next
;
966 if (!client
->medium
) {
968 error("No valid media types for %s!", ifi
->name
);
969 client
->medium
= config
->media
;
973 note("Trying medium \"%s\" %d", client
->medium
->string
,
975 script_init("MEDIUM", client
->medium
);
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 out a packet. */
1022 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1024 add_timeout(cur_time
+ 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
;
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. */
1047 while (client
->active
) {
1048 if (client
->active
->expiry
> cur_time
) {
1049 note("Trying recorded lease %s",
1050 piaddr(client
->active
->address
));
1051 /* Run the client script with the existing
1053 script_init("TIMEOUT",
1054 client
->active
->medium
);
1055 script_write_params("new_", client
->active
);
1057 script_write_params("alias_",
1060 /* If the old lease is still good and doesn't
1061 yet need renewal, go into BOUND state and
1062 timeout at the renewal time. */
1065 client
->active
->renewal
) {
1066 client
->state
= S_BOUND
;
1067 note("bound: renewal in %ld seconds.",
1068 client
->active
->renewal
-
1070 add_timeout(client
->active
->renewal
,
1073 client
->state
= S_BOUND
;
1074 note("bound: immediate renewal.");
1077 reinitialize_interface();
1083 /* If there are no other leases, give up. */
1084 if (!client
->leases
) {
1085 client
->leases
= client
->active
;
1086 client
->active
= NULL
;
1091 /* Otherwise, put the active lease at the end of the
1092 lease list, and try another lease.. */
1093 for (lp
= client
->leases
; lp
->next
; lp
= lp
->next
)
1095 lp
->next
= client
->active
;
1097 lp
->next
->next
= NULL
;
1098 client
->active
= client
->leases
;
1099 client
->leases
= client
->leases
->next
;
1101 /* If we already tried this lease, we've exhausted the
1102 set of leases, so we might as well give up for
1104 if (client
->active
== loop
)
1107 loop
= client
->active
;
1110 /* No leases were available, or what was available didn't work, so
1111 tell the shell script that we failed to allocate an address,
1112 and try again later. */
1113 note("No working leases in persistent database - sleeping.");
1114 script_init("FAIL", NULL
);
1116 script_write_params("alias_", client
->alias
);
1118 client
->state
= S_INIT
;
1119 add_timeout(cur_time
+ config
->retry_interval
, state_init
);
1126 struct sockaddr_in destination
;
1127 struct in_addr from
;
1130 /* Figure out how long it's been since we started transmitting. */
1131 interval
= cur_time
- client
->first_sending
;
1133 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1134 past the reboot timeout, go to INIT and see if we can
1135 DISCOVER an address... */
1136 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1137 means either that we're on a network with no DHCP server,
1138 or that our server is down. In the latter case, assuming
1139 that there is a backup DHCP server, DHCPDISCOVER will get
1140 us a new address, but we could also have successfully
1141 reused our old address. In the former case, we're hosed
1142 anyway. This is not a win-prone situation. */
1143 if ((client
->state
== S_REBOOTING
||
1144 client
->state
== S_REQUESTING
) &&
1145 interval
> config
->reboot_timeout
) {
1147 client
->state
= S_INIT
;
1148 cancel_timeout(send_request
);
1153 /* If we're in the reboot state, make sure the media is set up
1155 if (client
->state
== S_REBOOTING
&&
1157 client
->active
->medium
) {
1158 script_init("MEDIUM", client
->active
->medium
);
1160 /* If the medium we chose won't fly, go to INIT state. */
1164 /* Record the medium. */
1165 client
->medium
= client
->active
->medium
;
1168 /* If the lease has expired, relinquish the address and go back
1169 to the INIT state. */
1170 if (client
->state
!= S_REQUESTING
&&
1171 cur_time
> client
->active
->expiry
) {
1172 /* Run the client script with the new parameters. */
1173 script_init("EXPIRE", NULL
);
1174 script_write_params("old_", client
->active
);
1176 script_write_params("alias_", client
->alias
);
1179 /* Now do a preinit on the interface so that we can
1180 discover a new address. */
1181 script_init("PREINIT", NULL
);
1183 script_write_params("alias_", client
->alias
);
1186 client
->state
= S_INIT
;
1191 /* Do the exponential backoff... */
1192 if (!client
->interval
)
1193 client
->interval
= config
->initial_interval
;
1195 client
->interval
+= ((arc4random() >> 2) %
1196 (2 * client
->interval
));
1198 /* Don't backoff past cutoff. */
1199 if (client
->interval
> config
->backoff_cutoff
)
1200 client
->interval
= ((config
->backoff_cutoff
/ 2) +
1201 ((arc4random() >> 2) % client
->interval
));
1203 /* If the backoff would take us to the expiry time, just set the
1204 timeout to the expiry time. */
1205 if (client
->state
!= S_REQUESTING
&& cur_time
+ client
->interval
>
1206 client
->active
->expiry
)
1207 client
->interval
= client
->active
->expiry
- cur_time
+ 1;
1209 /* If the lease T2 time has elapsed, or if we're not yet bound,
1210 broadcast the DHCPREQUEST rather than unicasting. */
1211 memset(&destination
, 0, sizeof(destination
));
1212 if (client
->state
== S_REQUESTING
||
1213 client
->state
== S_REBOOTING
||
1214 cur_time
> client
->active
->rebind
)
1215 destination
.sin_addr
.s_addr
= INADDR_BROADCAST
;
1217 memcpy(&destination
.sin_addr
.s_addr
, client
->destination
.iabuf
,
1218 sizeof(destination
.sin_addr
.s_addr
));
1219 destination
.sin_port
= htons(REMOTE_PORT
);
1220 destination
.sin_family
= AF_INET
;
1221 destination
.sin_len
= sizeof(destination
);
1223 if (client
->state
!= S_REQUESTING
)
1224 memcpy(&from
, client
->active
->address
.iabuf
, sizeof(from
));
1226 from
.s_addr
= INADDR_ANY
;
1228 /* Record the number of seconds since we started sending. */
1229 if (client
->state
== S_REQUESTING
)
1230 client
->packet
.secs
= client
->secs
;
1232 if (interval
< 65536)
1233 client
->packet
.secs
= htons(interval
);
1235 client
->packet
.secs
= htons(65535);
1238 note("DHCPREQUEST on %s to %s port %d", ifi
->name
,
1239 inet_ntoa(destination
.sin_addr
), ntohs(destination
.sin_port
));
1241 /* Send out a packet. */
1242 send_packet(from
, &destination
, NULL
);
1244 add_timeout(cur_time
+ client
->interval
, send_request
);
1250 note("DHCPDECLINE on %s to %s port %d", ifi
->name
,
1251 inet_ntoa(sockaddr_broadcast
.sin_addr
),
1252 ntohs(sockaddr_broadcast
.sin_port
));
1254 /* Send out a packet. */
1255 send_packet(inaddr_any
, &sockaddr_broadcast
, NULL
);
1259 make_discover(struct client_lease
*lease
)
1261 unsigned char discover
= DHCPDISCOVER
;
1262 struct option_data options
[256];
1265 memset(options
, 0, sizeof(options
));
1266 memset(&client
->packet
, 0, sizeof(client
->packet
));
1268 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1269 i
= DHO_DHCP_MESSAGE_TYPE
;
1270 options
[i
].data
= &discover
;
1271 options
[i
].len
= sizeof(discover
);
1273 /* Request the options we want */
1274 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1275 options
[i
].data
= config
->requested_options
;
1276 options
[i
].len
= config
->requested_option_count
;
1278 /* If we had an address, try to get it again. */
1280 client
->requested_address
= lease
->address
;
1281 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1282 options
[i
].data
= lease
->address
.iabuf
;
1283 options
[i
].len
= lease
->address
.len
;
1285 client
->requested_address
.len
= 0;
1287 /* Send any options requested in the config file. */
1288 for (i
= 0; i
< 256; i
++)
1289 if (!options
[i
].data
&&
1290 config
->send_options
[i
].data
) {
1291 options
[i
].data
= config
->send_options
[i
].data
;
1292 options
[i
].len
= config
->send_options
[i
].len
;
1295 /* Set up the option buffer to fit in a minimal UDP packet. */
1296 i
= cons_options(client
->packet
.options
, 576 - DHCP_FIXED_LEN
,
1298 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1299 error("options do not fit in DHCPDISCOVER packet.");
1300 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1301 if (client
->packet_length
< BOOTP_MIN_LEN
)
1302 client
->packet_length
= BOOTP_MIN_LEN
;
1304 client
->packet
.op
= BOOTREQUEST
;
1305 client
->packet
.htype
= ifi
->hw_address
.htype
;
1306 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1307 client
->packet
.hops
= 0;
1308 client
->packet
.xid
= arc4random();
1309 client
->packet
.secs
= 0; /* filled in by send_discover. */
1310 client
->packet
.flags
= 0;
1312 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1313 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1314 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1315 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1316 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1317 ifi
->hw_address
.hlen
);
1321 make_request(struct client_lease
* lease
)
1323 unsigned char request
= DHCPREQUEST
;
1324 struct option_data options
[256];
1327 memset(options
, 0, sizeof(options
));
1328 memset(&client
->packet
, 0, sizeof(client
->packet
));
1330 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1331 i
= DHO_DHCP_MESSAGE_TYPE
;
1332 options
[i
].data
= &request
;
1333 options
[i
].len
= sizeof(request
);
1335 /* Request the options we want */
1336 i
= DHO_DHCP_PARAMETER_REQUEST_LIST
;
1337 options
[i
].data
= config
->requested_options
;
1338 options
[i
].len
= config
->requested_option_count
;
1340 /* If we are requesting an address that hasn't yet been assigned
1341 to us, use the DHCP Requested Address option. */
1342 if (client
->state
== S_REQUESTING
) {
1343 /* Send back the server identifier... */
1344 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1345 options
[i
].data
= lease
->options
[i
].data
;
1346 options
[i
].len
= lease
->options
[i
].len
;
1348 if (client
->state
== S_REQUESTING
||
1349 client
->state
== S_REBOOTING
) {
1350 client
->requested_address
= lease
->address
;
1351 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1352 options
[i
].data
= lease
->address
.iabuf
;
1353 options
[i
].len
= lease
->address
.len
;
1355 client
->requested_address
.len
= 0;
1357 /* Send any options requested in the config file. */
1358 for (i
= 0; i
< 256; i
++)
1359 if (!options
[i
].data
&& config
->send_options
[i
].data
) {
1360 options
[i
].data
= config
->send_options
[i
].data
;
1361 options
[i
].len
= config
->send_options
[i
].len
;
1364 /* Set up the option buffer to fit in a minimal UDP packet. */
1365 i
= cons_options(client
->packet
.options
, 576 - DHCP_FIXED_LEN
,
1367 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1368 error("options do not fit in DHCPREQUEST packet.");
1369 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1370 if (client
->packet_length
< BOOTP_MIN_LEN
)
1371 client
->packet_length
= BOOTP_MIN_LEN
;
1373 client
->packet
.op
= BOOTREQUEST
;
1374 client
->packet
.htype
= ifi
->hw_address
.htype
;
1375 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1376 client
->packet
.hops
= 0;
1377 client
->packet
.xid
= client
->xid
;
1378 client
->packet
.secs
= 0; /* Filled in by send_request. */
1379 client
->packet
.flags
= 0;
1381 /* If we own the address we're requesting, put it in ciaddr;
1382 otherwise set ciaddr to zero. */
1383 if (client
->state
== S_BOUND
||
1384 client
->state
== S_RENEWING
||
1385 client
->state
== S_REBINDING
) {
1386 memcpy(&client
->packet
.ciaddr
,
1387 lease
->address
.iabuf
, lease
->address
.len
);
1389 memset(&client
->packet
.ciaddr
, 0,
1390 sizeof(client
->packet
.ciaddr
));
1393 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1394 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1395 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1396 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1397 ifi
->hw_address
.hlen
);
1401 make_decline(struct client_lease
*lease
)
1403 struct option_data options
[256];
1404 unsigned char decline
= DHCPDECLINE
;
1407 memset(options
, 0, sizeof(options
));
1408 memset(&client
->packet
, 0, sizeof(client
->packet
));
1410 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1411 i
= DHO_DHCP_MESSAGE_TYPE
;
1412 options
[i
].data
= &decline
;
1413 options
[i
].len
= sizeof(decline
);
1415 /* Send back the server identifier... */
1416 i
= DHO_DHCP_SERVER_IDENTIFIER
;
1417 options
[i
].data
= lease
->options
[i
].data
;
1418 options
[i
].len
= lease
->options
[i
].len
;
1420 /* Send back the address we're declining. */
1421 i
= DHO_DHCP_REQUESTED_ADDRESS
;
1422 options
[i
].data
= lease
->address
.iabuf
;
1423 options
[i
].len
= lease
->address
.len
;
1425 /* Send the uid if the user supplied one. */
1426 i
= DHO_DHCP_CLIENT_IDENTIFIER
;
1427 if (config
->send_options
[i
].len
) {
1428 options
[i
].data
= config
->send_options
[i
].data
;
1429 options
[i
].len
= config
->send_options
[i
].len
;
1432 /* Set up the option buffer to fit in a minimal UDP packet. */
1433 i
= cons_options(client
->packet
.options
, 576 - DHCP_FIXED_LEN
,
1435 if (i
== -1 || client
->packet
.options
[i
] != DHO_END
)
1436 error("options do not fit in DHCPDECLINE packet.");
1437 client
->packet_length
= DHCP_FIXED_NON_UDP
+i
+1;
1438 if (client
->packet_length
< BOOTP_MIN_LEN
)
1439 client
->packet_length
= BOOTP_MIN_LEN
;
1441 client
->packet
.op
= BOOTREQUEST
;
1442 client
->packet
.htype
= ifi
->hw_address
.htype
;
1443 client
->packet
.hlen
= ifi
->hw_address
.hlen
;
1444 client
->packet
.hops
= 0;
1445 client
->packet
.xid
= client
->xid
;
1446 client
->packet
.secs
= 0; /* Filled in by send_request. */
1447 client
->packet
.flags
= 0;
1449 /* ciaddr must always be zero. */
1450 memset(&client
->packet
.ciaddr
, 0, sizeof(client
->packet
.ciaddr
));
1451 memset(&client
->packet
.yiaddr
, 0, sizeof(client
->packet
.yiaddr
));
1452 memset(&client
->packet
.siaddr
, 0, sizeof(client
->packet
.siaddr
));
1453 memset(&client
->packet
.giaddr
, 0, sizeof(client
->packet
.giaddr
));
1454 memcpy(client
->packet
.chaddr
, ifi
->hw_address
.haddr
,
1455 ifi
->hw_address
.hlen
);
1459 free_client_lease(struct client_lease
*lease
)
1463 if (lease
->server_name
)
1464 free(lease
->server_name
);
1465 if (lease
->filename
)
1466 free(lease
->filename
);
1467 for (i
= 0; i
< 256; i
++) {
1468 if (lease
->options
[i
].len
)
1469 free(lease
->options
[i
].data
);
1475 rewrite_client_leases(void)
1477 struct client_lease
*lp
;
1479 if (!leaseFile
) /* XXX */
1480 error("lease file not open");
1485 for (lp
= client
->leases
; lp
; lp
= lp
->next
)
1486 write_client_lease(lp
, 1);
1488 write_client_lease(client
->active
, 1);
1491 ftruncate(fileno(leaseFile
), ftello(leaseFile
));
1492 fsync(fileno(leaseFile
));
1496 write_client_lease(struct client_lease
*lease
, int rewrite
)
1498 static int leases_written
;
1503 if (leases_written
++ > 20) {
1504 rewrite_client_leases();
1509 /* If the lease came from the config file, we don't need to stash
1510 a copy in the lease database. */
1511 if (lease
->is_static
)
1514 if (!leaseFile
) /* XXX */
1515 error("lease file not open");
1517 fprintf(leaseFile
, "lease {\n");
1518 if (lease
->is_bootp
)
1519 fprintf(leaseFile
, " bootp;\n");
1520 fprintf(leaseFile
, " interface \"%s\";\n", ifi
->name
);
1521 fprintf(leaseFile
, " fixed-address %s;\n", piaddr(lease
->address
));
1522 if (lease
->filename
)
1523 fprintf(leaseFile
, " filename \"%s\";\n", lease
->filename
);
1524 if (lease
->server_name
)
1525 fprintf(leaseFile
, " server-name \"%s\";\n",
1526 lease
->server_name
);
1528 fprintf(leaseFile
, " medium \"%s\";\n", lease
->medium
->string
);
1529 for (i
= 0; i
< 256; i
++)
1530 if (lease
->options
[i
].len
)
1531 fprintf(leaseFile
, " option %s %s;\n",
1532 dhcp_options
[i
].name
,
1533 pretty_print_option(i
, lease
->options
[i
].data
,
1534 lease
->options
[i
].len
, 1, 1));
1536 t
= gmtime(&lease
->renewal
);
1537 fprintf(leaseFile
, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1538 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1539 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1540 t
= gmtime(&lease
->rebind
);
1541 fprintf(leaseFile
, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1542 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1543 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1544 t
= gmtime(&lease
->expiry
);
1545 fprintf(leaseFile
, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1546 t
->tm_wday
, t
->tm_year
+ 1900, t
->tm_mon
+ 1, t
->tm_mday
,
1547 t
->tm_hour
, t
->tm_min
, t
->tm_sec
);
1548 fprintf(leaseFile
, "}\n");
1553 script_init(char *reason
, struct string_list
*medium
)
1555 size_t len
, mediumlen
= 0;
1556 struct imsg_hdr hdr
;
1559 if (medium
!= NULL
&& medium
->string
!= NULL
)
1560 mediumlen
= strlen(medium
->string
);
1562 hdr
.code
= IMSG_SCRIPT_INIT
;
1563 hdr
.len
= sizeof(struct imsg_hdr
) +
1564 sizeof(size_t) + mediumlen
+
1565 sizeof(size_t) + strlen(reason
);
1567 buf
= buf_open(hdr
.len
);
1569 buf_add(buf
, &hdr
, sizeof(hdr
));
1570 buf_add(buf
, &mediumlen
, sizeof(mediumlen
));
1572 buf_add(buf
, medium
->string
, mediumlen
);
1573 len
= strlen(reason
);
1574 buf_add(buf
, &len
, sizeof(len
));
1575 buf_add(buf
, reason
, len
);
1577 buf_close(privfd
, buf
);
1581 priv_script_init(char *reason
, char *medium
)
1583 client
->scriptEnvsize
= 100;
1584 if (client
->scriptEnv
== NULL
)
1586 calloc(client
->scriptEnvsize
, sizeof(char *));
1587 if (client
->scriptEnv
== NULL
)
1588 error("script_init: no memory for environment");
1590 client
->scriptEnv
[0] = strdup(CLIENT_PATH
);
1591 if (client
->scriptEnv
[0] == NULL
)
1592 error("script_init: no memory for environment");
1594 client
->scriptEnv
[1] = NULL
;
1596 script_set_env("", "interface", ifi
->name
);
1599 script_set_env("", "medium", medium
);
1601 script_set_env("", "reason", reason
);
1605 priv_script_write_params(char *prefix
, struct client_lease
*lease
)
1607 u_int8_t dbuf
[1500];
1611 script_set_env(prefix
, "ip_address", piaddr(lease
->address
));
1613 if (lease
->options
[DHO_SUBNET_MASK
].len
&&
1614 (lease
->options
[DHO_SUBNET_MASK
].len
<
1615 sizeof(lease
->address
.iabuf
))) {
1616 struct iaddr netmask
, subnet
, broadcast
;
1618 memcpy(netmask
.iabuf
, lease
->options
[DHO_SUBNET_MASK
].data
,
1619 lease
->options
[DHO_SUBNET_MASK
].len
);
1620 netmask
.len
= lease
->options
[DHO_SUBNET_MASK
].len
;
1622 subnet
= subnet_number(lease
->address
, netmask
);
1624 script_set_env(prefix
, "network_number",
1626 if (!lease
->options
[DHO_BROADCAST_ADDRESS
].len
) {
1627 broadcast
= broadcast_addr(subnet
, netmask
);
1629 script_set_env(prefix
,
1630 "broadcast_address",
1636 if (lease
->filename
)
1637 script_set_env(prefix
, "filename", lease
->filename
);
1638 if (lease
->server_name
)
1639 script_set_env(prefix
, "server_name",
1640 lease
->server_name
);
1641 for (i
= 0; i
< 256; i
++) {
1642 u_int8_t
*dp
= NULL
;
1644 if (config
->defaults
[i
].len
) {
1645 if (lease
->options
[i
].len
) {
1646 switch (config
->default_actions
[i
]) {
1647 case ACTION_DEFAULT
:
1648 dp
= lease
->options
[i
].data
;
1649 len
= lease
->options
[i
].len
;
1651 case ACTION_SUPERSEDE
:
1653 dp
= config
->defaults
[i
].data
;
1654 len
= config
->defaults
[i
].len
;
1656 case ACTION_PREPEND
:
1657 len
= config
->defaults
[i
].len
+
1658 lease
->options
[i
].len
;
1659 if (len
> sizeof(dbuf
)) {
1660 warning("no space to %s %s",
1662 dhcp_options
[i
].name
);
1667 config
->defaults
[i
].data
,
1668 config
->defaults
[i
].len
);
1670 config
->defaults
[i
].len
,
1671 lease
->options
[i
].data
,
1672 lease
->options
[i
].len
);
1676 len
= config
->defaults
[i
].len
+
1677 lease
->options
[i
].len
;
1678 if (len
> sizeof(dbuf
)) {
1679 warning("no space to %s %s",
1681 dhcp_options
[i
].name
);
1685 memcpy(dp
, lease
->options
[i
].data
,
1686 lease
->options
[i
].len
);
1687 memcpy(dp
+ lease
->options
[i
].len
,
1688 config
->defaults
[i
].data
,
1689 config
->defaults
[i
].len
);
1693 dp
= config
->defaults
[i
].data
;
1694 len
= config
->defaults
[i
].len
;
1696 } else if (lease
->options
[i
].len
) {
1697 len
= lease
->options
[i
].len
;
1698 dp
= lease
->options
[i
].data
;
1705 if (dhcp_option_ev_name(name
, sizeof(name
),
1707 script_set_env(prefix
, name
,
1708 pretty_print_option(i
, dp
, len
, 0, 0));
1711 snprintf(tbuf
, sizeof(tbuf
), "%d", (int)lease
->expiry
);
1712 script_set_env(prefix
, "expiry", tbuf
);
1716 script_write_params(char *prefix
, struct client_lease
*lease
)
1718 size_t fn_len
= 0, sn_len
= 0, pr_len
= 0;
1719 struct imsg_hdr hdr
;
1723 if (lease
->filename
!= NULL
)
1724 fn_len
= strlen(lease
->filename
);
1725 if (lease
->server_name
!= NULL
)
1726 sn_len
= strlen(lease
->server_name
);
1728 pr_len
= strlen(prefix
);
1730 hdr
.code
= IMSG_SCRIPT_WRITE_PARAMS
;
1731 hdr
.len
= sizeof(hdr
) + sizeof(struct client_lease
) +
1732 sizeof(size_t) + fn_len
+ sizeof(size_t) + sn_len
+
1733 sizeof(size_t) + pr_len
;
1735 for (i
= 0; i
< 256; i
++)
1736 hdr
.len
+= sizeof(int) + lease
->options
[i
].len
;
1738 scripttime
= time(NULL
);
1740 buf
= buf_open(hdr
.len
);
1742 buf_add(buf
, &hdr
, sizeof(hdr
));
1743 buf_add(buf
, lease
, sizeof(struct client_lease
));
1744 buf_add(buf
, &fn_len
, sizeof(fn_len
));
1745 buf_add(buf
, lease
->filename
, fn_len
);
1746 buf_add(buf
, &sn_len
, sizeof(sn_len
));
1747 buf_add(buf
, lease
->server_name
, sn_len
);
1748 buf_add(buf
, &pr_len
, sizeof(pr_len
));
1749 buf_add(buf
, prefix
, pr_len
);
1751 for (i
= 0; i
< 256; i
++) {
1752 buf_add(buf
, &lease
->options
[i
].len
,
1753 sizeof(lease
->options
[i
].len
));
1754 buf_add(buf
, lease
->options
[i
].data
,
1755 lease
->options
[i
].len
);
1758 buf_close(privfd
, buf
);
1764 struct imsg_hdr hdr
;
1768 scripttime
= time(NULL
);
1770 hdr
.code
= IMSG_SCRIPT_GO
;
1771 hdr
.len
= sizeof(struct imsg_hdr
);
1773 buf
= buf_open(hdr
.len
);
1775 buf_add(buf
, &hdr
, sizeof(hdr
));
1776 buf_close(privfd
, buf
);
1778 bzero(&hdr
, sizeof(hdr
));
1779 buf_read(privfd
, &hdr
, sizeof(hdr
));
1780 if (hdr
.code
!= IMSG_SCRIPT_GO_RET
)
1781 error("unexpected msg type %u", hdr
.code
);
1782 if (hdr
.len
!= sizeof(hdr
) + sizeof(int))
1783 error("received corrupted message");
1784 buf_read(privfd
, &ret
, sizeof(ret
));
1790 priv_script_go(void)
1792 char *scriptName
, *argv
[2], **envp
;
1793 int pid
, wpid
, wstatus
;
1795 scripttime
= time(NULL
);
1797 scriptName
= config
->script_name
;
1798 envp
= client
->scriptEnv
;
1800 argv
[0] = scriptName
;
1809 wpid
= wait(&wstatus
);
1810 } while (wpid
!= pid
&& wpid
> 0);
1816 execve(scriptName
, argv
, envp
);
1817 error("execve (%s, ...): %m", scriptName
);
1822 return (WEXITSTATUS(wstatus
));
1826 script_set_env(const char *prefix
, const char *name
, const char *value
)
1830 namelen
= strlen(name
);
1832 for (i
= 0; client
->scriptEnv
[i
]; i
++)
1833 if (strncmp(client
->scriptEnv
[i
], name
, namelen
) == 0 &&
1834 client
->scriptEnv
[i
][namelen
] == '=')
1837 if (client
->scriptEnv
[i
])
1838 /* Reuse the slot. */
1839 free(client
->scriptEnv
[i
]);
1841 /* New variable. Expand if necessary. */
1842 if (i
>= client
->scriptEnvsize
- 1) {
1843 char **newscriptEnv
;
1844 int newscriptEnvsize
= client
->scriptEnvsize
+ 50;
1846 newscriptEnv
= realloc(client
->scriptEnv
,
1848 if (newscriptEnv
== NULL
) {
1849 free(client
->scriptEnv
);
1850 client
->scriptEnv
= NULL
;
1851 client
->scriptEnvsize
= 0;
1852 error("script_set_env: no memory for variable");
1854 client
->scriptEnv
= newscriptEnv
;
1855 client
->scriptEnvsize
= newscriptEnvsize
;
1857 /* need to set the NULL pointer at end of array beyond
1859 client
->scriptEnv
[i
+ 1] = NULL
;
1861 /* Allocate space and format the variable in the appropriate slot. */
1862 client
->scriptEnv
[i
] = malloc(strlen(prefix
) + strlen(name
) + 1 +
1864 if (client
->scriptEnv
[i
] == NULL
)
1865 error("script_set_env: no memory for variable assignment");
1867 /* No `` or $() command substitution allowed in environment values! */
1868 for (j
= 0; j
< strlen(value
); j
++)
1872 error("illegal character (%c) in value '%s'", value
[j
],
1876 snprintf(client
->scriptEnv
[i
], strlen(prefix
) + strlen(name
) +
1877 1 + strlen(value
) + 1, "%s%s=%s", prefix
, name
, value
);
1881 script_flush_env(void)
1885 for (i
= 0; client
->scriptEnv
[i
]; i
++) {
1886 free(client
->scriptEnv
[i
]);
1887 client
->scriptEnv
[i
] = NULL
;
1889 client
->scriptEnvsize
= 0;
1893 dhcp_option_ev_name(char *buf
, size_t buflen
, const struct option
*option
)
1897 for (i
= 0; option
->name
[i
]; i
++) {
1898 if (i
+ 1 == buflen
)
1900 if (option
->name
[i
] == '-')
1903 buf
[i
] = option
->name
[i
];
1913 static int state
= 0;
1915 if (no_daemon
|| state
)
1920 /* Stop logging to stderr... */
1923 if (daemon(1, 0) == -1)
1926 /* we are chrooted, daemon(3) fails to open /dev/null */
1928 dup2(nullfd
, STDIN_FILENO
);
1929 dup2(nullfd
, STDOUT_FILENO
);
1930 dup2(nullfd
, STDERR_FILENO
);
1937 check_option(struct client_lease
*l
, int option
)
1942 /* we use this, since this is what gets passed to dhclient-script */
1944 opbuf
= pretty_print_option(option
, l
->options
[option
].data
,
1945 l
->options
[option
].len
, 0, 0);
1947 sbuf
= option_as_string(option
, l
->options
[option
].data
,
1948 l
->options
[option
].len
);
1951 case DHO_SUBNET_MASK
:
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_SWAP_SERVER
:
1962 case DHO_BROADCAST_ADDRESS
:
1963 case DHO_NIS_SERVERS
:
1964 case DHO_NTP_SERVERS
:
1965 case DHO_NETBIOS_NAME_SERVERS
:
1966 case DHO_NETBIOS_DD_SERVER
:
1967 case DHO_FONT_SERVERS
:
1968 case DHO_DHCP_SERVER_IDENTIFIER
:
1969 if (!ipv4addrs(opbuf
)) {
1970 warning("Invalid IP address in option: %s", opbuf
);
1975 case DHO_DOMAIN_NAME
:
1976 case DHO_NIS_DOMAIN
:
1977 if (!res_hnok(sbuf
)) {
1978 warning("Bogus Host Name option %d: %s (%s)", option
,
1980 l
->options
[option
].len
= 0;
1981 free(l
->options
[option
].data
);
1985 case DHO_TIME_OFFSET
:
1987 case DHO_MERIT_DUMP
:
1989 case DHO_EXTENSIONS_PATH
:
1990 case DHO_IP_FORWARDING
:
1991 case DHO_NON_LOCAL_SOURCE_ROUTING
:
1992 case DHO_POLICY_FILTER
:
1993 case DHO_MAX_DGRAM_REASSEMBLY
:
1994 case DHO_DEFAULT_IP_TTL
:
1995 case DHO_PATH_MTU_AGING_TIMEOUT
:
1996 case DHO_PATH_MTU_PLATEAU_TABLE
:
1997 case DHO_INTERFACE_MTU
:
1998 case DHO_ALL_SUBNETS_LOCAL
:
1999 case DHO_PERFORM_MASK_DISCOVERY
:
2000 case DHO_MASK_SUPPLIER
:
2001 case DHO_ROUTER_DISCOVERY
:
2002 case DHO_ROUTER_SOLICITATION_ADDRESS
:
2003 case DHO_STATIC_ROUTES
:
2004 case DHO_TRAILER_ENCAPSULATION
:
2005 case DHO_ARP_CACHE_TIMEOUT
:
2006 case DHO_IEEE802_3_ENCAPSULATION
:
2007 case DHO_DEFAULT_TCP_TTL
:
2008 case DHO_TCP_KEEPALIVE_INTERVAL
:
2009 case DHO_TCP_KEEPALIVE_GARBAGE
:
2010 case DHO_VENDOR_ENCAPSULATED_OPTIONS
:
2011 case DHO_NETBIOS_NODE_TYPE
:
2012 case DHO_NETBIOS_SCOPE
:
2013 case DHO_X_DISPLAY_MANAGER
:
2014 case DHO_DHCP_REQUESTED_ADDRESS
:
2015 case DHO_DHCP_LEASE_TIME
:
2016 case DHO_DHCP_OPTION_OVERLOAD
:
2017 case DHO_DHCP_MESSAGE_TYPE
:
2018 case DHO_DHCP_PARAMETER_REQUEST_LIST
:
2019 case DHO_DHCP_MESSAGE
:
2020 case DHO_DHCP_MAX_MESSAGE_SIZE
:
2021 case DHO_DHCP_RENEWAL_TIME
:
2022 case DHO_DHCP_REBINDING_TIME
:
2023 case DHO_DHCP_CLASS_IDENTIFIER
:
2024 case DHO_DHCP_CLIENT_IDENTIFIER
:
2025 case DHO_DHCP_USER_CLASS_ID
:
2029 warning("unknown dhcp option value 0x%x", option
);
2030 return (unknown_ok
);
2035 res_hnok(const char *name
)
2037 const char *dn
= name
;
2038 int pch
= '.', ch
= *dn
++;
2041 while (ch
!= '\0') {
2046 } else if (pch
== '.' || nch
== '.' || nch
== '\0') {
2049 } else if (!isalnum(ch
) && ch
!= '-' && ch
!= '_')
2051 else if (ch
== '_' && warn
== 0) {
2052 warning("warning: hostname %s contains an "
2053 "underscore which violates RFC 952", name
);
2061 /* Does buf consist only of dotted decimal ipv4 addrs?
2062 * return how many if so,
2063 * otherwise, return 0
2066 ipv4addrs(char * buf
)
2071 while (inet_aton(buf
, &jnk
) == 1){
2073 while (*buf
== '.' || isdigit(*buf
))
2084 option_as_string(unsigned int code
, unsigned char *data
, int len
)
2086 static char optbuf
[32768]; /* XXX */
2088 int opleft
= sizeof(optbuf
);
2089 unsigned char *dp
= data
;
2092 error("option_as_string: bad code %d", code
);
2094 for (; dp
< data
+ len
; dp
++) {
2095 if (!isascii(*dp
) || !isprint(*dp
)) {
2096 if (dp
+ 1 != data
+ len
|| *dp
!= 0) {
2098 snprintf(op
, opleft
, "\\%03o", *dp
);
2103 } else if (*dp
== '"' || *dp
== '\'' || *dp
== '$' ||
2104 *dp
== '`' || *dp
== '\\') {
2118 warning("dhcp option too large");
2123 fork_privchld(int fd
, int fd2
)
2125 struct pollfd pfd
[1];
2130 error("cannot fork");
2138 if (chdir("/") == -1)
2139 error("chdir(\"/\")");
2141 setproctitle("%s [priv]", ifi
->name
);
2143 dup2(nullfd
, STDIN_FILENO
);
2144 dup2(nullfd
, STDOUT_FILENO
);
2145 dup2(nullfd
, STDERR_FILENO
);
2151 pfd
[0].events
= POLLIN
;
2152 if ((nfds
= poll(pfd
, 1, INFTIM
)) == -1)
2154 error("poll error");
2156 if (nfds
== 0 || !(pfd
[0].revents
& POLLIN
))