Home | History | Annotate | Download | only in tcpdump
      1 /*
      2  * Copyright (c) 2009
      3  * 	Siemens AG, All rights reserved.
      4  * 	Dmitry Eremin-Solenikov (dbaryshkov (at) 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 #define NETDISSECT_REWORKED
     24 #ifdef HAVE_CONFIG_H
     25 #include "config.h"
     26 #endif
     27 
     28 #include <tcpdump-stdinc.h>
     29 
     30 #include "interface.h"
     31 #include "addrtoname.h"
     32 
     33 #include "extract.h"
     34 
     35 static const char *ftypes[] = {
     36 	"Beacon",			/* 0 */
     37 	"Data",				/* 1 */
     38 	"ACK",				/* 2 */
     39 	"Command",			/* 3 */
     40 	"Reserved",			/* 4 */
     41 	"Reserved",			/* 5 */
     42 	"Reserved",			/* 6 */
     43 	"Reserved",			/* 7 */
     44 };
     45 
     46 static int
     47 extract_header_length(uint16_t fc)
     48 {
     49 	int len = 0;
     50 
     51 	switch ((fc >> 10) & 0x3) {
     52 	case 0x00:
     53 		if (fc & (1 << 6)) /* intra-PAN with none dest addr */
     54 			return -1;
     55 		break;
     56 	case 0x01:
     57 		return -1;
     58 	case 0x02:
     59 		len += 4;
     60 		break;
     61 	case 0x03:
     62 		len += 10;
     63 		break;
     64 	}
     65 
     66 	switch ((fc >> 14) & 0x3) {
     67 	case 0x00:
     68 		break;
     69 	case 0x01:
     70 		return -1;
     71 	case 0x02:
     72 		len += 4;
     73 		break;
     74 	case 0x03:
     75 		len += 10;
     76 		break;
     77 	}
     78 
     79 	if (fc & (1 << 6)) {
     80 		if (len < 2)
     81 			return -1;
     82 		len -= 2;
     83 	}
     84 
     85 	return len;
     86 }
     87 
     88 
     89 u_int
     90 ieee802_15_4_if_print(netdissect_options *ndo,
     91                       const struct pcap_pkthdr *h, const u_char *p)
     92 {
     93 	u_int caplen = h->caplen;
     94 	int hdrlen;
     95 	uint16_t fc;
     96 	uint8_t seq;
     97 
     98 	if (caplen < 3) {
     99 		ND_PRINT((ndo, "[|802.15.4] %x", caplen));
    100 		return caplen;
    101 	}
    102 
    103 	fc = EXTRACT_LE_16BITS(p);
    104 	hdrlen = extract_header_length(fc);
    105 
    106 	seq = EXTRACT_LE_8BITS(p + 2);
    107 
    108 	p += 3;
    109 	caplen -= 3;
    110 
    111 	ND_PRINT((ndo,"IEEE 802.15.4 %s packet ", ftypes[fc & 0x7]));
    112 	if (ndo->ndo_vflag)
    113 		ND_PRINT((ndo,"seq %02x ", seq));
    114 	if (hdrlen == -1) {
    115 		ND_PRINT((ndo,"malformed! "));
    116 		return caplen;
    117 	}
    118 
    119 
    120 	if (!ndo->ndo_vflag) {
    121 		p+= hdrlen;
    122 		caplen -= hdrlen;
    123 	} else {
    124 		uint16_t panid = 0;
    125 
    126 		switch ((fc >> 10) & 0x3) {
    127 		case 0x00:
    128 			ND_PRINT((ndo,"none "));
    129 			break;
    130 		case 0x01:
    131 			ND_PRINT((ndo,"reserved destination addressing mode"));
    132 			return 0;
    133 		case 0x02:
    134 			panid = EXTRACT_LE_16BITS(p);
    135 			p += 2;
    136 			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
    137 			p += 2;
    138 			break;
    139 		case 0x03:
    140 			panid = EXTRACT_LE_16BITS(p);
    141 			p += 2;
    142 			ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)));
    143 			p += 8;
    144 			break;
    145 		}
    146 		ND_PRINT((ndo,"< "));
    147 
    148 		switch ((fc >> 14) & 0x3) {
    149 		case 0x00:
    150 			ND_PRINT((ndo,"none "));
    151 			break;
    152 		case 0x01:
    153 			ND_PRINT((ndo,"reserved source addressing mode"));
    154 			return 0;
    155 		case 0x02:
    156 			if (!(fc & (1 << 6))) {
    157 				panid = EXTRACT_LE_16BITS(p);
    158 				p += 2;
    159 			}
    160 			ND_PRINT((ndo,"%04x:%04x ", panid, EXTRACT_LE_16BITS(p)));
    161 			p += 2;
    162 			break;
    163 		case 0x03:
    164 			if (!(fc & (1 << 6))) {
    165 				panid = EXTRACT_LE_16BITS(p);
    166 				p += 2;
    167 			}
    168                         ND_PRINT((ndo,"%04x:%s ", panid, le64addr_string(p)));
    169 			p += 8;
    170 			break;
    171 		}
    172 
    173 		caplen -= hdrlen;
    174 	}
    175 
    176 	if (!ndo->ndo_suppress_default_print)
    177 		ND_DEFAULTPRINT(p, caplen);
    178 
    179 	return 0;
    180 }
    181