X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Futils_dns.c;h=cfa4a5cbefff989c28e4a46accb89e00f1a93f59;hp=9a2e479c5ce500a60d396c30140768d9091ab769;hb=ba2ee9aec4c0454eed8f29b4c6ce96c6fc372346;hpb=b96e6dd0fe5583ca809b66b2519e74081c79e4f3 diff --git a/src/utils_dns.c b/src/utils_dns.c index 9a2e479c..cfa4a5cb 100644 --- a/src/utils_dns.c +++ b/src/utils_dns.c @@ -291,13 +291,18 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns off_t no = 0; unsigned char c; size_t len; - assert(ns > 0); + static int loop_detect = 0; + if (loop_detect > 2) + return 4; /* compression loop */ + if (ns <= 0) + return 4; /* probably compression loop */ do { if ((*off) >= sz) break; c = *(buf + (*off)); if (c > 191) { /* blasted compression */ + int rc; unsigned short s; off_t ptr; memcpy(&s, buf + (*off), sizeof(s)); @@ -305,18 +310,23 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns (*off) += sizeof(s); /* Sanity check */ if ((*off) >= sz) - return 1; + return 1; /* message too short */ ptr = s & 0x3FFF; /* Make sure the pointer is inside this message */ if (ptr >= sz) - return 2; - return rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no); + return 2; /* bad compression ptr */ + if (ptr < DNS_MSG_HDR_SZ) + return 2; /* bad compression ptr */ + loop_detect++; + rc = rfc1035NameUnpack(buf, sz, &ptr, name + no, ns - no); + loop_detect--; + return rc; } else if (c > RFC1035_MAXLABELSZ) { /* * "(The 10 and 01 combinations are reserved for future use.)" */ + return 3; /* reserved label/compression flags */ break; - return 3; } else { (*off)++; len = (size_t) c; @@ -324,15 +334,18 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns break; if (len > (ns - 1)) len = ns - 1; - if ((*off) + len > sz) /* message is too short */ - return 4; + if ((*off) + len > sz) + return 4; /* message is too short */ + if (no + len + 1 > ns) + return 5; /* qname would overflow name buffer */ memcpy(name + no, buf + (*off), len); (*off) += len; no += len; *(name + (no++)) = '.'; } } while (c > 0); - *(name + no - 1) = '\0'; + if (no > 0) + *(name + no - 1) = '\0'; /* make sure we didn't allow someone to overflow the name buffer */ assert(no <= ns); return 0; @@ -345,10 +358,10 @@ handle_dns(const char *buf, int len) uint16_t us; off_t offset; char *t; - int x; + int status; /* The DNS header is 12 bytes long */ - if (len < 12) + if (len < DNS_MSG_HDR_SZ) return 0; memcpy(&us, buf + 0, 2); @@ -379,11 +392,15 @@ handle_dns(const char *buf, int len) memcpy(&us, buf + 10, 2); qh.arcount = ntohs(us); - offset = 12; + offset = DNS_MSG_HDR_SZ; memset(qh.qname, '\0', MAX_QNAME_SZ); - x = rfc1035NameUnpack(buf, len, &offset, qh.qname, MAX_QNAME_SZ); - if (0 != x) + status = rfc1035NameUnpack(buf, len, &offset, qh.qname, MAX_QNAME_SZ); + if (status != 0) + { + INFO ("utils_dns: handle_dns: rfc1035NameUnpack failed " + "with status %i.", status); return 0; + } if ('\0' == qh.qname[0]) sstrncpy (qh.qname, ".", sizeof (qh.qname)); while ((t = strchr(qh.qname, '\n'))) @@ -424,6 +441,7 @@ handle_udp(const struct udphdr *udp, int len) return 1; } +#if HAVE_NETINET_IP6_H static int handle_ipv6 (struct ip6_hdr *ipv6, int len) { @@ -493,6 +511,16 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len) return (1); /* Success */ } /* int handle_ipv6 */ +/* #endif HAVE_NETINET_IP6_H */ + +#else /* if !HAVE_NETINET_IP6_H */ +static int +handle_ipv6 (__attribute__((unused)) void *pkg, + __attribute__((unused)) int len) +{ + return (0); +} +#endif /* !HAVE_NETINET_IP6_H */ static int handle_ip(const struct ip *ip, int len) @@ -503,7 +531,7 @@ handle_ip(const struct ip *ip, int len) struct in6_addr d_addr; if (ip->ip_v == 6) - return (handle_ipv6 ((struct ip6_hdr *) ip, len)); + return (handle_ipv6 ((void *) ip, len)); in6_addr_from_buffer (&s_addr, &ip->ip_src.s_addr, sizeof (ip->ip_src.s_addr), AF_INET); in6_addr_from_buffer (&d_addr, &ip->ip_dst.s_addr, sizeof (ip->ip_dst.s_addr), AF_INET); @@ -601,7 +629,7 @@ handle_ether(const u_char * pkt, int len) return 0; memcpy(buf, pkt, len); if (ETHERTYPE_IPV6 == etype) - return (handle_ipv6 ((struct ip6_hdr *) buf, len)); + return (handle_ipv6 ((void *) buf, len)); else return handle_ip((struct ip *) buf, len); } @@ -634,7 +662,7 @@ handle_linux_sll (const u_char *pkt, int len) return 0; if (ETHERTYPE_IPV6 == etype) - return (handle_ipv6 ((struct ip6_hdr *) pkt, len)); + return (handle_ipv6 ((void *) pkt, len)); else return handle_ip((struct ip *) pkt, len); } @@ -645,10 +673,6 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt { int status; - DEBUG ("handle_pcap (udata = %p, hdr = %p, pkt = %p): hdr->caplen = %i\n", - (void *) udata, (void *) hdr, (void *) pkt, - hdr->caplen); - if (hdr->caplen < ETHER_HDR_LEN) return; @@ -682,7 +706,7 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt break; default: - ERROR ("handle_pcap: unsupported data link type %d\n", + ERROR ("handle_pcap: unsupported data link type %d", pcap_datalink(pcap_obj)); status = 0; break;