예제 #1
0
void
handle_ether(const u_char * pkt, int len, void *userdata)
{
    struct ether_header *e = (struct ether_header *)pkt;
    unsigned short etype;
    if (len < ETHER_HDR_LEN)
	return;
    etype = nptohs(&e->ether_type);
    if (callback_ether)
	if (0 != callback_ether(pkt, len, userdata))
	    return;
    pkt += ETHER_HDR_LEN;
    len -= ETHER_HDR_LEN;
    if (ETHERTYPE_8021Q == etype) {
	unsigned short vlan = nptohs((unsigned short *) pkt);
	if (callback_vlan)
	    if (0 != callback_vlan(vlan, userdata))
		return;
	etype = nptohs((unsigned short *)(pkt + 2));
	pkt += 4;
	len -= 4;
    }
    if (len < 0)
	return;
    /* fprintf(stderr, "Ethernet packet of len %d ethertype %#04x\n", len, etype); */
    if (is_ethertype_ip(etype)) {
	handle_ip((struct ip *)pkt, len, userdata);
    }
}
예제 #2
0
void
handle_ppp(const u_char * pkt, int len, void *userdata)
{
    char buf[PCAP_SNAPLEN];
    unsigned short proto;
    if (len < 2)
	return NULL;
    if (*pkt == PPP_ADDRESS_VAL && *(pkt + 1) == PPP_CONTROL_VAL) {
	pkt += 2;		/* ACFC not used */
	len -= 2;
    }
    if (len < 2)
	return NULL;
    if (*pkt % 2) {
	proto = *pkt;		/* PFC is used */
	pkt++;
	len--;
    } else {
	proto = nptohs(pkt);
	pkt += 2;
	len -= 2;
    }
    if (is_ethertype_ip(proto))
	handle_ip((struct ip *)pkt, len, userdata);
}
예제 #3
0
void
handle_linux_sll(const u_char * pkt, int len, void *userdata)
{
    struct sll_header *s = (struct sll_header *)pkt;
    unsigned short etype, eproto;

    if (len < SLL_HDR_LEN)
	return;
    etype = nptohs(&s->sll_pkttype);
    if (etype == LINUX_SLL_BROADCAST || etype == LINUX_SLL_MULTICAST)
	return;
    eproto = nptohs(&s->sll_protocol);
    if (eproto != ETHERTYPE_IP)
	return;
    pkt += SLL_HDR_LEN;
    len -= SLL_HDR_LEN;
    /* fprintf(stderr, "linnux cooked packet of len %d type %#04x proto %#04x\n", len, etype, eproto); */
    handle_ip((struct ip *)pkt, len, userdata);
}
예제 #4
0
void
handle_gre(const u_char * gre, int len, void *userdata)
{
    int grelen = 4;
    unsigned short flags = nptohs(gre);
    unsigned short etype = nptohs(gre + 2);
    if (len < grelen)
	return;
    if (callback_gre)
	callback_gre(gre, len, userdata);
    if (flags & 0x0001)		/* checksum present? */
	grelen += 4;
    if (flags & 0x0004)		/* key present? */
	grelen += 4;
    if (flags & 0x0008)		/* sequence number present? */
	grelen += 4;
    if (is_ethertype_ip(etype))
	handle_ip((struct ip *) (gre + grelen), len - grelen, userdata);
}
예제 #5
0
static off_t
grok_additional_for_opt_rr(const u_char *buf, int len, off_t offset, dns_message * m)
{
    int x;
    unsigned short sometype;
    unsigned short someclass;
    unsigned short us;
    char somename[MAX_QNAME_SZ];
    x = rfc1035NameUnpack(buf, len, &offset, somename, MAX_QNAME_SZ);
    if (0 != x)
	return 0;
    if (offset + 10 > len)
	return 0;
    sometype = nptohs(buf + offset);
    someclass = nptohs(buf + offset + 2);
    if (sometype == T_OPT) {
	m->edns.found = 1;
	m->edns.bufsiz = someclass;
	memcpy(&m->edns.version, buf + offset + 5, 1);
	us = nptohs(buf + offset + 6);
	m->edns.DO = (us >> 15) & 0x01;		/* RFC 3225 */
    }
예제 #6
0
static off_t
grok_question(const u_char *buf, int len, off_t offset, char *qname, unsigned short *qtype, unsigned short *qclass)
{
    char *t;
    int x;
    x = rfc1035NameUnpack(buf, len, &offset, qname, MAX_QNAME_SZ);
    if (0 != x)
	return 0;
    if ('\0' == *qname)
	strcpy(qname, ".");
    /* XXX remove special characters from QNAME */
    while ((t = strchr(qname, '\n')))
	*t = ' ';
    while ((t = strchr(qname, '\r')))
	*t = ' ';
    for (t = qname; *t; t++)
	*t = tolower(*t);
    if (offset + 4 > len)
	return 0;
    *qtype = nptohs(buf + offset);
    *qclass = nptohs(buf + offset + 2);
    offset += 4;
    return offset;
}
예제 #7
0
/*
 * When passing on to the next layers, use the ip_len
 * value for the length, unless the given len happens to
 * to be less for some reason.  Note that ip_len might
 * be less than len due to Ethernet padding.
 */
void
handle_ipv4(const struct ip *ip, int len, void *userdata)
{
    int offset;
    int iplen;
    uint16_t ip_off;
    if (len < sizeof(*ip))
	return;
    offset = ip->ip_hl << 2;
    iplen = XMIN(nptohs(&ip->ip_len), len);
    if (callback_ipv4)
	if (0 != callback_ipv4(ip, iplen, userdata))
	    return;
    ip_off = ntohs(ip->ip_off);
    if ((ip_off & (IP_OFFMASK | IP_MF)) && _reassemble_fragments) {
	handle_ipv4_fragment(ip, iplen, userdata);
    } else if (IPPROTO_UDP == ip->ip_p) {
	handle_udp((struct udphdr *)((char *)ip + offset), iplen - offset, userdata);
    } else if (IPPROTO_TCP == ip->ip_p) {
	handle_tcp((struct tcphdr *)((char *)ip + offset), iplen - offset, userdata);
    } else if (IPPROTO_GRE == ip->ip_p) {
	handle_gre((u_char *)ip + offset, iplen - offset, userdata);
    }
}
예제 #8
0
static int
rfc1035NameUnpack(const u_char *buf, size_t sz, off_t * off, char *name, int ns)
{
    off_t no = 0;
    unsigned char c;
    size_t len;
    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;
	    s = nptohs(buf + (*off));
	    (*off) += sizeof(s);
	    /* Sanity check */
	    if ((*off) >= sz)
		return 1;	/* message too short */
	    ptr = s & 0x3FFF;
	    /* Make sure the pointer is inside this message */
	    if (ptr >= 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.)"
	     */
	    return 3;		/* reserved label/compression flags */
	    break;
	} else {
	    (*off)++;
	    len = (size_t) c;
	    if (len == 0)
		break;
	    if (len > (ns - 1))
		len = ns - 1;
	    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);
    if (no > 0)
	*(name + no - 1) = '\0';
    /* make sure we didn't allow someone to overflow the name buffer */
    assert(no <= ns);
    return 0;
}
예제 #9
0
    x = rfc1035NameUnpack(buf, len, &offset, somename, MAX_QNAME_SZ);
    if (0 != x)
	return 0;
    if (offset + 10 > len)
	return 0;
    sometype = nptohs(buf + offset);
    someclass = nptohs(buf + offset + 2);
    if (sometype == T_OPT) {
	m->edns.found = 1;
	m->edns.bufsiz = someclass;
	memcpy(&m->edns.version, buf + offset + 5, 1);
	us = nptohs(buf + offset + 6);
	m->edns.DO = (us >> 15) & 0x01;		/* RFC 3225 */
    }
    /* get rdlength */
    us = nptohs(buf + offset + 8);
    offset += 10;
    if (offset + us > len)
	return 0;
    offset += us;
    return offset;
}

