2011-03-31 08:47:27 +05:30
|
|
|
/* arp.c - arp ping checking
|
2011-06-25 19:32:09 +05:30
|
|
|
* Time-stamp: <2011-06-16 21:37:52 njk>
|
2011-03-31 09:29:22 +05:30
|
|
|
*
|
2011-03-31 08:47:27 +05:30
|
|
|
* Copyright 2010-2011 Nicholas J. Kain <njkain@gmail.com>
|
|
|
|
*
|
2011-03-31 09:29:22 +05:30
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
2010-11-16 06:36:50 +05:30
|
|
|
*/
|
|
|
|
#include <unistd.h>
|
2010-12-24 20:02:58 +05:30
|
|
|
#include <stdlib.h>
|
2010-11-16 06:36:50 +05:30
|
|
|
#include <string.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/socket.h>
|
|
|
|
#include <netinet/if_ether.h>
|
2010-12-24 20:02:58 +05:30
|
|
|
#include <netinet/in.h>
|
|
|
|
#include <arpa/inet.h>
|
2010-11-16 06:36:50 +05:30
|
|
|
#include <sys/time.h>
|
2011-06-25 22:32:56 +05:30
|
|
|
#include <linux/if_packet.h>
|
2011-06-25 20:10:41 +05:30
|
|
|
#include <fcntl.h>
|
2010-11-16 06:36:50 +05:30
|
|
|
#include <errno.h>
|
2010-12-24 20:28:47 +05:30
|
|
|
#include "arp.h"
|
2010-12-24 20:11:52 +05:30
|
|
|
#include "packet.h"
|
2010-12-24 20:02:58 +05:30
|
|
|
#include "sys.h"
|
2010-12-24 20:42:41 +05:30
|
|
|
#include "ifchange.h"
|
2011-04-20 02:07:43 +05:30
|
|
|
#include "leasefile.h"
|
2010-11-16 06:36:50 +05:30
|
|
|
#include "log.h"
|
|
|
|
#include "io.h"
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
#define ARP_MSG_SIZE 0x2a
|
|
|
|
#define ARP_RETRY_COUNT 3
|
|
|
|
|
2010-12-24 20:02:58 +05:30
|
|
|
static struct arpMsg arpreply;
|
|
|
|
static int arpreply_offset;
|
|
|
|
static struct dhcpMessage arp_dhcp_packet;
|
2011-03-31 12:02:34 +05:30
|
|
|
static int arp_packet_num;
|
|
|
|
|
2011-06-25 22:32:56 +05:30
|
|
|
static int arp_open_fd(struct client_state_t *cs)
|
2010-11-16 06:36:50 +05:30
|
|
|
{
|
2011-06-26 02:01:21 +05:30
|
|
|
if (cs->arpFd != -1)
|
|
|
|
return 0;
|
2010-11-16 06:36:50 +05:30
|
|
|
|
2011-06-26 02:01:21 +05:30
|
|
|
int fd = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP));
|
|
|
|
if (fd == -1) {
|
|
|
|
log_error("arp: failed to create socket: %s", strerror(errno));
|
|
|
|
goto out;
|
2010-11-16 06:36:50 +05:30
|
|
|
}
|
2011-06-26 02:01:21 +05:30
|
|
|
|
|
|
|
int opt = 1;
|
|
|
|
if (setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &opt, sizeof opt) == -1) {
|
|
|
|
log_error("arp: failed to set broadcast: %s", strerror(errno));
|
|
|
|
goto out_fd;
|
|
|
|
}
|
|
|
|
if (fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) == -1) {
|
|
|
|
log_error("arp: failed to set non-blocking: %s", strerror(errno));
|
|
|
|
goto out_fd;
|
|
|
|
}
|
|
|
|
struct sockaddr_ll saddr = {
|
|
|
|
.sll_family = AF_PACKET,
|
|
|
|
.sll_protocol = htons(ETH_P_ARP),
|
|
|
|
.sll_ifindex = client_config.ifindex,
|
|
|
|
};
|
|
|
|
if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_ll)) < 0) {
|
|
|
|
log_error("arp: bind failed: %s", strerror(errno));
|
|
|
|
goto out_fd;
|
|
|
|
}
|
|
|
|
|
|
|
|
cs->arpFd = fd;
|
|
|
|
epoll_add(cs, fd);
|
2011-06-25 22:32:56 +05:30
|
|
|
return 0;
|
2011-06-26 02:01:21 +05:30
|
|
|
out_fd:
|
|
|
|
close(fd);
|
|
|
|
out:
|
|
|
|
return -1;
|
2011-06-25 22:32:56 +05:30
|
|
|
}
|
|
|
|
|
2011-06-26 02:01:21 +05:30
|
|
|
static void arp_close_fd(struct client_state_t *cs)
|
2011-06-25 22:32:56 +05:30
|
|
|
{
|
2011-06-26 02:01:21 +05:30
|
|
|
if (cs->arpFd == -1)
|
|
|
|
return;
|
|
|
|
epoll_del(cs, cs->arpFd);
|
|
|
|
close(cs->arpFd);
|
|
|
|
cs->arpFd = -1;
|
2011-06-25 22:32:56 +05:30
|
|
|
}
|
|
|
|
|
|
|
|
// Returns 0 on success, -1 on failure.
|
|
|
|
static int arpping(struct client_state_t *cs, uint32_t test_ip)
|
|
|
|
{
|
|
|
|
if (arp_open_fd(cs) == -1)
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
struct arpMsg arp = {
|
|
|
|
.h_proto = htons(ETH_P_ARP),
|
|
|
|
.htype = htons(ARPHRD_ETHER),
|
|
|
|
.ptype = htons(ETH_P_IP),
|
|
|
|
.hlen = 6,
|
|
|
|
.plen = 4,
|
|
|
|
.operation = htons(ARPOP_REQUEST),
|
|
|
|
};
|
|
|
|
memset(arp.h_dest, 0xff, 6);
|
|
|
|
memcpy(arp.h_source, client_config.arp, 6);
|
|
|
|
memcpy(arp.smac, client_config.arp, 6);
|
|
|
|
memcpy(arp.dip4, &test_ip, sizeof test_ip);
|
|
|
|
|
|
|
|
struct sockaddr_ll addr = {
|
|
|
|
.sll_family = AF_PACKET,
|
|
|
|
.sll_ifindex = client_config.ifindex,
|
|
|
|
.sll_halen = 6,
|
|
|
|
};
|
|
|
|
memcpy(addr.sll_addr, client_config.arp, 6);
|
2010-11-16 06:36:50 +05:30
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
if (safe_sendto(cs->arpFd, (const char *)&arp, sizeof arp,
|
2011-06-25 22:32:56 +05:30
|
|
|
0, (struct sockaddr *)&addr, sizeof addr) < 0) {
|
2011-06-02 20:18:58 +05:30
|
|
|
log_error("arp: sendto failed: %s", strerror(errno));
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
2010-12-02 10:03:25 +05:30
|
|
|
return -1;
|
2010-11-16 06:36:50 +05:30
|
|
|
}
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_packet_num = 0;
|
|
|
|
return 0;
|
2010-11-16 06:36:50 +05:30
|
|
|
}
|
2010-12-24 20:02:58 +05:30
|
|
|
|
2011-05-31 20:54:40 +05:30
|
|
|
static void arpreply_clear()
|
|
|
|
{
|
|
|
|
memset(&arpreply, 0, sizeof arpreply);
|
|
|
|
arpreply_offset = 0;
|
|
|
|
}
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
int arp_check(struct client_state_t *cs, struct dhcpMessage *packet)
|
2010-12-24 20:02:58 +05:30
|
|
|
{
|
2011-06-25 21:12:15 +05:30
|
|
|
if (arpping(cs, arp_dhcp_packet.yiaddr) == -1)
|
2011-03-31 12:02:34 +05:30
|
|
|
return -1;
|
2010-12-24 20:02:58 +05:30
|
|
|
cs->arpPrevState = cs->dhcpState;
|
|
|
|
cs->dhcpState = DS_ARP_CHECK;
|
|
|
|
cs->timeout = 2000;
|
2011-03-31 12:02:34 +05:30
|
|
|
memcpy(&arp_dhcp_packet, packet, sizeof (struct dhcpMessage));
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-03-31 12:02:34 +05:30
|
|
|
return 0;
|
2010-12-24 20:02:58 +05:30
|
|
|
}
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
int arp_gw_check(struct client_state_t *cs)
|
2011-03-31 05:43:48 +05:30
|
|
|
{
|
2011-06-25 21:12:15 +05:30
|
|
|
if (arpping(cs, cs->routerAddr) == -1)
|
2011-03-31 12:02:34 +05:30
|
|
|
return -1;
|
2011-03-31 05:43:48 +05:30
|
|
|
cs->arpPrevState = cs->dhcpState;
|
|
|
|
cs->dhcpState = DS_ARP_GW_CHECK;
|
|
|
|
cs->oldTimeout = cs->timeout;
|
|
|
|
cs->timeout = 2000;
|
2011-03-31 12:02:34 +05:30
|
|
|
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpMessage));
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-03-31 12:02:34 +05:30
|
|
|
return 0;
|
2011-03-31 05:43:48 +05:30
|
|
|
}
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
int arp_get_gw_hwaddr(struct client_state_t *cs)
|
2011-03-31 08:47:27 +05:30
|
|
|
{
|
|
|
|
if (cs->dhcpState != DS_BOUND)
|
2011-06-02 20:18:58 +05:30
|
|
|
log_error("arp_get_gw_hwaddr: called when state != DS_BOUND");
|
2011-06-25 21:12:15 +05:30
|
|
|
if (arpping(cs, cs->routerAddr) == -1)
|
2011-03-31 12:02:34 +05:30
|
|
|
return -1;
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Searching for gw address");
|
2011-03-31 08:47:27 +05:30
|
|
|
memset(&arp_dhcp_packet, 0, sizeof (struct dhcpMessage));
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-03-31 12:02:34 +05:30
|
|
|
return 0;
|
2011-03-31 08:47:27 +05:30
|
|
|
}
|
|
|
|
|
2010-12-24 20:02:58 +05:30
|
|
|
static void arp_failed(struct client_state_t *cs)
|
|
|
|
{
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Offered address is in use -- declining");
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
2010-12-24 20:02:58 +05:30
|
|
|
send_decline(cs->xid, cs->serverAddr, arp_dhcp_packet.yiaddr);
|
|
|
|
|
|
|
|
if (cs->arpPrevState != DS_REQUESTING)
|
2010-12-24 20:42:41 +05:30
|
|
|
ifchange(NULL, IFCHANGE_DECONFIG);
|
2010-12-24 20:02:58 +05:30
|
|
|
cs->dhcpState = DS_INIT_SELECTING;
|
|
|
|
cs->requestedIP = 0;
|
|
|
|
cs->timeout = 0;
|
|
|
|
cs->packetNum = 0;
|
2010-12-24 20:11:52 +05:30
|
|
|
change_listen_mode(cs, LM_RAW);
|
2010-12-24 20:02:58 +05:30
|
|
|
}
|
|
|
|
|
2011-03-31 05:43:48 +05:30
|
|
|
void arp_gw_failed(struct client_state_t *cs)
|
|
|
|
{
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Gateway appears to have changed, getting new lease");
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
2011-03-31 05:43:48 +05:30
|
|
|
|
|
|
|
// Same as packet.c: line 258
|
|
|
|
ifchange(NULL, IFCHANGE_DECONFIG);
|
|
|
|
cs->dhcpState = DS_INIT_SELECTING;
|
|
|
|
cs->oldTimeout = 0;
|
|
|
|
cs->timeout = 0;
|
|
|
|
cs->requestedIP = 0;
|
|
|
|
cs->packetNum = 0;
|
|
|
|
change_listen_mode(cs, LM_RAW);
|
|
|
|
}
|
|
|
|
|
2010-12-24 20:02:58 +05:30
|
|
|
void arp_success(struct client_state_t *cs)
|
|
|
|
{
|
|
|
|
struct in_addr temp_addr;
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
2010-12-24 20:02:58 +05:30
|
|
|
|
|
|
|
cs->t1 = cs->lease >> 1;
|
2011-06-25 22:32:56 +05:30
|
|
|
cs->t2 = (cs->lease * 0x7) >> 3; // T2 = lease * 0.875
|
2010-12-24 20:02:58 +05:30
|
|
|
cs->timeout = cs->t1 * 1000;
|
|
|
|
cs->leaseStartTime = curms();
|
|
|
|
|
|
|
|
temp_addr.s_addr = arp_dhcp_packet.yiaddr;
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Lease of %s obtained, lease time %ld",
|
2010-12-24 20:02:58 +05:30
|
|
|
inet_ntoa(temp_addr), cs->lease);
|
|
|
|
cs->requestedIP = arp_dhcp_packet.yiaddr;
|
2011-03-31 08:47:27 +05:30
|
|
|
cs->dhcpState = DS_BOUND;
|
2010-12-24 20:42:41 +05:30
|
|
|
ifchange(&arp_dhcp_packet,
|
|
|
|
((cs->arpPrevState == DS_RENEWING ||
|
|
|
|
cs->arpPrevState == DS_REBINDING)
|
|
|
|
? IFCHANGE_RENEW : IFCHANGE_BOUND));
|
2010-12-24 20:11:52 +05:30
|
|
|
change_listen_mode(cs, LM_NONE);
|
2011-04-20 02:07:43 +05:30
|
|
|
write_leasefile(temp_addr);
|
2010-12-24 20:02:58 +05:30
|
|
|
if (client_config.quit_after_lease)
|
|
|
|
exit(EXIT_SUCCESS);
|
|
|
|
if (!client_config.foreground)
|
2010-12-27 20:35:43 +05:30
|
|
|
background(cs);
|
2010-12-24 20:02:58 +05:30
|
|
|
}
|
|
|
|
|
2011-05-31 20:54:40 +05:30
|
|
|
static void arp_gw_success(struct client_state_t *cs)
|
2011-03-31 05:43:48 +05:30
|
|
|
{
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Gateway seems unchanged");
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
|
|
|
|
2011-03-31 05:43:48 +05:30
|
|
|
cs->timeout = cs->oldTimeout;
|
|
|
|
cs->dhcpState = cs->arpPrevState;
|
|
|
|
}
|
|
|
|
|
2011-06-25 19:32:09 +05:30
|
|
|
// Note that this function will see all ARP traffic on the interface.
|
|
|
|
// Therefore the validation shouldn't be noisy, and should silently
|
|
|
|
// reject non-malformed ARP packets that are irrelevant.
|
2011-05-31 20:31:08 +05:30
|
|
|
static int arp_validate(struct arpMsg *am)
|
|
|
|
{
|
|
|
|
if (!am)
|
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
if (am->h_proto != htons(ETH_P_ARP)) {
|
|
|
|
log_warning("arp: IP header does not indicate ARP protocol");
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (am->htype != htons(ARPHRD_ETHER)) {
|
|
|
|
log_warning("arp: ARP hardware type field invalid");
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (am->ptype != htons(ETH_P_IP)) {
|
|
|
|
log_warning("arp: ARP protocol type field invalid");
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (am->hlen != 6) {
|
|
|
|
log_warning("arp: ARP hardware address length invalid");
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (am->plen != 4) {
|
|
|
|
log_warning("arp: ARP protocol address length invalid");
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (am->operation != htons(ARPOP_REPLY)) {
|
2011-06-25 19:32:09 +05:30
|
|
|
/* log_warning("arp: ARP operation type is not 'reply': %x", */
|
|
|
|
/* ntohs(am->operation)); */
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (memcmp(am->h_dest, client_config.arp, 6)) {
|
2011-06-25 19:32:09 +05:30
|
|
|
/* log_warning("arp: Ethernet destination does not equal our MAC"); */
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
|
|
|
if (memcmp(am->dmac, client_config.arp, 6)) {
|
2011-06-25 19:32:09 +05:30
|
|
|
/* log_warning("arp: ARP destination does not equal our MAC"); */
|
2011-05-31 20:31:08 +05:30
|
|
|
return 0;
|
2011-06-02 20:11:34 +05:30
|
|
|
}
|
2011-05-31 20:31:08 +05:30
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2010-12-24 20:02:58 +05:30
|
|
|
void handle_arp_response(struct client_state_t *cs)
|
|
|
|
{
|
|
|
|
if (arpreply_offset < sizeof arpreply) {
|
|
|
|
int r = safe_read(cs->arpFd, (char *)&arpreply + arpreply_offset,
|
|
|
|
sizeof arpreply - arpreply_offset);
|
|
|
|
if (r < 0) {
|
2011-05-30 20:24:05 +05:30
|
|
|
if (errno == EWOULDBLOCK || errno == EAGAIN)
|
|
|
|
return;
|
2011-06-02 20:18:58 +05:30
|
|
|
log_error("arp: ARP response read failed: %s", strerror(errno));
|
2011-03-31 12:02:34 +05:30
|
|
|
switch (cs->dhcpState) {
|
|
|
|
case DS_ARP_CHECK: arp_failed(cs); break;
|
|
|
|
case DS_ARP_GW_CHECK: arp_gw_failed(cs); break;
|
|
|
|
case DS_BOUND: break; // keep trying for finding gw mac
|
|
|
|
default: break;
|
|
|
|
}
|
2010-12-24 20:02:58 +05:30
|
|
|
} else
|
|
|
|
arpreply_offset += r;
|
|
|
|
}
|
|
|
|
|
2011-03-31 08:47:27 +05:30
|
|
|
if (arpreply_offset < ARP_MSG_SIZE) {
|
2011-06-02 20:18:58 +05:30
|
|
|
log_warning("arp: Received short ARP message -- ignoring");
|
2011-03-31 08:47:27 +05:30
|
|
|
return;
|
|
|
|
}
|
2011-03-31 12:02:34 +05:30
|
|
|
|
2011-06-25 19:32:09 +05:30
|
|
|
if (!arp_validate(&arpreply))
|
2011-05-31 20:31:08 +05:30
|
|
|
return;
|
|
|
|
|
2011-03-31 12:02:34 +05:30
|
|
|
++arp_packet_num;
|
2011-03-31 08:47:27 +05:30
|
|
|
switch (cs->dhcpState) {
|
2011-05-31 20:44:50 +05:30
|
|
|
case DS_ARP_CHECK:
|
|
|
|
if (!memcmp(arpreply.sip4, &arp_dhcp_packet.yiaddr, 4)) {
|
|
|
|
// Check to see if we replied to our own ARP query.
|
|
|
|
if (!memcmp(client_config.arp, arpreply.smac, 6))
|
|
|
|
arp_success(cs);
|
|
|
|
else
|
|
|
|
arp_failed(cs);
|
|
|
|
return;
|
|
|
|
} else {
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Ping noise while waiting for check timeout");
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-05-31 20:44:50 +05:30
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DS_ARP_GW_CHECK:
|
|
|
|
if (!memcmp(arpreply.sip4, &cs->routerAddr, 4)) {
|
|
|
|
// Success only if the router/gw MAC matches stored value
|
|
|
|
if (!memcmp(cs->routerArp, arpreply.smac, 6))
|
|
|
|
arp_gw_success(cs);
|
|
|
|
else
|
|
|
|
arp_gw_failed(cs);
|
|
|
|
return;
|
|
|
|
} else {
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Still waiting for gateway to reply to arp ping");
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-05-31 20:44:50 +05:30
|
|
|
}
|
|
|
|
break;
|
|
|
|
case DS_BOUND:
|
|
|
|
if (!memcmp(arpreply.sip4, &cs->routerAddr, 4)) {
|
|
|
|
memcpy(cs->routerArp, arpreply.smac, 6);
|
2011-03-31 12:02:34 +05:30
|
|
|
arp_close_fd(cs);
|
2011-05-31 20:44:50 +05:30
|
|
|
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Gateway hardware address %02x:%02x:%02x:%02x:%02x:%02x",
|
2011-05-31 20:44:50 +05:30
|
|
|
cs->routerArp[0], cs->routerArp[1],
|
|
|
|
cs->routerArp[2], cs->routerArp[3],
|
|
|
|
cs->routerArp[4], cs->routerArp[5]);
|
2011-03-31 12:02:34 +05:30
|
|
|
return;
|
2011-05-31 20:44:50 +05:30
|
|
|
} else {
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Still looking for gateway hardware address");
|
2011-05-31 20:54:40 +05:30
|
|
|
arpreply_clear();
|
2011-05-31 20:44:50 +05:30
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
arp_close_fd(cs);
|
2011-06-02 20:18:58 +05:30
|
|
|
log_error("handle_arp_response: called in invalid state 0x%02x",
|
|
|
|
cs->dhcpState);
|
2011-05-31 20:44:50 +05:30
|
|
|
return;
|
2011-03-31 12:02:34 +05:30
|
|
|
}
|
|
|
|
if (arp_packet_num >= ARP_RETRY_COUNT) {
|
|
|
|
switch (cs->dhcpState) {
|
|
|
|
case DS_BOUND:
|
2011-06-25 21:12:15 +05:30
|
|
|
if (arpping(cs, cs->routerAddr) == -1)
|
2011-06-02 20:18:58 +05:30
|
|
|
log_warning("arp: Failed to retransmit arp packet for finding gw mac addr");
|
2011-03-31 12:02:34 +05:30
|
|
|
break;
|
|
|
|
default:
|
2011-06-02 20:18:58 +05:30
|
|
|
log_line("arp: Not yet bothering with arp retransmit for non-DS_BOUND state");
|
2011-03-31 12:02:34 +05:30
|
|
|
break;
|
|
|
|
}
|
2010-12-24 20:02:58 +05:30
|
|
|
}
|
|
|
|
}
|