1d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan/* 2d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * dhcpcd - DHCP client daemon 3d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Copyright (c) 2006-2015 Roy Marples <roy@marples.name> 4d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * All rights reserved 5d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 6d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Redistribution and use in source and binary forms, with or without 7d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * modification, are permitted provided that the following conditions 8d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * are met: 9d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 1. Redistributions of source code must retain the above copyright 10d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer. 11d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 2. Redistributions in binary form must reproduce the above copyright 12d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * notice, this list of conditions and the following disclaimer in the 13d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * documentation and/or other materials provided with the distribution. 14d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * 15d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SUCH DAMAGE. 26d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan */ 27d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 28d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <errno.h> 29d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <signal.h> 30d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <stdlib.h> 31d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <string.h> 32d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include <unistd.h> 33d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 34d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#define ELOOP_QUEUE 6 35d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "config.h" 36d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "arp.h" 37d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "common.h" 38d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "dhcp.h" 39d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "eloop.h" 40d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if.h" 41d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "if-options.h" 42d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#include "ipv4ll.h" 43d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 44d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic struct dhcp_message * 45d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_make_lease(uint32_t addr) 46d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 47d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint32_t u32; 48d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_message *dhcp; 49d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan uint8_t *p; 50d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 51d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp = calloc(1, sizeof(*dhcp)); 52d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (dhcp == NULL) 53d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return NULL; 54d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Put some LL options in */ 55d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp->yiaddr = addr; 56d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p = dhcp->options; 57d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = DHO_SUBNETMASK; 58d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = sizeof(u32); 59d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u32 = htonl(LINKLOCAL_MASK); 60d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, &u32, sizeof(u32)); 61d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += sizeof(u32); 62d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = DHO_BROADCAST; 63d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = sizeof(u32); 64d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan u32 = htonl(LINKLOCAL_BRDC); 65d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(p, &u32, sizeof(u32)); 66d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan p += sizeof(u32); 67d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan *p++ = DHO_END; 68d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 69d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return dhcp; 70d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 71d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 72d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic in_addr_t 73d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_pick_addr(const struct arp_state *astate) 74d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 75d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan in_addr_t addr; 76d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct interface *ifp; 77d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan const struct dhcp_state *state; 78d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 79d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan for (;;) { 80d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* RFC 3927 Section 2.1 states that the first 256 and 81d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * last 256 addresses are reserved for future use. 82d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * See ipv4ll_start for why we don't use arc4_random. */ 83d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan addr = ntohl(LINKLOCAL_ADDR | 84d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ((uint32_t)(random() % 0xFD00) + 0x0100)); 85d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 86d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* No point using a failed address */ 87d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (addr == astate->failed.s_addr) 88d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan continue; 89d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 90d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Ensure we don't have the address on another interface */ 91d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan TAILQ_FOREACH(ifp, astate->iface->ctx->ifaces, next) { 92d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state = D_CSTATE(ifp); 93d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state && state->addr.s_addr == addr) 94d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 95d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 96d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 97d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Yay, this should be a unique and workable IPv4LL address */ 98d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ifp == NULL) 99d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan break; 100d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 101d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return addr; 102d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 103d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 104d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 105d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_probed(struct arp_state *astate) 106d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 107d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state = D_STATE(astate->iface); 108d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 109d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->state == DHS_IPV4LL_BOUND) { 110d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4_finaliseaddr(astate->iface); 111d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 112d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 113d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 114d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->state != DHS_BOUND) { 115d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_message *offer; 116d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 117d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* A DHCP lease could have already been offered. 118d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * Backup and replace once the IPv4LL address is bound */ 119d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan offer = state->offer; 120d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->offer = ipv4ll_make_lease(astate->addr.s_addr); 121d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->offer == NULL) 122d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(astate->iface->ctx, LOG_ERR, "%s: %m", __func__); 123d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan else 124d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp_bind(astate->iface, astate); 125d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->offer = offer; 126d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 127d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 128d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 129d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 130d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_announced(struct arp_state *astate) 131d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 132d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state = D_STATE(astate->iface); 133d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 134d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->conflicts = 0; 135d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* Need to keep the arp state so we can defend our IP. */ 136d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 137d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 138d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 139d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_probe(void *arg) 140d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 141d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 142d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IN_IFF_TENTATIVE 143d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4ll_probed(arg); 144d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 145d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan arp_probe(arg); 146d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 147d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 148d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 149d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanstatic void 150d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg) 151d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 152d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state = D_STATE(astate->iface); 153d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan in_addr_t fail; 154d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 155d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fail = 0; 156d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* RFC 3927 2.2.1, Probe Conflict Detection */ 157d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (amsg == NULL || 158d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (amsg->sip.s_addr == astate->addr.s_addr || 159d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan (amsg->sip.s_addr == 0 && amsg->tip.s_addr == astate->addr.s_addr))) 160d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fail = astate->addr.s_addr; 161d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 162d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* RFC 3927 2.5, Conflict Defense */ 163d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN_LINKLOCAL(htonl(state->addr.s_addr)) && 164d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan amsg && amsg->sip.s_addr == state->addr.s_addr) 165d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan fail = state->addr.s_addr; 166d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 167d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (fail == 0) 168d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 169d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 170d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->failed.s_addr = fail; 171d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan arp_report_conflicted(astate, amsg); 172d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 173d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (astate->failed.s_addr == state->addr.s_addr) { 174d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan time_t up; 175d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 176d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* RFC 3927 Section 2.5 */ 177d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan up = uptime(); 178d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->defend + DEFEND_INTERVAL > up) { 179d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(astate->iface->ctx, LOG_WARNING, 180d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: IPv4LL %d second defence failed for %s", 181d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->iface->name, DEFEND_INTERVAL, 182d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan inet_ntoa(state->addr)); 183d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan dhcp_drop(astate->iface, "EXPIRE"); 184d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else { 185d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(astate->iface->ctx, LOG_DEBUG, 186d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: defended IPv4LL address %s", 187d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->iface->name, inet_ntoa(state->addr)); 188d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->defend = up; 189d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 190d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 191d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 192d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 193d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan arp_cancel(astate); 194d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (++state->conflicts == MAX_CONFLICTS) 195d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(astate->iface->ctx, LOG_ERR, 196d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan "%s: failed to acquire an IPv4LL address", 197d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->iface->name); 198d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr.s_addr = ipv4ll_pick_addr(astate); 199d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eloop_timeout_add_sec(astate->iface->ctx->eloop, 200d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->conflicts >= MAX_CONFLICTS ? 201d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan RATE_LIMIT_INTERVAL : PROBE_WAIT, 202d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4ll_probe, astate); 203d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 204d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 205d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 206d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_start(void *arg) 207d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 208d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct interface *ifp = arg; 209d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state = D_STATE(ifp); 210d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct arp_state *astate; 211d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct ipv4_addr *ap; 212d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 213d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->arp_ipv4ll) 214d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 215d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 216d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* RFC 3927 Section 2.1 states that the random number generator 217d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * SHOULD be seeded with a value derived from persistent information 218d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * such as the IEEE 802 MAC address so that it usually picks 219d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan * the same address without persistent storage. */ 220d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->conflicts == 0) { 221d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan unsigned int seed; 222d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 223d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (sizeof(seed) > ifp->hwlen) { 224d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan seed = 0; 225d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&seed, ifp->hwaddr, ifp->hwlen); 226d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 227d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan memcpy(&seed, ifp->hwaddr + ifp->hwlen - sizeof(seed), 228d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan sizeof(seed)); 229d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan initstate(seed, state->randomstate, sizeof(state->randomstate)); 230d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 231d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 232d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if ((astate = arp_new(ifp, NULL)) == NULL) 233d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 234d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 235d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->arp_ipv4ll = astate; 236d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->probed_cb = ipv4ll_probed; 237d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->announced_cb = ipv4ll_announced; 238d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->conflicted_cb = ipv4ll_conflicted; 239d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 240d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (IN_LINKLOCAL(htonl(state->addr.s_addr))) { 241d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr = state->addr; 242d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan arp_announce(astate); 243d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 244d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 245d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 246d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (state->offer && IN_LINKLOCAL(ntohl(state->offer->yiaddr))) { 247d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr.s_addr = state->offer->yiaddr; 248d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan free(state->offer); 249d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan state->offer = NULL; 250d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ap = ipv4_iffindaddr(ifp, &astate->addr, NULL); 251d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } else 252d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ap = ipv4_iffindlladdr(ifp); 253d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (ap) { 254d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr = ap->addr; 255d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4ll_probed(astate); 256d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan return; 257d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 258d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 259d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan setstate(state->randomstate); 260d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan /* We maybe rebooting an IPv4LL address. */ 261d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (!IN_LINKLOCAL(htonl(astate->addr.s_addr))) { 262d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan logger(ifp->ctx, LOG_INFO, "%s: probing for an IPv4LL address", 263d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ifp->name); 264d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr.s_addr = INADDR_ANY; 265d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan } 266d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan if (astate->addr.s_addr == INADDR_ANY) 267d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan astate->addr.s_addr = ipv4ll_pick_addr(astate); 268d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#ifdef IN_IFF_TENTATIVE 269d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan ipv4ll_probed(astate); 270d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#else 271d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan arp_probe(astate); 272d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan#endif 273d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 274d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 275d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanvoid 276d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tanipv4ll_stop(struct interface *ifp) 277d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan{ 278d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan struct dhcp_state *state = D_STATE(ifp); 279d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan 280d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan eloop_timeout_delete(ifp->ctx->eloop, NULL, state->arp_ipv4ll); 281d7ed851d6fc26c5e7db96971dbe6b44342b97727Samuel Tan} 282