X-Git-Url: https://git.octo.it/?a=blobdiff_plain;f=src%2Futils_dns.c;h=25ef18998bb9f62ad928130e49b531f71501f15f;hb=61a1fa91ba73e4fe3a34949f77c5f017056f2b7a;hp=19afe55e904fe08d75b64e333f790cbdcbb796e1;hpb=db71b0fa19cc0217f1460499f891a36ecc8f1c8e;p=collectd.git diff --git a/src/utils_dns.c b/src/utils_dns.c index 19afe55e..9a2e479c 100644 --- a/src/utils_dns.c +++ b/src/utils_dns.c @@ -33,39 +33,68 @@ * Florian octo Forster */ -#include -#include -#include - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#ifdef __APPLE__ -#include -#endif - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include +#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 +#if HAVE_NET_IF_PPP_H +# include +#endif + +#if HAVE_NETDB_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_PCAP_H +# include +#endif #define PCAP_SNAPLEN 1460 #ifndef ETHER_HDR_LEN @@ -80,7 +109,6 @@ # define ETHERTYPE_IPV6 0x86DD #endif -#include #ifndef PPP_ADDRESS_VAL # define PPP_ADDRESS_VAL 0xff /* The address byte value */ #endif @@ -88,9 +116,14 @@ # define PPP_CONTROL_VAL 0x03 /* The control byte value */ #endif -#ifdef __linux__ -#define uh_sport source -#define uh_dport dest +#if HAVE_STRUCT_UDPHDR_UH_DPORT && HAVE_STRUCT_UDPHDR_UH_SPORT +# define UDP_DEST uh_dport +# define UDP_SRC uh_dport +#elif HAVE_STRUCT_UDPHDR_DEST && HAVE_STRUCT_UDPHDR_SOURCE +# define UDP_DEST dest +# define UDP_SRC source +#else +# error "`struct udphdr' is unusable." #endif #include "utils_dns.h" @@ -126,33 +159,39 @@ int qtype_counts[T_MAX]; int opcode_counts[OP_MAX]; int qclass_counts[C_MAX]; +#if HAVE_PCAP_H static pcap_t *pcap_obj = NULL; +#endif static ip_list_t *IgnoreList = NULL; +#if HAVE_PCAP_H static void (*Callback) (const rfc1035_header_t *) = NULL; static int query_count_intvl = 0; static int query_count_total = 0; -#ifdef __OpenBSD__ +# ifdef __OpenBSD__ static struct bpf_timeval last_ts; -#else +# else static struct timeval last_ts; -#endif +# endif /* __OpenBSD__ */ +#endif /* HAVE_PCAP_H */ static int cmp_in6_addr (const struct in6_addr *a, const struct in6_addr *b) { int i; - for (i = 0; i < 4; i++) - if (a->s6_addr32[i] != b->s6_addr32[i]) + assert (sizeof (struct in6_addr) == 16); + + for (i = 0; i < 16; i++) + if (a->s6_addr[i] != b->s6_addr[i]) break; - if (i >= 4) + if (i >= 16) return (0); - return (a->s6_addr32[i] > b->s6_addr32[i] ? 1 : -1); + return (a->s6_addr[i] > b->s6_addr[i] ? 1 : -1); } /* int cmp_addrinfo */ static inline int ignore_list_match (const struct in6_addr *addr) @@ -200,10 +239,10 @@ void ignore_list_add_name (const char *name) { if (ai_ptr->ai_family == AF_INET) { - addr.s6_addr32[0] = 0; - addr.s6_addr32[1] = 0; - addr.s6_addr32[2] = htonl (0x0000FFFF); - addr.s6_addr32[3] = ((struct sockaddr_in *) ai_ptr->ai_addr)->sin_addr.s_addr; + memset (&addr, '\0', sizeof (addr)); + addr.s6_addr[10] = 0xFF; + addr.s6_addr[11] = 0xFF; + memcpy (addr.s6_addr + 12, &((struct sockaddr_in *) ai_ptr->ai_addr)->sin_addr, 4); ignore_list_add (&addr); } @@ -216,6 +255,7 @@ void ignore_list_add_name (const char *name) freeaddrinfo (ai_list); } +#if HAVE_PCAP_H static void in6_addr_from_buffer (struct in6_addr *ia, const void *buf, size_t buf_len, int family) @@ -223,8 +263,9 @@ static void in6_addr_from_buffer (struct in6_addr *ia, memset (ia, 0, sizeof (struct in6_addr)); if ((AF_INET == family) && (sizeof (uint32_t) == buf_len)) { - ia->s6_addr32[2] = htonl (0x0000FFFF); - ia->s6_addr32[3] = *((uint32_t *) buf); + ia->s6_addr[10] = 0xFF; + ia->s6_addr[11] = 0xFF; + memcpy (ia->s6_addr + 12, buf, buf_len); } else if ((AF_INET6 == family) && (sizeof (struct in6_addr) == buf_len)) { @@ -298,9 +339,7 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns } 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; @@ -317,7 +356,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; @@ -347,13 +385,13 @@ handle_dns(const char *buf, int len, if (0 != x) 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); @@ -374,16 +412,14 @@ 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->uh_dport) != 53) - && (ntohs (udp->uh_sport) != 53)) + 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; } @@ -392,17 +428,18 @@ 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; 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; payload_len = ntohs (ipv6->ip6_plen); if (ignore_list_match (&s_addr)) @@ -422,7 +459,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. */ @@ -442,7 +479,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); @@ -451,7 +488,7 @@ 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 */ @@ -475,11 +512,12 @@ handle_ip(const struct ip *ip, int len) 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; } +#if HAVE_NET_IF_PPP_H static int handle_ppp(const u_char * pkt, int len) { @@ -509,6 +547,7 @@ handle_ppp(const u_char * pkt, int len) memcpy(buf, pkt, len); return handle_ip((struct ip *) buf, len); } +#endif /* HAVE_NET_IF_PPP_H */ static int handle_null(const u_char * pkt, int len) @@ -567,12 +606,46 @@ handle_ether(const u_char * pkt, int len) return handle_ip((struct ip *) buf, len); } +#ifdef DLT_LINUX_SLL +static int +handle_linux_sll (const u_char *pkt, int len) +{ + struct sll_header + { + uint16_t pkt_type; + uint16_t dev_type; + uint16_t addr_len; + uint8_t addr[8]; + uint16_t proto_type; + } *hdr; + uint16_t etype; + + if ((0 > len) || ((unsigned int)len < sizeof (struct sll_header))) + return (0); + + hdr = (struct sll_header *) pkt; + pkt = (u_char *) (hdr + 1); + len -= sizeof (struct sll_header); + + etype = ntohs (hdr->proto_type); + + if ((ETHERTYPE_IP != etype) + && (ETHERTYPE_IPV6 != etype)) + return 0; + + if (ETHERTYPE_IPV6 == etype) + return (handle_ipv6 ((struct ip6_hdr *) pkt, len)); + else + return handle_ip((struct ip *) pkt, len); +} +#endif /* DLT_LINUX_SLL */ + /* public function */ 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", + DEBUG ("handle_pcap (udata = %p, hdr = %p, pkt = %p): hdr->caplen = %i\n", (void *) udata, (void *) hdr, (void *) pkt, hdr->caplen); @@ -584,9 +657,11 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt case DLT_EN10MB: status = handle_ether (pkt, hdr->caplen); break; +#if HAVE_NET_IF_PPP_H case DLT_PPP: status = handle_ppp (pkt, hdr->caplen); break; +#endif #ifdef DLT_LOOP case DLT_LOOP: status = handle_loop (pkt, hdr->caplen); @@ -597,12 +672,17 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt status = handle_raw (pkt, hdr->caplen); break; #endif +#ifdef DLT_LINUX_SLL + case DLT_LINUX_SLL: + status = handle_linux_sll (pkt, hdr->caplen); + break; +#endif case DLT_NULL: status = handle_null (pkt, hdr->caplen); break; default: - fprintf (stderr, "unsupported data link type %d\n", + ERROR ("handle_pcap: unsupported data link type %d\n", pcap_datalink(pcap_obj)); status = 0; break; @@ -615,11 +695,13 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt query_count_total++; last_ts = hdr->ts; } +#endif /* HAVE_PCAP_H */ const char *qtype_str(int t) { static char buf[32]; switch (t) { +#if (defined (__NAMESER)) && (__NAMESER >= 19991001) case ns_t_a: return ("A"); case ns_t_ns: return ("NS"); case ns_t_md: return ("MD"); @@ -661,16 +743,76 @@ 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"); case ns_t_maila: return ("MAILA"); case ns_t_any: return ("ANY"); case ns_t_zxfr: return ("ZXFR"); +/* #endif __NAMESER >= 19991006 */ +#elif (defined (__BIND)) && (__BIND >= 19950621) + case T_A: return ("A"); /* 1 ... */ + case T_NS: return ("NS"); + case T_MD: return ("MD"); + case T_MF: return ("MF"); + case T_CNAME: return ("CNAME"); + case T_SOA: return ("SOA"); + case T_MB: return ("MB"); + case T_MG: return ("MG"); + case T_MR: return ("MR"); + case T_NULL: return ("NULL"); + case T_WKS: return ("WKS"); + case T_PTR: return ("PTR"); + case T_HINFO: return ("HINFO"); + case T_MINFO: return ("MINFO"); + case T_MX: return ("MX"); + case T_TXT: return ("TXT"); + case T_RP: return ("RP"); + case T_AFSDB: return ("AFSDB"); + case T_X25: return ("X25"); + case T_ISDN: return ("ISDN"); + case T_RT: return ("RT"); + case T_NSAP: return ("NSAP"); + case T_NSAP_PTR: return ("NSAP_PTR"); + case T_SIG: return ("SIG"); + case T_KEY: return ("KEY"); + case T_PX: return ("PX"); + case T_GPOS: return ("GPOS"); + case T_AAAA: return ("AAAA"); + case T_LOC: return ("LOC"); + case T_NXT: return ("NXT"); + case T_EID: return ("EID"); + case T_NIMLOC: return ("NIMLOC"); + case T_SRV: return ("SRV"); + case T_ATMA: return ("ATMA"); + case T_NAPTR: return ("NAPTR"); /* ... 35 */ +#if (__BIND >= 19960801) + case T_KX: return ("KX"); /* 36 ... */ + case T_CERT: return ("CERT"); + case T_A6: return ("A6"); + case T_DNAME: return ("DNAME"); + case T_SINK: return ("SINK"); + case T_OPT: return ("OPT"); + case T_APL: return ("APL"); + case T_DS: return ("DS"); + case T_SSHFP: return ("SSHFP"); + case T_RRSIG: return ("RRSIG"); + case T_NSEC: return ("NSEC"); + case T_DNSKEY: return ("DNSKEY"); /* ... 48 */ + case T_TKEY: return ("TKEY"); /* 249 */ +#endif /* __BIND >= 19960801 */ + case T_TSIG: return ("TSIG"); /* 250 ... */ + case T_IXFR: return ("IXFR"); + case T_AXFR: return ("AXFR"); + case T_MAILB: return ("MAILB"); + case T_MAILA: return ("MAILA"); + 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 */ @@ -697,7 +839,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 */ @@ -708,6 +850,7 @@ const char *rcode_str (int rcode) static char buf[32]; switch (rcode) { +#if (defined (__NAMESER)) && (__NAMESER >= 19991006) case ns_r_noerror: return ("NOERROR"); case ns_r_formerr: return ("FORMERR"); case ns_r_servfail: return ("SERVFAIL"); @@ -723,9 +866,24 @@ const char *rcode_str (int rcode) case ns_r_badsig: return ("BADSIG"); case ns_r_badkey: return ("BADKEY"); case ns_r_badtime: return ("BADTIME"); +/* #endif __NAMESER >= 19991006 */ +#elif (defined (__BIND)) && (__BIND >= 19950621) + case NOERROR: return ("NOERROR"); + case FORMERR: return ("FORMERR"); + case SERVFAIL: return ("SERVFAIL"); + case NXDOMAIN: return ("NXDOMAIN"); + case NOTIMP: return ("NOTIMP"); + case REFUSED: return ("REFUSED"); +#if defined (YXDOMAIN) && defined (NXRRSET) + case YXDOMAIN: return ("YXDOMAIN"); + case YXRRSET: return ("YXRRSET"); + case NXRRSET: return ("NXRRSET"); + case NOTAUTH: return ("NOTAUTH"); + case NOTZONE: return ("NOTZONE"); +#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 */ @@ -831,7 +989,7 @@ main(int argc, char *argv[]) case DLT_EN10MB: handle_datalink = handle_ether; break; -#if USE_PPP +#if HAVE_NET_IF_PPP_H case DLT_PPP: handle_datalink = handle_ppp; break; @@ -898,3 +1056,6 @@ main(int argc, char *argv[]) return 0; } /* static int main(int argc, char *argv[]) */ #endif +/* + * vim:shiftwidth=4:tabstop=8:softtabstop=4 + */