diff options
author | Dave Barach <dave@barachs.net> | 2017-11-16 10:01:12 -0500 |
---|---|---|
committer | Florin Coras <florin.coras@gmail.com> | 2017-11-16 16:56:17 +0000 |
commit | 52925385345e2222151b6e8c28e3d914ff0b407f (patch) | |
tree | 991e5f2fb3636289d45634a45c9952830b3a2cb6 | |
parent | f11cbc4fc0a8b0dcfb02732999f6d9427138b709 (diff) |
Deal with double name-pointer chases
Change-Id: I153b07b4348133535b16b6bf55527d19a6b927c6
Signed-off-by: Dave Barach <dave@barachs.net>
-rw-r--r-- | src/vnet/dns/dns.c | 215 |
1 files changed, 167 insertions, 48 deletions
diff --git a/src/vnet/dns/dns.c b/src/vnet/dns/dns.c index d361aa11b3b..cf76439ac8e 100644 --- a/src/vnet/dns/dns.c +++ b/src/vnet/dns/dns.c @@ -1075,10 +1075,11 @@ vnet_dns_response_to_reply (u8 * response, dns_rr_t *rr; int i, limit; u8 len; - u8 *curpos, *pos; + u8 *curpos, *pos, *pos2; u16 flags; u16 rcode; u32 ttl; + int pointer_chase; h = (dns_header_t *) response; flags = clib_net_to_host_u16 (h->flags); @@ -1134,29 +1135,42 @@ vnet_dns_response_to_reply (u8 * response, for (i = 0; i < limit; i++) { - pos = curpos; + pos = pos2 = curpos; + pointer_chase = 0; /* Expect pointer chases in the answer section... */ - if ((pos[0] & 0xC0) == 0xC0) - curpos += 2; - else + if ((pos2[0] & 0xC0) == 0xC0) { - len = *pos++; - while (len) + pos = pos2 + 2; + pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1]; + pointer_chase = 1; + } + + len = *pos2++; + + while (len) + { + pos2 += len; + if ((pos2[0] & 0xc0) == 0xc0) { - if ((pos[0] & 0xC0) == 0xC0) - { - curpos = pos + 2; - goto curpos_set; - } - pos += len; - len = *pos++; + /* + * If we've already done one pointer chase, + * do not move the pos pointer. + */ + if (pointer_chase == 0) + pos = pos2 + 2; + pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1]; + len = *pos2++; + pointer_chase = 1; } - curpos = pos; + else + len = *pos2++; } - curpos_set: - rr = (dns_rr_t *) curpos; + if (pointer_chase == 0) + pos = pos2; + + rr = (dns_rr_t *) pos; switch (clib_net_to_host_u16 (rr->type)) { @@ -1176,13 +1190,15 @@ vnet_dns_response_to_reply (u8 * response, *min_ttlp = ttl; rmp->ip6_set = 1; break; + default: break; } /* Might as well stop ASAP */ if (rmp->ip4_set && rmp->ip6_set) break; - curpos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength); + pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength); + curpos = pos; } if ((rmp->ip4_set + rmp->ip6_set) == 0) @@ -1200,13 +1216,14 @@ vnet_dns_response_to_name (u8 * response, dns_rr_t *rr; int i, limit; u8 len; - u8 *curpos, *pos; + u8 *curpos, *pos, *pos2; u16 flags; u16 rcode; u8 *name; u32 ttl; u8 *junk __attribute__ ((unused)); int name_set = 0; + int pointer_chase; h = (dns_header_t *) response; flags = clib_net_to_host_u16 (h->flags); @@ -1262,29 +1279,42 @@ vnet_dns_response_to_name (u8 * response, for (i = 0; i < limit; i++) { - pos = curpos; + pos = pos2 = curpos; + pointer_chase = 0; /* Expect pointer chases in the answer section... */ - if ((pos[0] & 0xC0) == 0xC0) - curpos += 2; - else + if ((pos2[0] & 0xC0) == 0xC0) { - len = *pos++; - while (len) + pos = pos2 + 2; + pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1]; + pointer_chase = 1; + } + + len = *pos2++; + + while (len) + { + pos2 += len; + if ((pos2[0] & 0xc0) == 0xc0) { - if ((pos[0] & 0xC0) == 0xC0) - { - curpos = pos + 2; - goto curpos_set; - } - pos += len; - len = *pos++; + /* + * If we've already done one pointer chase, + * do not move the pos pointer. + */ + if (pointer_chase == 0) + pos = pos2 + 2; + pos2 = response + ((pos2[0] & 0x3f) << 8) + pos2[1]; + len = *pos2++; + pointer_chase = 1; } - curpos = pos; + else + len = *pos2++; } - curpos_set: - rr = (dns_rr_t *) curpos; + if (pointer_chase == 0) + pos = pos2; + + rr = (dns_rr_t *) pos; switch (clib_net_to_host_u16 (rr->type)) { @@ -1292,7 +1322,7 @@ vnet_dns_response_to_name (u8 * response, name = vnet_dns_labels_to_name (rr->rdata, response, &junk); memcpy (rmp->name, name, vec_len (name)); ttl = clib_net_to_host_u32 (rr->ttl); - if (*min_ttlp) + if (min_ttlp) *min_ttlp = ttl; rmp->name[vec_len (name)] = 0; name_set = 1; @@ -1303,7 +1333,8 @@ vnet_dns_response_to_name (u8 * response, /* Might as well stop ASAP */ if (name_set == 1) break; - curpos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength); + pos += sizeof (*rr) + clib_net_to_host_u16 (rr->rdlength); + curpos = pos; } if (name_set == 0) @@ -1700,7 +1731,7 @@ format_dns_reply_data (u8 * s, va_list * args) u8 *pos, *pos2; dns_rr_t *rr; int i; - int initial_pointer_chase = 0; + int pointer_chase = 0; u16 *tp; u16 rrtype_host_byte_order; @@ -1710,11 +1741,11 @@ format_dns_reply_data (u8 * s, va_list * args) s = format (s, " "); /* chase pointer? almost always yes here... */ - if (pos2[0] == 0xc0) + if ((pos2[0] & 0xc0) == 0xc0) { - pos2 = reply + pos2[1]; - pos += 2; - initial_pointer_chase = 1; + pos = pos2 + 2; + pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1]; + pointer_chase = 1; } len = *pos2++; @@ -1727,7 +1758,20 @@ format_dns_reply_data (u8 * s, va_list * args) vec_add1 (s, *pos2); pos2++; } - len = *pos2++; + if ((pos2[0] & 0xc0) == 0xc0) + { + /* + * If we've already done one pointer chase, + * do not move the pos pointer. + */ + if (pointer_chase == 0) + pos = pos2 + 2; + pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1]; + len = *pos2++; + pointer_chase = 1; + } + else + len = *pos2++; if (len) { if (verbose > 1) @@ -1740,7 +1784,7 @@ format_dns_reply_data (u8 * s, va_list * args) } } - if (initial_pointer_chase == 0) + if (pointer_chase == 0) pos = pos2; rr = (dns_rr_t *) pos; @@ -1826,8 +1870,11 @@ format_dns_reply_data (u8 * s, va_list * args) pos2 = rr->rdata; /* chase pointer? */ - if (pos2[0] == 0xc0) - pos2 = reply + pos2[1]; + if ((pos2[0] & 0xc0) == 0xc0) + { + pos = pos2 + 2; + pos2 = reply + ((pos2[0] & 0x3f) << 8) + pos2[1]; + } len = *pos2++; @@ -2270,7 +2317,7 @@ VLIB_CLI_COMMAND (dns_cache_add_del_command) = }; /* *INDENT-ON* */ -#define DNS_FORMAT_TEST 1 +#define DNS_FORMAT_TEST 0 #if DNS_FORMAT_TEST > 0 #if 0 @@ -2334,8 +2381,80 @@ static u8 dns_reply_data_initializer[] = { 0x03, 0x63, 0x6f, 0x6d, 0x06, 0x61, 0x6b, 0x61, 0x64, 0x6e, 0x73, 0x03, 0x6e, 0x65, 0x74, 0x00, }; -#else + +/* bind8 (linux widget, w/ nasty double pointer chasees */ +static u8 dns_reply_data_initializer[] = { + /* 0 */ + 0x00, 0x01, 0x81, 0x80, 0x00, 0x01, 0x00, 0x08, + /* 8 */ + 0x00, 0x06, 0x00, 0x06, 0x0a, 0x6f, 0x72, 0x69, + /* 16 */ + 0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77, 0x77, 0x05, + /* 24 */ + 0x63, 0x69, 0x73, 0x63, 0x6f, 0x03, 0x63, 0x6f, + /* 32 */ + 0x6d, 0x00, 0x00, 0xff, 0x00, 0x01, 0x0a, 0x6f, + /* 40 */ + 0x72, 0x69, 0x67, 0x69, 0x6e, 0x2d, 0x77, 0x77, + /* 48 */ + 0x77, 0x05, 0x43, 0x49, 0x53, 0x43, 0x4f, 0xc0, + + /* 56 */ + 0x1d, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, + + /* 64 */ + 0x9a, 0x00, 0x18, 0x15, 0x72, 0x63, 0x64, + 0x6e, 0x39, 0x2d, 0x31, 0x34, 0x70, 0x2d, 0x64, 0x63, + 0x7a, 0x30, 0x35, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, + 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x05, 0x9a, 0x00, 0x1a, 0x17, 0x61, 0x6c, 0x6c, + 0x6e, 0x30, 0x31, 0x2d, 0x61, 0x67, 0x30, 0x39, 0x2d, + 0x64, 0x63, 0x7a, 0x30, 0x33, 0x6e, 0x2d, 0x67, 0x73, + 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, 0x00, + 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x10, 0x0d, 0x72, + 0x74, 0x70, 0x35, 0x2d, 0x64, 0x6d, 0x7a, 0x2d, 0x67, + 0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x18, 0x15, + 0x6d, 0x74, 0x76, 0x35, 0x2d, 0x61, 0x70, 0x31, 0x30, + 0x2d, 0x64, 0x63, 0x7a, 0x30, 0x36, 0x6e, 0x2d, 0x67, + 0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, 0x26, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x1b, 0x18, + 0x73, 0x6e, 0x67, 0x64, 0x63, 0x30, 0x31, 0x2d, 0x61, + 0x62, 0x30, 0x37, 0x2d, 0x64, 0x63, 0x7a, 0x30, 0x31, + 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0, 0x17, 0xc0, + 0x26, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, + 0x00, 0x1a, 0x17, 0x61, 0x65, 0x72, 0x30, 0x31, 0x2d, + 0x72, 0x34, 0x63, 0x32, 0x35, 0x2d, 0x64, 0x63, 0x7a, + 0x30, 0x31, 0x6e, 0x2d, 0x67, 0x73, 0x73, 0x31, 0xc0, + 0x17, 0xc0, 0x26, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x00, 0x81, 0x00, 0x04, 0x48, 0xa3, 0x04, 0xa1, 0xc0, + 0x26, 0x00, 0x1c, 0x00, 0x01, 0x00, 0x00, 0x00, 0x82, + 0x00, 0x10, 0x20, 0x01, 0x04, 0x20, 0x12, 0x01, 0x00, + 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, + 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, + 0x9a, 0x00, 0x02, 0xc0, 0xf4, 0xc0, 0x0c, 0x00, 0x02, + 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0, + 0xcd, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, + 0x05, 0x9a, 0x00, 0x02, 0xc0, 0x8d, 0xc0, 0x0c, 0x00, + 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, 0x02, + 0xc0, 0x43, 0xc0, 0x0c, 0x00, 0x02, 0x00, 0x01, 0x00, + 0x00, 0x05, 0x9a, 0x00, 0x02, 0xc0, 0xa9, 0xc0, 0x0c, + 0x00, 0x02, 0x00, 0x01, 0x00, 0x00, 0x05, 0x9a, 0x00, + 0x02, 0xc0, 0x67, 0xc0, 0x8d, 0x00, 0x01, 0x00, 0x01, + 0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0x40, 0x66, 0xf6, + 0x05, 0xc0, 0xa9, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, + 0x07, 0x08, 0x00, 0x04, 0xad, 0x24, 0xe0, 0x64, 0xc0, + 0x43, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08, + 0x00, 0x04, 0x48, 0xa3, 0x04, 0x1c, 0xc0, 0xf4, 0x00, + 0x01, 0x00, 0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04, + 0xad, 0x26, 0xd4, 0x6c, 0xc0, 0x67, 0x00, 0x01, 0x00, + 0x01, 0x00, 0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x25, + 0x90, 0x64, 0xc0, 0xcd, 0x00, 0x01, 0x00, 0x01, 0x00, + 0x00, 0x07, 0x08, 0x00, 0x04, 0xad, 0x27, 0x70, 0x44, +}; + /* google.com */ +#else static u8 dns_reply_data_initializer[] = { 0x0, 0x0, 0x81, 0x80, 0x0, 0x1, 0x0, 0xe, 0x0, 0x0, 0x0, 0x0, 0x6, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3, 0x63, 0x6f, 0x6d, 0x0, 0x0, 0xff, |