* Florian octo Forster <octo at verplant.org>
*/
+#define _BSD_SOURCE
+
#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
#if HAVE_NETINET_IN_SYSTM_H
# include <netinet/in_systm.h>
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));
(*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;
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);
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;
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])
- strncpy (qh.qname, ".", sizeof (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);
}
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;
}
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 */
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;
}
{
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;
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;
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 */
return "Update";
break;
default:
- snprintf(buf, 30, "Opcode%d", o);
+ ssnprintf(buf, sizeof (buf), "Opcode%d", o);
return buf;
}
/* NOTREACHED */
#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 */