Give up on fingerprinting relay agent/server if it doesn't reply.

Try to send/wait three times; then if there's no response, then
assume that the relay agent is ignoring or firewalled from
receiving ARP requests.
This commit is contained in:
Nicholas J. Kain 2020-10-19 03:07:23 -04:00
parent ba046c02c7
commit 7bd551d564
3 changed files with 29 additions and 8 deletions

View File

@ -49,6 +49,7 @@
#define ARP_MSG_SIZE 0x2a
#define ARP_RETRANS_DELAY 5000 // ms
#define ARP_MAX_TRIES 3
// From RFC5227
int arp_probe_wait = 1000; // initial random delay (ms)
@ -307,7 +308,8 @@ static int arp_get_gw_hwaddr(struct client_state_t cs[static 1])
else
log_line("%s: arp: Searching for dhcp server address...",
client_config.interface);
cs->got_server_arp = false;
cs->server_arp_state = ARP_QUERY;
++cs->server_arp_sent;
if (arp_ping(cs, cs->srcAddr) < 0)
return -1;
if (cs->routerAddr) {
@ -472,9 +474,16 @@ int arp_gw_query_timeout(struct client_state_t cs[static 1], long long nowts)
return ARPR_FAIL;
}
}
if (!cs->got_server_arp) {
if (cs->server_arp_state == ARP_QUERY) {
if (cs->server_arp_sent >= ARP_MAX_TRIES) {
log_line("%s: arp: DHCP agent is ignoring ARPs.",
client_config.interface);
cs->server_arp_state = ARP_FAILED;
return ARPR_OK;
}
log_line("%s: arp: Still looking for DHCP agent hardware address...",
client_config.interface);
++cs->server_arp_sent;
if (arp_ping(cs, cs->srcAddr) < 0) {
log_warning("%s: arp: Failed to send ARP ping in retransmission.",
client_config.interface);
@ -648,7 +657,7 @@ int arp_do_gw_query(struct client_state_t cs[static 1])
cs->got_router_arp = true;
if (cs->routerAddr == cs->srcAddr)
goto server_is_router;
if (cs->got_server_arp) {
if (cs->server_arp_state != ARP_QUERY) {
garp.wake_ts[AS_GW_QUERY] = -1;
if (arp_open_fd(cs, true) < 0)
return ARPR_FAIL;
@ -663,7 +672,7 @@ server_is_router:
client_config.interface, cs->serverArp[0], cs->serverArp[1],
cs->serverArp[2], cs->serverArp[3],
cs->serverArp[4], cs->serverArp[5]);
cs->got_server_arp = true;
cs->server_arp_state = ARP_FOUND;
if (cs->got_router_arp) {
garp.wake_ts[AS_GW_QUERY] = -1;
if (arp_open_fd(cs, true) < 0)

View File

@ -34,18 +34,26 @@
#include <net/if.h>
#include "nk/random.h"
enum arp_state {
ARP_QUERY = 0,
ARP_FOUND,
ARP_FAILED,
};
struct client_state_t {
struct nk_random_state rnd_state;
long long leaseStartTime, renewTime, rebindTime;
long long dhcp_wake_ts;
int ifDeconfig; // Set if the interface has already been deconfigured.
int epollFd, signalFd, listenFd, arpFd, nlFd, rfkillFd;
int server_arp_sent;
uint32_t nlPortId;
unsigned int num_dhcp_requests;
uint32_t clientAddr, serverAddr, srcAddr, routerAddr;
uint32_t lease, xid;
uint8_t routerArp[6], serverArp[6];
bool using_dhcp_bpf, got_router_arp, got_server_arp, arp_is_defense,
enum arp_state server_arp_state;
bool using_dhcp_bpf, got_router_arp, arp_is_defense,
check_fingerprint, program_init;
bool sent_gw_query, sent_first_announce, sent_second_announce,
init_fingerprint_inprogress;

View File

@ -77,8 +77,9 @@ static void reinit_shared_deconfig(struct client_state_t cs[static 1])
{
cs->clientAddr = 0;
cs->num_dhcp_requests = 0;
cs->server_arp_sent = 0;
cs->server_arp_state = ARP_QUERY;
cs->got_router_arp = false;
cs->got_server_arp = false;
cs->check_fingerprint = false;
cs->sent_gw_query = false;
cs->sent_first_announce = false;
@ -417,6 +418,8 @@ static int frenew(struct client_state_t cs[static 1], bool is_bound)
static int ifup_action(struct client_state_t cs[static 1])
{
if (cs->routerAddr && cs->serverAddr) {
if ((cs->routerAddr == cs->serverAddr) && cs->server_arp_state != ARP_FOUND)
goto no_fingerprint;
if (cs->init_fingerprint_inprogress) {
suicide("%s: Carrier lost during initial fingerprint. Forcing restart.",
client_config.interface);
@ -431,6 +434,7 @@ static int ifup_action(struct client_state_t cs[static 1])
return IFUP_FAIL;
}
}
no_fingerprint:
log_line("%s: Interface is back. Searching for new lease...",
client_config.interface);
return IFUP_NEWLEASE;
@ -622,7 +626,7 @@ skip_to_requesting:
scrReturn(ret);
continue;
} else BAD_STATE();
if (!cs->got_router_arp || !cs->got_server_arp) {
if (!cs->got_router_arp || cs->server_arp_state == ARP_QUERY) {
r = arp_do_gw_query(cs);
if (r == ARPR_OK) {
} else if (r == ARPR_FREE) {
@ -657,7 +661,7 @@ skip_to_requesting:
arp_announce_timeout(cs, nowts);
if (!cs->sent_gw_query)
arp_query_gateway_timeout(cs, nowts);
else if (!cs->got_router_arp || !cs->got_server_arp) {
else if (!cs->got_router_arp || cs->server_arp_state == ARP_QUERY) {
int r = arp_gw_query_timeout(cs, nowts);
if (r == ARPR_OK) {
} else if (r == ARPR_FAIL) {