#include <pcap.h>
#include <string.h>
+#include "interface.h"
+#include "addrtoname.h"
+
+#include "extract.h"
+
+static const char *ftypes[] = {
+ "Beacon", /* 0 */
+ "Data", /* 1 */
+ "ACK", /* 2 */
+ "Command", /* 3 */
+ "Reserved", /* 4 */
+ "Reserved", /* 5 */
+ "Reserved", /* 6 */
+ "Reserved", /* 7 */
+};
+
+static int
+extract_header_length(u_int16_t fc)
+{
+ int len = 0;
+
+ switch ((fc >> 10) & 0x3) {
+ case 0x0:
+ if (fc & (1 << 6)) /* intra-PAN with none dest addr */
+ return -1;
+ break;
+ case 0x1:
+ return -1;
+ case 0x02:
+ len += 4;
+ break;
+ case 0x03:
+ len += 10;
+ break;
+ }
+
+ switch ((fc >> 14) & 0x3) {
+ case 0x0:
+ break;
+ case 0x1:
+ return -1;
+ case 0x02:
+ len += 4;
+ break;
+ case 0x03:
+ len += 10;
+ break;
+ }
+
+ if (fc & (1 << 6))
+ len -= 2;
+
+ return len;
+}
+
+
u_int
ieee802_15_4_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
- printf("IEEE 802.15.4 packet");
+ u_int caplen = h->caplen;
+ u_int hdrlen;
+ u_int16_t fc;
+ u_int8_t seq;
+
+ if (caplen < 3) {
+ printf("[|802.15.4] %x", caplen);
+ return caplen;
+ }
+
+ fc = EXTRACT_LE_16BITS(p);
+ hdrlen = extract_header_length(fc);
+
+ seq = EXTRACT_LE_8BITS(p + 2);
+
+ p += 3;
+ caplen -= 3;
+
+ printf("IEEE 802.15.4 %s packet ", ftypes[fc & 0x7]);
+ if (vflag)
+ printf("seq %02x ", seq);
+ if (hdrlen == -1) {
+ printf("malformed! ");
+ return caplen;
+ }
+
+
+ if (!vflag) {
+ p+= hdrlen;
+ caplen -= hdrlen;
+ } else {
+ u_int16_t panid;
+
+ switch ((fc >> 10) & 0x3) {
+ case 0x00:
+ printf("none ");
+ break;
+ case 0x02:
+ panid = EXTRACT_LE_16BITS(p);
+ p += 2;
+ printf("%04x:%04x ", panid, EXTRACT_LE_16BITS(p));
+ p += 2;
+ break;
+ case 0x03:
+ panid = EXTRACT_LE_16BITS(p);
+ p += 2;
+ printf("%04x:%s ", panid, le64addr_string(p));
+ p += 8;
+ break;
+ }
+ printf("< ");
+
+ switch ((fc >> 14) & 0x3) {
+ case 0x00:
+ printf("none ");
+ break;
+ case 0x02:
+ if (!(fc & (1 << 6))) {
+ panid = EXTRACT_LE_16BITS(p);
+ p += 2;
+ }
+ printf("%04x:%04x ", panid, EXTRACT_LE_16BITS(p));
+ p += 2;
+ break;
+ case 0x03:
+ if (!(fc & (1 << 6))) {
+ panid = EXTRACT_LE_16BITS(p);
+ p += 2;
+ }
+ printf("%04x:%s ", panid, le64addr_string(p));
+ p += 8;
+ break;
+ }
+
+ caplen -= hdrlen;
+ }
+
+ if (!suppress_default_print)
+ default_print(p, caplen);
+
return 0;
}