1e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt/* 2e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * dhcpcd - DHCP client daemon 3e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Copyright (c) 2006-2008 Roy Marples <roy@marples.name> 4e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * All rights reserved 5e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 6e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * Redistribution and use in source and binary forms, with or without 7e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * modification, are permitted provided that the following conditions 8e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * are met: 9e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 1. Redistributions of source code must retain the above copyright 10e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * notice, this list of conditions and the following disclaimer. 11e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 2. Redistributions in binary form must reproduce the above copyright 12e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * notice, this list of conditions and the following disclaimer in the 13e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * documentation and/or other materials provided with the distribution. 14e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * 15e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt * SUCH DAMAGE. 26e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt */ 27e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 28e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <errno.h> 29e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <signal.h> 30e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <stdlib.h> 31e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <string.h> 32e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <syslog.h> 33e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include <unistd.h> 34e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 35e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "arp.h" 36e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "common.h" 37e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "dhcpcd.h" 38e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "eloop.h" 39e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "if-options.h" 40e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "ipv4ll.h" 41e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt#include "net.h" 42e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 43e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message * 44e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtmake_ipv4ll_lease(uint32_t addr) 45e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 46e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint32_t u32; 47e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct dhcp_message *dhcp; 48e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint8_t *p; 49e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 50e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp = xzalloc(sizeof(*dhcp)); 51e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* Put some LL options in */ 52e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt dhcp->yiaddr = addr; 53e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p = dhcp->options; 54e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = DHO_SUBNETMASK; 55e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = sizeof(u32); 56e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt u32 = htonl(LINKLOCAL_MASK); 57e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, &u32, sizeof(u32)); 58e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += sizeof(u32); 59e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = DHO_BROADCAST; 60e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = sizeof(u32); 61e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt u32 = htonl(LINKLOCAL_BRDC); 62e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt memcpy(p, &u32, sizeof(u32)); 63e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt p += sizeof(u32); 64e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt *p++ = DHO_END; 65e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 66e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return dhcp; 67e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 68e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 69e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstatic struct dhcp_message * 70e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtfind_ipv4ll_lease(uint32_t old_addr) 71e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 72e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint32_t addr; 73e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 74e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt for (;;) { 75e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = htonl(LINKLOCAL_ADDR | 76e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt (((uint32_t)abs((int)arc4random()) 77e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt % 0xFD00) + 0x0100)); 78e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr != old_addr && 79e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt IN_LINKLOCAL(ntohl(addr))) 80e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt break; 81e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 82e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return make_ipv4ll_lease(addr); 83e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 84e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 85e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 86e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtstart_ipv4ll(void *arg) 87e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 88e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 89e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt uint32_t addr; 90e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 91e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 92e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->probes = 0; 93e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->claims = 0; 94e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->addr.s_addr) { 95e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->conflicts = 0; 96e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (IN_LINKLOCAL(htonl(iface->addr.s_addr))) { 97e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_arp_announce(iface); 98e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 99e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 100e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 101e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 102e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->offer == NULL) 103e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = 0; 104e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else { 105e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = iface->state->offer->yiaddr; 106e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 107e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 108e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt /* We maybe rebooting an IPv4LL address. */ 109e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (!IN_LINKLOCAL(htonl(addr))) { 110e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_INFO, "%s: probing for an IPv4LL address", 111e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 112e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt addr = 0; 113e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 114e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (addr == 0) 115e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = find_ipv4ll_lease(addr); 116e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt else 117e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = make_ipv4ll_lease(addr); 118e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->lease.frominfo = 0; 119e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt send_arp_probe(iface); 120e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 121e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 122e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidtvoid 123e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidthandle_ipv4ll_failure(void *arg) 124e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt{ 125e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt struct interface *iface = arg; 126e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt time_t up; 127e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 128e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->fail.s_addr == iface->addr.s_addr) { 129e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt up = uptime(); 130e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (iface->state->defend + DEFEND_INTERVAL > up) { 131e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, 132e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt "%s: IPv4LL %d second defence failed", 133e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name, DEFEND_INTERVAL); 134e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt drop_config(iface, "EXPIRE"); 135e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->conflicts = -1; 136e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 137e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_DEBUG, "%s: defended IPv4LL address", 138e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 139e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->defend = up; 140e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt return; 141e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 142e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 143e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt 144e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt close_sockets(iface); 145e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt free(iface->state->offer); 146e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->offer = NULL; 147e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt delete_timeout(NULL, iface); 148e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt if (++iface->state->conflicts > MAX_CONFLICTS) { 149e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt syslog(LOG_ERR, "%s: failed to acquire an IPv4LL address", 150e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->name); 151e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt iface->state->interval = RATE_LIMIT_INTERVAL / 2; 152e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt start_discover(iface); 153e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } else { 154e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt add_timeout_sec(PROBE_WAIT, start_ipv4ll, iface); 155e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt } 156e86eee143ed21592f88a46623a81f71002430459Dmitry Shmidt} 157