/* \summary: IEEE 802.11 printer */
-#ifdef HAVE_CONFIG_H
#include <config.h>
-#endif
#include "netdissect-stdinc.h"
#define IEEE802_11_STATUS_LEN 2
#define IEEE802_11_REASON_LEN 2
-/* Length of previous AP in reassocation frame */
+/* Length of previous AP in reassociation frame */
#define IEEE802_11_AP_LEN 6
#define T_MGMT 0x0 /* management */
struct mgmt_header_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr da;
- nd_mac_addr sa;
- nd_mac_addr bssid;
+ nd_mac48 da;
+ nd_mac48 sa;
+ nd_mac48 bssid;
nd_uint16_t seq_ctrl;
};
uint8_t bitmap[251];
};
+struct meshid_t {
+ u_int length;
+ u_char meshid[33]; /* 32 + 1 for null */
+};
+
#define E_SSID 0
#define E_RATES 1
#define E_FH 2
/* reserved 19 */
/* reserved 16 */
/* reserved 16 */
+#define E_MESHID 114
struct mgmt_body_t {
struct fh_t fh;
int tim_present;
struct tim_t tim;
+ int meshid_present;
+ struct meshid_t meshid;
};
struct ctrl_control_wrapper_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr addr1;
+ nd_mac48 addr1;
nd_uint16_t carried_fc[IEEE802_11_CARRIED_FC_LEN];
nd_uint16_t ht_control[IEEE802_11_HT_CONTROL_LEN];
};
struct ctrl_rts_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
- nd_mac_addr ta;
+ nd_mac48 ra;
+ nd_mac48 ta;
};
#define CTRL_RTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
struct ctrl_cts_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
+ nd_mac48 ra;
};
#define CTRL_CTS_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
struct ctrl_ack_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
+ nd_mac48 ra;
};
#define CTRL_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
struct ctrl_ps_poll_hdr_t {
nd_uint16_t fc;
nd_uint16_t aid;
- nd_mac_addr bssid;
- nd_mac_addr ta;
+ nd_mac48 bssid;
+ nd_mac48 ta;
};
#define CTRL_PS_POLL_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_AID_LEN+\
struct ctrl_end_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
- nd_mac_addr bssid;
+ nd_mac48 ra;
+ nd_mac48 bssid;
};
#define CTRL_END_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
struct ctrl_end_ack_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
- nd_mac_addr bssid;
+ nd_mac48 ra;
+ nd_mac48 bssid;
};
#define CTRL_END_ACK_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
struct ctrl_ba_hdr_t {
nd_uint16_t fc;
nd_uint16_t duration;
- nd_mac_addr ra;
+ nd_mac48 ra;
+ nd_mac48 ta;
};
-#define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+IEEE802_11_RA_LEN)
+#define CTRL_BA_HDRLEN (IEEE802_11_FC_LEN+IEEE802_11_DUR_LEN+\
+ IEEE802_11_RA_LEN+IEEE802_11_TA_LEN)
struct ctrl_bar_hdr_t {
nd_uint16_t fc;
nd_uint16_t dur;
- nd_mac_addr ra;
- nd_mac_addr ta;
+ nd_mac48 ra;
+ nd_mac48 ta;
nd_uint16_t ctl;
nd_uint16_t seq;
};
nd_uint8_t flags;
nd_uint8_t ttl;
nd_uint32_t seq;
- nd_mac_addr addr4;
- nd_mac_addr addr5;
- nd_mac_addr addr6;
+ nd_mac48 addr4;
+ nd_mac48 addr5;
+ nd_mac48 addr6;
};
#define IV_IV(iv) ((iv) & 0xFFFFFF)
ND_PRINT("%s", \
CAPABILITY_PRIVACY(p.capability_info) ? ", PRIVACY" : "");
+#define PRINT_MESHID(p) \
+ if (p.meshid_present) { \
+ ND_PRINT(" (MESHID: "); \
+ fn_print_str(ndo, p.meshid.meshid); \
+ ND_PRINT(")"); \
+ }
+
#define MAX_MCS_INDEX 76
/*
"Reserved", /* 69 */
"Reserved", /* 70 */
"Reserved", /* 71 */
- "Invalid contents of RSNE", /* 72 */
- "U-APSD coexistence is not supported", /* 73 */
+ "Invalid contents of RSNE", /* 72 */
+ "U-APSD coexistence is not supported", /* 73 */
"Requested U-APSD coexistence mode is not supported", /* 74 */
"Requested Interval/Duration value cannot be "
"supported with U-APSD coexistence", /* 75 */
"Spectrum Management field is unacceptable", /* 103 */
"Association denied because the requesting STA "
"does not support VHT features", /* 104 */
- "Enablement denied", /* 105 */
+ "Enablement denied", /* 105 */
"Enablement denied due to restriction from an "
"authorized GDB", /* 106 */
"Authorization deenabled", /* 107 */
struct ds_t ds;
struct cf_t cf;
struct tim_t tim;
+ struct meshid_t meshid;
/*
* We haven't seen any elements yet.
pbody->ds_present = 0;
pbody->cf_present = 0;
pbody->tim_present = 0;
+ pbody->meshid_present = 0;
while (length != 0) {
/* Make sure we at least have the element ID and length. */
length -= cf.length;
break;
}
- memcpy(&cf.count, p + offset, 6);
- offset += 6;
- length -= 6;
+ cf.count = GET_U_1(p + offset);
+ offset += 1;
+ length -= 1;
+ cf.period = GET_U_1(p + offset);
+ offset += 1;
+ length -= 1;
+ cf.max_duration = GET_LE_U_2(p + offset);
+ offset += 2;
+ length -= 2;
+ cf.dur_remaining = GET_LE_U_2(p + offset);
+ offset += 2;
+ length -= 2;
/*
* Present and not truncated.
*
}
if (tim.length - 3U > sizeof(tim.bitmap))
return 0;
- memcpy(&tim.count, p + offset, 3);
- offset += 3;
- length -= 3;
-
+ tim.count = GET_U_1(p + offset);
+ offset += 1;
+ length -= 1;
+ tim.period = GET_U_1(p + offset);
+ offset += 1;
+ length -= 1;
+ tim.bitmap_control = GET_U_1(p + offset);
+ offset += 1;
+ length -= 1;
memcpy(tim.bitmap, p + offset, tim.length - 3);
offset += tim.length - 3;
length -= tim.length - 3;
pbody->tim_present = 1;
}
break;
+ case E_MESHID:
+ meshid.length = elementlen;
+ offset += 2;
+ length -= 2;
+ if (meshid.length != 0) {
+ if (meshid.length > sizeof(meshid.meshid) - 1)
+ return 0;
+ memcpy(&meshid.meshid, p + offset, meshid.length);
+ offset += meshid.length;
+ length -= meshid.length;
+ }
+ meshid.meshid[meshid.length] = '\0';
+ /*
+ * Present and not truncated.
+ *
+ * If we haven't already seen a MESHID IE,
+ * copy this one, otherwise ignore this one,
+ * so we later report the first one we saw.
+ */
+ if (!pbody->meshid_present) {
+ pbody->meshid = meshid;
+ pbody->meshid_present = 1;
+ }
+ break;
default:
#if 0
ND_PRINT("(1) unhandled element_id (%u) ",
ND_PRINT(" %s",
CAPABILITY_ESS(pbody.capability_info) ? "ESS" : "IBSS");
PRINT_DS_CHANNEL(pbody);
+ PRINT_MESHID(pbody);
return ret;
trunc:
ret = parse_elements(ndo, &pbody, p, offset, length);
PRINT_SSID(pbody);
- ND_PRINT(" AP : %s", etheraddr_string(ndo, pbody.ap ));
+ ND_PRINT(" AP : %s", mac48_string(ndo, pbody.ap ));
return ret;
trunc:
PRINT_SSID(pbody);
PRINT_RATES(pbody);
PRINT_DS_CHANNEL(pbody);
+ PRINT_MESHID(pbody);
return ret;
trunc:
if (ndo->ndo_eflag) {
ND_PRINT(": %s", reason);
} else {
- ND_PRINT(" (%s): %s", GET_ETHERADDR_STRING(src), reason);
+ ND_PRINT(" (%s): %s", GET_MAC48_STRING(src), reason);
}
return 1;
trunc:
{ 3, "BA" },
{ 7, "HT" },
{ 13, "MeshAction" },
- { 14, "MultiohopAction" },
+ { 14, "MultihopAction" },
{ 15, "SelfprotectAction" },
{ 127, "Vendor" },
{ 0, NULL }
if (ndo->ndo_eflag) {
ND_PRINT(": ");
} else {
- ND_PRINT(" (%s): ", GET_ETHERADDR_STRING(src));
+ ND_PRINT(" (%s): ", GET_MAC48_STRING(src));
}
category = GET_U_1(p);
ND_PRINT("%s ", tok2str(category_str, "Reserved(%u)", category));
ND_TCHECK_LEN(p, CTRL_BAR_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
- GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
- GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
+ GET_MAC48_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
break;
ND_TCHECK_LEN(p, CTRL_BA_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
break;
case CTRL_PS_POLL:
ND_TCHECK_LEN(p, CTRL_PS_POLL_HDRLEN);
ND_TCHECK_LEN(p, CTRL_RTS_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" TA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
+ GET_MAC48_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
break;
case CTRL_CTS:
ND_TCHECK_LEN(p, CTRL_CTS_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
break;
case CTRL_ACK:
ND_TCHECK_LEN(p, CTRL_ACK_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
break;
case CTRL_CF_END:
ND_TCHECK_LEN(p, CTRL_END_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_end_hdr_t *)p)->ra));
break;
case CTRL_END_ACK:
ND_TCHECK_LEN(p, CTRL_END_ACK_HDRLEN);
if (!ndo->ndo_eflag)
ND_PRINT(" RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra));
break;
}
return 1;
if (!FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
ND_PRINT("DA:%s SA:%s BSSID:%s ",
- GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
- GET_ETHERADDR_STRING(ADDR3));
+ GET_MAC48_STRING(ADDR1), GET_MAC48_STRING(ADDR2),
+ GET_MAC48_STRING(ADDR3));
} else if (!FC_TO_DS(fc) && FC_FROM_DS(fc)) {
ND_PRINT("DA:%s BSSID:%s SA:%s ",
- GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
- GET_ETHERADDR_STRING(ADDR3));
+ GET_MAC48_STRING(ADDR1), GET_MAC48_STRING(ADDR2),
+ GET_MAC48_STRING(ADDR3));
} else if (FC_TO_DS(fc) && !FC_FROM_DS(fc)) {
ND_PRINT("BSSID:%s SA:%s DA:%s ",
- GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
- GET_ETHERADDR_STRING(ADDR3));
+ GET_MAC48_STRING(ADDR1), GET_MAC48_STRING(ADDR2),
+ GET_MAC48_STRING(ADDR3));
} else if (FC_TO_DS(fc) && FC_FROM_DS(fc)) {
ND_PRINT("RA:%s TA:%s DA:%s SA:%s ",
- GET_ETHERADDR_STRING(ADDR1), GET_ETHERADDR_STRING(ADDR2),
- GET_ETHERADDR_STRING(ADDR3), GET_ETHERADDR_STRING(ADDR4));
+ GET_MAC48_STRING(ADDR1), GET_MAC48_STRING(ADDR2),
+ GET_MAC48_STRING(ADDR3), GET_MAC48_STRING(ADDR4));
}
#undef ADDR1
const struct mgmt_header_t *hp = (const struct mgmt_header_t *) p;
ND_PRINT("BSSID:%s DA:%s SA:%s ",
- GET_ETHERADDR_STRING((hp)->bssid), GET_ETHERADDR_STRING((hp)->da),
- GET_ETHERADDR_STRING((hp)->sa));
+ GET_MAC48_STRING((hp)->bssid), GET_MAC48_STRING((hp)->da),
+ GET_MAC48_STRING((hp)->sa));
}
static void
switch (FC_SUBTYPE(fc)) {
case CTRL_BAR:
ND_PRINT(" RA:%s TA:%s CTL(%x) SEQ(%u) ",
- GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
- GET_ETHERADDR_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
+ GET_MAC48_STRING(((const struct ctrl_bar_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_bar_hdr_t *)p)->ta),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->ctl),
GET_LE_U_2(((const struct ctrl_bar_hdr_t *)p)->seq));
break;
case CTRL_BA:
- ND_PRINT("RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ba_hdr_t *)p)->ra));
+ ND_PRINT("RA:%s TA:%s ",
+ GET_MAC48_STRING(((const struct ctrl_ba_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_ba_hdr_t *)p)->ta));
break;
case CTRL_PS_POLL:
ND_PRINT("BSSID:%s TA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
- GET_ETHERADDR_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
+ GET_MAC48_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->bssid),
+ GET_MAC48_STRING(((const struct ctrl_ps_poll_hdr_t *)p)->ta));
break;
case CTRL_RTS:
ND_PRINT("RA:%s TA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
- GET_ETHERADDR_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
+ GET_MAC48_STRING(((const struct ctrl_rts_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_rts_hdr_t *)p)->ta));
break;
case CTRL_CTS:
ND_PRINT("RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_cts_hdr_t *)p)->ra));
break;
case CTRL_ACK:
ND_PRINT("RA:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
+ GET_MAC48_STRING(((const struct ctrl_ack_hdr_t *)p)->ra));
break;
case CTRL_CF_END:
ND_PRINT("RA:%s BSSID:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
- GET_ETHERADDR_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
+ GET_MAC48_STRING(((const struct ctrl_end_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_end_hdr_t *)p)->bssid));
break;
case CTRL_END_ACK:
ND_PRINT("RA:%s BSSID:%s ",
- GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
- GET_ETHERADDR_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
+ GET_MAC48_STRING(((const struct ctrl_end_ack_hdr_t *)p)->ra),
+ GET_MAC48_STRING(((const struct ctrl_end_ack_hdr_t *)p)->bssid));
break;
default:
/* We shouldn't get here - we should already have quit */
ND_PRINT("MeshData (AE %u TTL %u seq %u", ae,
GET_U_1(mc->ttl), GET_LE_U_4(mc->seq));
if (ae > 0)
- ND_PRINT(" A4:%s", GET_ETHERADDR_STRING(mc->addr4));
+ ND_PRINT(" A4:%s", GET_MAC48_STRING(mc->addr4));
if (ae > 1)
- ND_PRINT(" A5:%s", GET_ETHERADDR_STRING(mc->addr5));
+ ND_PRINT(" A5:%s", GET_MAC48_STRING(mc->addr5));
if (ae > 2)
- ND_PRINT(" A6:%s", GET_ETHERADDR_STRING(mc->addr6));
+ ND_PRINT(" A6:%s", GET_MAC48_STRING(mc->addr6));
ND_PRINT(") ");
}
caplen -= hdrlen;
p += hdrlen;
- src.addr_string = etheraddr_string;
- dst.addr_string = etheraddr_string;
+ src.addr_string = mac48_string;
+ dst.addr_string = mac48_string;
switch (FC_TYPE(fc)) {
case T_MGMT:
get_mgmt_src_dst_mac(p - hdrlen, &src.addr, &dst.addr);