source: rtems-libbsd/dhcpcd/ipv4ll.c @ 1f7037d

55-freebsd-126-freebsd-12
Last change on this file since 1f7037d was f2ed769, checked in by Sebastian Huber <sebastian.huber@…>, on 01/30/14 at 12:29:46

DHCPCD(8): Import

Import DHCPCD(8) from:

http://roy.marples.name/projects/dhcpcd/

The upstream sources can be obtained via:

fossil clone http://roy.marples.name/projects/dhcpcd

The imported version is 2014-01-29 19:46:44 [6b209507bb].

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
4 * All rights reserved
5
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.
14 *
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.
26 */
27
28#include <errno.h>
29#include <signal.h>
30#include <stdlib.h>
31#include <string.h>
32#include <syslog.h>
33#include <unistd.h>
34
35#include "config.h"
36#include "arp.h"
37#include "common.h"
38#include "dhcp.h"
39#include "eloop.h"
40#include "if-options.h"
41#include "ipv4ll.h"
42#include "net.h"
43
44static struct dhcp_message *
45ipv4ll_make_lease(uint32_t addr)
46{
47        uint32_t u32;
48        struct dhcp_message *dhcp;
49        uint8_t *p;
50
51        dhcp = calloc(1, sizeof(*dhcp));
52        if (dhcp == NULL)
53                return NULL;
54        /* Put some LL options in */
55        dhcp->yiaddr = addr;
56        p = dhcp->options;
57        *p++ = DHO_SUBNETMASK;
58        *p++ = sizeof(u32);
59        u32 = htonl(LINKLOCAL_MASK);
60        memcpy(p, &u32, sizeof(u32));
61        p += sizeof(u32);
62        *p++ = DHO_BROADCAST;
63        *p++ = sizeof(u32);
64        u32 = htonl(LINKLOCAL_BRDC);
65        memcpy(p, &u32, sizeof(u32));
66        p += sizeof(u32);
67        *p++ = DHO_END;
68
69        return dhcp;
70}
71
72static struct dhcp_message *
73ipv4ll_find_lease(uint32_t old_addr)
74{
75        uint32_t addr;
76
77        for (;;) {
78                addr = htonl(LINKLOCAL_ADDR |
79                    (((uint32_t)abs((int)arc4random())
80                        % 0xFD00) + 0x0100));
81                if (addr != old_addr &&
82                    IN_LINKLOCAL(ntohl(addr)))
83                        break;
84        }
85        return ipv4ll_make_lease(addr);
86}
87
88void
89ipv4ll_start(void *arg)
90{
91        struct interface *ifp = arg;
92        struct dhcp_state *state = D_STATE(ifp);
93        uint32_t addr;
94
95        eloop_timeout_delete(NULL, ifp);
96        state->probes = 0;
97        state->claims = 0;
98        if (state->addr.s_addr) {
99                state->conflicts = 0;
100                if (IN_LINKLOCAL(htonl(state->addr.s_addr))) {
101                        arp_announce(ifp);
102                        return;
103                }
104        }
105
106        if (state->offer == NULL)
107                addr = 0;
108        else {
109                addr = state->offer->yiaddr;
110                free(state->offer);
111        }
112        /* We maybe rebooting an IPv4LL address. */
113        if (!IN_LINKLOCAL(htonl(addr))) {
114                syslog(LOG_INFO, "%s: probing for an IPv4LL address",
115                    ifp->name);
116                addr = 0;
117        }
118        if (addr == 0)
119                state->offer = ipv4ll_find_lease(addr);
120        else
121                state->offer = ipv4ll_make_lease(addr);
122        if (state->offer == NULL)
123                syslog(LOG_ERR, "%s: %m", __func__);
124        else {
125                state->lease.frominfo = 0;
126                arp_probe(ifp);
127        }
128}
129
130void
131ipv4ll_handle_failure(void *arg)
132{
133        struct interface *ifp = arg;
134        struct dhcp_state *state = D_STATE(ifp);
135        time_t up;
136
137        if (state->fail.s_addr == state->addr.s_addr) {
138                /* RFC 3927 Section 2.5 */
139                up = uptime();
140                if (state->defend + DEFEND_INTERVAL > up) {
141                        syslog(LOG_WARNING,
142                            "%s: IPv4LL %d second defence failed",
143                            ifp->name, DEFEND_INTERVAL);
144                        dhcp_drop(ifp, "EXPIRE");
145                        state->conflicts = -1;
146                } else {
147                        syslog(LOG_DEBUG, "%s: defended IPv4LL address",
148                            ifp->name);
149                        state->defend = up;
150                        return;
151                }
152        }
153
154        dhcp_close(ifp);
155        free(state->offer);
156        state->offer = NULL;
157        eloop_timeout_delete(NULL, ifp);
158        if (++state->conflicts > MAX_CONFLICTS) {
159                syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address",
160                    ifp->name);
161                if (ifp->options->options & DHCPCD_DHCP) {
162                        state->interval = RATE_LIMIT_INTERVAL / 2;
163                        dhcp_discover(ifp);
164                } else
165                        eloop_timeout_add_sec(RATE_LIMIT_INTERVAL,
166                            ipv4ll_start, ifp);
167        } else {
168                eloop_timeout_add_sec(PROBE_WAIT, ipv4ll_start, ifp);
169        }
170}
Note: See TracBrowser for help on using the repository browser.