From f807e10e761f59e2750370d47914c89a9ff5ba9e Mon Sep 17 00:00:00 2001 From: "Nicholas J. Kain" Date: Sat, 9 Feb 2013 00:30:19 -0500 Subject: [PATCH] Make the ARP-based lease address collision checks configurable in delay times and number of probes. --- ndhc/arp.c | 17 +++++++++-------- ndhc/arp.h | 4 ++++ ndhc/ndhc.c | 41 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 50 insertions(+), 12 deletions(-) diff --git a/ndhc/arp.c b/ndhc/arp.c index 9a68df2..ce4c690 100644 --- a/ndhc/arp.c +++ b/ndhc/arp.c @@ -1,6 +1,6 @@ /* arp.c - arp ping checking * - * Copyright (c) 2010-2011 Nicholas J. Kain + * Copyright (c) 2010-2013 Nicholas J. Kain * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -53,10 +53,10 @@ #define ARP_RETRANS_DELAY 5000 // ms // From RFC5227 -#define PROBE_WAIT 1000 // initial random delay -#define PROBE_NUM 3 // number of probe packets -#define PROBE_MIN 1000 // minimum delay until repeated probe -#define PROBE_MAX 2000 // maximum delay until repeated probe +int arp_probe_wait = 1000; // initial random delay (ms) +int arp_probe_num = 3; // number of probe packets +int arp_probe_min = 1000; // minimum delay until repeated probe (ms) +int arp_probe_max = 2000; // maximum delay until repeated probe (ms) #define ANNOUNCE_WAIT 2000 // delay before announcing #define ANNOUNCE_NUM 2 // number of Announcement packets #define ANNOUNCE_INTERVAL 2000 // time between Announcement packets @@ -64,6 +64,7 @@ #define RATE_LIMIT_INTERVAL 60000 // delay between successive attempts #define DEFEND_INTERVAL 10000 // minimum interval between defensive ARPs + typedef enum { AS_NONE = 0, // Nothing to react to wrt ARP AS_COLLISION_CHECK, // Checking to see if another host has our IP before @@ -383,7 +384,7 @@ int arp_check(struct client_state_t *cs, struct dhcpmsg *packet) cs->arpPrevState = cs->dhcpState; cs->dhcpState = DS_COLLISION_CHECK; arp_check_start_ts = arp_send_stats[ASEND_COLLISION_CHECK].ts; - probe_wait_time = PROBE_WAIT; + probe_wait_time = arp_probe_wait; arp_wake_ts[AS_COLLISION_CHECK] = arp_check_start_ts + probe_wait_time; return 0; } @@ -561,7 +562,7 @@ static int arp_is_query_reply(struct arpMsg *am) static int arp_gen_probe_wait(void) { // This is not a uniform distribution but it doesn't matter here. - return PROBE_MIN + rand() % (PROBE_MAX - PROBE_MIN); + return arp_probe_min + rand() % (arp_probe_max - arp_probe_min); } static void arp_defense_timeout(struct client_state_t *cs, long long nowts) @@ -626,7 +627,7 @@ static void arp_collision_timeout(struct client_state_t *cs, long long nowts) arp_defense_timeout(cs, nowts); if (nowts >= arp_check_start_ts + ANNOUNCE_WAIT || - arp_send_stats[ASEND_COLLISION_CHECK].count >= PROBE_NUM) { + arp_send_stats[ASEND_COLLISION_CHECK].count >= arp_probe_num) { arp_success(cs); return; } diff --git a/ndhc/arp.h b/ndhc/arp.h index 6cec2f2..7a77641 100644 --- a/ndhc/arp.h +++ b/ndhc/arp.h @@ -53,6 +53,10 @@ struct arpMsg { uint8_t pad[18]; // 2a pad for min. ethernet payload (60 bytes) }; +extern int arp_probe_wait; +extern int arp_probe_num; +extern int arp_probe_min; +extern int arp_probe_max; extern int arp_relentless_def; void arp_reset_send_stats(void); diff --git a/ndhc/ndhc.c b/ndhc/ndhc.c index a1a1e8d..7d274cb 100644 --- a/ndhc/ndhc.c +++ b/ndhc/ndhc.c @@ -1,6 +1,6 @@ /* ndhc.c - DHCP client * - * Copyright (c) 2004-2012 Nicholas J. Kain + * Copyright (c) 2004-2013 Nicholas J. Kain * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -107,6 +107,10 @@ static void show_usage(void) " -C, --chroot=DIR Chroot to this directory\n" " -d, --relentless-defense Never back off in defending IP against\n" " conflicting hosts (servers only)\n" +" -w, --arp-probe-wait Time to delay before first ARP probe\n" +" -W, --arp-probe-num Number of ARP probes before lease is ok\n" +" -m, --arp-probe-min Min ms to wait for ARP response\n" +" -M, --arp-probe-max Max ms to wait for ARP response\n" " -v, --version Display version\n" ); exit(EXIT_SUCCESS); @@ -324,6 +328,10 @@ int main(int argc, char **argv) {"user", required_argument, 0, 'u'}, {"chroot", required_argument, 0, 'C'}, {"relentless-defense", no_argument, 0, 'd'}, + {"arp-probe-wait", required_argument, 0, 'w'}, + {"arp-probe-num", required_argument, 0, 'W'}, + {"arp-probe-min", required_argument, 0, 'm'}, + {"arp-probe-max", required_argument, 0, 'M'}, {"version", no_argument, 0, 'v'}, {"help", no_argument, 0, '?'}, {0, 0, 0, 0} @@ -331,8 +339,8 @@ int main(int argc, char **argv) while (1) { int option_index = 0; - c = getopt_long(argc, argv, "c:fbp:h:i:np:l:qr:V:u:C:dv", arg_options, - &option_index); + c = getopt_long(argc, argv, "c:fbp:h:i:np:l:qr:V:u:C:dw:W:m:M:v", + arg_options, &option_index); if (c == -1) break; switch (c) { @@ -389,9 +397,34 @@ int main(int argc, char **argv) case 'd': arp_relentless_def = 1; break; + case 'w': + case 'W': { + int t = atoi(optarg); + if (t < 0) + break; + if (c == 'w') + arp_probe_wait = t; + else + arp_probe_num = t; + break; + } + case 'm': + case 'M': { + int t = atoi(optarg); + if (c == 'm') + arp_probe_min = t; + else + arp_probe_max = t; + if (arp_probe_min > arp_probe_max) { + t = arp_probe_max; + arp_probe_max = arp_probe_min; + arp_probe_min = t; + } + break; + } case 'v': printf("ndhc %s, dhcp client.\n", NDHC_VERSION); - printf("Copyright (c) 2004-2012 Nicholas J. Kain\n" + printf("Copyright (c) 2004-2013 Nicholas J. Kain\n" "All rights reserved.\n\n" "Redistribution and use in source and binary forms, with or without\n" "modification, are permitted provided that the following conditions are met:\n\n"