2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2008 Roy Marples <roy@marples.name>
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 #include "if-options.h"
43 static struct dhcp_message
*
44 make_ipv4ll_lease(uint32_t old_addr
)
47 struct dhcp_message
*dhcp
;
50 dhcp
= xzalloc(sizeof(*dhcp
));
51 /* Put some LL options in */
53 *p
++ = DHO_SUBNETMASK
;
55 u32
= htonl(LINKLOCAL_MASK
);
56 memcpy(p
, &u32
, sizeof(u32
));
60 u32
= htonl(LINKLOCAL_BRDC
);
61 memcpy(p
, &u32
, sizeof(u32
));
66 dhcp
->yiaddr
= htonl(LINKLOCAL_ADDR
|
67 (((uint32_t)abs((int)arc4random())
69 if (dhcp
->yiaddr
!= old_addr
&&
70 IN_LINKLOCAL(ntohl(dhcp
->yiaddr
)))
77 start_ipv4ll(void *arg
)
79 struct interface
*iface
= arg
;
81 iface
->state
->probes
= 0;
82 iface
->state
->claims
= 0;
83 if (iface
->addr
.s_addr
) {
84 iface
->state
->conflicts
= 0;
85 if (IN_LINKLOCAL(htonl(iface
->addr
.s_addr
))) {
86 send_arp_announce(iface
);
91 /* We maybe rebooting an IPv4LL address. */
92 if (!iface
->state
->offer
||
93 !IN_LINKLOCAL(htonl(iface
->state
->offer
->yiaddr
)))
95 syslog(LOG_INFO
, "%s: probing for an IPv4LL address",
97 delete_timeout(NULL
, iface
);
98 free(iface
->state
->offer
);
99 iface
->state
->offer
= make_ipv4ll_lease(0);
100 iface
->state
->lease
.frominfo
= 0;
102 send_arp_probe(iface
);
106 handle_ipv4ll_failure(void *arg
)
108 struct interface
*iface
= arg
;
111 if (iface
->state
->fail
.s_addr
== iface
->state
->lease
.addr
.s_addr
) {
113 if (iface
->state
->defend
+ DEFEND_INTERVAL
> up
) {
114 drop_config(iface
, "EXPIRE");
115 iface
->state
->conflicts
= -1;
117 iface
->state
->defend
= up
;
122 close_sockets(iface
);
123 free(iface
->state
->offer
);
124 iface
->state
->offer
= NULL
;
125 if (++iface
->state
->conflicts
> MAX_CONFLICTS
) {
126 syslog(LOG_ERR
, "%s: failed to acquire an IPv4LL address",
128 iface
->state
->interval
= RATE_LIMIT_INTERVAL
/ 2;
129 start_discover(iface
);
131 add_timeout_sec(PROBE_WAIT
, start_ipv4ll
, iface
);