summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiers O'Hanlon <p.ohanlon@gmail.com>2018-01-07 13:38:15 +0000
committerRoy Marples <roy@marples.name>2018-01-07 13:38:15 +0000
commitc8d73eef22dcb4e58360b9b51d388f8d187915f3 (patch)
treef11257b3e7f065323323d10eb7e384bea76f36fd
parent41b5cd4596d3749038a027c14b803751ce0b928a (diff)
downloaddhcpcd-6.11.1-DNA.tar.xz
* Enable Detection of Network Attachment (DNA) functionality (opt: dna <no args> )dhcpcd-6.11.1-DNA
- Enables Base DNA (RFC4436) functionality * Randomised ordering (opt: dna_random <integer> [1: Enable randomised ordering of DNA requests]) - This mechanism provides for randomised delivery of candidate link layer addresses in the DNA reachability tests, so as to enhance the location privacy with respect to the location and time-based analysis of the device's movement patterns. * Dummy addresses (opt: dna_dummy <integer> [0-N: Number of dummy addresses, -1: Automatic choice of number of dummy addresses]) - This mechanism allows for the introduction of dummy addresses into the DNA reachability tests to enhance location privacy, with respect to location identification and time-based analysis of the device's movement patterns. - With the R2 release, we introduce a new option that provides for automated the choice of the number of dummy addresses. * Pre-analysis phase of the address privacy metrics (opt: dna_preanalysis <integer> [1: Enable use of geolocation based pre-filtering of DNA requests]; opt: dna_geourl <string:URL> [URL to be used for geolocation (Google Geolocate json-based API e.g. https://www.googleapis.com/geolocation/v1/geolocate?key=GOOGLE_API_KEY ) - This mechanism allows for the set of existing candidate link layer (MAC) addresses for DNA to be analysed once assigned but before use in DNA to ascertain their privacy metrics with release Release v2. Specifically, we provide for the option to check and filter geolocatable candidate MAC address pairs so that a device can't be easily geolocated from their DNA reachability tests.
-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;