source: lib/protocols_pktmeta.c @ 41c254d

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 41c254d was 41c254d, checked in by Scott Raynel <smr26@…>, 13 years ago

Don't use sizeof(struct libtrace_linux_sll_t) and instead compute the
header length based on the contents of the header. This fixes a bug
visible via trace_get_payload_from_meta() which returns the correct
pointer but an incorrect remaining byte count.

This bug may also affect demote_packet() but this hasn't been looked at
yet.

  • Property mode set to 100644
File size: 7.2 KB
Line 
1/* Protocol decodes for packet metadata headers */
2#include "libtrace.h"
3#include "libtrace_int.h"
4#include "protocols.h"
5#include <assert.h>
6
7#ifndef WIN32
8#include <net/if_arp.h>
9#endif
10
11#ifndef ARPHRD_ETHER
12#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
13#endif
14
15#ifndef ARPHRD_PPP
16#define ARPHRD_PPP      512
17#endif
18
19/* NB: type is returned as an ARPHRD_ type for SLL*/
20void *trace_get_payload_from_linux_sll(const void *link,
21                uint16_t *type, uint32_t *remaining) 
22{
23        libtrace_sll_header_t *sll = (libtrace_sll_header_t*) link;
24
25        /* Determine SLL header length */
26        uint32_t hlen = ntohs(sll->halen) + (sizeof(uint16_t) * 4);
27
28        if (remaining) {
29                if (*remaining <= hlen) {
30                        *remaining = 0;
31                        return NULL;
32                }
33                *remaining -= hlen;
34        }
35
36        if (type) *type = ntohs(sll->hatype);
37
38        return (void*) ((char*)sll + hlen);
39
40}
41
42/* NB: type is returned as an ethertype */
43static void *trace_get_payload_from_pflog(const void *link,
44                libtrace_linktype_t *type, uint32_t *remaining)
45{
46        libtrace_pflog_header_t *pflog = (libtrace_pflog_header_t*)link;
47        if (remaining) {
48                if (*remaining<=sizeof(*pflog)) {
49                        *remaining = 0;
50                        return NULL;
51                }
52                *remaining-=sizeof(*pflog);
53        }
54        if (type) {
55                *type = TRACE_TYPE_NONE;
56        }
57        return (void*)((char*)pflog+ sizeof(*pflog));
58}
59
60/* Returns the 'payload' of the prism header, which is the 802.11 frame */
61static void *trace_get_payload_from_prism (const void *link,
62                libtrace_linktype_t *type, uint32_t *remaining)
63{
64        if (remaining) {
65                if (*remaining<=144) {
66                        *remaining = 0;
67                        return NULL;
68                }
69                *remaining-=144;
70        }
71
72        if (type) *type = TRACE_TYPE_80211;
73
74        return (void *) ((char*)link+144);
75}
76
77/* Returns the 'payload' of the radiotap header, which is the 802.11 frame */
78static void *trace_get_payload_from_radiotap (const void *link, 
79                libtrace_linktype_t *type, uint32_t *remaining)
80{
81        struct libtrace_radiotap_t *rtap = (struct libtrace_radiotap_t*)link;
82        uint16_t rtaplen = bswap_le_to_host16(rtap->it_len);
83        if (remaining) {
84                if (*remaining <= rtaplen) {
85                        *remaining = 0;
86                        return NULL;
87                }
88                *remaining -= rtaplen;
89        }
90
91        if (type) *type = TRACE_TYPE_80211;
92
93        return (void*) ((char*)link + rtaplen);
94}
95
96DLLEXPORT void *trace_get_packet_meta(const libtrace_packet_t *packet, 
97                libtrace_linktype_t *linktype,
98                uint32_t *remaining)
99{
100        uint32_t dummyrem;
101        void *pktbuf = NULL;
102        assert(packet != NULL);
103        assert(linktype != NULL);
104       
105        if (remaining == NULL) 
106                remaining = &dummyrem;
107       
108        pktbuf = trace_get_packet_buffer(packet, linktype, remaining);
109        switch (*linktype) {
110                case TRACE_TYPE_LINUX_SLL:
111                case TRACE_TYPE_80211_RADIO:
112                case TRACE_TYPE_80211_PRISM:
113                        return pktbuf;
114                /* Non metadata packets */
115                case TRACE_TYPE_HDLC_POS:
116                case TRACE_TYPE_ETH:
117                case TRACE_TYPE_ATM:
118                case TRACE_TYPE_80211:
119                case TRACE_TYPE_NONE:
120                case TRACE_TYPE_PFLOG:
121                case TRACE_TYPE_POS:
122                case TRACE_TYPE_AAL5:
123                case TRACE_TYPE_DUCK:
124                case TRACE_TYPE_LLCSNAP:
125                case TRACE_TYPE_PPP:
126                case TRACE_TYPE_METADATA:
127                        return NULL;
128        }
129
130        /* Shouldn't get here */
131        return NULL;
132}
133
134DLLEXPORT void *trace_get_payload_from_meta(const void *meta,
135                libtrace_linktype_t *linktype,
136                uint32_t *remaining)
137{
138        void *nexthdr; 
139        uint16_t arphrd;
140       
141        assert(meta != NULL);
142        assert(linktype != NULL);
143        assert(remaining != NULL);
144       
145        switch(*linktype) {
146                case TRACE_TYPE_LINUX_SLL:
147                        nexthdr = trace_get_payload_from_linux_sll(meta,
148                                        &arphrd, remaining);
149                        *linktype = arphrd_type_to_libtrace(arphrd);
150                        return nexthdr;
151                case TRACE_TYPE_80211_RADIO:
152                        nexthdr = trace_get_payload_from_radiotap(meta,
153                                        linktype, remaining);
154                        return nexthdr;
155                case TRACE_TYPE_80211_PRISM:
156                        nexthdr = trace_get_payload_from_prism(meta,
157                                        linktype, remaining);
158                        return nexthdr;
159                case TRACE_TYPE_PFLOG:
160                        nexthdr = trace_get_payload_from_pflog(meta,
161                                        linktype, remaining);
162                        return nexthdr;
163                case TRACE_TYPE_HDLC_POS:
164                case TRACE_TYPE_ETH:
165                case TRACE_TYPE_ATM:
166                case TRACE_TYPE_80211:
167                case TRACE_TYPE_NONE:
168                case TRACE_TYPE_POS:
169                case TRACE_TYPE_AAL5:
170                case TRACE_TYPE_DUCK:
171                case TRACE_TYPE_LLCSNAP:
172                case TRACE_TYPE_PPP:
173                case TRACE_TYPE_METADATA:
174                        /* In this case, the pointer passed in does not point
175                         * to a metadata header and so we cannot get the
176                         * payload.
177                         */
178                        return NULL;
179        }
180        /* Shouldn't get here */
181        return NULL;
182}
183
184/* Take a pointer to the start of an IEEE 802.11 MAC frame and return a pointer
185 * to the source MAC address. 
186 * If the frame does not contain a sender address, e.g. ACK frame, return NULL.
187 * If the frame is a 4-address WDS frame, return TA, i.e. addr2.
188 * NB: This function decodes the 802.11 header, so it assumes that there are no
189 * bit-errors. If there are, all bets are off.
190 */
191static
192uint8_t *get_source_mac_from_wifi(void *wifi) {
193        struct libtrace_80211_t *w;
194        if (wifi == NULL) return NULL;
195        w = (struct libtrace_80211_t *) wifi;
196       
197        /* If the frame is of type CTRL */
198        if (w->type == 0x1) 
199                /* If bit 2 of the subtype field is zero, this indicates that
200                 * there is no transmitter address, i.e. the frame is either an
201                 * ACK or a CTS frame */
202                if ((w->subtype & 0x2) == 0)
203                        return NULL;
204
205        /* Always return the address of the transmitter, i.e. address 2 */
206        return (uint8_t *) &w->mac2;
207}
208
209DLLEXPORT uint8_t *trace_get_source_mac(libtrace_packet_t *packet) {
210        void *link;
211        uint32_t remaining;
212        libtrace_linktype_t linktype;
213        assert(packet);
214        link = trace_get_layer2(packet,&linktype,&remaining);
215
216        if (!link)
217                return NULL;
218       
219        switch (linktype) {
220                case TRACE_TYPE_ETH:
221                        return (uint8_t *)&(((libtrace_ether_t*)link)->ether_shost);
222                case TRACE_TYPE_80211:
223                        return get_source_mac_from_wifi(link);
224                /* These packets don't have MAC addresses */
225                case TRACE_TYPE_POS:
226                case TRACE_TYPE_NONE:
227                case TRACE_TYPE_HDLC_POS:
228                case TRACE_TYPE_PFLOG:
229                case TRACE_TYPE_ATM:
230                case TRACE_TYPE_DUCK:
231                case TRACE_TYPE_METADATA:
232                case TRACE_TYPE_AAL5:
233                case TRACE_TYPE_LLCSNAP:
234                case TRACE_TYPE_PPP:
235                        return NULL;
236
237                /* Metadata headers should already be skipped */
238                case TRACE_TYPE_LINUX_SLL:
239                case TRACE_TYPE_80211_PRISM:
240                case TRACE_TYPE_80211_RADIO:
241                        assert(!"Metadata headers should already be skipped");
242                        break;
243        }
244        fprintf(stderr,"%s not implemented for linktype %i\n", __func__, linktype);
245        assert(0);
246        return NULL;
247}
248
249DLLEXPORT uint8_t *trace_get_destination_mac(libtrace_packet_t *packet) 
250{
251        void *link;
252        libtrace_linktype_t linktype;
253        uint32_t remaining;
254        libtrace_80211_t *wifi;
255        libtrace_ether_t *ethptr;
256       
257        link = trace_get_layer2(packet,&linktype,&remaining);
258
259        ethptr = (libtrace_ether_t*)link;
260
261
262        if (!link)
263                return NULL;
264
265        switch (linktype) {
266                case TRACE_TYPE_80211:
267                        wifi=(libtrace_80211_t*)link;
268                        return (uint8_t*)&wifi->mac1;
269                case TRACE_TYPE_80211_RADIO:
270                        wifi=(libtrace_80211_t*)trace_get_payload_from_radiotap(
271                                        link,NULL,NULL);
272                        return (uint8_t*)&wifi->mac1;
273                case TRACE_TYPE_80211_PRISM:
274                        wifi=(libtrace_80211_t*)((char*)link+144);
275                        return (uint8_t*)&wifi->mac1;
276                case TRACE_TYPE_ETH:
277                        return (uint8_t*)&ethptr->ether_dhost;
278                case TRACE_TYPE_POS:
279                case TRACE_TYPE_NONE:
280                case TRACE_TYPE_ATM:
281                case TRACE_TYPE_HDLC_POS:
282                case TRACE_TYPE_LINUX_SLL:
283                case TRACE_TYPE_PFLOG:
284                case TRACE_TYPE_DUCK:
285                case TRACE_TYPE_METADATA:
286                        /* No MAC address */
287                        return NULL;
288                default:
289                        break;
290        }
291        fprintf(stderr,"Not implemented\n");
292        assert(0);
293        return NULL;
294}
295
296
Note: See TracBrowser for help on using the repository browser.