/* * Function to decode the layer 2 header in the packet. * You need to fill out: * - ctx->l2len * - ctx->srcaddr * - ctx->dstaddr * - ctx->proto * - ctx->decoded_extra * Returns: TCPEDIT_ERROR | TCPEDIT_OK | TCPEDIT_WARN */ int dlt_ieee80211_decode(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) { assert(ctx); assert(packet); assert(pktlen >= dlt_ieee80211_l2len(ctx, packet, pktlen)); dbgx(3, "Decoding 802.11 packet " COUNTER_SPEC, ctx->tcpedit->runtime.packetnum); if (! ieee80211_is_data(ctx, packet, pktlen)) { tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is not a normal 802.11 data frame", ctx->tcpedit->runtime.packetnum); return TCPEDIT_SOFT_ERROR; } if (ieee80211_is_encrypted(ctx, packet, pktlen)) { tcpedit_seterr(ctx->tcpedit, "Packet " COUNTER_SPEC " is encrypted. Unable to decode frame.", ctx->tcpedit->runtime.packetnum); return TCPEDIT_SOFT_ERROR; } ctx->l2len = dlt_ieee80211_l2len(ctx, packet, pktlen); memcpy(&(ctx->srcaddr), ieee80211_get_src((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN); memcpy(&(ctx->dstaddr), ieee80211_get_dst((ieee80211_hdr_t *)packet), ETHER_ADDR_LEN); ctx->proto = dlt_ieee80211_proto(ctx, packet, pktlen); return TCPEDIT_OK; /* success */ }
/* * return the length of the L2 header w/ 802.11 header of the current packet */ int dlt_radiotap_80211_l2len(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) { int radiolen; u_char *data; radiolen = dlt_radiotap_l2len(ctx, packet, pktlen); data = dlt_radiotap_get_80211(ctx, packet, pktlen, radiolen); radiolen += dlt_ieee80211_l2len(ctx, data, pktlen - radiolen); return radiolen; }
/* * Function returns a pointer to the layer 3 protocol header or NULL on error */ u_char * dlt_radiotap_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen) { int radiolen, l2len; u_char *data; assert(ctx); assert(packet); radiolen = dlt_radiotap_l2len(ctx, packet, pktlen); data = dlt_radiotap_get_80211(ctx, packet, pktlen, radiolen); l2len = dlt_ieee80211_l2len(ctx, data, pktlen - radiolen); return tcpedit_dlt_l3data_copy(ctx, data, pktlen - radiolen, l2len); }
/* * Function returns a pointer to the layer 3 protocol header or NULL on error */ u_char * dlt_ieee80211_get_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen) { int l2len; assert(ctx); assert(packet); l2len = dlt_ieee80211_l2len(ctx, packet, pktlen); assert(pktlen >= l2len); dbgx(1, "Getting data for packet " COUNTER_SPEC " from offset: %d", ctx->tcpedit->runtime.packetnum, l2len); return tcpedit_dlt_l3data_copy(ctx, packet, pktlen, l2len); }
/* * function merges the packet (containing L2 and old L3) with the l3data buffer * containing the new l3 data. Note, if L2 % 4 == 0, then they're pointing to the * same buffer, otherwise there was a memcpy involved on strictly aligned architectures * like SPARC */ u_char * dlt_ieee80211_merge_layer3(tcpeditdlt_t *ctx, u_char *packet, const int pktlen, u_char *l3data) { int l2len; assert(ctx); assert(packet); assert(l3data); l2len = dlt_ieee80211_l2len(ctx, packet, pktlen); assert(pktlen >= l2len); return tcpedit_dlt_l3data_merge(ctx, packet, pktlen, l3data, l2len); }
/* * Function returns the Layer 3 protocol type of the given packet, or TCPEDIT_ERROR on error */ int dlt_ieee80211_proto(tcpeditdlt_t *ctx, const u_char *packet, const int pktlen) { int l2len; int hdrlen = 0; u_int16_t *frame_control, fc; struct tcpr_802_2snap_hdr *hdr; assert(ctx); assert(packet); l2len = dlt_ieee80211_l2len(ctx, packet, pktlen); assert(pktlen >= l2len); /* check 802.11 frame control field */ frame_control = (u_int16_t *)packet; fc = ntohs(*frame_control); /* Not all 802.11 frames have data */ if ((fc & ieee80211_FC_TYPE_MASK) != ieee80211_FC_TYPE_DATA) return TCPEDIT_SOFT_ERROR; /* Some data frames are QoS and have no data if (((fc & ieee80211_FC_SUBTYPE_MASK) & ieee80211_FC_SUBTYPE_QOS) == ieee80211_FC_SUBTYPE_QOS) return TCPEDIT_SOFT_ERROR; */ if ((fc & ieee80211_FC_SUBTYPE_QOS) == ieee80211_FC_SUBTYPE_QOS) { hdrlen += 2; } /* figure out the actual header length */ if (ieee80211_USE_4(fc)) { hdrlen += sizeof(ieee80211_addr4_hdr_t); } else { hdrlen += sizeof(ieee80211_hdr_t); } hdr = (struct tcpr_802_2snap_hdr *)&packet[hdrlen]; /* verify the header is 802.2SNAP (8 bytes) not 802.2 (3 bytes) */ if (hdr->snap_dsap == 0xAA && hdr->snap_ssap == 0xAA) return hdr->snap_type; return TCPEDIT_SOFT_ERROR; /* 802.2 has no type field */ }