print-802_15_4.c revision 235427
182867Sdfr/*
2139790Simp * Copyright (c) 2009
3139790Simp * 	Siemens AG, All rights reserved.
482867Sdfr * 	Dmitry Eremin-Solenikov (dbaryshkov@gmail.com)
582867Sdfr *
682867Sdfr * Redistribution and use in source and binary forms, with or without
782867Sdfr * modification, are permitted provided that: (1) source code distributions
882867Sdfr * retain the above copyright notice and this paragraph in its entirety, (2)
982867Sdfr * distributions including binary code include the above copyright notice and
1082867Sdfr * this paragraph in its entirety in the documentation or other materials
1182867Sdfr * provided with the distribution, and (3) all advertising materials mentioning
1282867Sdfr * features or use of this software display the following acknowledgement:
1382867Sdfr * ``This product includes software developed by the University of California,
1482867Sdfr * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1582867Sdfr * the University nor the names of its contributors may be used to endorse
1682867Sdfr * or promote products derived from this software without specific prior
1782867Sdfr * written permission.
1882867Sdfr * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1982867Sdfr * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
2082867Sdfr * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2182867Sdfr */
2282867Sdfr
2382867Sdfr#ifdef HAVE_CONFIG_H
2482867Sdfr#include "config.h"
2582867Sdfr#endif
2682867Sdfr
2782867Sdfr#include <tcpdump-stdinc.h>
2882867Sdfr
2982867Sdfr#include <stdio.h>
3082867Sdfr#include <pcap.h>
3182867Sdfr#include <string.h>
3282867Sdfr
3382867Sdfr#include "interface.h"
3482867Sdfr#include "addrtoname.h"
3582867Sdfr
3682867Sdfr#include "extract.h"
3782867Sdfr
3882867Sdfrstatic const char *ftypes[] = {
3982867Sdfr	"Beacon",			/* 0 */
4082867Sdfr	"Data",				/* 1 */
4182867Sdfr	"ACK",				/* 2 */
4282867Sdfr	"Command",			/* 3 */
4382867Sdfr	"Reserved",			/* 4 */
4482867Sdfr	"Reserved",			/* 5 */
4582867Sdfr	"Reserved",			/* 6 */
4682867Sdfr	"Reserved",			/* 7 */
4782867Sdfr};
4882867Sdfr
4982867Sdfrstatic int
5082867Sdfrextract_header_length(u_int16_t fc)
5182867Sdfr{
5282867Sdfr	int len = 0;
5382867Sdfr
5482867Sdfr	switch ((fc >> 10) & 0x3) {
5582867Sdfr	case 0x00:
5682867Sdfr		if (fc & (1 << 6)) /* intra-PAN with none dest addr */
5782867Sdfr			return -1;
5882867Sdfr		break;
5982867Sdfr	case 0x01:
6082867Sdfr		return -1;
6182867Sdfr	case 0x02:
6282867Sdfr		len += 4;
6382867Sdfr		break;
6482867Sdfr	case 0x03:
6582867Sdfr		len += 10;
6682867Sdfr		break;
6782867Sdfr	}
6882867Sdfr
6982867Sdfr	switch ((fc >> 14) & 0x3) {
7082867Sdfr	case 0x00:
7182867Sdfr		break;
7282867Sdfr	case 0x01:
7382867Sdfr		return -1;
7482867Sdfr	case 0x02:
7582867Sdfr		len += 4;
7682867Sdfr		break;
7782867Sdfr	case 0x03:
7882867Sdfr		len += 10;
7982867Sdfr		break;
8082867Sdfr	}
8182867Sdfr
8282867Sdfr	if (fc & (1 << 6)) {
8382867Sdfr		if (len < 2)
8482867Sdfr			return -1;
8582867Sdfr		len -= 2;
8682867Sdfr	}
8782867Sdfr
8882867Sdfr	return len;
8982867Sdfr}
9082867Sdfr
9182867Sdfr
9282867Sdfru_int
9382867Sdfrieee802_15_4_if_print(struct netdissect_options *ndo,
9482867Sdfr                      const struct pcap_pkthdr *h, const u_char *p)
9582867Sdfr{
9682867Sdfr	u_int caplen = h->caplen;
9782867Sdfr	int hdrlen;
9882867Sdfr	u_int16_t fc;
9982867Sdfr	u_int8_t seq;
10082867Sdfr
10182867Sdfr	if (caplen < 3) {
10282867Sdfr		ND_PRINT((ndo, "[|802.15.4] %x", caplen));
10382867Sdfr		return caplen;
10482867Sdfr	}
10582867Sdfr
10682867Sdfr	fc = EXTRACT_LE_16BITS(p);
10782867Sdfr	hdrlen = extract_header_length(fc);
10882867Sdfr
10982867Sdfr	seq = EXTRACT_LE_8BITS(p + 2);
11082867Sdfr
11182867Sdfr	p += 3;
11282867Sdfr	caplen -= 3;
11382867Sdfr
11482867Sdfr	ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7]));
11582867Sdfr	if (vflag)
11682867Sdfr		ND_PRINT((ndo,"seq %02x ", seq));
11782867Sdfr	if (hdrlen == -1) {
11882867Sdfr		ND_PRINT((ndo,"malformed! "));
11982867Sdfr		return caplen;
12082867Sdfr	}
12182867Sdfr
12282867Sdfr
12382867Sdfr	if (!vflag) {
12482867Sdfr		p+= hdrlen;
12582867Sdfr		caplen -= hdrlen;
12682867Sdfr	} else {
12782867Sdfr		u_int16_t panid = 0;
12882867Sdfr
12982867Sdfr		switch ((fc >> 10) & 0x3) {
13082867Sdfr		case 0x00:
13182867Sdfr			ND_PRINT((ndo,"none "));
13282867Sdfr			break;
13382867Sdfr		case 0x01:
13482867Sdfr			ND_PRINT((ndo,"reserved destination addressing mode"));
13582867Sdfr			return 0;
13682867Sdfr		case 0x02:
13782867Sdfr			panid = EXTRACT_LE_16BITS(p);
13882867Sdfr			p += 2;
13982867Sdfr			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
14082867Sdfr			p += 2;
14182867Sdfr			break;
14282867Sdfr		case 0x03:
14382867Sdfr			panid = EXTRACT_LE_16BITS(p);
14482867Sdfr			p += 2;
14582867Sdfr			ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)));
14682867Sdfr			p += 8;
14782867Sdfr			break;
14882867Sdfr		}
14982867Sdfr		ND_PRINT((ndo,"< ");
15082867Sdfr
15182867Sdfr		switch ((fc >> 14) & 0x3) {
15282867Sdfr		case 0x00:
15382867Sdfr			ND_PRINT((ndo,"none "));
15482867Sdfr			break;
15582867Sdfr		case 0x01:
15682867Sdfr			ND_PRINT((ndo,"reserved source addressing mode"));
15782867Sdfr			return 0;
15882867Sdfr		case 0x02:
15982867Sdfr			if (!(fc & (1 << 6))) {
16082867Sdfr				panid = EXTRACT_LE_16BITS(p);
16182867Sdfr				p += 2;
16282867Sdfr			}
16382867Sdfr			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
16482867Sdfr			p += 2;
16582867Sdfr			break;
16682867Sdfr		case 0x03:
16782867Sdfr			if (!(fc & (1 << 6))) {
16882867Sdfr				panid = EXTRACT_LE_16BITS(p);
16982867Sdfr				p += 2;
17082867Sdfr			}
17182867Sdfr                        ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))));
17282867Sdfr			p += 8;
17382867Sdfr			break;
17482867Sdfr		}
17582867Sdfr
17682867Sdfr		caplen -= hdrlen;
17782867Sdfr	}
17882867Sdfr
17982867Sdfr	if (!suppress_default_print)
18082867Sdfr		(ndo->ndo_default_print)(ndo, p, caplen);
18182867Sdfr
18282867Sdfr	return 0;
18382867Sdfr}
18482867Sdfr