[f6730d8] | 1 | /* |
---|
| 2 | * |
---|
[ee6e802] | 3 | * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand. |
---|
[f6730d8] | 4 | * All rights reserved. |
---|
| 5 | * |
---|
[ee6e802] | 6 | * This file is part of libtrace. |
---|
| 7 | * |
---|
| 8 | * This code has been developed by the University of Waikato WAND |
---|
[f6730d8] | 9 | * research group. For further information please see http://www.wand.net.nz/ |
---|
| 10 | * |
---|
| 11 | * libtrace is free software; you can redistribute it and/or modify |
---|
[ee6e802] | 12 | * it under the terms of the GNU Lesser General Public License as published by |
---|
| 13 | * the Free Software Foundation; either version 3 of the License, or |
---|
[f6730d8] | 14 | * (at your option) any later version. |
---|
| 15 | * |
---|
| 16 | * libtrace is distributed in the hope that it will be useful, |
---|
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
[ee6e802] | 19 | * GNU Lesser General Public License for more details. |
---|
[f6730d8] | 20 | * |
---|
[ee6e802] | 21 | * You should have received a copy of the GNU Lesser General Public License |
---|
| 22 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
---|
[f6730d8] | 23 | * |
---|
| 24 | * |
---|
| 25 | */ |
---|
[a81d2fc] | 26 | #include "libtrace_int.h" |
---|
[1326d5f] | 27 | #include "libtrace.h" |
---|
[a81d2fc] | 28 | #include "protocols.h" |
---|
| 29 | #include <assert.h> |
---|
| 30 | |
---|
[b663d33] | 31 | #ifdef HAVE_WANDDER |
---|
| 32 | #include <libwandder_etsili.h> |
---|
| 33 | #endif |
---|
| 34 | |
---|
[f6730d8] | 35 | /* This file contains all the protocol decoding functions for the meta-data |
---|
| 36 | * headers that may be prepended to captured packets. |
---|
| 37 | * |
---|
| 38 | * Supported protocols include (but are not limited to): |
---|
| 39 | * Linux SLL |
---|
| 40 | * PFLOG |
---|
| 41 | * RadioTap |
---|
| 42 | * Prism |
---|
| 43 | */ |
---|
| 44 | |
---|
[a81d2fc] | 45 | /* NB: type is returned as an ARPHRD_ type for SLL*/ |
---|
| 46 | void *trace_get_payload_from_linux_sll(const void *link, |
---|
[9cc1266] | 47 | uint16_t *arphrd_type, uint16_t *next, |
---|
| 48 | uint32_t *remaining) |
---|
[a81d2fc] | 49 | { |
---|
[ab25522] | 50 | libtrace_sll_header_t *sll; |
---|
[a81d2fc] | 51 | |
---|
[ab25522] | 52 | sll = (libtrace_sll_header_t*) link; |
---|
[a81d2fc] | 53 | |
---|
| 54 | if (remaining) { |
---|
[aa22b5b] | 55 | if (*remaining < sizeof(*sll)) { |
---|
[35782f6] | 56 | *remaining = 0; |
---|
[a81d2fc] | 57 | return NULL; |
---|
[35782f6] | 58 | } |
---|
[ab25522] | 59 | *remaining-=sizeof(*sll); |
---|
[a81d2fc] | 60 | } |
---|
| 61 | |
---|
[9cc1266] | 62 | /* The SLL header is actually in place of a link layer header, so |
---|
| 63 | * we want to use the protocol field to tell our caller what the |
---|
| 64 | * next header is going to be */ |
---|
| 65 | if (next) *next = (libtrace_linktype_t)(ntohs(sll->protocol)); |
---|
| 66 | if (arphrd_type) *arphrd_type = ntohs(sll->hatype); |
---|
[a81d2fc] | 67 | |
---|
[ab25522] | 68 | return (void*)((char*)sll+sizeof(*sll)); |
---|
[a81d2fc] | 69 | |
---|
| 70 | } |
---|
| 71 | |
---|
[8b98289] | 72 | /* NB: type is returned as an ethertype */ |
---|
| 73 | static void *trace_get_payload_from_pflog(const void *link, |
---|
| 74 | libtrace_linktype_t *type, uint32_t *remaining) |
---|
[a81d2fc] | 75 | { |
---|
| 76 | libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link; |
---|
[8b98289] | 77 | if (remaining) { |
---|
[aa22b5b] | 78 | if (*remaining<sizeof(*pflog)) { |
---|
[35782f6] | 79 | *remaining = 0; |
---|
[a81d2fc] | 80 | return NULL; |
---|
[35782f6] | 81 | } |
---|
[a81d2fc] | 82 | *remaining-=sizeof(*pflog); |
---|
| 83 | } |
---|
| 84 | if (type) { |
---|
[8b98289] | 85 | *type = TRACE_TYPE_NONE; |
---|
[a81d2fc] | 86 | } |
---|
| 87 | return (void*)((char*)pflog+ sizeof(*pflog)); |
---|
| 88 | } |
---|
| 89 | |
---|
| 90 | /* Returns the 'payload' of the prism header, which is the 802.11 frame */ |
---|
[8b98289] | 91 | static void *trace_get_payload_from_prism (const void *link, |
---|
[a81d2fc] | 92 | libtrace_linktype_t *type, uint32_t *remaining) |
---|
| 93 | { |
---|
| 94 | if (remaining) { |
---|
[aa22b5b] | 95 | /* Prism header is 144 bytes long */ |
---|
| 96 | if (*remaining<144) { |
---|
[35782f6] | 97 | *remaining = 0; |
---|
[a81d2fc] | 98 | return NULL; |
---|
[35782f6] | 99 | } |
---|
[a81d2fc] | 100 | *remaining-=144; |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | if (type) *type = TRACE_TYPE_80211; |
---|
| 104 | |
---|
| 105 | return (void *) ((char*)link+144); |
---|
| 106 | } |
---|
| 107 | |
---|
| 108 | /* Returns the 'payload' of the radiotap header, which is the 802.11 frame */ |
---|
[8b98289] | 109 | static void *trace_get_payload_from_radiotap (const void *link, |
---|
[a81d2fc] | 110 | libtrace_linktype_t *type, uint32_t *remaining) |
---|
| 111 | { |
---|
| 112 | struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link; |
---|
| 113 | uint16_t rtaplen = bswap_le_to_host16(rtap->it_len); |
---|
| 114 | if (remaining) { |
---|
[aa22b5b] | 115 | if (*remaining < rtaplen) { |
---|
[35782f6] | 116 | *remaining = 0; |
---|
[a81d2fc] | 117 | return NULL; |
---|
[35782f6] | 118 | } |
---|
[a81d2fc] | 119 | *remaining -= rtaplen; |
---|
| 120 | } |
---|
| 121 | |
---|
| 122 | if (type) *type = TRACE_TYPE_80211; |
---|
| 123 | |
---|
| 124 | return (void*) ((char*)link + rtaplen); |
---|
| 125 | } |
---|
| 126 | |
---|
[b663d33] | 127 | static void *trace_get_payload_from_etsili(const void *link, |
---|
| 128 | libtrace_linktype_t *type, uint32_t *remaining) { |
---|
| 129 | |
---|
| 130 | #ifdef HAVE_WANDDER |
---|
[00365c6] | 131 | wandder_etsispec_t *dec; |
---|
[b663d33] | 132 | uint8_t *ccptr; |
---|
| 133 | |
---|
[00365c6] | 134 | /* XXX Bit annoying to be creating and freeing this every time */ |
---|
| 135 | dec = wandder_create_etsili_decoder(); |
---|
| 136 | wandder_attach_etsili_buffer(dec, (uint8_t *)link, *remaining, false); |
---|
| 137 | ccptr = wandder_etsili_get_cc_contents(dec, remaining); |
---|
[b663d33] | 138 | /* Assuming all CCs are IP for now */ |
---|
| 139 | *type = TRACE_TYPE_NONE; |
---|
[00365c6] | 140 | wandder_free_etsili_decoder(dec); |
---|
[b663d33] | 141 | return ccptr; |
---|
| 142 | |
---|
| 143 | #else |
---|
| 144 | *remaining = NULL; |
---|
| 145 | return NULL; |
---|
| 146 | #endif |
---|
| 147 | |
---|
| 148 | } |
---|
| 149 | |
---|
[a81d2fc] | 150 | DLLEXPORT void *trace_get_packet_meta(const libtrace_packet_t *packet, |
---|
| 151 | libtrace_linktype_t *linktype, |
---|
| 152 | uint32_t *remaining) |
---|
| 153 | { |
---|
| 154 | uint32_t dummyrem; |
---|
[3ac4bf7] | 155 | void *pktbuf = NULL; |
---|
[a81d2fc] | 156 | assert(packet != NULL); |
---|
| 157 | assert(linktype != NULL); |
---|
| 158 | |
---|
| 159 | if (remaining == NULL) |
---|
| 160 | remaining = &dummyrem; |
---|
| 161 | |
---|
[3ac4bf7] | 162 | pktbuf = trace_get_packet_buffer(packet, linktype, remaining); |
---|
[a81d2fc] | 163 | switch (*linktype) { |
---|
| 164 | case TRACE_TYPE_LINUX_SLL: |
---|
| 165 | case TRACE_TYPE_80211_RADIO: |
---|
| 166 | case TRACE_TYPE_80211_PRISM: |
---|
[a857389] | 167 | case TRACE_TYPE_ERF_META: |
---|
[b663d33] | 168 | case TRACE_TYPE_ETSILI: |
---|
[a81d2fc] | 169 | return pktbuf; |
---|
| 170 | /* Non metadata packets */ |
---|
| 171 | case TRACE_TYPE_HDLC_POS: |
---|
| 172 | case TRACE_TYPE_ETH: |
---|
| 173 | case TRACE_TYPE_ATM: |
---|
| 174 | case TRACE_TYPE_80211: |
---|
| 175 | case TRACE_TYPE_NONE: |
---|
| 176 | case TRACE_TYPE_PFLOG: |
---|
| 177 | case TRACE_TYPE_POS: |
---|
| 178 | case TRACE_TYPE_AAL5: |
---|
| 179 | case TRACE_TYPE_DUCK: |
---|
| 180 | case TRACE_TYPE_LLCSNAP: |
---|
| 181 | case TRACE_TYPE_PPP: |
---|
| 182 | case TRACE_TYPE_METADATA: |
---|
[307892f] | 183 | case TRACE_TYPE_NONDATA: |
---|
[77f79c7] | 184 | case TRACE_TYPE_OPENBSD_LOOP: |
---|
[f7bcbfb] | 185 | case TRACE_TYPE_UNKNOWN: |
---|
[a81d2fc] | 186 | return NULL; |
---|
| 187 | } |
---|
| 188 | |
---|
| 189 | /* Shouldn't get here */ |
---|
| 190 | return NULL; |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | DLLEXPORT void *trace_get_payload_from_meta(const void *meta, |
---|
| 194 | libtrace_linktype_t *linktype, |
---|
| 195 | uint32_t *remaining) |
---|
| 196 | { |
---|
| 197 | void *nexthdr; |
---|
[26c2d4c] | 198 | uint16_t arphrd = 0; |
---|
| 199 | uint16_t next = 0; |
---|
[a81d2fc] | 200 | |
---|
| 201 | assert(meta != NULL); |
---|
| 202 | assert(linktype != NULL); |
---|
| 203 | assert(remaining != NULL); |
---|
| 204 | |
---|
| 205 | switch(*linktype) { |
---|
| 206 | case TRACE_TYPE_LINUX_SLL: |
---|
| 207 | nexthdr = trace_get_payload_from_linux_sll(meta, |
---|
[8ccb7897] | 208 | &arphrd, &next, remaining); |
---|
[9cc1266] | 209 | |
---|
| 210 | /* Ethernet header is usually absent in SLL captures, |
---|
| 211 | * so we don't want to skip it just yet */ |
---|
[8ccb7897] | 212 | if (arphrd_type_to_libtrace(arphrd) == TRACE_TYPE_ETH && next != 0x0060) |
---|
[9cc1266] | 213 | *linktype = TRACE_TYPE_NONE; |
---|
| 214 | else |
---|
| 215 | *linktype = arphrd_type_to_libtrace(arphrd); |
---|
[a81d2fc] | 216 | return nexthdr; |
---|
| 217 | case TRACE_TYPE_80211_RADIO: |
---|
| 218 | nexthdr = trace_get_payload_from_radiotap(meta, |
---|
| 219 | linktype, remaining); |
---|
| 220 | return nexthdr; |
---|
| 221 | case TRACE_TYPE_80211_PRISM: |
---|
| 222 | nexthdr = trace_get_payload_from_prism(meta, |
---|
| 223 | linktype, remaining); |
---|
| 224 | return nexthdr; |
---|
[8b98289] | 225 | case TRACE_TYPE_PFLOG: |
---|
| 226 | nexthdr = trace_get_payload_from_pflog(meta, |
---|
| 227 | linktype, remaining); |
---|
| 228 | return nexthdr; |
---|
[b663d33] | 229 | case TRACE_TYPE_ETSILI: |
---|
| 230 | nexthdr = trace_get_payload_from_etsili(meta, |
---|
| 231 | linktype, remaining); |
---|
| 232 | return nexthdr; |
---|
| 233 | |
---|
[a81d2fc] | 234 | case TRACE_TYPE_HDLC_POS: |
---|
| 235 | case TRACE_TYPE_ETH: |
---|
| 236 | case TRACE_TYPE_ATM: |
---|
| 237 | case TRACE_TYPE_80211: |
---|
| 238 | case TRACE_TYPE_NONE: |
---|
| 239 | case TRACE_TYPE_POS: |
---|
| 240 | case TRACE_TYPE_AAL5: |
---|
| 241 | case TRACE_TYPE_DUCK: |
---|
| 242 | case TRACE_TYPE_LLCSNAP: |
---|
| 243 | case TRACE_TYPE_PPP: |
---|
| 244 | case TRACE_TYPE_METADATA: |
---|
[307892f] | 245 | case TRACE_TYPE_NONDATA: |
---|
[77f79c7] | 246 | case TRACE_TYPE_OPENBSD_LOOP: |
---|
[a857389] | 247 | case TRACE_TYPE_ERF_META: |
---|
[f7bcbfb] | 248 | case TRACE_TYPE_UNKNOWN: |
---|
[a81d2fc] | 249 | /* In this case, the pointer passed in does not point |
---|
| 250 | * to a metadata header and so we cannot get the |
---|
| 251 | * payload. |
---|
| 252 | */ |
---|
| 253 | return NULL; |
---|
| 254 | } |
---|
| 255 | /* Shouldn't get here */ |
---|
| 256 | return NULL; |
---|
| 257 | } |
---|
| 258 | |
---|