diff --git a/src/utils_dns.c b/src/utils_dns.c
index 2899bd4140223229a1ae45533429d186572ddd35..71a14d87ddc7fe75f2326165e11b86cdaf4ce139 100644 (file)
--- a/src/utils_dns.c
+++ b/src/utils_dns.c
/*
* collectd - src/utils_dns.c
/*
* 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.
* All rights reserved.
- *
+ *
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
- *
+ *
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright notice,
*
* Authors:
* The Measurement Factory, Inc. <http://www.measurement-factory.com/>
*
* Authors:
* The Measurement Factory, Inc. <http://www.measurement-factory.com/>
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
*/
*/
+#define _DEFAULT_SOURCE
#define _BSD_SOURCE
#include "collectd.h"
#include "plugin.h"
#include "common.h"
#define _BSD_SOURCE
#include "collectd.h"
#include "plugin.h"
#include "common.h"
-#if HAVE_NETINET_IN_SYSTM_H
-# include <netinet/in_systm.h>
-#endif
-#if HAVE_NETINET_IN_H
-# include <netinet/in.h>
-#endif
-#if HAVE_ARPA_INET_H
-# include <arpa/inet.h>
-#endif
-#if HAVE_SYS_SOCKET_H
-# include <sys/socket.h>
-#endif
-
-#if HAVE_ARPA_NAMESER_H
-# include <arpa/nameser.h>
-#endif
-#if HAVE_ARPA_NAMESER_COMPAT_H
-# include <arpa/nameser_compat.h>
-#endif
-
#if HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
#if HAVE_NET_IF_ARP_H
# include <net/if_arp.h>
#endif
#if HAVE_NET_IF_H
# include <net/if.h>
#endif
-#if HAVE_NETINET_IF_ETHER_H
-# include <netinet/if_ether.h>
-#endif
#if HAVE_NET_PPP_DEFS_H
# include <net/ppp_defs.h>
#endif
#if HAVE_NET_PPP_DEFS_H
# include <net/ppp_defs.h>
#endif
# include <net/if_ppp.h>
#endif
# include <net/if_ppp.h>
#endif
-#if HAVE_NETDB_H
-# include <netdb.h>
+#if HAVE_NETINET_IN_SYSTM_H
+# include <netinet/in_systm.h>
+#endif
+#if HAVE_NETINET_IN_H
+# include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP6_H
+# include <netinet/ip6.h>
+#endif
+#if HAVE_NETINET_IF_ETHER_H
+# include <netinet/if_ether.h>
#endif
#endif
-
#if HAVE_NETINET_IP_H
# include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_IP_VAR_H
# include <netinet/ip_var.h>
#endif
#if HAVE_NETINET_IP_H
# include <netinet/ip.h>
#endif
#ifdef HAVE_NETINET_IP_VAR_H
# include <netinet/ip_var.h>
#endif
-#if HAVE_NETINET_IP6_H
-# include <netinet/ip6.h>
-#endif
#if HAVE_NETINET_UDP_H
# include <netinet/udp.h>
#endif
#if HAVE_NETINET_UDP_H
# include <netinet/udp.h>
#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+#if HAVE_ARPA_NAMESER_H
+# include <arpa/nameser.h>
+#endif
+#if HAVE_ARPA_NAMESER_COMPAT_H
+# include <arpa/nameser_compat.h>
+#endif
+
+#if HAVE_NETDB_H
+# include <netdb.h>
+#endif
+
#if HAVE_PCAP_H
# include <pcap.h>
#endif
#if HAVE_PCAP_H
# include <pcap.h>
#endif
# error "`struct udphdr' is unusable."
#endif
# error "`struct udphdr' is unusable."
#endif
+#if HAVE_NETINET_IP6_H && HAVE_STRUCT_IP6_EXT
+# define HAVE_IPV6 1
+#endif
+
#include "utils_dns.h"
/*
#include "utils_dns.h"
/*
@@ -291,32 +292,42 @@ 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;
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 {
do {
- if ((*off) >= sz)
+ if ((*off) >= ((off_t) sz))
break;
c = *(buf + (*off));
if (c > 191) {
/* blasted compression */
break;
c = *(buf + (*off));
if (c > 191) {
/* blasted compression */
+ int rc;
unsigned short s;
off_t ptr;
memcpy(&s, buf + (*off), sizeof(s));
s = ntohs(s);
(*off) += sizeof(s);
/* Sanity check */
unsigned short s;
off_t ptr;
memcpy(&s, buf + (*off), sizeof(s));
s = ntohs(s);
(*off) += sizeof(s);
/* Sanity check */
- if ((*off) >= sz)
- return 1;
+ if ((*off) >= ((off_t) sz))
+ return 1; /* message too short */
ptr = s & 0x3FFF;
/* Make sure the pointer is inside this message */
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);
+ if (ptr >= ((off_t) sz))
+ 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.)"
*/
} else if (c > RFC1035_MAXLABELSZ) {
/*
* "(The 10 and 01 combinations are reserved for future use.)"
*/
+ return 3; /* reserved label/compression flags */
break;
break;
- return 3;
} else {
(*off)++;
len = (size_t) c;
} else {
(*off)++;
len = (size_t) c;
@@ -324,17 +335,20 @@ rfc1035NameUnpack(const char *buf, size_t sz, off_t * off, char *name, size_t ns
break;
if (len > (ns - 1))
len = ns - 1;
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);
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 */
/* make sure we didn't allow someone to overflow the name buffer */
- assert(no <= ns);
+ assert(no <= ((off_t) ns));
return 0;
}
return 0;
}
uint16_t us;
off_t offset;
char *t;
uint16_t us;
off_t offset;
char *t;
- int x;
+ int status;
/* The DNS header is 12 bytes long */
/* The DNS header is 12 bytes long */
- if (len < 12)
+ if (len < DNS_MSG_HDR_SZ)
return 0;
memcpy(&us, buf + 0, 2);
return 0;
memcpy(&us, buf + 0, 2);
memcpy(&us, buf + 10, 2);
qh.arcount = ntohs(us);
memcpy(&us, buf + 10, 2);
qh.arcount = ntohs(us);
- offset = 12;
+ offset = DNS_MSG_HDR_SZ;
memset(qh.qname, '\0', MAX_QNAME_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;
return 0;
+ }
if ('\0' == qh.qname[0])
sstrncpy (qh.qname, ".", sizeof (qh.qname));
while ((t = strchr(qh.qname, '\n')))
if ('\0' == qh.qname[0])
sstrncpy (qh.qname, ".", sizeof (qh.qname));
while ((t = strchr(qh.qname, '\n')))
return 1;
}
return 1;
}
+#if HAVE_IPV6
static int
handle_ipv6 (struct ip6_hdr *ipv6, int len)
{
static int
handle_ipv6 (struct ip6_hdr *ipv6, int len)
{
return (1); /* Success */
} /* int handle_ipv6 */
return (1); /* Success */
} /* int handle_ipv6 */
+/* #endif HAVE_IPV6 */
+
+#else /* if !HAVE_IPV6 */
+static int
+handle_ipv6 (__attribute__((unused)) void *pkg,
+ __attribute__((unused)) int len)
+{
+ return (0);
+}
+#endif /* !HAVE_IPV6 */
static int
handle_ip(const struct ip *ip, int len)
static int
handle_ip(const struct ip *ip, int len)
struct in6_addr c_dst_addr;
if (ip->ip_v == 6)
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);
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);
return 0;
memcpy(buf, pkt, len);
if (ETHERTYPE_IPV6 == etype)
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);
}
else
return handle_ip((struct ip *) buf, len);
}
return 0;
if (ETHERTYPE_IPV6 == etype)
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);
}
else
return handle_ip((struct ip *) pkt, len);
}
@@ -644,10 +673,6 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt
{
int status;
{
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;
if (hdr->caplen < ETHER_HDR_LEN)
return;
@@ -681,7 +706,7 @@ void handle_pcap(u_char *udata, const struct pcap_pkthdr *hdr, const u_char *pkt
break;
default:
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;
pcap_datalink(pcap_obj));
status = 0;
break;