X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_dns.c;h=b7dc79134ab6e48db7c8fcdc54a067c6061858de;hb=633c3966f770e4d46651a2fe219a18d8a9907a9f;hp=a412809fab051c77c718b158b623f813a2cbf49e;hpb=2b6176cab4f092354177473bbc74c5cdc2eaa2ec;p=collectd.git diff --git a/src/utils_dns.c b/src/utils_dns.c index a412809f..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,40 +30,25 @@ * * Authors: * The Measurement Factory, Inc. - * Florian octo Forster + * Florian octo Forster */ +#define _BSD_SOURCE + #include "collectd.h" +#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 @@ -71,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 @@ -114,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 @@ -287,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)); @@ -301,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; @@ -320,33 +337,34 @@ 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; } static int -handle_dns(const char *buf, int len, - const struct in6_addr *s_addr, - const struct in6_addr *d_addr) +handle_dns(const char *buf, int len) { rfc1035_header_t qh; 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); @@ -354,7 +372,6 @@ handle_dns(const char *buf, int len, memcpy(&us, buf + 2, 2); us = ntohs(us); - fprintf (stderr, "Bytes 0, 1: 0x%04hx\n", us); qh.qr = (us >> 15) & 0x01; qh.opcode = (us >> 11) & 0x0F; qh.aa = (us >> 10) & 0x01; @@ -378,19 +395,23 @@ 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]) - strcpy(qh.qname, "."); + sstrncpy (qh.qname, ".", sizeof (qh.qname)); while ((t = strchr(qh.qname, '\n'))) *t = ' '; while ((t = strchr(qh.qname, '\r'))) *t = ' '; for (t = qh.qname; *t; t++) - *t = tolower(*t); + *t = tolower((int) *t); memcpy(&us, buf + offset, 2); qh.qtype = ntohs(us); @@ -411,38 +432,38 @@ handle_dns(const char *buf, int len, } static int -handle_udp(const struct udphdr *udp, int len, - const struct in6_addr *s_addr, - const struct in6_addr *d_addr) +handle_udp(const struct udphdr *udp, int len) { char buf[PCAP_SNAPLEN]; if ((ntohs (udp->UDP_DEST) != 53) && (ntohs (udp->UDP_SRC) != 53)) return 0; memcpy(buf, udp + 1, len - sizeof(*udp)); - if (0 == handle_dns(buf, len - sizeof(*udp), s_addr, d_addr)) + if (0 == handle_dns(buf, len - sizeof(*udp))) return 0; return 1; } +#if HAVE_NETINET_IP6_H static int handle_ipv6 (struct ip6_hdr *ipv6, int len) { char buf[PCAP_SNAPLEN]; - int offset; + unsigned int offset; int nexthdr; - struct in6_addr s_addr; - struct in6_addr d_addr; + struct in6_addr c_src_addr; uint16_t payload_len; + if (0 > len) + return (0); + offset = sizeof (struct ip6_hdr); nexthdr = ipv6->ip6_nxt; - s_addr = ipv6->ip6_src; - d_addr = ipv6->ip6_dst; + c_src_addr = ipv6->ip6_src; payload_len = ntohs (ipv6->ip6_plen); - if (ignore_list_match (&s_addr)) + if (ignore_list_match (&c_src_addr)) return (0); /* Parse extension headers. This only handles the standard headers, as @@ -451,7 +472,6 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len) || (IPPROTO_HOPOPTS == nexthdr) /* Hop-by-Hop options. */ || (IPPROTO_FRAGMENT == nexthdr) /* fragmentation header. */ || (IPPROTO_DSTOPTS == nexthdr) /* destination options. */ - || (IPPROTO_DSTOPTS == nexthdr) /* destination options. */ || (IPPROTO_AH == nexthdr) /* destination options. */ || (IPPROTO_ESP == nexthdr)) /* encapsulating security payload. */ { @@ -459,7 +479,7 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len) uint16_t ext_hdr_len; /* Catch broken packets */ - if ((offset + sizeof (struct ip6_ext)) > len) + if ((offset + sizeof (struct ip6_ext)) > (unsigned int)len) return (0); /* Cannot handle fragments. */ @@ -479,7 +499,7 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len) } /* while */ /* Catch broken and empty packets */ - if (((offset + payload_len) > len) + if (((offset + payload_len) > (unsigned int)len) || (payload_len == 0) || (payload_len > PCAP_SNAPLEN)) return (0); @@ -488,31 +508,41 @@ handle_ipv6 (struct ip6_hdr *ipv6, int len) return (0); memcpy (buf, (char *) ipv6 + offset, payload_len); - if (handle_udp ((struct udphdr *) buf, payload_len, &s_addr, &d_addr) == 0) + if (handle_udp ((struct udphdr *) buf, payload_len) == 0) return (0); 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) { char buf[PCAP_SNAPLEN]; int offset = ip->ip_hl << 2; - struct in6_addr s_addr; - struct in6_addr d_addr; + struct in6_addr c_src_addr; + 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 (&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); - if (ignore_list_match (&s_addr)) + 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); + if (ignore_list_match (&c_src_addr)) return (0); if (IPPROTO_UDP != ip->ip_p) return 0; memcpy(buf, (void *) ip + offset, len - offset); - if (0 == handle_udp((struct udphdr *) buf, len - offset, &s_addr, &d_addr)) + if (0 == handle_udp((struct udphdr *) buf, len - offset)) return 0; return 1; } @@ -601,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); } @@ -620,7 +650,7 @@ handle_linux_sll (const u_char *pkt, int len) } *hdr; uint16_t etype; - if (len < sizeof (struct sll_header)) + if ((0 > len) || ((unsigned int)len < sizeof (struct sll_header))) return (0); hdr = (struct sll_header *) pkt; @@ -634,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); } @@ -645,10 +675,6 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt { int status; - fprintf (stderr, "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 +708,7 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt break; default: - fprintf (stderr, "unsupported data link type %d\n", + ERROR ("handle_pcap: unsupported data link type %d", pcap_datalink(pcap_obj)); status = 0; break; @@ -701,7 +727,7 @@ const char *qtype_str(int t) { static char buf[32]; switch (t) { -#if (defined (__NAMESER)) && (__NAMESER >= 19991006) +#if (defined (__NAMESER)) && (__NAMESER >= 19991001) case ns_t_a: return ("A"); case ns_t_ns: return ("NS"); case ns_t_md: return ("MD"); @@ -743,7 +769,9 @@ const char *qtype_str(int t) case ns_t_dname: return ("DNAME"); case ns_t_sink: return ("SINK"); case ns_t_opt: return ("OPT"); +# if __NAMESER >= 19991006 case ns_t_tsig: return ("TSIG"); +# endif case ns_t_ixfr: return ("IXFR"); case ns_t_axfr: return ("AXFR"); case ns_t_mailb: return ("MAILB"); @@ -810,8 +838,7 @@ const char *qtype_str(int t) case T_ANY: return ("ANY"); /* ... 255 */ #endif /* __BIND >= 19950621 */ default: - snprintf (buf, 32, "#%i", t); - buf[31] = '\0'; + ssnprintf (buf, sizeof (buf), "#%i", t); return (buf); }; /* switch (t) */ /* NOTREACHED */ @@ -838,7 +865,7 @@ const char *opcode_str (int o) return "Update"; break; default: - snprintf(buf, 30, "Opcode%d", o); + ssnprintf(buf, sizeof (buf), "Opcode%d", o); return buf; } /* NOTREACHED */ @@ -882,8 +909,7 @@ const char *rcode_str (int rcode) #endif /* RFC2136 rcodes */ #endif /* __BIND >= 19950621 */ default: - snprintf (buf, 32, "RCode%i", rcode); - buf[31] = '\0'; + ssnprintf (buf, sizeof (buf), "RCode%i", rcode); return (buf); } /* Never reached */