X-Git-Url: https://git.octo.it/?p=collectd.git;a=blobdiff_plain;f=src%2Futils_dns.c;h=712b1aece8e3b1fe584715ee7e0e1e128cec97f4;hp=73db619b6816b60f25616006446e9bf4ace56e64;hb=633c3966f770e4d46651a2fe219a18d8a9907a9f;hpb=e06c9a7cbc62b82c9ef5a4074a94c037174ca723 diff --git a/src/utils_dns.c b/src/utils_dns.c index 73db619b..712b1aec 100644 --- a/src/utils_dns.c +++ b/src/utils_dns.c @@ -1,7 +1,7 @@ /* * collectd - src/utils_dns.c - * Modifications Copyright (C) 2006 Florian octo Forster - * Copyright (C) 2002 The Measurement Factory, Inc. + * Copyright (C) 2006 Florian octo Forster + * Copyright (C) 2002 The Measurement Factory, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -30,7 +30,7 @@ * * Authors: * The Measurement Factory, Inc. - * Florian octo Forster + * Florian octo Forster */ #define _BSD_SOURCE @@ -39,35 +39,16 @@ #include "plugin.h" #include "common.h" -#if HAVE_NETINET_IN_SYSTM_H -# include -#endif -#if HAVE_NETINET_IN_H -# include -#endif -#if HAVE_ARPA_INET_H -# include -#endif #if HAVE_SYS_SOCKET_H # include #endif -#if HAVE_ARPA_NAMESER_H -# include -#endif -#if HAVE_ARPA_NAMESER_COMPAT_H -# include -#endif - #if HAVE_NET_IF_ARP_H # include #endif #if HAVE_NET_IF_H # include #endif -#if HAVE_NETINET_IF_ETHER_H -# include -#endif #if HAVE_NET_PPP_DEFS_H # include #endif @@ -75,23 +56,45 @@ # include #endif -#if HAVE_NETDB_H -# include +#if HAVE_NETINET_IN_SYSTM_H +# include +#endif +#if HAVE_NETINET_IN_H +# include +#endif +#if HAVE_NETINET_IP6_H +# include +#endif +#if HAVE_NETINET_IP_COMPAT_H +# include +#endif +#if HAVE_NETINET_IF_ETHER_H +# include #endif - #if HAVE_NETINET_IP_H # include #endif #ifdef HAVE_NETINET_IP_VAR_H # include #endif -#if HAVE_NETINET_IP6_H -# include -#endif #if HAVE_NETINET_UDP_H # include #endif +#if HAVE_ARPA_INET_H +# include +#endif +#if HAVE_ARPA_NAMESER_H +# include +#endif +#if HAVE_ARPA_NAMESER_COMPAT_H +# include +#endif + +#if HAVE_NETDB_H +# include +#endif + #if HAVE_PCAP_H # include #endif @@ -118,7 +121,7 @@ #if HAVE_STRUCT_UDPHDR_UH_DPORT && HAVE_STRUCT_UDPHDR_UH_SPORT # define UDP_DEST uh_dport -# define UDP_SRC uh_dport +# define UDP_SRC uh_sport #elif HAVE_STRUCT_UDPHDR_DEST && HAVE_STRUCT_UDPHDR_SOURCE # define UDP_DEST dest # define UDP_SRC source @@ -291,13 +294,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 +313,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 +337,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 +361,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 +395,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 +444,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) { @@ -492,6 +513,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) @@ -502,7 +533,7 @@ handle_ip(const struct ip *ip, int len) struct in6_addr c_dst_addr; if (ip->ip_v == 6) - return (handle_ipv6 ((struct ip6_hdr *) ip, len)); + return (handle_ipv6 ((void *) ip, len)); in6_addr_from_buffer (&c_src_addr, &ip->ip_src.s_addr, sizeof (ip->ip_src.s_addr), AF_INET); in6_addr_from_buffer (&c_dst_addr, &ip->ip_dst.s_addr, sizeof (ip->ip_dst.s_addr), AF_INET); @@ -600,7 +631,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); } @@ -633,7 +664,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); } @@ -644,10 +675,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; @@ -681,7 +708,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;