Rebase Cradlepoint diff over v2.90
Run these commands only if remote upstream is not added:
1. git remote add upstream http://thekelleys.org.uk/git/dnsmasq.git
2. git remote -v show
3. git fetch upstream
Following are the commands used for generating the diff
between upstream version 2.85 and origin/cp-main:
1. git diff v2.85 origin/cp-main > ../dnsmasq_v2.85-to-cp_main.gitdiff
2. patch -p1 < ../dnsmasq_v2.85-to-cp_main.gitdiff
3. git add . && git commit -m "Rebase Cradlepoint diff over v2.90"
And then fix all the rejects generated while applying ‘patch -p1 < ../dnsmasq_v2.85-to-cp_main.gitdiff’
EDNS_PKTSZ and SAFE_PKTSZ were already present due to backport of CVE
patch:
Fix up ./man/dnsmasq.8
Fix up ./src/config.h
Fix up ./CHANGELOG
As domain is no longer used in upstream, we removed the check for OPT_EDNS_RESTRICT:
Fix up ./src/forward.c
Fix up ./src/dhcp.c
Fix up ./src/dhcp6.c
Fix up ./src/dns-protocol.h
Fix up ./src/dnsmasq.c
Fix up ./src/dnsmasq.h
Fix up ./src/edns0.c
Fix up ./src/option.c
Fix up ./src/radv.c
Fix up ./src/rfc1035.c
Fix up ./src/util.c
Fix up ./Makefile
Compilation fixes for cache.c
Change-Id: Ibb8d162526168e5963aedb98b6333ded5f054a82
diff --git a/src/opendns.c b/src/opendns.c
new file mode 100644
index 0000000..d0b4348
--- /dev/null
+++ b/src/opendns.c
@@ -0,0 +1,231 @@
+
+#include "dnsmasq.h"
+#include "opendns.h"
+
+const unsigned char *
+opendns_ssid_to_device_id(size_t * const device_id_len_p,
+ const unsigned char * const ssid,
+ const size_t ssid_len)
+{
+ unsigned char *map = daemon->ssid_device_id_map.map;
+ unsigned char *map_tmp;
+ unsigned char *ssid_tmp;
+ unsigned char *device_id_tmp;
+ size_t ssid_tmp_len;
+ size_t device_id_len;
+
+ if (map == NULL || ssid == NULL) {
+ return NULL;
+ }
+ map_tmp = map;
+ while ((ssid_tmp_len = (size_t) *map_tmp) > 0U) {
+ ssid_tmp = ++map_tmp;
+ map_tmp += ssid_tmp_len;
+ device_id_len = (size_t) *map_tmp;
+ device_id_tmp = ++map_tmp;
+ if (ssid_tmp_len == ssid_len &&
+ memcmp(ssid_tmp, ssid, ssid_len) == 0) {
+ *device_id_len_p = device_id_len;
+ return device_id_tmp;
+ }
+ map_tmp += device_id_len;
+ }
+ return NULL;
+}
+
+static int
+opendns_parse_hex_char(unsigned char * const device_id,
+ size_t * const device_id_pos_p, int * const state_p,
+ unsigned char * const val_p, size_t device_id_len_max,
+ const int c)
+{
+ unsigned char c_val;
+
+ switch (*state_p) {
+ case 0:
+ case 1:
+ if (isspace(c) || (c == ':' && *state_p == 0)) {
+ break;
+ }
+ if (c == '#') {
+ *state_p = 2;
+ break;
+ }
+ if (!isxdigit(c)) {
+ return -1;
+ }
+ c_val = (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10;
+ if (*state_p == 0) {
+ *val_p = c_val * 16U;
+ *state_p = 1;
+ } else {
+ *val_p |= c_val;
+ device_id[(*device_id_pos_p)++] = *val_p;
+ if (*device_id_pos_p >= device_id_len_max) {
+ return 0;
+ }
+ *state_p = 0;
+ }
+ break;
+ case 2:
+ if (c == '\n') {
+ *state_p = 0;
+ }
+ }
+ return 1;
+}
+
+size_t
+opendns_parse_hex(const char * const device_id_hex,
+ unsigned char * const device_id,
+ const size_t device_id_len_max)
+{
+ const char *p = device_id_hex;
+ size_t device_id_pos = (size_t) 0U;
+ int c;
+ int ret;
+ int state = 0;
+ unsigned char val = 0U;
+
+ if (device_id_hex == NULL) {
+ return (size_t) 0U;
+ }
+ while ((c = tolower((int) (unsigned char) *p)) != 0) {
+ ret = opendns_parse_hex_char(device_id, &device_id_pos,
+ &state, &val, device_id_len_max, c);
+ if (ret < 0) {
+ return (size_t) 0U;
+ }
+ if (ret == 0) {
+ break;
+ }
+ p++;
+ }
+ return device_id_pos;
+}
+
+char *
+opendns_parse_device_id_opt(char * const arg)
+{
+ struct ssid_device_id_map * const ssid_device_id_map =
+ &daemon->ssid_device_id_map;
+ unsigned char *device_id;
+ unsigned char *tmp_map;
+ char *device_id_hex;
+ char *sep;
+ char *ssid;
+ size_t device_id_hex_len;
+ size_t device_id_len;
+ size_t device_id_len_max;
+ size_t pos;
+ size_t ssid_len;
+ size_t tmp_map_size;
+
+ if ((sep = strrchr(arg, ',')) == NULL ||
+ *(device_id_hex = sep + 1) == 0) {
+ return _("missing device id");
+ }
+ *sep = 0;
+ if (*(ssid = arg) == 0) {
+ return _("missing SSID");
+ }
+ ssid_len = (size_t) (sep - ssid);
+ if (ssid_len > 255U) {
+ return _("SSID too long");
+ }
+ device_id_hex_len = strlen(device_id_hex);
+ device_id_len_max = (device_id_hex_len + 1U) / 2U;
+ device_id = safe_malloc(device_id_len_max);
+ if (device_id_len_max > 255U) {
+ free(device_id);
+ return _("device id too long");
+ }
+ device_id_len = opendns_parse_hex(device_id_hex, device_id,
+ device_id_len_max);
+ if (device_id_len <= 0U) {
+ free(device_id);
+ return _("unable to parse a hex device id");
+ }
+ if (device_id_len > device_id_len_max) {
+ free(device_id);
+ return _("parsed device id too long");
+ }
+ tmp_map_size = ssid_device_id_map->map_size + 1U +
+ ssid_len + 1U + device_id_len;
+ if (ssid_device_id_map->map == NULL) {
+ tmp_map_size++;
+ }
+ if ((tmp_map = realloc(ssid_device_id_map->map,
+ tmp_map_size)) == NULL) {
+ die(_("could not get memory"), NULL, EC_NOMEM);
+ }
+ if (ssid_device_id_map->map_size <= 0U) {
+ pos = 0U;
+ } else {
+ pos = ssid_device_id_map->map_size - 1U;
+ }
+ tmp_map[pos++] = (unsigned char) ssid_len;
+ memcpy(&tmp_map[pos], ssid, ssid_len);
+ pos += ssid_len;
+ tmp_map[pos++] = (unsigned char) device_id_len;
+ memcpy(&tmp_map[pos], device_id, device_id_len);
+ pos += device_id_len;
+ free(device_id);
+ tmp_map[pos] = 0U;
+ ssid_device_id_map->map = tmp_map;
+ ssid_device_id_map->map_size = tmp_map_size;
+
+ return NULL;
+}
+
+int
+opendns_pop_tag_from_query(unsigned char * const packet,
+ size_t * const packet_size_p,
+ unsigned char * * const edns_options,
+ size_t *edns_options_len_p)
+{
+ static unsigned char edns_options_tpl[2U + 2U + 7U + 255U] = {
+ 0U, 4U, 0U, 0U, 'O', 'p', 'e', 'n', 'D', 'N', 'S'
+ };
+ const unsigned char *device_id;
+ const unsigned char *tag;
+ unsigned char *tmp;
+ size_t edns_options_len;
+ size_t device_id_len;
+ size_t packet_size = *packet_size_p;
+ size_t tag_len;
+
+ if (packet_size <= 0U) {
+ *edns_options = NULL;
+ *edns_options_len_p = 0U;
+ return -1;
+ }
+ tag_len = (size_t) packet[packet_size - 1U];
+ if (tag_len >= packet_size) {
+ *edns_options = NULL;
+ *edns_options_len_p = 0U;
+ return -1;
+ }
+ tag = &packet[packet_size - tag_len - 1U];
+ if ((device_id = opendns_ssid_to_device_id(&device_id_len,
+ tag, tag_len)) == NULL) {
+ return -1;
+ }
+ edns_options_len = 2U + 2U + sizeof "OpenDNS" - 1U + device_id_len;
+ if (edns_options_len > sizeof edns_options_tpl) {
+ return -1;
+ }
+ memcpy(edns_options_tpl + 2U + 2U + sizeof "OpenDNS" - 1U,
+ device_id, device_id_len);
+ if (packet_size <= 1U + device_id_len) {
+ return -1;
+ }
+ tmp = edns_options_tpl + 2U;
+ PUTSHORT(sizeof "OpenDNS" - 1U + device_id_len, tmp);
+ *edns_options = edns_options_tpl;
+ *edns_options_len_p = edns_options_len;
+ packet_size -= 1U + tag_len;
+ *packet_size_p = packet_size;
+
+ return 0;
+}