summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arp.c75
-rw-r--r--arp.h20
-rw-r--r--common.c7
-rw-r--r--defs.h2
-rw-r--r--dhcp-common.h2
-rw-r--r--dhcp.c859
-rw-r--r--dhcp.h25
-rw-r--r--dhcpcd.conf9
-rw-r--r--eloop.c1
-rw-r--r--if-bsd.c4
-rw-r--r--if-linux.c56
-rw-r--r--if-options.c51
-rw-r--r--if-options.h8
-rw-r--r--if-sun.c4
-rw-r--r--if.h4
-rw-r--r--ipv4.c2
-rw-r--r--ipv4ll.c10
17 files changed, 1030 insertions, 109 deletions
diff --git a/arp.c b/arp.c
index 5b35ccdd..59f04f89 100644
--- a/arp.c
+++ b/arp.c
@@ -56,7 +56,7 @@
(sizeof(struct arphdr) + (2 * sizeof(uint32_t)) + (2 * HWADDR_LEN))
ssize_t
-arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
+arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip, const unsigned char *hwaddr)
{
uint8_t arp_buffer[ARP_LEN];
struct arphdr ar;
@@ -85,13 +85,13 @@ arp_request(const struct interface *ifp, in_addr_t sip, in_addr_t tip)
#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));
+ APPEND(ifp->hwaddr, ifp->hwlen); // Piers: Sender HW address (SHA)
+ APPEND(&sip, sizeof(sip)); // Sender Protocol (IP) address (SPA)
+ ZERO(ifp->hwlen); // Target HW addr (THA) [0: Ignored in Request]
+ APPEND(&tip, sizeof(tip)); // Target Protocol (IP) addr (TPA)
state = ARP_CSTATE(ifp);
- return if_sendraw(ifp, state->fd, ETHERTYPE_ARP, arp_buffer, len);
+ return if_sendraw(ifp, state->fd, ETHERTYPE_ARP, arp_buffer, len, hwaddr);
eexit:
errno = ENOBUFS;
@@ -134,7 +134,7 @@ arp_packet(void *arg)
state = ARP_STATE(ifp);
flags = 0;
- bytes = if_readraw(ifp, state->fd, buf, sizeof(buf), &flags);
+ bytes = if_readraw(ifp, state->fd, buf, sizeof(buf), &flags, NULL);
if (bytes == -1) {
logger(ifp->ctx, LOG_ERR,
"%s: arp if_readrawpacket: %m", ifp->name);
@@ -174,7 +174,7 @@ arp_packet(void *arg)
break;
}
if (ifn) {
-#if 0
+#if 1
logger(ifp->ctx, LOG_DEBUG,
"%s: ignoring ARP from self", ifp->name);
#endif
@@ -188,9 +188,12 @@ arp_packet(void *arg)
/* Run the conflicts */
TAILQ_FOREACH_SAFE(astate, &state->arp_states, next, astaten) {
+ char hwaddr_buf[HWADDR_LEN * 3];
+// logger(ifp->ctx, LOG_DEBUG, "%s: arp_packet() Looping sip: %s SHA: %s ", ifp->name, inet_ntoa(arm.sip), hwaddr_ntoa(hw_s, ar.ar_hln, hwaddr_buf, sizeof(hwaddr_buf)));
if (astate->conflicted_cb)
astate->conflicted_cb(astate, &arm);
}
+// logger(ifp->ctx, LOG_DEBUG, "%s: arp_packet() Looped", ifp->name);
}
int
@@ -241,7 +244,7 @@ arp_announce1(void *arg)
"%s: ARP announcing %s (%d of %d)",
ifp->name, inet_ntoa(astate->addr),
astate->claims, ANNOUNCE_NUM);
- if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr) == -1)
+ if (arp_request(ifp, astate->addr.s_addr, astate->addr.s_addr, NULL) == -1)
logger(ifp->ctx, LOG_ERR, "send_arp: %m");
eloop_timeout_add_sec(ifp->ctx->eloop, ANNOUNCE_WAIT,
astate->claims < ANNOUNCE_NUM ? arp_announce1 : arp_announced,
@@ -266,7 +269,8 @@ arp_probed(void *arg)
{
struct arp_state *astate = arg;
- astate->probed_cb(astate);
+ if (astate->probed_cb)
+ astate->probed_cb(astate);
}
static void
@@ -287,13 +291,24 @@ arp_probe1(void *arg)
tv.tv_nsec = 0;
eloop_timeout_add_tv(ifp->ctx->eloop, &tv, arp_probed, astate);
}
- logger(ifp->ctx, LOG_DEBUG,
- "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
- ifp->name, inet_ntoa(astate->addr),
- astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
- timespec_to_double(&tv));
- if (arp_request(ifp, 0, astate->addr.s_addr) == -1)
- logger(ifp->ctx, LOG_ERR, "send_arp: %m");
+ if (astate->tipaddr.s_addr) {
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: DNA probing %s (%d of %d), next in %0.1f seconds",
+ ifp->name, inet_ntoa(astate->addr),
+ astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
+ timespec_to_double(&tv));
+ if (arp_request(ifp, astate->addr.s_addr, astate->tipaddr.s_addr,
+ astate->hwaddr) == -1)
+ logger(ifp->ctx, LOG_ERR, "send_dna: %m");
+ } else {
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: ARP probing %s (%d of %d), next in %0.1f seconds",
+ ifp->name, inet_ntoa(astate->addr),
+ astate->probes ? astate->probes : PROBE_NUM, PROBE_NUM,
+ timespec_to_double(&tv));
+ if (arp_request(ifp, 0, astate->addr.s_addr, NULL) == -1)
+ logger(ifp->ctx, LOG_ERR, "send_arp: %m");
+ }
}
void
@@ -329,7 +344,7 @@ out:
}
struct arp_state *
-arp_new(struct interface *ifp, const struct in_addr *addr)
+arp_new(struct interface *ifp, const struct in_addr *addr, const unsigned char *hwaddr, const struct in_addr *tipaddr)
{
struct iarp_state *state;
struct arp_state *astate;
@@ -344,7 +359,7 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
state->fd = -1;
TAILQ_INIT(&state->arp_states);
} else {
- if (addr && (astate = arp_find(ifp, addr)))
+ if (addr && (astate = arp_find(ifp, addr)) && !tipaddr)
return astate;
}
@@ -355,6 +370,10 @@ arp_new(struct interface *ifp, const struct in_addr *addr)
astate->iface = ifp;
if (addr)
astate->addr = *addr;
+ if (tipaddr)
+ astate->tipaddr = *tipaddr;
+ if (hwaddr)
+ memcpy(astate->hwaddr, hwaddr, ifp->hwlen);
state = ARP_STATE(ifp);
TAILQ_INSERT_TAIL(&state->arp_states, astate, next);
return astate;
@@ -395,6 +414,24 @@ arp_free(struct arp_state *astate)
}
}
+void
+arp_free_dna_but1(struct interface *ifp, struct bootp *bootp)
+{
+ struct iarp_state *state;
+
+ if ((state = ARP_STATE(ifp)) != NULL) {
+ struct arp_state *p, *n;
+
+ TAILQ_FOREACH_SAFE(p, &state->arp_states, next, n) {
+ if (p->dna_lease)
+ if (p->dna_lease->bootp != bootp && p->tipaddr.s_addr) {
+ free(p->dna_lease->bootp);
+ arp_free(p);
+ }
+ }
+ }
+}
+
static void
arp_free_but1(struct interface *ifp, struct arp_state *astate)
{
diff --git a/arp.h b/arp.h
index b844e498..28a80f42 100644
--- a/arp.h
+++ b/arp.h
@@ -42,13 +42,14 @@
#include "dhcpcd.h"
#include "if.h"
+#include "dhcp.h"
struct arp_msg {
uint16_t op;
- unsigned char sha[HWADDR_LEN];
- struct in_addr sip;
- unsigned char tha[HWADDR_LEN];
- struct in_addr tip;
+ unsigned char sha[HWADDR_LEN]; // Sender HW addr/MAC (SHA)
+ struct in_addr sip; // Sender Protocol (IP) address (SPA)
+ unsigned char tha[HWADDR_LEN]; // Target HW addr (THA) [0: Ignored in Request]
+ struct in_addr tip; // Target Protocol (IP) addr (TPA)
};
struct arp_state {
@@ -61,6 +62,10 @@ struct arp_state {
void (*free_cb)(struct arp_state *);
struct in_addr addr;
+ struct in_addr tipaddr;
+ unsigned char hwaddr[HWADDR_LEN]; //Piers: DNA
+ struct dhcp_lease *dna_lease;
+
int probes;
int claims;
struct in_addr failed;
@@ -78,15 +83,18 @@ struct iarp_state {
((const struct iarp_state *)(ifp)->if_data[IF_DATA_ARP])
#ifdef INET
+struct bootp;
int arp_open(struct interface *);
-ssize_t arp_request(const struct interface *, in_addr_t, in_addr_t);
+ssize_t arp_request(const struct interface *, in_addr_t, in_addr_t, const unsigned char *hwaddr);
void arp_report_conflicted(const struct arp_state *, const struct arp_msg *);
void arp_announce(struct arp_state *);
void arp_probe(struct arp_state *);
-struct arp_state *arp_new(struct interface *, const struct in_addr *);
+void dna_probe(struct arp_state *);
+struct arp_state *arp_new(struct interface *, const struct in_addr *, const unsigned char *, const struct in_addr *);
void arp_cancel(struct arp_state *);
void arp_free(struct arp_state *);
void arp_free_but(struct arp_state *);
+void arp_free_dna_but1(struct interface *, struct bootp *);
struct arp_state *arp_find(struct interface *, const struct in_addr *);
void arp_close(struct interface *);
diff --git a/common.c b/common.c
index 8c6060c6..30965c7d 100644
--- a/common.c
+++ b/common.c
@@ -185,6 +185,13 @@ logger(struct dhcpcd_ctx *ctx, int pri, const char *fmt, ...)
if (ctx && ctx->options & (DHCPCD_DUMPLEASE | DHCPCD_TEST))
goto out;
+ if (pri < LOG_DEBUG || (ctx->options & DHCPCD_DEBUG)) {
+ struct timeval tv;
+ if (gettimeofday(&tv, NULL) != -1) {
+ fprintf(stdout, "%ld.%ld:", tv.tv_sec,tv.tv_usec);
+ }
+ }
+
if (ctx && ctx->log_fd != -1) {
if (pri < LOG_DEBUG || (ctx->options & DHCPCD_DEBUG)) {
struct timeval tv;
diff --git a/defs.h b/defs.h
index 1b207eb8..74f3da49 100644
--- a/defs.h
+++ b/defs.h
@@ -28,7 +28,7 @@
#define CONFIG_H
#define PACKAGE "dhcpcd"
-#define VERSION "6.11.1"
+#define VERSION "6.11.1-DIP-v2.1"
#ifndef CONFIG
# define CONFIG SYSCONFDIR "/" PACKAGE ".conf"
diff --git a/dhcp-common.h b/dhcp-common.h
index 61eccf18..e7d98c1b 100644
--- a/dhcp-common.h
+++ b/dhcp-common.h
@@ -118,6 +118,6 @@ size_t dhcp_envoption(struct dhcpcd_ctx *,
const uint8_t *, size_t, struct dhcp_opt **),
const uint8_t *od, size_t ol);
void dhcp_zero_index(struct dhcp_opt *);
-size_t dhcp_read_lease_fd(int, uint8_t **);
+size_t dhcp_read_lease_fd(int fd, uint8_t **lease);
#endif
diff --git a/dhcp.c b/dhcp.c
index 0fa35d7f..09c923c8 100644
--- a/dhcp.c
+++ b/dhcp.c
@@ -50,6 +50,7 @@
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
+#include <glob.h> //Piers: dna_file
#define ELOOP_QUEUE 2
#include "config.h"
@@ -119,6 +120,9 @@ struct udp_bootp_packet
static int dhcp_open(struct interface *);
static void dhcp_arp_conflicted(struct arp_state *, const struct arp_msg *);
+void dhcp_dna_addresses(struct interface *);
+
+static void dhcp_reboot(struct interface *);
void
dhcp_printoptions(const struct dhcpcd_ctx *ctx,
@@ -1109,18 +1113,544 @@ write_lease(const struct interface *ifp, const struct bootp *bootp, size_t len)
int fd;
ssize_t bytes;
const struct dhcp_state *state = D_CSTATE(ifp);
+ char *dna_fname, *hwaddr_str;
+ const char *file_ext=".lease";
+ const struct dhcp_lease *lease = &state->lease;
+ struct if_options *ifo = ifp->options;
logger(ifp->ctx, LOG_DEBUG, "%s: writing lease `%s'",
ifp->name, state->leasefile);
+ // Piers: Only writes one lease as O_TRUNC sets file len to zero
fd = open(state->leasefile, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd == -1)
return -1;
bytes = write(fd, bootp, len);
close(fd);
+
+ if (ifo->options & DHCPCD_DNA) {
+ dna_fname=malloc(strlen(state->leasefile)+2*(size_t)ifp->hwlen+2);
+ strncpy(dna_fname, state->leasefile,
+ strlen(state->leasefile)-strlen(file_ext));
+ hwaddr_str=&dna_fname[strlen(state->leasefile)-strlen(file_ext)+1];
+ hwaddr_str[-1]='-';
+ for (int i=0; i<ifp->hwlen; i++)
+ sprintf(&hwaddr_str[i*2],"%02x",lease->hwaddr[i]);
+ hwaddr_str[ifp->hwlen*2]='\0';
+ strcat(dna_fname,file_ext);
+
+ logger(ifp->ctx, LOG_DEBUG, "%s: writing DNA lease:'%s'",
+ ifp->name, dna_fname);
+ fd = open(dna_fname, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (fd == -1)
+ return -1;
+ bytes = write(fd, bootp, len);
+ close(fd);
+ free(dna_fname);
+ }
return bytes;
}
+/*int globerr(const char *epath, int eerrno)
+{
+ printf("epath: %s, eerrno: %d\n", epath , eerrno);
+ return 0;
+}*/
+static void
+get_lease(struct interface *, struct dhcp_lease *, const struct bootp *, size_t);
+
+int
+dhcp_dna_dummy_addr(struct interface *ifp, struct dhcp_lease **dna_leases)
+{
+ struct dhcp_state *state = D_STATE(ifp);
+ struct dhcp_lease *lease;
+ uint32_t rand;
+
+ if (ifp->options->dna_dum == -1) {
+ /* Auto mode */
+ ifp->options->dna_dum = state->dna_lease_len/2;
+ }
+ for (int i=0; i< ifp->options->dna_dum; i++) {
+ char buf[HWADDR_LEN * 3];
+
+ if ((*dna_leases = realloc(*dna_leases, sizeof(struct dhcp_lease)*
+ (state->dna_lease_len + 1))) == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: realloc: %m", __func__);
+ return 0;
+ }
+ lease = &(*dna_leases)[state->dna_lease_len];
+
+ *lease = lease[-1];
+ lease->bootp = malloc(lease[-1].bootp_len);
+ memcpy(lease->bootp, lease[-1].bootp, lease[-1].bootp_len);
+ rand = arc4random();
+ lease->hwaddr[3]=(unsigned char)rand;
+ rand>>=8;
+ lease->hwaddr[4]=(unsigned char)rand;
+ rand>>=8;
+ lease->hwaddr[5]=(unsigned char)rand;
+
+ state->dna_lease_len++;
+
+ logger(ifp->ctx, LOG_DEBUG, "%s: Dummy MAC is hwaddr %s",
+ ifp->name, hwaddr_ntoa(lease->hwaddr, ifp->hwlen,
+ buf, sizeof(buf)));
+ }
+}
+
+static size_t
+read_dna_leases(struct interface *ifp, struct dhcp_lease **dna_leases)
+{
+ size_t i;
+ int j, fd;
+ size_t bytes;
+ uint8_t *bootp;
+ struct dhcp_state *state = D_STATE(ifp);
+ glob_t globbuf;
+ char *globstr, *chaddr_str_start;
+ char *mac_glob;
+ const char *mac_byte_glob="[A-Fa-f0-9][A-Fa-f0-9]";
+ const char *file_ext=".lease";
+ struct stat st;
+ struct dhcp_lease lease;
+
+ state->dna_lease_len=0;
+ mac_glob=malloc(ifp->hwlen*sizeof(char)*strlen(mac_byte_glob)+2);
+ if (mac_glob == NULL) {
+ // Note %m results in printing of errno
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return 0;
+ }
+ mac_glob[0]='-';
+ mac_glob[1]='\0';
+ for (i=0; i < ifp->hwlen; i++)
+ strcat(mac_glob,mac_byte_glob);
+
+ globstr=malloc(strlen(state->leasefile)+strlen(mac_glob)+1);
+ if (globstr == NULL) {
+ // Note %m results in printing of errno
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return 0;
+ }
+ strncpy(globstr, state->leasefile, strlen(state->leasefile)-strlen(file_ext));
+ globstr[strlen(state->leasefile)-strlen(file_ext)]='\0';
+ strcat(globstr, mac_glob);
+ strcat(globstr, file_ext);
+ if ((j=glob(globstr, 0, NULL, &globbuf))) {
+ if (j==GLOB_NOMATCH)
+ logger(ifp->ctx, LOG_DEBUG, "%s: No DNA leases found",
+ ifp->name);
+ else
+ logger(ifp->ctx, LOG_DEBUG, "%s: No DNA leases found (Err:%d)",
+ ifp->name, j);
+ free(mac_glob);
+ return 0;
+ }
+ logger(ifp->ctx, LOG_DEBUG, "%s: Number of DNA lease files found: %lu",
+ ifp->name,globbuf.gl_pathc);
+ for (i=0; i < globbuf.gl_pathc; i++) {
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA lease[%ld]: %s",
+ ifp->name, i, globbuf.gl_pathv[i]);
+ fd = open(globbuf.gl_pathv[i], O_RDONLY);
+ if (fd == -1) {
+ logger(ifp->ctx, LOG_DEBUG, "%s: Skipping Bad DNA lease[%lu]: %s",
+ ifp->name, i, globbuf.gl_pathv[i]);
+ continue;
+ }
+ bytes = dhcp_read_lease_fd(fd, &bootp);
+ close(fd);
+ if (bytes == 0) {
+ free(bootp);
+ logger(ifp->ctx, LOG_ERR, "%s: dhcp_read_lease_fd", __func__);
+ continue;
+ }
+
+ /* Ensure the packet is at least BOOTP sized
+ * with a vendor area of 4 octets
+ * (it should be more, and our read packet enforces this so this
+ * code should not be needed, but of course people could
+ * scribble whatever in the stored lease file. */
+ if (bytes < offsetof(struct bootp, vend) + 4) {
+ free(bootp);
+ logger(ifp->ctx, LOG_ERR, "%s: truncated bootp", __func__);
+ continue;
+ }
+
+ get_lease(ifp, &lease, (const struct bootp *)bootp, bytes);
+
+ if (lease.leasetime != ~0U &&
+ stat(globbuf.gl_pathv[i], &st) == 0)
+ {
+ time_t now;
+ uint32_t l;
+
+ /* Offset lease times and check expiry */
+ now = time(NULL);
+ if (now == -1 ||
+ (time_t)lease.leasetime < now - st.st_mtime)
+ {
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: deleting expired DNA lease", ifp->name);
+ unlink(globbuf.gl_pathv[i]);
+ free(bootp);
+ continue;
+ } else {
+ l = (uint32_t)(now - st.st_mtime);
+ lease.leasetime -= l;
+ lease.renewaltime -= l;
+ lease.rebindtime -= l;
+ }
+ }
+
+ if (*dna_leases == NULL) {
+ if ((*dna_leases = malloc(sizeof(struct dhcp_lease))) == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return 0;
+ }
+ } else {
+ if ((*dna_leases = realloc(*dna_leases, sizeof(struct
+ dhcp_lease)*(state->dna_lease_len+1))) == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: realloc: %m", __func__);
+ return 0;
+ }
+ }
+ (*dna_leases)[state->dna_lease_len]=lease;
+ chaddr_str_start=globbuf.gl_pathv[i]+strlen(globbuf.gl_pathv[i])-ifp->hwlen*2-strlen(file_ext);
+ (*dna_leases)[state->dna_lease_len].bootp_len = bytes;
+ char c[3];
+ c[2]='\0';
+ for (j=0; j<ifp->hwlen*2; j+=2) {
+ c[0]=chaddr_str_start[j];
+ c[1]=chaddr_str_start[j+1];
+ (*dna_leases)[state->dna_lease_len].hwaddr[j/2] =
+ (uint8_t)strtol(c, NULL, 16);
+ //logger(ifp->ctx, LOG_DEBUG, "%s: Converted DNA lease[%d]: %s: %d", ifp->name,i, c, (uint8_t)strtol(c, NULL, 16));
+ }
+ (*dna_leases)[state->dna_lease_len++].bootp = (struct bootp *)bootp;
+ }
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA valid leases: %lu", ifp->name,
+ state->dna_lease_len);
+ if (state->dna_lease_len && ifp->options->dna_dum)
+ dhcp_dna_dummy_addr(ifp, dna_leases);
+ free(mac_glob);
+ globfree(&globbuf);
+ free(globstr);
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA active leases: %lu", ifp->name,
+ state->dna_lease_len);
+ return state->dna_lease_len;
+}
+
+/* in[] ---> Input Array
+ istart & iend ---> Staring and Ending indexes in in[]
+ combotmp[] ---> Temporary array to store current combination
+ cindex ---> Current index in combo[]
+ r ---> Requested Number of elements per combination
+ out Output array of combinations
+ out_num Number elements in output array */
+void combinationUtil(int in[], int combotmp[], int istart, int iend,
+ int cindex, int r, int **out, int *out_num)
+{
+ // Current combination is ready to be stored
+ if (cindex == r)
+ {
+ if (*out==NULL)
+ *out=malloc(sizeof(int)*r);
+ else
+ *out=realloc(*out, (*out_num+1)*sizeof(int)*r);
+ if (out == NULL) {
+ // Note %m results in printing of errno
+ //logger(ifp->ctx, LOG_ERR, "%s: {m/re}alloc: %m", __func__);
+ return;
+ }
+ for (int j=0; j<r; j++) {
+ (*out)[*out_num*r+j]=combotmp[j];
+ printf("%d ", combotmp[j]);
+ }
+ printf("\n");
+ (*out_num)++;
+ return;
+ }
+
+ // replace cindex with all possible elements. The condition
+ // "iend-i+1 >= r-cindex" makes sure that including one element
+ // at cindex will make a combination with remaining elements
+ // at remaining positions
+ for (int i=istart; i<=iend && iend-i+1 >= r-cindex; i++)
+ {
+ combotmp[cindex] = in[i];
+ combinationUtil(in, combotmp, i+1, iend, cindex+1, r, out, out_num);
+ }
+}
+
+#include <curl/curl.h>
+#include <string.h>
+
+struct MemoryStruct {
+ char *memory;
+ size_t size;
+};
+
+static size_t
+WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
+{
+ size_t realsize = size * nmemb;
+ struct MemoryStruct *mem = (struct MemoryStruct *)userp;
+
+ mem->memory = realloc(mem->memory, mem->size + realsize + 1);
+ if(mem->memory == NULL) {
+ /* out of memory! */
+ printf("not enough memory (realloc returned NULL)\n");
+ return 0;
+ }
+
+ memcpy(&(mem->memory[mem->size]), contents, realsize);
+ mem->size += realsize;
+ mem->memory[mem->size] = 0;
+
+ return realsize;
+}
+
+int query_geo_macs(struct interface *ifp, int combonum, int *combomap, char **dna_macs, int *geolocated) {
+ CURL *curlhandle;
+ CURLcode res;
+ struct MemoryStruct chunk;
+ char* jsonObj = "{\"considerIp\": \"false\",\"wifiAccessPoints\": [\
+ { \"macAddress\": \"%s\"},{ \"macAddress\": \"%s\"}]}";
+ char dynObj[strlen(jsonObj)+2*(5*2+5)];
+ struct curl_slist *headers = NULL;
+ int i, numlocated=0;
+
+ chunk.memory = malloc(1); /* will be grown as needed by the realloc above */
+ if (chunk.memory == NULL) {
+ //logger(ifp->ctx, LOG_ERR, "%s: realloc: %m", __func__);
+ printf("%s: realloc: %m", __func__);
+ return -1;
+ }
+
+ curl_global_init(CURL_GLOBAL_ALL);
+ curlhandle = curl_easy_init();
+ if (curlhandle == NULL) {
+ return -1;
+ }
+ /* send all data to this function */
+ curl_easy_setopt(curlhandle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
+
+ /* we pass our 'chunk' struct to the callback function */
+ curl_easy_setopt(curlhandle, CURLOPT_WRITEDATA, (void *)&chunk);
+
+ headers = curl_slist_append(headers, "Accept: application/json");
+ headers = curl_slist_append(headers, "Content-Type: application/json");
+ headers = curl_slist_append(headers, "charsets: utf-8");
+
+ curl_easy_setopt(curlhandle, CURLOPT_URL, ifp->options->dna_gurl);
+
+ curl_easy_setopt(curlhandle, CURLOPT_CUSTOMREQUEST, "POST");
+ curl_easy_setopt(curlhandle, CURLOPT_HTTPHEADER, headers);
+ curl_easy_setopt(curlhandle, CURLOPT_POSTFIELDS, dynObj);
+ curl_easy_setopt(curlhandle, CURLOPT_USERAGENT, "libcurl/1.1");
+
+ printf("GEO Checking %d leases with geolocation provider: %s\n",combonum, ifp->options->dna_gurl);
+ for (i=0; i<combonum; i++) {
+
+ sprintf(dynObj, jsonObj, dna_macs[combomap[i*2]], dna_macs[combomap[i*2+1]]);
+
+ printf("MAC Check #%d:%s\n",i, dynObj);
+
+ chunk.size = 0; /* set the data chunk size to zero */
+ res = curl_easy_perform(curlhandle);
+
+ /* check for errors */
+ if (res != CURLE_OK) {
+ fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
+ } else {
+ printf("Curl recieved %lu bytes:\n", (long)chunk.size);
+ printf("%s\n", chunk.memory);
+ if (!strcasestr(chunk.memory,"error")) {
+ geolocated[numlocated++]=i;
+ }
+ }
+ }
+ free(chunk.memory);
+ curl_easy_cleanup(curlhandle);
+ curl_global_cleanup();
+ return numlocated;
+}
+
+void check_dna_geo(struct interface *ifp)
+{
+ //size_t i;
+ int i, j, fd;
+ size_t bytes;
+ uint8_t *bootp;
+ struct dhcp_state *state = D_STATE(ifp);
+ glob_t globbuf;
+ char *globstr, *chaddr_str_start;
+ char *mac_glob;
+ const char *mac_byte_glob="[A-Fa-f0-9][A-Fa-f0-9]";
+ const char *file_ext=".lease";
+ struct stat st;
+ int dna_mac_len, k;
+ char **dna_macs;
+
+ mac_glob=malloc(ifp->hwlen*sizeof(char)*strlen(mac_byte_glob)+2);
+ if (mac_glob == NULL) {
+ // Note %m results in printing of errno
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return;
+ }
+ mac_glob[0]='-';
+ mac_glob[1]='\0';
+ for (i=0; i < ifp->hwlen; i++)
+ strcat(mac_glob,mac_byte_glob);
+
+ globstr=malloc(strlen(state->leasefile)+strlen(mac_glob)+1);
+ if (globstr == NULL) {
+ // Note %m results in printing of errno
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return;
+ }
+ strncpy(globstr, state->leasefile, strlen(state->leasefile)-strlen(file_ext));
+ globstr[strlen(state->leasefile)-strlen(file_ext)]='\0';
+ strcat(globstr, mac_glob);
+ strcat(globstr, file_ext);
+ //printf("DNA Globstr:'%s (strlen:%lu, sizeof:%lu')\n",globstr, strlen(globstr), sizeof(globstr));
+ if ((j=glob(globstr, GLOB_NOSORT, NULL, &globbuf))) {
+ if (j==GLOB_NOMATCH)
+ logger(ifp->ctx, LOG_DEBUG, "%s: No DNA leases found",
+ ifp->name);
+ else
+ logger(ifp->ctx, LOG_DEBUG, "%s: No DNA leases found (Err:%d)",
+ ifp->name, j);
+ free(mac_glob);
+ return;
+ }
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA leases: %lu",
+ ifp->name, globbuf.gl_pathc);
+
+ unsigned long remaining = globbuf.gl_pathc;
+
+ dna_mac_len = ifp->hwlen*2+6;
+ if ((dna_macs = malloc(globbuf.gl_pathc*sizeof(char*))) == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return;
+ }
+ if ((dna_macs[0] = malloc(globbuf.gl_pathc*dna_mac_len*sizeof(char))) == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: malloc: %m", __func__);
+ return;
+ }
+ // Explicitly set pointer values http://www.c-faq.com/aryptr/dynmuldimary.html
+ for (i=1; i< globbuf.gl_pathc; i++)
+ dna_macs[i]=dna_macs[0]+i*dna_mac_len;
+
+ // Extract DNA MACs
+ for (i=0; i < globbuf.gl_pathc; i++) {
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA lease[%d]: %s",
+ ifp->name, i, globbuf.gl_pathv[i]);
+
+ chaddr_str_start=globbuf.gl_pathv[i]+strlen(globbuf.gl_pathv[i])-ifp->hwlen*2-strlen(file_ext);
+ k=0;
+ for (j=0; j<ifp->hwlen*2; j+=2) {
+ memcpy(dna_macs[i]+k,&chaddr_str_start[j],2);
+ dna_macs[i][k+2]=':';
+ k+=3;
+ }
+ dna_macs[i][k-1]='\0';
+ logger(ifp->ctx, LOG_DEBUG, "%s: Extracted DNA lease[%d]: %s", ifp->name,i, dna_macs[i]);
+ }
+
+ if (globbuf.gl_pathc > 1) {
+ int tmp[2], c, matches=0;
+ int combonum=0;
+ int *combomap=NULL;
+ int *in=NULL;
+ int numlocated;
+
+ in = malloc(sizeof(int)*globbuf.gl_pathc);
+ // Set in array to containing an index of the existing MACs
+ for (i=0; i < globbuf.gl_pathc; i++)
+ in[i]=i;
+
+ printf("Generating Combos*******************\n");
+
+ // Recursively generate all combinations
+ combinationUtil(in, tmp, 0, globbuf.gl_pathc-1, 0, 2, &combomap, &combonum);
+ int dna_mac_rm[combonum];
+ int *geolocated = malloc(combonum*sizeof(int)); /* will be grown as needed by the realloc above */
+ if (geolocated == NULL) {
+ //logger(ifp->ctx, LOG_ERR, "%s: realloc: %m", __func__);
+ printf("%s: realloc: %m", __func__);
+ return;
+ }
+ printf("Querying Combos*******************\n");
+ numlocated = query_geo_macs(ifp, combonum, combomap, dna_macs, geolocated);
+ printf("Matched Combos:%d\n", numlocated);
+
+ // reset in array for count mutually matching MACs
+ for (i=0; i < globbuf.gl_pathc; i++)
+ in[i]=0;
+ // Find any mutual matching MACs
+ for (i=0; i < numlocated; i++) {
+ for (j=i+1; j < numlocated; j++) {
+ if ((c=combomap[geolocated[i]*2]) ==
+ combomap[geolocated[j]*2])
+ in[c]++;
+ if (c==combomap[geolocated[j]*2+1])
+ in[c]++;
+ if ((c=combomap[geolocated[i]*2+1]) ==
+ combomap[geolocated[j]*2])
+ in[c]++;
+ if (c==combomap[geolocated[j]*2+1])
+ in[c]++;
+ }
+ }
+ for (i=0; i < globbuf.gl_pathc; i++) {
+ printf("Checking Mutual Matching MACs[%d]:%d\n", i, in[i]);
+ if (in[i]) {
+ matches++;
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: deleting GEOmatched Mutual DNA lease:[%d] %s", ifp->name, i, globbuf.gl_pathv[i]);
+ unlink(globbuf.gl_pathv[i]);
+ remaining--;
+ }
+ }
+ printf("Total seperate Mutual Matching MACs:%d\n", matches);
+ int already_mutual_matched=0;
+ for (i=0; i < globbuf.gl_pathc; i++) {
+ for (j=0; j< numlocated; j++) {
+ if (in[i]) {
+ if (i == combomap[geolocated[j]*2])
+ already_mutual_matched++;
+ if (i == combomap[geolocated[j]*2+1])
+ already_mutual_matched++;
+ }
+ }
+ }
+ if (already_mutual_matched != numlocated) {
+ for (i=0; i< numlocated; i++) {
+ // Random choice as to which lease is deleted: one needs to go..
+ if (arc4random() > 0x3FFFFFFF) {
+ c=combomap[geolocated[i]*2];
+ unlink(globbuf.gl_pathv[c]);
+ remaining--;
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: deleting GEOmatched DNA lease:[%d] %s", ifp->name, c,globbuf.gl_pathv[c]);
+ } else {
+ c=combomap[geolocated[i]*2+1];
+ unlink(globbuf.gl_pathv[c]);
+ remaining--;
+ logger(ifp->ctx, LOG_DEBUG,
+ "%s: deleting GEOmatched DNA lease:[%d] %s", ifp->name, c,globbuf.gl_pathv[c]);
+ }
+ }
+ }
+ }
+ free(mac_glob);
+ globfree(&globbuf);
+ free(globstr);
+ logger(ifp->ctx, LOG_DEBUG, "%s: Remaining DNA active leases - after GEOmatch test: %lu", ifp->name, remaining);
+}
+
+
static size_t
read_lease(struct interface *ifp, struct bootp **bootp)
{
@@ -1753,7 +2283,7 @@ send_message(struct interface *ifp, uint8_t type,
logger(ifp->ctx, LOG_ERR, "dhcp_makeudppacket: %m");
} else {
r = if_sendraw(ifp, state->raw_fd,
- ETHERTYPE_IP, (uint8_t *)udp, ulen);
+ ETHERTYPE_IP, (uint8_t *)udp, ulen, NULL);
free(udp);
}
/* If we failed to send a raw packet this normally means
@@ -1870,7 +2400,7 @@ dhcp_leaseextend(struct interface *ifp)
if (ifp->options->options & DHCPCD_ARP) {
struct arp_state *astate;
- if ((astate = arp_new(ifp, NULL)) == NULL)
+ if ((astate = arp_new(ifp, NULL, NULL, NULL)) == NULL)
return -1;
if (arp_open(ifp) == -1)
@@ -1979,19 +2509,25 @@ dhcp_arp_probed(struct arp_state *astate)
{
struct dhcp_state *state;
struct if_options *ifo;
+ struct interface *ifp;
+
+ ifp = astate->iface;
state = D_STATE(astate->iface);
ifo = astate->iface->options;
- if (state->arping_index < ifo->arping_len) {
+ if (state->arping_index != -1 &&
+ state->arping_index < ifo->arping_len) {
/* We didn't find a profile for this
* address or hwaddr, so move to the next
* arping profile */
if (++state->arping_index < ifo->arping_len) {
astate->addr.s_addr =
- ifo->arping[state->arping_index - 1];
+ ifo->arping[state->arping_index];
arp_probe(astate);
+ return;
}
- dhcpcd_startinterface(astate->iface);
+ arp_free(astate);
+ dhcpcd_startinterface(ifp);
return;
}
@@ -2032,6 +2568,84 @@ dhcp_arp_probed(struct arp_state *astate)
}
static void
+dhcp_dna_probed(struct arp_state *astate)
+{
+ logger(astate->iface->ctx, LOG_DEBUG, "%s: DNA timed out for %s",
+ astate->iface->name, inet_ntoa(astate->addr));
+ arp_free(astate);
+}
+
+
+static void
+dhcp_dna_response(struct arp_state *astate, const struct arp_msg *amsg)
+{
+ struct interface *ifp;
+ struct dhcp_state *state;
+ char *sip_str=strdup(inet_ntoa(amsg->sip));
+
+ ifp = astate->iface;
+ state = D_STATE(ifp);
+
+ if (!memcmp(amsg->sha, astate->hwaddr, ifp->hwlen)) {
+ logger(astate->iface->ctx, LOG_DEBUG,
+ "%s: DNA MATCHING response received for astate:%s, Sender IP:%s",
+ astate->iface->name, inet_ntoa(astate->addr), sip_str);
+ if (state->state == DHS_INIT || state->state == DHS_DISCOVER) {
+ struct ipv4_addr *ia;
+ state->offer= astate->dna_lease->bootp;
+ state->offer_len = astate->dna_lease->bootp_len;
+ state->dna_matched_lease = astate->dna_lease->bootp;
+ state->lease = *astate->dna_lease;
+ state->lease.frominfo = 1;
+ if (state->new == NULL &&
+ (ia = ipv4_iffindaddr(ifp,
+ &state->lease.addr, &state->lease.mask)) != NULL)
+ {
+ /* We still have the IP address from the
+ * last lease. Fake add the address and
+ * routes from it so the lease
+ * can be cleaned up. */
+ state->new = malloc(state->offer_len);
+ if (state->new) {
+ memcpy(state->new,
+ state->offer, state->offer_len);
+ state->new_len = state->offer_len;
+ state->addr = ia;
+ state->added |= STATE_ADDED | STATE_FAKE;
+ ipv4_buildroutes(ifp->ctx);
+ } else
+ logger(ifp->ctx, LOG_ERR, "%s: %m",
+ __func__);
+ }
+ logger(astate->iface->ctx, LOG_DEBUG,
+ "%s: DNA initiated reboot Sender IP:%s",
+ astate->iface->name, sip_str);
+ dhcp_reboot(ifp);
+ } else {
+ logger(astate->iface->ctx, LOG_DEBUG,
+ "%s: DNA reboot NOT initiated as state is:%d",
+ astate->iface->name, state->state);
+ }
+ arp_free(astate);
+ free(sip_str);
+ return;
+ } else {
+ logger(astate->iface->ctx, LOG_DEBUG,
+ "%s: DNA Non-Matching response received for astate:%s, Sender IP:%s",
+ astate->iface->name, inet_ntoa(astate->addr), sip_str);
+ if (state->state == DHS_BOUND) {
+ logger(astate->iface->ctx, LOG_DEBUG,
+ "%s: DHCP Bound so DNA terminated for astate:%s, Sender IP:%s",
+ astate->iface->name, inet_ntoa(astate->addr), sip_str);
+ arp_free_dna_but1(astate->iface, NULL);
+ free(state->dna_leases);
+ state->dna_leases=NULL;
+ }
+ }
+ free(sip_str);
+}
+
+static void
dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
{
struct interface *ifp;
@@ -2041,17 +2655,18 @@ dhcp_arp_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
ifp = astate->iface;
ifo = ifp->options;
state = D_STATE(ifp);
- if (state->arping_index &&
- state->arping_index <= ifo->arping_len &&
+ /* Piers: This if is only entered if any ARPING entries are configured */
+ if (state->arping_index != -1 &&
+ state->arping_index < ifo->arping_len &&
amsg &&
- (amsg->sip.s_addr == ifo->arping[state->arping_index - 1] ||
+ (amsg->sip.s_addr == ifo->arping[state->arping_index] ||
(amsg->sip.s_addr == 0 &&
- amsg->tip.s_addr == ifo->arping[state->arping_index - 1])))
+ amsg->tip.s_addr == ifo->arping[state->arping_index])))
{
char buf[HWADDR_LEN * 3];
- astate->failed.s_addr = ifo->arping[state->arping_index - 1];
- arp_report_conflicted(astate, amsg);
+ astate->failed.s_addr = ifo->arping[state->arping_index];
+ arp_report_conflicted(astate, amsg); //Just log it
hwaddr_ntoa(amsg->sha, ifp->hwlen, buf, sizeof(buf));
if (dhcpcd_selectprofile(ifp, buf) == -1 &&
dhcpcd_selectprofile(ifp,
@@ -2231,13 +2846,15 @@ dhcp_bind(struct interface *ifp)
ifp->name, lease->renewaltime, lease->rebindtime);
}
state->state = DHS_BOUND;
- if (!state->lease.frominfo &&
- !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
+ if ( !state->lease.frominfo &&
+ !(ifo->options & (DHCPCD_INFORM | DHCPCD_STATIC)))
if (write_lease(ifp, state->new, state->new_len) == -1)
logger(ifp->ctx, LOG_ERR,
"%s: write_lease: %m", __func__);
ipv4_applyaddr(ifp);
+ if (ifp->options->dna_pran)
+ check_dna_geo(ifp);
}
static void
@@ -2292,6 +2909,72 @@ dhcp_message_new(struct bootp **bootp,
return sizeof(**bootp);
}
+#define O_RANDOM 1
+
+void dhcp_dna_order(size_t *map, size_t maplen, int order);
+
+void
+dhcp_dna_order(size_t *map, size_t maplen, int order)
+{
+ size_t i, r, t;
+
+ for (i=0; i < maplen; i++)
+ map[i]=i;
+
+ if (order == O_RANDOM) {
+ /* Randomise order using Fisher–Yates Durstenfeld shuffle */
+ for (i=maplen-1; i>0; i--) {
+ r = (size_t)arc4random_uniform(i);
+ t = map[i];
+ map[i]= map[r];
+ map[r]= t;
+ }
+ // printf("DNA Random map[%lu]:",maplen);
+ } else {
+ // printf("DNA NON-Random map[%lu]:",maplen);
+ }
+/* for (i=0; i < maplen; i++)
+ printf("%lu, ",map[i]);
+ printf("\n");*/
+}
+
+void
+dhcp_dna_addresses(struct interface *ifp)
+{
+ size_t i, *map;
+ struct dhcp_lease dlease;
+ struct in_addr saddr, yaddr;
+ struct arp_state *astate;
+ struct dhcp_state *state = D_STATE(ifp);
+
+ if (!state->dna_lease_len) return;
+
+ //eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
+
+ map=malloc(state->dna_lease_len*sizeof(size_t));
+ if (map == NULL) {
+ logger(ifp->ctx, LOG_ERR, "%s: %m", __func__);
+ return;
+ }
+ dhcp_dna_order(map, state->dna_lease_len, ifp->options->dna_ord);
+
+ for (i=0; i < state->dna_lease_len; i++) {
+ dlease = state->dna_leases[map[i]];
+ saddr.s_addr = dlease.bootp->siaddr;
+ yaddr.s_addr = dlease.bootp->yiaddr;
+ astate = arp_new(ifp, &yaddr, dlease.hwaddr, &saddr);
+ if (astate) {
+ // probed_cb is called after no response
+ astate->probed_cb = dhcp_dna_probed;
+ // 'conflicted_cb' called when response is received
+ astate->conflicted_cb = dhcp_dna_response;
+ astate->dna_lease = &state->dna_leases[map[i]];
+ arp_probe(astate);
+ }
+ }
+ free(map);
+}
+
static int
dhcp_arp_address(struct interface *ifp)
{
@@ -2308,11 +2991,38 @@ dhcp_arp_address(struct interface *ifp)
state->offer->ciaddr : state->offer->yiaddr;
/* If the interface already has the address configured
* then we can't ARP for duplicate detection. */
- ia = ipv4_findaddr(ifp->ctx, &addr);
+ ia = ipv4_findaddr(ifp->ctx, &addr);
+
+ if (ifp->options->options & DHCPCD_DNA) {
+ if (state->dna_lease_len) {
+ arp_close(ifp);
+ if (state->dna_matched_lease != NULL) {
+ if (state->dna_matched_lease->yiaddr ==
+ state->offer->yiaddr ) {
+ state->dna_matched_lease = NULL;
+ logger(ifp->ctx, LOG_INFO,
+ "%s: Skip DAD as DNA address Match:%s",
+ ifp->name, inet_ntoa(addr));
+ state->dna_lease_len=0;
+ arp_free_dna_but1(ifp, state->dna_matched_lease);
+ free(state->dna_leases);
+ state->dna_leases=NULL;
+ return 1;
+ }
+ } else {
+ logger(ifp->ctx, LOG_INFO,
+ "%s: DNA cancelled as no address match", ifp->name);
+ }
+ arp_free_dna_but1(ifp, NULL);
+ free(state->dna_leases);
+ state->dna_leases=NULL;
+ state->dna_lease_len=0;
+ }
+ }
#ifdef IN_IFF_TENTATIVE
if (ia == NULL || ia->addr_flags & IN_IFF_NOTUSEABLE) {
- if ((astate = arp_new(ifp, &addr)) != NULL) {
+ if ((astate = arp_new(ifp, &addr, NULL, NULL)) != NULL) {
astate->probed_cb = dhcp_arp_probed;
astate->conflicted_cb = dhcp_arp_conflicted;
}
@@ -2334,7 +3044,7 @@ dhcp_arp_address(struct interface *ifp)
get_lease(ifp, &l, state->offer, state->offer_len);
logger(ifp->ctx, LOG_INFO, "%s: probing address %s/%d",
ifp->name, inet_ntoa(l.addr), inet_ntocidr(l.mask));
- if ((astate = arp_new(ifp, &addr)) != NULL) {
+ if ((astate = arp_new(ifp, &addr, NULL, NULL)) != NULL) {
astate->probed_cb = dhcp_arp_probed;
astate->conflicted_cb = dhcp_arp_conflicted;
/* We need to handle DAD. */
@@ -2499,7 +3209,8 @@ dhcp_reboot(struct interface *ifp)
logger(ifp->ctx, LOG_INFO, "%s: rebinding lease of %s",
ifp->name, inet_ntoa(state->lease.addr));
- state->xid = dhcp_xid(ifp);
+ if (!state->xid)
+ state->xid = dhcp_xid(ifp);
state->lease.server.s_addr = 0;
eloop_timeout_delete(ifp->ctx->eloop, NULL, ifp);
@@ -2536,6 +3247,9 @@ dhcp_drop(struct interface *ifp, const char *reason)
return;
}
+#ifdef ARPING
+ state->arping_index = -1;
+#endif
if (ifp->options->options & DHCPCD_RELEASE &&
!(ifp->options->options & DHCPCD_INFORM))
{
@@ -2679,7 +3393,7 @@ log_dhcp(int lvl, const char *msg,
static void
dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
- const struct in_addr *from)
+ const struct in_addr *from, const unsigned char *hwaddr)
{
struct dhcp_state *state = D_STATE(ifp);
struct if_options *ifo = ifp->options;
@@ -2725,7 +3439,7 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
type = 0;
else if (ifo->options & DHCPCD_BOOTP) {
logger(ifp->ctx, LOG_DEBUG,
- "%s: ignoring DHCP reply (excpecting BOOTP)",
+ "%s: ignoring DHCP reply (expecting BOOTP)",
ifp->name);
return;
}
@@ -2757,6 +3471,8 @@ dhcp_handledhcp(struct interface *ifp, struct bootp *bootp, size_t bootp_len,
}
LOGDHCP0(LOG_WARNING, "no authentication");
}
+ // Piers; Copy DHCP server hwaddr into lease
+ memcpy(lease->hwaddr, hwaddr, ifp->hwlen);
/* RFC 3203 */
if (type == DHCP_FORCERENEW) {
@@ -3133,11 +3849,12 @@ dhcp_handlepacket(void *arg)
struct in_addr from;
int i, flags;
const struct dhcp_state *state = D_CSTATE(ifp);
+ unsigned char hwaddr[ETH_ALEN];
/* Need this API due to BPF */
flags = 0;
bootp = NULL;
- bytes = (size_t)if_readraw(ifp, state->raw_fd,buf, sizeof(buf), &flags);
+ bytes = (size_t)if_readraw(ifp, state->raw_fd, buf, sizeof(buf), &flags, hwaddr);
if ((ssize_t)bytes == -1) {
logger(ifp->ctx, LOG_ERR,
"%s: dhcp if_readrawpacket: %m", ifp->name);
@@ -3189,7 +3906,7 @@ dhcp_handlepacket(void *arg)
while (bytes < offsetof(struct bootp, vend) + 4)
bootp[bytes++] = '\0';
- dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from);
+ dhcp_handledhcp(ifp, (struct bootp *)bootp, bytes, &from, hwaddr);
}
static void
@@ -3315,6 +4032,9 @@ dhcp_init(struct interface *ifp)
return -1;
/* 0 is a valid fd, so init to -1 */
state->raw_fd = -1;
+#ifdef ARPING
+ state->arping_index = -1;
+#endif
/* Now is a good time to find IPv4 routes */
if_initrt(ifp->ctx);
@@ -3392,45 +4112,11 @@ dhcp_start1(void *arg)
uint32_t l;
int nolease;
- if (!(ifo->options & DHCPCD_IPV4))
- return;
-
- /* Listen on *.*.*.*:bootpc so that the kernel never sends an
- * ICMP port unreachable message back to the DHCP server */
- if (ifp->ctx->udp_fd == -1) {
- ifp->ctx->udp_fd = dhcp_openudp(NULL);
- if (ifp->ctx->udp_fd == -1) {
- /* Don't log an error if some other process
- * is handling this. */
- if (errno != EADDRINUSE)
- logger(ifp->ctx, LOG_ERR,
- "%s: dhcp_openudp: %m", __func__);
- } else
- eloop_event_add(ifp->ctx->eloop,
- ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx);
- }
-
- if (dhcp_init(ifp) == -1) {
- logger(ifp->ctx, LOG_ERR, "%s: dhcp_init: %m", ifp->name);
- return;
- }
-
state = D_STATE(ifp);
clock_gettime(CLOCK_MONOTONIC, &state->started);
free(state->offer);
state->offer = NULL;
- if (state->arping_index < ifo->arping_len) {
- struct arp_state *astate;
-
- astate = arp_new(ifp, NULL);
- if (astate) {
- astate->probed_cb = dhcp_arp_probed;
- astate->conflicted_cb = dhcp_arp_conflicted;
- dhcp_arp_probed(astate);
- }
- return;
- }
if (ifo->options & DHCPCD_STATIC) {
dhcp_static(ifp);
@@ -3478,9 +4164,11 @@ dhcp_start1(void *arg)
}
}
}
+
if (state->offer) {
struct ipv4_addr *ia;
+ //Piers: Copy lease from file (state->offer) to state->lease
get_lease(ifp, &state->lease, state->offer, state->offer_len);
state->lease.frominfo = 1;
if (state->new == NULL &&
@@ -3554,7 +4242,8 @@ dhcp_start1(void *arg)
}
if (state->offer == NULL || !IS_DHCP(state->offer))
- dhcp_discover(ifp);
+ //eloop_timeout_add_tv(ifp->ctx->eloop, &tv, callback, dhcp_discover,ifp);
+ dhcp_discover(ifp);
else
dhcp_reboot(ifp);
}
@@ -3563,6 +4252,7 @@ void
dhcp_start(struct interface *ifp)
{
struct timespec tv;
+ struct dhcp_state *state;
if (!(ifp->options->options & DHCPCD_IPV4))
return;
@@ -3606,6 +4296,56 @@ dhcp_start(struct interface *ifp)
return;
}
+ if (!(ifp->options->options & DHCPCD_IPV4))
+ return;
+
+ /* Listen on *.*.*.*:bootpc so that the kernel never sends an
+ * ICMP port unreachable message back to the DHCP server */
+ if (ifp->ctx->udp_fd == -1) {
+ ifp->ctx->udp_fd = dhcp_openudp(NULL);
+ if (ifp->ctx->udp_fd == -1) {
+ /* Don't log an error if some other process
+ * is handling this. */
+ if (errno != EADDRINUSE)
+ logger(ifp->ctx, LOG_ERR,
+ "%s: dhcp_openudp: %m", __func__);
+ } else
+ eloop_event_add(ifp->ctx->eloop,
+ ifp->ctx->udp_fd, dhcp_handleudp, ifp->ctx);
+ }
+
+ if (dhcp_init(ifp) == -1) {
+ logger(ifp->ctx, LOG_ERR, "%s: dhcp_init: %m", ifp->name);
+ return;
+ }
+
+ state = D_STATE(ifp);
+ free(state->offer);
+ state->offer = NULL;
+
+ if (state->arping_index != -1 &&
+ state->arping_index < ifp->options->arping_len) {
+ struct arp_state *astate;
+
+ astate = arp_new(ifp, NULL, NULL, NULL);
+ if (astate) {
+ astate->probed_cb = dhcp_arp_probed;
+ astate->conflicted_cb = dhcp_arp_conflicted;
+ dhcp_arp_probed(astate);
+ }
+ return;
+ }
+
+ /* Initiate DNA */
+ //logger(ifp->ctx, LOG_DEBUG, "%s: DNA Check", ifp->name);
+ if (ifp->options->options & DHCPCD_DNA) {
+ logger(ifp->ctx, LOG_DEBUG, "%s: DNA Option Present", ifp->name);
+ state->dna_lease_len = read_dna_leases(ifp, &state->dna_leases);
+ if (state->dna_leases) {
+ dhcp_dna_addresses(ifp);
+ }
+ }
+
tv.tv_sec = DHCP_MIN_DELAY;
tv.tv_nsec = (suseconds_t)arc4random_uniform(
(DHCP_MAX_DELAY - DHCP_MIN_DELAY) * NSEC_PER_SEC);
@@ -3620,6 +4360,13 @@ dhcp_start(struct interface *ifp)
void
dhcp_abort(struct interface *ifp)
{
+#ifdef ARPING
+ struct dhcp_state *state;
+
+ state = D_STATE(ifp);
+ if (state != NULL)
+ state->arping_index = -1;
+#endif
eloop_timeout_delete(ifp->ctx->eloop, dhcp_start1, ifp);
}
diff --git a/dhcp.h b/dhcp.h
index f573735f..01f36b80 100644
--- a/dhcp.h
+++ b/dhcp.h
@@ -97,7 +97,7 @@ enum DHO {
DHO_LEASETIME = 51,
DHO_OPTSOVERLOADED = 52,
DHO_MESSAGETYPE = 53,
- DHO_SERVERID = 54,
+ DHO_SERVERID = 54, /* RFC 2132: Piers */
DHO_PARAMETERREQUESTLIST = 55,
DHO_MESSAGE = 56,
DHO_MAXMESSAGESIZE = 57,
@@ -160,8 +160,8 @@ struct bootp {
uint16_t flags; /* such as broadcast flag */
uint32_t ciaddr; /* (previously allocated) client IP */
uint32_t yiaddr; /* 'your' client IP address */
- uint32_t siaddr; /* should be zero in client's messages */
- uint32_t giaddr; /* should be zero in client's messages */
+ uint32_t siaddr; /* Server IP(should be zero in client's messages)*/
+ uint32_t giaddr; /* Relay IP (should be zero in client's messages)*/
uint8_t chaddr[BOOTP_CHADDR_LEN]; /* client's hardware address */
uint8_t sname[BOOTP_SNAME_LEN]; /* server host name */
uint8_t file[BOOTP_FILE_LEN]; /* boot file name */
@@ -179,6 +179,9 @@ struct dhcp_lease {
struct in_addr server;
uint8_t frominfo;
uint32_t cookie;
+ unsigned char hwaddr[HWADDR_LEN]; //Piers MAC addr of DHCP server
+ struct bootp *bootp;
+ size_t bootp_len;
};
enum DHS {
@@ -195,6 +198,12 @@ enum DHS {
DHS_RELEASE
};
+/*struct dna_lease {
+ struct bootp *lease;
+ size_t lease_len;
+ unsigned char shaddr[HWADDR_LEN]; * +Piers:server's hardware address */
+//};
+
struct dhcp_state {
enum DHS state;
struct bootp *sent;
@@ -212,15 +221,20 @@ struct dhcp_state {
uint32_t xid;
int socket;
+ /*Piers: DNA Leases */
+ struct dhcp_lease *dna_leases;
+ size_t dna_lease_len;
+ struct bootp *dna_matched_lease;
+
int raw_fd;
struct ipv4_addr *addr;
uint8_t added;
- char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4)];
+ char leasefile[sizeof(LEASEFILE) + IF_NAMESIZE + (IF_SSIDLEN * 4) + BOOTP_CHADDR_LEN];
struct timespec started;
unsigned char *clientid;
struct authstate auth;
- size_t arping_index;
+ ssize_t arping_index;
};
#define D_STATE(ifp) \
@@ -230,6 +244,7 @@ struct dhcp_state {
#define D_STATE_RUNNING(ifp) \
(D_CSTATE((ifp)) && D_CSTATE((ifp))->new && D_CSTATE((ifp))->reason)
+/* Check for the DHCP 'magic cookie' */
#define IS_DHCP(b) ((b)->vend[0] == 0x63 && \
(b)->vend[1] == 0x82 && \
(b)->vend[2] == 0x53 && \
diff --git a/dhcpcd.conf b/dhcpcd.conf
index aeba3567..2692c54e 100644
--- a/dhcpcd.conf
+++ b/dhcpcd.conf
@@ -36,3 +36,12 @@ require dhcp_server_identifier
# Generate Stable Private IPv6 Addresses instead of hardware based ones
slaac private
+
+# Enable DNA functionality
+dna
+
+# Enable DNA Privacy: Random Address type 1
+dna_random 1
+
+# Enable DNA Privacy: Dummy Address type 1
+dna_dummy 1
diff --git a/eloop.c b/eloop.c
index c72f0c5b..ae9d5009 100644
--- a/eloop.c
+++ b/eloop.c
@@ -575,6 +575,7 @@ eloop_q_timeout_delete(struct eloop *eloop, int queue,
assert(eloop != NULL);
+ //Piers: Delete timeout if it matches OR is called with NULL
TAILQ_FOREACH_SAFE(t, &eloop->timeouts, next, tt) {
if ((queue == 0 || t->queue == queue) &&
t->arg == arg &&
diff --git a/if-bsd.c b/if-bsd.c
index 1628a121..ec1d53ef 100644
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -474,7 +474,7 @@ eexit:
ssize_t
if_sendraw(__unused const struct interface *ifp, int fd, uint16_t protocol,
- const void *data, size_t len)
+ const void *data, size_t len, const unsigned char *hwaddr)
{
struct iovec iov[2];
struct ether_header hw;
@@ -492,7 +492,7 @@ if_sendraw(__unused const struct interface *ifp, int fd, uint16_t protocol,
/* BPF requires that we read the entire buffer.
* So we pass the buffer in the API so we can loop on >1 packet. */
ssize_t
-if_readraw(struct interface *ifp, int fd, void *data, size_t len, int *flags)
+if_readraw(struct interface *ifp, int fd, void *data, size_t len, int *flags, unsigned char *hwaddr)
{
struct bpf_hdr packet;
ssize_t bytes;
diff --git a/if-linux.c b/if-linux.c
index 4bb800bc..5cd07de4 100644
--- a/if-linux.c
+++ b/if-linux.c
@@ -86,7 +86,7 @@ int if_getssid_wext(const char *ifname, uint8_t *ssid);
#define bpf_insn sock_filter
#define BPF_SKIPTYPE
-#define BPF_ETHCOOK -ETH_HLEN
+//#define BPF_ETHCOOK -ETH_HLEN
#define BPF_WHOLEPACKET 0x0fffffff /* work around buggy LPF filters */
#include "bpf-filter.h"
@@ -1235,12 +1235,13 @@ if_openraw(struct interface *ifp, uint16_t protocol)
struct sockaddr_storage ss;
} su;
struct sock_fprog pf;
+
#ifdef PACKET_AUXDATA
int n;
#endif
#define SF SOCK_CLOEXEC | SOCK_NONBLOCK
- if ((s = xsocket(PF_PACKET, SOCK_DGRAM | SF, htons(protocol))) == -1)
+ if ((s = xsocket(PF_PACKET, SOCK_RAW | SF , htons(protocol))) == -1)
return -1;
#undef SF
@@ -1278,13 +1279,26 @@ eexit:
ssize_t
if_sendraw(const struct interface *ifp, int fd, uint16_t protocol,
- const void *data, size_t len)
+ const void *data, size_t len, const unsigned char *hwaddr)
{
union sockunion {
struct sockaddr sa;
struct sockaddr_ll sll;
struct sockaddr_storage ss;
} su;
+ struct ether_header ehdr;
+ struct iovec iov[2] = {{
+ .iov_base = &ehdr,
+ .iov_len = sizeof(ehdr),
+ },{
+ .iov_base = (void*)data,
+ .iov_len = len,
+ }};
+ struct msghdr msg = {
+ .msg_iov = iov,
+ .msg_iovlen = 2,
+ };
+
memset(&su, 0, sizeof(su));
su.sll.sll_family = AF_PACKET;
@@ -1298,26 +1312,39 @@ if_sendraw(const struct interface *ifp, int fd, uint16_t protocol,
* Ugly as sin, but it works. */
/* coverity[buffer_size] */
/* coverity[overrun-buffer-arg] */
+ //Piers: Set dest_addr as broadcast address
memcpy(&su.sll.sll_addr,
&ipv4_bcast_addr, sizeof(ipv4_bcast_addr));
} else
+ if (!hwaddr) // TODO: Handle IPoIB
memset(&su.sll.sll_addr, 0xff, ifp->hwlen);
+ else
+ memcpy(&su.sll.sll_addr, hwaddr, ifp->hwlen);
- return sendto(fd, data, len, 0, &su.sa, sizeof(su.sll));
+ memcpy(&ehdr.ether_dhost, &su.sll.sll_addr, ifp->hwlen);
+ memcpy(&ehdr.ether_shost, ifp->hwaddr, ifp->hwlen);
+ ehdr.ether_type=htons(protocol);
+ return sendmsg(fd, &msg, 0);
}
ssize_t
if_readraw(__unused struct interface *ifp, int fd,
- void *data, size_t len, int *flags)
+ void *data, size_t len, int *flags, unsigned char *hwaddr)
{
- struct iovec iov = {
+ struct ether_header ehdr;
+ struct iovec iov[2] = {{
+ .iov_base = &ehdr,
+ .iov_len = sizeof(ehdr),
+ },{
.iov_base = data,
.iov_len = len,
- };
+ }};
struct msghdr msg = {
- .msg_iov = &iov,
- .msg_iovlen = 1,
+ .msg_iov = iov,
+ .msg_iovlen = 2,
};
+
+
#ifdef PACKET_AUXDATA
unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
struct cmsghdr *cmsg;
@@ -1350,6 +1377,17 @@ if_readraw(__unused struct interface *ifp, int fd,
}
#endif
}
+
+/* printf("bytes recv:%lu; ether_dhost",bytes);
+ for (int i=0; i<ETH_ALEN; i++)
+ printf(":%02x",ehdr.ether_dhost[i]);
+ printf(", ether_shost");
+ for (int i=0; i<ETH_ALEN; i++)
+ printf(":%02x",ehdr.ether_shost[i]);
+ printf("\n");*/
+
+ if (hwaddr)
+ memcpy(hwaddr, ehdr.ether_shost, ETH_ALEN);
return bytes;
}
diff --git a/if-options.c b/if-options.c
index 3334d413..91380377 100644
--- a/if-options.c
+++ b/if-options.c
@@ -101,6 +101,11 @@
#define O_NODELAY O_BASE + 44
#define O_INFORM6 O_BASE + 45
#define O_LASTLEASE_EXTEND O_BASE + 46
+#define O_DNA O_BASE + 47
+#define O_DNA_ORD O_BASE + 48
+#define O_DNA_DUM O_BASE + 49
+#define O_DNA_PRAN O_BASE + 50
+#define O_DNA_GURL O_BASE + 51
const struct option cf_options[] = {
{"background", no_argument, NULL, 'b'},
@@ -200,6 +205,11 @@ const struct option cf_options[] = {
{"nodelay", no_argument, NULL, O_NODELAY},
{"noup", no_argument, NULL, O_NOUP},
{"lastleaseextend", no_argument, NULL, O_LASTLEASE_EXTEND},
+ {"dna", no_argument, NULL, O_DNA},
+ {"dna_random", required_argument, NULL, O_DNA_ORD},
+ {"dna_dummy", required_argument, NULL, O_DNA_DUM},
+ {"dna_preanalysis", required_argument, NULL, O_DNA_PRAN},
+ {"dna_geourl", required_argument, NULL, O_DNA_GURL},
{NULL, 0, NULL, '\0'}
};
@@ -933,7 +943,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
if (ifname == NULL)
ctx->ifav = splitv(ctx, &ctx->ifac, ctx->ifav, arg);
break;
- case 'A':
+ case 'A': /* noarp */
ifo->options &= ~DHCPCD_ARP;
/* IPv4LL requires ARP */
ifo->options &= ~DHCPCD_IPV4LL;
@@ -1252,7 +1262,7 @@ parse_option(struct dhcpcd_ctx *ctx, const char *ifname, struct if_options *ifo,
if (parse_addr(ctx, &addr, NULL, arg) != 0)
return -1;
naddr = realloc(ifo->arping,
- sizeof(in_addr_t) * (ifo->arping_len + 1));
+ sizeof(in_addr_t) * ((size_t)ifo->arping_len + 1));
if (naddr == NULL) {
logger(ctx, LOG_ERR, "%s: %m", __func__);
return -1;
@@ -2133,6 +2143,42 @@ err_sla:
case O_LASTLEASE_EXTEND:
ifo->options |= DHCPCD_LASTLEASE | DHCPCD_LASTLEASE_EXTEND;
break;
+ case O_DNA:
+ ifo->options |= DHCPCD_DNA;
+ break;
+ case O_DNA_ORD:
+ ARG_REQUIRED;
+ ifo->dna_ord = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
+ if (e) {
+ logger(ctx, LOG_ERR, "failed to convert DNA order %s", arg);
+ return -1;
+ }
+ break;
+ case O_DNA_DUM:
+ ARG_REQUIRED;
+ ifo->dna_dum = (int)strtoi(arg, NULL, 0, -1, INT32_MAX, &e);
+ if (e) {
+ logger(ctx, LOG_ERR, "failed to convert DNA dummy %s", arg);
+ return -1;
+ }
+ break;
+ case O_DNA_PRAN:
+ ARG_REQUIRED;
+ ifo->dna_pran = (int)strtoi(arg, NULL, 0, 0, INT32_MAX, &e);
+ if (e) {
+ logger(ctx, LOG_ERR, "failed to convert DNA preanalysis %s", arg);
+ return -1;
+ }
+ break;
+ case O_DNA_GURL:
+ ARG_REQUIRED;
+ ifo->dna_gurl = (char*)malloc(strlen(arg)*sizeof(char));
+ if (ifo->dna_gurl == NULL) {
+ logger(ctx, LOG_ERR, "%s: Failed Malloc for GeoURL %m", __func__);
+ return -1;
+ }
+ strcpy(ifo->dna_gurl, arg);
+ break;
default:
return 0;
}
@@ -2420,6 +2466,7 @@ read_config(struct dhcpcd_ctx *ctx,
/* Parse our options file */
fp = fopen(ctx->cffile, "r");
+ logger(ctx, LOG_DEBUG, "Using Config file: %s", ctx->cffile);
if (fp == NULL) {
if (strcmp(ctx->cffile, CONFIG))
logger(ctx, LOG_ERR, "fopen `%s': %m", ctx->cffile);
diff --git a/if-options.h b/if-options.h
index a0be326a..b4214718 100644
--- a/if-options.h
+++ b/if-options.h
@@ -115,6 +115,7 @@
#define DHCPCD_INITIAL_DELAY (1ULL << 58)
#define DHCPCD_PRINT_PIDFILE (1ULL << 59)
#define DHCPCD_ONESHOT (1ULL << 60)
+#define DHCPCD_DNA (1ULL << 61)
#define DHCPCD_NODROP (DHCPCD_EXITING | DHCPCD_PERSISTENT)
@@ -195,7 +196,7 @@ struct if_options {
in_addr_t *blacklist;
size_t whitelist_len;
in_addr_t *whitelist;
- size_t arping_len;
+ ssize_t arping_len;
in_addr_t *arping;
char *fallback;
@@ -215,6 +216,11 @@ struct if_options {
size_t vivso_override_len;
struct auth auth;
+
+ int dna_ord;
+ int dna_dum;
+ int dna_pran;
+ char* dna_gurl;
};
struct if_options *default_config(struct dhcpcd_ctx *);
diff --git a/if-sun.c b/if-sun.c
index e701a8e6..00bceed9 100644
--- a/if-sun.c
+++ b/if-sun.c
@@ -957,7 +957,7 @@ failed1:
ssize_t
if_sendraw(const struct interface *cifp, int fd, __unused uint16_t protocol,
- const void *data, size_t len)
+ const void *data, size_t len, const unsigned char *hwaddr)
{
struct dl_if *di;
int r;
@@ -971,7 +971,7 @@ if_sendraw(const struct interface *cifp, int fd, __unused uint16_t protocol,
ssize_t
if_readraw(struct interface *ifp, int fd,
- void *data, size_t len, int *flags)
+ void *data, size_t len, int *flags, unsigned char *hwaddr)
{
struct dl_if *di;
int r;
diff --git a/if.h b/if.h
index 79d04ed6..d8011e3b 100644
--- a/if.h
+++ b/if.h
@@ -142,8 +142,8 @@ int if_handlelink(struct dhcpcd_ctx *);
extern const char *if_pfname;
int if_openraw(struct interface *, uint16_t);
ssize_t if_sendraw(const struct interface *, int, uint16_t,
- const void *, size_t);
-ssize_t if_readraw(struct interface *, int, void *, size_t, int *);
+ const void *, size_t, const unsigned char *);
+ssize_t if_readraw(struct interface *, int, void *, size_t, int *, unsigned char *);
void if_closeraw(struct interface *, int);
int if_address(unsigned char, const struct ipv4_addr *);
diff --git a/ipv4.c b/ipv4.c
index 12945b34..13993ed6 100644
--- a/ipv4.c
+++ b/ipv4.c
@@ -1195,7 +1195,7 @@ ipv4_applyaddr(void *arg)
if (ifo->options & DHCPCD_ARP) {
struct arp_state *astate;
- if ((astate = arp_new(ifp, &state->addr->addr)) != NULL)
+ if ((astate = arp_new(ifp, &state->addr->addr, NULL, NULL)) != NULL)
arp_announce(astate);
}
if (state->state == DHS_BOUND) {
diff --git a/ipv4ll.c b/ipv4ll.c
index 0a82f4a4..4e55bfe3 100644
--- a/ipv4ll.c
+++ b/ipv4ll.c
@@ -244,6 +244,12 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
ifp = astate->iface;
state = IPV4LL_STATE(ifp);
assert(state != NULL);
+ if (state->addr == NULL) {
+ logger(ifp->ctx, LOG_WARNING,
+ "%s: IPv4LL %d No addr configured",
+ ifp->name, DEFEND_INTERVAL);
+ return;
+ }
assert(state->addr != NULL);
fail = 0;
@@ -283,7 +289,7 @@ ipv4ll_conflicted(struct arp_state *astate, const struct arp_msg *amsg)
"%s: IPv4LL %d second defence failed for %s",
ifp->name, DEFEND_INTERVAL, state->addr->saddr);
else if (arp_request(ifp,
- state->addr->addr.s_addr, state->addr->addr.s_addr) == -1)
+ state->addr->addr.s_addr, state->addr->addr.s_addr, NULL) == -1)
logger(ifp->ctx, LOG_ERR,
"%s: arp_request: %m", __func__);
else {
@@ -369,7 +375,7 @@ ipv4ll_start(void *arg)
setstate(ifp->ctx->randomstate);
}
- if ((astate = arp_new(ifp, NULL)) == NULL)
+ if ((astate = arp_new(ifp, NULL, NULL, NULL)) == NULL)
return;
state->arp = astate;