void
handle_dns(const u_char *buf, uint16_t len, transport_message *tm, DMC *dns_message_callback)
{
    unsigned short us;
    off_t offset;
    int qdcount;
    int ancount;
    int nscount;
예제 #10
0
void
handle_ipv6(const struct ip6_hdr *ip6, int len, void *userdata)
{
    int offset;
    int nexthdr;
    uint16_t payload_len;

    if (len < sizeof(*ip6))
	return;
    if (callback_ipv6)
	if (0 != callback_ipv6(ip6, len, userdata))
	    return;

    offset = sizeof(struct ip6_hdr);
    nexthdr = ip6->ip6_nxt;
    payload_len = nptohs(&ip6->ip6_plen);

    /*
     * Parse extension headers. This only handles the standard headers, as
     * defined in RFC 2460, correctly. Fragments are discarded.
     */
    while ((IPPROTO_ROUTING == nexthdr)	/* routing header */
	||(IPPROTO_HOPOPTS == nexthdr)	/* Hop-by-Hop options. */
	||(IPPROTO_FRAGMENT == nexthdr)	/* fragmentation header. */
	||(IPPROTO_DSTOPTS == nexthdr)	/* destination options. */
	||(IPPROTO_AH == nexthdr)	/* authentication header. */
	||(IPPROTO_ESP == nexthdr)) {	/* encapsulating security payload. */
	typedef struct {
	    uint8_t nexthdr;
	    uint8_t length;
	}      ext_hdr_t;
	ext_hdr_t *ext_hdr;
	uint16_t ext_hdr_len;

	/* Catch broken packets */
	if ((offset + sizeof(ext_hdr)) > len)
	    return;

	/* Cannot handle fragments. */
	if (IPPROTO_FRAGMENT == nexthdr)
	    return;

	ext_hdr = (ext_hdr_t *) ((char *)ip6 + offset);
	nexthdr = ext_hdr->nexthdr;
	ext_hdr_len = (8 * (ext_hdr->length + 1));

	/* This header is longer than the packets payload.. WTF? */
	if (ext_hdr_len > payload_len)
	    return;

	offset += ext_hdr_len;
	payload_len -= ext_hdr_len;
    }				/* while */

    /* Catch broken and empty packets */
    if (((offset + payload_len) > len)
	|| (payload_len == 0)
	|| (payload_len > PCAP_SNAPLEN))
	return;

    if (IPPROTO_UDP == nexthdr) {
	handle_udp((struct udphdr *)((char *)ip6 + offset), payload_len, userdata);
    } else if (IPPROTO_TCP == nexthdr) {
	handle_tcp((struct tcphdr *)((char *)ip6 + offset), payload_len, userdata);
    } else if (IPPROTO_GRE == nexthdr) {
	handle_gre((u_char *)ip6 + offset, payload_len, userdata);
    }
}