https://fingerbank.org/about.html is a database of OS signatures based on the DHCP options populated and the order in which they appear. So for example, an Android device will typically send '1,33,3,6,15,26,28,51,58,59' while iOS sends '1,3,6,15,119,252'.
We modified dnsmasq to export DHCP OS signatures to a DNSMASQ_REQUESTED_OPTIONS environment variable when it forks the dhcp-script. The environment variable is formatted to match fingerbank. The dhcp-script we run writes the signature to a separate file, though of course this behavior is outside of dnsmasq itself. Is OS fingerprinting support something which could be more widely useful? Should I rebase the patch to the current tree and start discussion?
Allows fingerprinting of DHCP clients in the external dhcp-script. --- src/dhcp-protocol.h | 3 ++- src/dnsmasq.h | 1 + src/helper.c | 19 +++++++++++++++++++ src/lease.c | 1 + src/rfc2131.c | 11 +++++++++++ 5 files changed, 34 insertions(+), 1 deletion(-) diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h index a2750de..7e3c845 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 @@ struct dhcp_packet { 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 4d368c5..3beaba7 100644 --- a/src/dnsmasq.h +++ b/src/dnsmasq.h @@ -563,6 +563,7 @@ struct dhcp_lease { } *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 24c2afd..95aa657 100644 --- a/src/helper.c +++ b/src/helper.c @@ -72,6 +72,7 @@ struct script_data #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 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd) 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 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n 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 4b4d10a..e0329da 100644 --- a/src/lease.c +++ b/src/lease.c @@ -703,6 +703,7 @@ static struct dhcp_lease *lease_allocate(void) 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 a49e076..4a35356 100644 --- a/src/rfc2131.c +++ b/src/rfc2131.c @@ -1255,6 +1255,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, 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; @@ -1302,6 +1312,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index, ucp++, len--; lease_add_extradata(lease, ucp, len, 0); } + } #endif } -- 1.9.0.rc1.175.g0b1dcb5
_______________________________________________ Dnsmasq-discuss mailing list Dnsmasq-discuss@lists.thekelleys.org.uk http://lists.thekelleys.org.uk/mailman/listinfo/dnsmasq-discuss