No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / dhcpcd / dist / ipv4ll.c
bloba91a2f326b422a460957e6eebde55b9c0d4eb587
1 /*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2008 Roy Marples <roy@marples.name>
4 * All rights reserved
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
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
25 * SUCH DAMAGE.
28 #include <errno.h>
29 #include <signal.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <syslog.h>
33 #include <unistd.h>
35 #include "arp.h"
36 #include "common.h"
37 #include "dhcpcd.h"
38 #include "eloop.h"
39 #include "if-options.h"
40 #include "ipv4ll.h"
41 #include "net.h"
43 static struct dhcp_message*
44 make_ipv4ll_lease(uint32_t old_addr)
46 uint32_t u32;
47 struct dhcp_message *dhcp;
48 uint8_t *p;
50 dhcp = xzalloc(sizeof(*dhcp));
51 /* Put some LL options in */
52 p = dhcp->options;
53 *p++ = DHO_SUBNETMASK;
54 *p++ = sizeof(u32);
55 u32 = htonl(LINKLOCAL_MASK);
56 memcpy(p, &u32, sizeof(u32));
57 p += sizeof(u32);
58 *p++ = DHO_BROADCAST;
59 *p++ = sizeof(u32);
60 u32 = htonl(LINKLOCAL_BRDC);
61 memcpy(p, &u32, sizeof(u32));
62 p += sizeof(u32);
63 *p++ = DHO_END;
65 for (;;) {
66 dhcp->yiaddr = htonl(LINKLOCAL_ADDR |
67 (((uint32_t)abs((int)arc4random())
68 % 0xFD00) + 0x0100));
69 if (dhcp->yiaddr != old_addr &&
70 IN_LINKLOCAL(ntohl(dhcp->yiaddr)))
71 break;
73 return dhcp;
76 void
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);
87 return;
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",
96 iface->name);
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);
105 void
106 handle_ipv4ll_failure(void *arg)
108 struct interface *iface = arg;
109 time_t up;
111 if (iface->state->fail.s_addr == iface->state->lease.addr.s_addr) {
112 up = uptime();
113 if (iface->state->defend + DEFEND_INTERVAL > up) {
114 drop_config(iface, "EXPIRE");
115 iface->state->conflicts = -1;
116 } else {
117 iface->state->defend = up;
118 return;
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",
127 iface->name);
128 iface->state->interval = RATE_LIMIT_INTERVAL / 2;
129 start_discover(iface);
130 } else {
131 add_timeout_sec(PROBE_WAIT, start_ipv4ll, iface);