2013-04-05 04:31:04 +08:00
|
|
|
/*
|
2008-09-02 21:28:11 +08:00
|
|
|
* dhcpcd - DHCP client daemon
|
2014-01-22 18:39:30 +08:00
|
|
|
* Copyright (c) 2006-2014 Roy Marples <roy@marples.name>
|
2008-09-02 21:28:11 +08:00
|
|
|
* All rights reserved
|
|
|
|
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
|
|
* SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2014-04-25 19:11:05 +08:00
|
|
|
#include <sys/socket.h>
|
|
|
|
|
|
|
|
#include <net/if.h>
|
|
|
|
#include <netinet/in.h>
|
2014-04-25 18:42:37 +08:00
|
|
|
#include <netinet/if_ether.h>
|
|
|
|
|
2008-09-02 21:28:11 +08:00
|
|
|
#include <errno.h>
|
|
|
|
#include <signal.h>
|
|
|
|
#include <stdlib.h>
|
2009-07-14 21:59:30 +08:00
|
|
|
#include <string.h>
|
2008-09-06 02:24:34 +08:00
|
|
|
#include <syslog.h>
|
2008-09-02 21:28:11 +08:00
|
|
|
#include <unistd.h>
|
|
|
|
|
2014-01-24 19:09:39 +08:00
|
|
|
#include "config.h"
|
2008-09-02 21:28:11 +08:00
|
|
|
#include "arp.h"
|
2013-02-02 22:05:55 +08:00
|
|
|
#include "ipv4.h"
|
2008-09-02 21:28:11 +08:00
|
|
|
#include "common.h"
|
2013-02-02 22:05:55 +08:00
|
|
|
#include "dhcp.h"
|
2008-09-02 21:28:11 +08:00
|
|
|
#include "dhcpcd.h"
|
|
|
|
#include "eloop.h"
|
2014-04-25 18:42:37 +08:00
|
|
|
#include "if.h"
|
2008-09-02 21:28:11 +08:00
|
|
|
#include "if-options.h"
|
|
|
|
#include "ipv4ll.h"
|
|
|
|
|
2009-03-11 01:28:18 +08:00
|
|
|
#define ARP_LEN \
|
2008-09-04 16:31:00 +08:00
|
|
|
(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
|
|
|
|
|
2014-03-28 06:14:52 +08:00
|
|
|
static ssize_t
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_send(const struct interface *ifp, int op, in_addr_t sip, in_addr_t tip)
|
2008-09-04 16:31:00 +08:00
|
|
|
{
|
2008-09-05 21:12:35 +08:00
|
|
|
uint8_t arp_buffer[ARP_LEN];
|
2008-09-04 16:31:00 +08:00
|
|
|
struct arphdr ar;
|
|
|
|
size_t len;
|
|
|
|
uint8_t *p;
|
|
|
|
|
2012-11-13 19:25:51 +08:00
|
|
|
ar.ar_hrd = htons(ifp->family);
|
2008-09-04 16:31:00 +08:00
|
|
|
ar.ar_pro = htons(ETHERTYPE_IP);
|
2012-11-13 19:25:51 +08:00
|
|
|
ar.ar_hln = ifp->hwlen;
|
2008-09-04 16:31:00 +08:00
|
|
|
ar.ar_pln = sizeof(sip);
|
|
|
|
ar.ar_op = htons(op);
|
2013-02-20 00:22:04 +08:00
|
|
|
|
|
|
|
p = arp_buffer;
|
2014-03-28 06:14:52 +08:00
|
|
|
len = 0;
|
2013-02-20 00:22:04 +08:00
|
|
|
|
|
|
|
#define CHECK(fun, b, l) \
|
|
|
|
do { \
|
2014-03-28 06:14:52 +08:00
|
|
|
if (len + (l) > sizeof(arp_buffer)) \
|
2013-02-20 00:22:04 +08:00
|
|
|
goto eexit; \
|
|
|
|
fun(p, (b), (l)); \
|
|
|
|
p += (l); \
|
2014-03-28 06:14:52 +08:00
|
|
|
len += (l); \
|
2013-02-20 00:22:04 +08:00
|
|
|
} while (/* CONSTCOND */ 0)
|
|
|
|
#define APPEND(b, l) CHECK(memcpy, b, l)
|
|
|
|
#define ZERO(l) CHECK(memset, 0, l)
|
|
|
|
|
|
|
|
APPEND(&ar, sizeof(ar));
|
|
|
|
APPEND(ifp->hwaddr, ifp->hwlen);
|
|
|
|
APPEND(&sip, sizeof(sip));
|
|
|
|
ZERO(ifp->hwlen);
|
|
|
|
APPEND(&tip, sizeof(tip));
|
2014-04-25 18:42:37 +08:00
|
|
|
return if_sendrawpacket(ifp, ETHERTYPE_ARP, arp_buffer, len);
|
2013-02-20 00:22:04 +08:00
|
|
|
|
|
|
|
eexit:
|
2013-02-20 00:59:58 +08:00
|
|
|
errno = ENOBUFS;
|
2013-02-20 00:22:04 +08:00
|
|
|
return -1;
|
2008-09-04 16:31:00 +08:00
|
|
|
}
|
|
|
|
|
2008-09-02 21:28:11 +08:00
|
|
|
static void
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_failure(struct interface *ifp)
|
2008-09-02 21:28:11 +08:00
|
|
|
{
|
2013-02-04 06:55:45 +08:00
|
|
|
const struct dhcp_state *state = D_CSTATE(ifp);
|
2010-05-13 00:20:55 +08:00
|
|
|
|
|
|
|
/* If we failed without a magic cookie then we need to try
|
|
|
|
* and defend our IPv4LL address. */
|
2013-02-04 06:55:45 +08:00
|
|
|
if ((state->offer != NULL &&
|
2014-01-22 18:39:30 +08:00
|
|
|
state->offer->cookie != htonl(MAGIC_COOKIE)) ||
|
2013-02-04 06:55:45 +08:00
|
|
|
(state->new != NULL &&
|
2014-01-22 18:39:30 +08:00
|
|
|
state->new->cookie != htonl(MAGIC_COOKIE)))
|
2010-05-13 00:20:55 +08:00
|
|
|
{
|
2012-11-13 19:44:20 +08:00
|
|
|
ipv4ll_handle_failure(ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-05-13 00:20:55 +08:00
|
|
|
|
2013-02-04 06:55:45 +08:00
|
|
|
unlink(state->leasefile);
|
|
|
|
if (!state->lease.frominfo)
|
2013-02-02 22:05:55 +08:00
|
|
|
dhcp_decline(ifp);
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
2013-02-04 06:55:45 +08:00
|
|
|
if (state->lease.frominfo)
|
2014-04-28 20:02:12 +08:00
|
|
|
dhcpcd_startinterface(ifp);
|
2008-10-21 23:34:52 +08:00
|
|
|
else
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_sec(ifp->ctx->eloop,
|
2014-04-28 20:02:12 +08:00
|
|
|
DHCP_ARP_FAIL, dhcpcd_startinterface, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
|
|
|
|
2008-09-04 00:49:28 +08:00
|
|
|
static void
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_packet(void *arg)
|
2008-09-02 21:28:11 +08:00
|
|
|
{
|
2012-11-13 19:25:51 +08:00
|
|
|
struct interface *ifp = arg;
|
2008-09-05 21:12:35 +08:00
|
|
|
uint8_t arp_buffer[ARP_LEN];
|
2008-09-04 16:31:00 +08:00
|
|
|
struct arphdr ar;
|
2008-09-02 21:28:11 +08:00
|
|
|
uint32_t reply_s;
|
|
|
|
uint32_t reply_t;
|
|
|
|
uint8_t *hw_s, *hw_t;
|
|
|
|
ssize_t bytes;
|
2013-02-04 06:55:45 +08:00
|
|
|
struct dhcp_state *state;
|
2013-02-03 18:35:59 +08:00
|
|
|
struct if_options *opts = ifp->options;
|
2009-03-31 16:35:38 +08:00
|
|
|
const char *hwaddr;
|
|
|
|
struct in_addr ina;
|
2014-02-12 08:39:46 +08:00
|
|
|
char hwbuf[HWADDR_LEN * 3];
|
2008-09-02 21:28:11 +08:00
|
|
|
|
2013-02-04 06:55:45 +08:00
|
|
|
state = D_STATE(ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
state->fail.s_addr = 0;
|
|
|
|
for(;;) {
|
2014-04-25 18:42:37 +08:00
|
|
|
bytes = if_readrawpacket(ifp, ETHERTYPE_ARP,
|
2011-03-25 01:59:20 +08:00
|
|
|
arp_buffer, sizeof(arp_buffer), NULL);
|
2008-09-02 21:28:11 +08:00
|
|
|
if (bytes == 0 || bytes == -1)
|
|
|
|
return;
|
|
|
|
/* We must have a full ARP header */
|
2008-09-04 16:31:00 +08:00
|
|
|
if ((size_t)bytes < sizeof(ar))
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
2008-09-04 16:31:00 +08:00
|
|
|
memcpy(&ar, arp_buffer, sizeof(ar));
|
2008-09-02 21:28:11 +08:00
|
|
|
/* Protocol must be IP. */
|
2008-09-04 16:31:00 +08:00
|
|
|
if (ar.ar_pro != htons(ETHERTYPE_IP))
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
2008-09-04 16:31:00 +08:00
|
|
|
if (ar.ar_pln != sizeof(reply_s))
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
|
|
|
/* Only these types are recognised */
|
2008-09-04 16:31:00 +08:00
|
|
|
if (ar.ar_op != htons(ARPOP_REPLY) &&
|
|
|
|
ar.ar_op != htons(ARPOP_REQUEST))
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
|
|
|
|
|
|
|
/* Get pointers to the hardware addreses */
|
2008-09-04 16:31:00 +08:00
|
|
|
hw_s = arp_buffer + sizeof(ar);
|
|
|
|
hw_t = hw_s + ar.ar_hln + ar.ar_pln;
|
2008-09-02 21:28:11 +08:00
|
|
|
/* Ensure we got all the data */
|
2008-09-04 16:31:00 +08:00
|
|
|
if ((hw_t + ar.ar_hln + ar.ar_pln) - arp_buffer > bytes)
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
|
|
|
/* Ignore messages from ourself */
|
2012-11-13 19:25:51 +08:00
|
|
|
if (ar.ar_hln == ifp->hwlen &&
|
|
|
|
memcmp(hw_s, ifp->hwaddr, ifp->hwlen) == 0)
|
2008-09-02 21:28:11 +08:00
|
|
|
continue;
|
|
|
|
/* Copy out the IP addresses */
|
2008-09-04 16:31:00 +08:00
|
|
|
memcpy(&reply_s, hw_s + ar.ar_hln, ar.ar_pln);
|
|
|
|
memcpy(&reply_t, hw_t + ar.ar_hln, ar.ar_pln);
|
2008-09-02 21:28:11 +08:00
|
|
|
|
2009-03-31 16:35:38 +08:00
|
|
|
/* Check for arping */
|
|
|
|
if (state->arping_index &&
|
|
|
|
state->arping_index <= opts->arping_len &&
|
|
|
|
(reply_s == opts->arping[state->arping_index - 1] ||
|
2014-01-22 18:39:30 +08:00
|
|
|
(reply_s == 0 &&
|
|
|
|
reply_t == opts->arping[state->arping_index - 1])))
|
2009-03-31 16:35:38 +08:00
|
|
|
{
|
|
|
|
ina.s_addr = reply_s;
|
|
|
|
hwaddr = hwaddr_ntoa((unsigned char *)hw_s,
|
2014-02-12 08:39:46 +08:00
|
|
|
(size_t)ar.ar_hln, hwbuf, sizeof(hwbuf));
|
2009-03-31 16:35:38 +08:00
|
|
|
syslog(LOG_INFO,
|
|
|
|
"%s: found %s on hardware address %s",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, inet_ntoa(ina), hwaddr);
|
2014-04-28 20:02:12 +08:00
|
|
|
if (dhcpcd_selectprofile(ifp, hwaddr) == -1 &&
|
|
|
|
dhcpcd_selectprofile(ifp, inet_ntoa(ina)) == -1)
|
2014-02-24 22:40:29 +08:00
|
|
|
{
|
|
|
|
state->probes = 0;
|
|
|
|
/* We didn't find a profile for this
|
|
|
|
* address or hwaddr, so move to the next
|
|
|
|
* arping profile */
|
|
|
|
if (state->arping_index <
|
|
|
|
ifp->options->arping_len)
|
|
|
|
{
|
|
|
|
arp_probe(ifp);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2013-02-02 22:05:55 +08:00
|
|
|
dhcp_close(ifp);
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
|
2014-04-28 20:02:12 +08:00
|
|
|
dhcpcd_startinterface(ifp);
|
2009-03-31 16:35:38 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-01-22 18:39:30 +08:00
|
|
|
/* RFC 2131 3.1.5, Client-server interaction
|
|
|
|
* RFC 3927 2.2.1, Probe Conflict Detection */
|
2009-03-11 01:28:18 +08:00
|
|
|
if (state->offer &&
|
2008-09-02 21:28:11 +08:00
|
|
|
(reply_s == state->offer->yiaddr ||
|
2014-01-22 18:39:30 +08:00
|
|
|
(reply_s == 0 && reply_t == state->offer->yiaddr)))
|
2008-09-02 21:28:11 +08:00
|
|
|
state->fail.s_addr = state->offer->yiaddr;
|
|
|
|
|
2014-01-22 18:39:30 +08:00
|
|
|
/* RFC 3927 2.5, Conflict Defense */
|
2013-02-03 22:52:24 +08:00
|
|
|
if (IN_LINKLOCAL(htonl(state->addr.s_addr)) &&
|
2014-01-22 18:39:30 +08:00
|
|
|
reply_s == state->addr.s_addr)
|
2013-02-03 22:52:24 +08:00
|
|
|
state->fail.s_addr = state->addr.s_addr;
|
2008-09-02 21:28:11 +08:00
|
|
|
|
|
|
|
if (state->fail.s_addr) {
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_ERR, "%s: hardware address %s claims %s",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name,
|
2009-02-12 01:56:22 +08:00
|
|
|
hwaddr_ntoa((unsigned char *)hw_s,
|
2014-02-12 08:39:46 +08:00
|
|
|
(size_t)ar.ar_hln, hwbuf, sizeof(hwbuf)),
|
2009-02-12 01:56:22 +08:00
|
|
|
inet_ntoa(state->fail));
|
2008-09-02 21:28:11 +08:00
|
|
|
errno = EEXIST;
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_failure(ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_announce(void *arg)
|
2008-09-02 21:28:11 +08:00
|
|
|
{
|
2012-11-13 19:25:51 +08:00
|
|
|
struct interface *ifp = arg;
|
2013-02-04 06:55:45 +08:00
|
|
|
struct dhcp_state *state = D_STATE(ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
struct timeval tv;
|
|
|
|
|
2011-12-12 05:14:49 +08:00
|
|
|
if (state->new == NULL)
|
|
|
|
return;
|
2013-02-03 22:52:24 +08:00
|
|
|
if (state->arp_fd == -1) {
|
2014-04-25 18:42:37 +08:00
|
|
|
state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
|
2013-11-12 23:00:22 +08:00
|
|
|
if (state->arp_fd == -1) {
|
|
|
|
syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
|
|
|
|
return;
|
|
|
|
}
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_event_add(ifp->ctx->eloop,
|
|
|
|
state->arp_fd, arp_packet, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
2013-04-02 15:01:11 +08:00
|
|
|
if (++state->claims < ANNOUNCE_NUM)
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_DEBUG,
|
2009-02-12 01:56:22 +08:00
|
|
|
"%s: sending ARP announce (%d of %d), "
|
2014-01-25 09:35:53 +08:00
|
|
|
"next in %d.0 seconds",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, state->claims, ANNOUNCE_NUM, ANNOUNCE_WAIT);
|
2008-09-02 21:28:11 +08:00
|
|
|
else
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_DEBUG,
|
2009-02-12 01:56:22 +08:00
|
|
|
"%s: sending ARP announce (%d of %d)",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, state->claims, ANNOUNCE_NUM);
|
2013-02-02 22:05:55 +08:00
|
|
|
if (arp_send(ifp, ARPOP_REQUEST,
|
2009-02-12 01:56:22 +08:00
|
|
|
state->new->yiaddr, state->new->yiaddr) == -1)
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_ERR, "send_arp: %m");
|
2008-09-02 21:28:11 +08:00
|
|
|
if (state->claims < ANNOUNCE_NUM) {
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_sec(ifp->ctx->eloop,
|
|
|
|
ANNOUNCE_WAIT, arp_announce, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
return;
|
|
|
|
}
|
2010-02-18 06:23:17 +08:00
|
|
|
if (state->new->cookie != htonl(MAGIC_COOKIE)) {
|
2014-01-29 22:05:58 +08:00
|
|
|
/* Check if doing DHCP */
|
|
|
|
if (!(ifp->options->options & DHCPCD_DHCP))
|
|
|
|
return;
|
2008-09-02 21:28:11 +08:00
|
|
|
/* We should pretend to be at the end
|
2009-03-04 07:41:53 +08:00
|
|
|
* of the DHCP negotation cycle unless we rebooted */
|
|
|
|
if (state->interval != 0)
|
|
|
|
state->interval = 64;
|
2008-09-02 21:28:11 +08:00
|
|
|
state->probes = 0;
|
|
|
|
state->claims = 0;
|
|
|
|
tv.tv_sec = state->interval - DHCP_RAND_MIN;
|
|
|
|
tv.tv_usec = arc4random() % (DHCP_RAND_MAX_U - DHCP_RAND_MIN_U);
|
|
|
|
timernorm(&tv);
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, dhcp_discover, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
} else {
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
|
2013-02-03 22:52:24 +08:00
|
|
|
close(state->arp_fd);
|
|
|
|
state->arp_fd = -1;
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_probe(void *arg)
|
2008-09-02 21:28:11 +08:00
|
|
|
{
|
2012-11-13 19:25:51 +08:00
|
|
|
struct interface *ifp = arg;
|
2013-02-04 06:55:45 +08:00
|
|
|
struct dhcp_state *state = D_STATE(ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
struct in_addr addr;
|
|
|
|
struct timeval tv;
|
2009-03-31 16:35:38 +08:00
|
|
|
int arping = 0;
|
2008-09-02 21:28:11 +08:00
|
|
|
|
2013-02-18 02:17:29 +08:00
|
|
|
if (state->arp_fd == -1) {
|
2014-04-25 18:42:37 +08:00
|
|
|
state->arp_fd = if_openrawsocket(ifp, ETHERTYPE_ARP);
|
2013-11-12 23:00:22 +08:00
|
|
|
if (state->arp_fd == -1) {
|
|
|
|
syslog(LOG_ERR, "%s: %s: %m", __func__, ifp->name);
|
2013-02-18 02:17:29 +08:00
|
|
|
return;
|
2013-11-12 23:00:22 +08:00
|
|
|
}
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_event_add(ifp->ctx->eloop,
|
|
|
|
state->arp_fd, arp_packet, ifp);
|
2013-02-18 02:17:29 +08:00
|
|
|
}
|
|
|
|
|
2013-02-03 18:35:59 +08:00
|
|
|
if (state->arping_index < ifp->options->arping_len) {
|
|
|
|
addr.s_addr = ifp->options->arping[state->arping_index];
|
2009-03-31 16:35:38 +08:00
|
|
|
arping = 1;
|
|
|
|
} else if (state->offer) {
|
2008-11-19 23:48:18 +08:00
|
|
|
if (state->offer->yiaddr)
|
|
|
|
addr.s_addr = state->offer->yiaddr;
|
|
|
|
else
|
|
|
|
addr.s_addr = state->offer->ciaddr;
|
|
|
|
} else
|
2013-02-03 22:52:24 +08:00
|
|
|
addr.s_addr = state->addr.s_addr;
|
2008-11-19 17:48:11 +08:00
|
|
|
|
2008-09-02 21:28:11 +08:00
|
|
|
if (state->probes == 0) {
|
2009-03-31 16:35:38 +08:00
|
|
|
if (arping)
|
2013-05-24 05:50:34 +08:00
|
|
|
syslog(LOG_DEBUG, "%s: searching for %s",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, inet_ntoa(addr));
|
2009-03-31 16:35:38 +08:00
|
|
|
else
|
2013-05-24 05:50:34 +08:00
|
|
|
syslog(LOG_DEBUG, "%s: checking for %s",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, inet_ntoa(addr));
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
|
|
|
if (++state->probes < PROBE_NUM) {
|
|
|
|
tv.tv_sec = PROBE_MIN;
|
|
|
|
tv.tv_usec = arc4random() % (PROBE_MAX_U - PROBE_MIN_U);
|
|
|
|
timernorm(&tv);
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probe, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
} else {
|
|
|
|
tv.tv_sec = ANNOUNCE_WAIT;
|
|
|
|
tv.tv_usec = 0;
|
2009-03-31 16:35:38 +08:00
|
|
|
if (arping) {
|
|
|
|
state->probes = 0;
|
2013-02-03 18:35:59 +08:00
|
|
|
if (++state->arping_index < ifp->options->arping_len)
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_tv(ifp->ctx->eloop,
|
|
|
|
&tv, arp_probe, ifp);
|
2009-03-31 16:35:38 +08:00
|
|
|
else
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_tv(ifp->ctx->eloop,
|
2014-04-28 20:02:12 +08:00
|
|
|
&tv, dhcpcd_startinterface, ifp);
|
2009-03-31 16:35:38 +08:00
|
|
|
} else
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_timeout_add_tv(ifp->ctx->eloop,
|
|
|
|
&tv, dhcp_bind, ifp);
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_DEBUG,
|
2014-01-25 09:35:53 +08:00
|
|
|
"%s: sending ARP probe (%d of %d), next in %0.1f seconds",
|
2012-11-13 19:25:51 +08:00
|
|
|
ifp->name, state->probes ? state->probes : PROBE_NUM, PROBE_NUM,
|
2009-04-15 17:01:02 +08:00
|
|
|
timeval_to_double(&tv));
|
2013-02-02 22:05:55 +08:00
|
|
|
if (arp_send(ifp, ARPOP_REQUEST, 0, addr.s_addr) == -1)
|
2008-09-06 02:24:34 +08:00
|
|
|
syslog(LOG_ERR, "send_arp: %m");
|
2008-09-02 21:28:11 +08:00
|
|
|
}
|
2009-03-31 16:35:38 +08:00
|
|
|
|
|
|
|
void
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_start(struct interface *ifp)
|
2009-03-31 16:35:38 +08:00
|
|
|
{
|
2013-02-04 06:55:45 +08:00
|
|
|
struct dhcp_state *state = D_STATE(ifp);
|
2012-11-13 19:25:51 +08:00
|
|
|
|
2013-02-04 06:55:45 +08:00
|
|
|
state->probes = 0;
|
|
|
|
state->arping_index = 0;
|
2013-02-02 22:05:55 +08:00
|
|
|
arp_probe(ifp);
|
2009-03-31 16:35:38 +08:00
|
|
|
}
|
2014-01-31 19:47:27 +08:00
|
|
|
|
|
|
|
void
|
|
|
|
arp_close(struct interface *ifp)
|
|
|
|
{
|
|
|
|
struct dhcp_state *state = D_STATE(ifp);
|
|
|
|
|
|
|
|
if (state == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (state->arp_fd != -1) {
|
2014-02-12 08:39:46 +08:00
|
|
|
eloop_event_delete(ifp->ctx->eloop, state->arp_fd);
|
2014-01-31 19:47:27 +08:00
|
|
|
close(state->arp_fd);
|
|
|
|
state->arp_fd = -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|