Add requested options to dhcp-script environment.
Allows fingerprinting of DHCP clients in the external
dhcp-script.
Change-Id: I4ed3966249701a311e4d52b71c8b16c0bfab4735
diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
index 4c09614..6d4110f 100644
--- a/src/dhcp-protocol.h
+++ b/src/dhcp-protocol.h
@@ -85,6 +85,7 @@
#define BRDBAND_FORUM_IANA 3561 /* Broadband forum IANA enterprise */
#define DHCP_CHADDR_MAX 16
+#define DHCP_OPT_MAX 312
struct dhcp_packet {
u8 op, htype, hlen, hops;
@@ -92,5 +93,5 @@
u16 secs, flags;
struct in_addr ciaddr, yiaddr, siaddr, giaddr;
u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
- u8 options[312];
+ u8 options[DHCP_OPT_MAX];
};
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index d841fdc..418f815 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -674,6 +674,7 @@
} *slaac_address;
int vendorclass_count;
#endif
+ unsigned char req_options[DHCP_OPT_MAX];
struct dhcp_lease *next;
};
diff --git a/src/helper.c b/src/helper.c
index 4be53c3..636ab58 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -72,6 +72,7 @@
#endif
unsigned char hwaddr[DHCP_CHADDR_MAX];
char interface[IF_NAMESIZE];
+ unsigned char req_options[DHCP_OPT_MAX];
};
static struct script_data *buf = NULL;
@@ -499,6 +500,23 @@
my_setenv("DNSMASQ_DOMAIN", domain, &err);
+ {
+ unsigned char *p;
+ char strbuf[4096] = {0};
+ for (p = data.req_options; *p != OPTION_END; p++)
+ {
+ char d[16];
+ if (p != data.req_options) strcat(strbuf, ",");
+ snprintf(d, sizeof(d), "%u", *p);
+ if ((strlen(strbuf) + strlen(d) + 3) > sizeof(strbuf)) {
+ break;
+ }
+ strcat(strbuf, d);
+ }
+
+ my_setenv("DNSMASQ_REQUESTED_OPTIONS", strbuf, &err);
+ }
+
end = extradata + data.ed_len;
buf = extradata;
@@ -698,6 +716,7 @@
memcpy(buf->hwaddr, lease->hwaddr, DHCP_CHADDR_MAX);
if (!indextoname(fd, lease->last_interface, buf->interface))
buf->interface[0] = 0;
+ memcpy(buf->req_options, lease->req_options, sizeof(buf->req_options));
#ifdef HAVE_BROKEN_RTC
buf->length = lease->length;
diff --git a/src/lease.c b/src/lease.c
index 5d56b1b..41f8a51 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -729,6 +729,7 @@
lease->length = 0xffffffff; /* illegal value */
#endif
lease->hwaddr_len = 256; /* illegal value */
+ lease->req_options[0] = OPTION_END;
lease->next = leases;
leases = lease;
diff --git a/src/rfc2131.c b/src/rfc2131.c
index 5c90408..3c0a165 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -1261,6 +1261,16 @@
if (mess->giaddr.s_addr)
lease->giaddr = mess->giaddr;
+ if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
+ {
+ int len = sizeof(lease->req_options);
+ if (option_len(opt) < len) {
+ len = option_len(opt);
+ }
+ memcpy(lease->req_options, option_ptr(opt, 0), len);
+ lease->req_options[len] = OPTION_END;
+ }
+
free(lease->extradata);
lease->extradata = NULL;
lease->extradata_size = lease->extradata_len = 0;
@@ -1308,6 +1318,7 @@
ucp++, len--;
lease_add_extradata(lease, ucp, len, 0);
}
+
}
#endif
}