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 #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 
     38 static 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 
     49 static int
     50 extract_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 
     92 u_int
     93 ieee802_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