print-802_15_4.c revision 235427
1/*
2 * Copyright (c) 2009
3 * 	Siemens AG, All rights reserved.
4 * 	Dmitry Eremin-Solenikov (dbaryshkov@gmail.com)
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that: (1) source code distributions
8 * retain the above copyright notice and this paragraph in its entirety, (2)
9 * distributions including binary code include the above copyright notice and
10 * this paragraph in its entirety in the documentation or other materials
11 * provided with the distribution, and (3) all advertising materials mentioning
12 * features or use of this software display the following acknowledgement:
13 * ``This product includes software developed by the University of California,
14 * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
15 * the University nor the names of its contributors may be used to endorse
16 * or promote products derived from this software without specific prior
17 * written permission.
18 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
19 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include <tcpdump-stdinc.h>
28
29#include <stdio.h>
30#include <pcap.h>
31#include <string.h>
32
33#include "interface.h"
34#include "addrtoname.h"
35
36#include "extract.h"
37
38static const char *ftypes[] = {
39	"Beacon",			/* 0 */
40	"Data",				/* 1 */
41	"ACK",				/* 2 */
42	"Command",			/* 3 */
43	"Reserved",			/* 4 */
44	"Reserved",			/* 5 */
45	"Reserved",			/* 6 */
46	"Reserved",			/* 7 */
47};
48
49static int
50extract_header_length(u_int16_t fc)
51{
52	int len = 0;
53
54	switch ((fc >> 10) & 0x3) {
55	case 0x00:
56		if (fc & (1 << 6)) /* intra-PAN with none dest addr */
57			return -1;
58		break;
59	case 0x01:
60		return -1;
61	case 0x02:
62		len += 4;
63		break;
64	case 0x03:
65		len += 10;
66		break;
67	}
68
69	switch ((fc >> 14) & 0x3) {
70	case 0x00:
71		break;
72	case 0x01:
73		return -1;
74	case 0x02:
75		len += 4;
76		break;
77	case 0x03:
78		len += 10;
79		break;
80	}
81
82	if (fc & (1 << 6)) {
83		if (len < 2)
84			return -1;
85		len -= 2;
86	}
87
88	return len;
89}
90
91
92u_int
93ieee802_15_4_if_print(struct netdissect_options *ndo,
94                      const struct pcap_pkthdr *h, const u_char *p)
95{
96	u_int caplen = h->caplen;
97	int hdrlen;
98	u_int16_t fc;
99	u_int8_t seq;
100
101	if (caplen < 3) {
102		ND_PRINT((ndo, "[|802.15.4] %x", caplen));
103		return caplen;
104	}
105
106	fc = EXTRACT_LE_16BITS(p);
107	hdrlen = extract_header_length(fc);
108
109	seq = EXTRACT_LE_8BITS(p + 2);
110
111	p += 3;
112	caplen -= 3;
113
114	ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7]));
115	if (vflag)
116		ND_PRINT((ndo,"seq %02x ", seq));
117	if (hdrlen == -1) {
118		ND_PRINT((ndo,"malformed! "));
119		return caplen;
120	}
121
122
123	if (!vflag) {
124		p+= hdrlen;
125		caplen -= hdrlen;
126	} else {
127		u_int16_t panid = 0;
128
129		switch ((fc >> 10) & 0x3) {
130		case 0x00:
131			ND_PRINT((ndo,"none "));
132			break;
133		case 0x01:
134			ND_PRINT((ndo,"reserved destination addressing mode"));
135			return 0;
136		case 0x02:
137			panid = EXTRACT_LE_16BITS(p);
138			p += 2;
139			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
140			p += 2;
141			break;
142		case 0x03:
143			panid = EXTRACT_LE_16BITS(p);
144			p += 2;
145			ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)));
146			p += 8;
147			break;
148		}
149		ND_PRINT((ndo,"< ");
150
151		switch ((fc >> 14) & 0x3) {
152		case 0x00:
153			ND_PRINT((ndo,"none "));
154			break;
155		case 0x01:
156			ND_PRINT((ndo,"reserved source addressing mode"));
157			return 0;
158		case 0x02:
159			if (!(fc & (1 << 6))) {
160				panid = EXTRACT_LE_16BITS(p);
161				p += 2;
162			}
163			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
164			p += 2;
165			break;
166		case 0x03:
167			if (!(fc & (1 << 6))) {
168				panid = EXTRACT_LE_16BITS(p);
169				p += 2;
170			}
171                        ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p))));
172			p += 8;
173			break;
174		}
175
176		caplen -= hdrlen;
177	}
178
179	if (!suppress_default_print)
180		(ndo->ndo_default_print)(ndo, p, caplen);
181
182	return 0;
183}
184