source: lib/linktypes.c @ fc710bf

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since fc710bf was fc710bf, checked in by Perry Lorier <perry@…>, 12 years ago

Handle Experimental Ethernet

  • Property mode set to 100644
File size: 9.9 KB
Line 
1#include "libtrace.h"
2#include "config.h"
3
4#include "rt_protocol.h"
5#include <assert.h>
6#include "libtrace_int.h"
7#include <stdlib.h>
8#include <string.h>
9
10#ifndef WIN32
11#include <net/if_arp.h>
12#endif
13
14#ifndef ARPHRD_ETHER
15#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
16#endif
17
18#ifndef ARPHRD_EETHER
19#define ARPHRD_EETHER    2               /* Experimental Ethernet 10/100Mbps.  */
20#endif
21
22#ifndef ARPHRD_PPP
23#define ARPHRD_PPP      512
24#endif
25
26#ifndef ARPHRD_IEEE80211
27#define ARPHRD_IEEE80211        801
28#endif
29
30#ifndef ARPHRD_NONE
31#define ARPHRD_NONE     0xFFFE
32#endif
33
34
35/* This file maps libtrace types to/from pcap DLT and erf types
36 *
37 * When adding a new linktype to libtrace, add the mapping(s) here,
38 * and add the understanding of the type to get_ip(), and perhaps
39 * get_{source,destination}_mac (if your linklayer has mac's)
40 */
41
42libtrace_linktype_t pcap_linktype_to_libtrace(libtrace_dlt_t linktype)
43{
44        switch(linktype) {
45                case TRACE_DLT_RAW:
46                case TRACE_DLT_LINKTYPE_RAW: return TRACE_TYPE_NONE;
47                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
48                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
49                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
50                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
51                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
52                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
53                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
54                case TRACE_DLT_PPP_SERIAL: return TRACE_TYPE_POS;
55                /* Unhandled */
56                case TRACE_DLT_C_HDLC:
57                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
58                                         * header If you want raw L3 headers
59                                         * use TRACE_DLT_RAW
60                                         */
61                        break;
62        }
63        return ~0U;
64}
65
66libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
67{
68        /* If pcap doesn't have a DLT, you can either ask pcap to register
69         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
70         * can add it to demote_packet
71         */
72        switch(type) {
73                case TRACE_TYPE_NONE: return TRACE_DLT_RAW; 
74                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
75                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
76                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
77                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
78                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
79                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
80                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
81                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
82                /* Theres more than one type of PPP.  Who knew? */
83                case TRACE_TYPE_POS:    return TRACE_DLT_PPP_SERIAL; 
84
85                /* Below here are unsupported conversions */
86                /* Dispite hints to the contrary, there is no DLT
87                 * for 'raw atm packets that happen to be missing
88                 * the HEC' or even 'raw atm packets that have a hec'.
89                 *
90                 * The closest are DLT_ATM_RFC1483 but that doesn't
91                 * include the ATM header, only the LLCSNAP header.
92                 */
93                case TRACE_TYPE_ATM:
94                /* pcap has no DLT for DUCK */
95                case TRACE_TYPE_DUCK:
96                /* Used for test traces within WAND */
97                case TRACE_TYPE_80211_PRISM:   
98                /* Probably == PPP */
99                /* TODO: We haven't researched these yet */
100                case TRACE_TYPE_AAL5:
101                case TRACE_TYPE_METADATA:
102                        break;
103        }
104        return ~0U;
105}
106
107static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
108{
109        switch (linktype) {
110                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
111                default:
112                                    return linktype;
113        }
114}
115
116libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
117{
118        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
119}
120
121libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
122{
123        /* For pcap the rt type is just the linktype + a fixed value */
124        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
125}
126
127libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
128{
129        assert(rt_type >= TRACE_RT_DATA_DLT);
130        return rt_type - TRACE_RT_DATA_DLT;
131}
132
133libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
134{
135        switch (erf) {
136                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
137                case TYPE_ETH:          return TRACE_TYPE_ETH;
138                case TYPE_ATM:          return TRACE_TYPE_ATM;
139                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
140                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
141        }
142        return ~0U;
143}
144
145uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
146{
147        switch(linktype) {
148                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
149                case TRACE_TYPE_ETH:    return TYPE_ETH;
150                case TRACE_TYPE_ATM:    return TYPE_ATM;
151                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
152                /* Unsupported conversions */
153                case TRACE_TYPE_LLCSNAP:
154                case TRACE_TYPE_DUCK:
155                case TRACE_TYPE_80211_RADIO:
156                case TRACE_TYPE_80211_PRISM:
157                case TRACE_TYPE_80211:
158                case TRACE_TYPE_PFLOG:
159                case TRACE_TYPE_NONE:
160                case TRACE_TYPE_LINUX_SLL:
161                case TRACE_TYPE_PPP:
162                case TRACE_TYPE_POS:
163                case TRACE_TYPE_METADATA:
164                        break;
165        }
166        return 255;
167}
168
169libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
170        switch(arphrd) {
171                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
172                case ARPHRD_EETHER: return TRACE_TYPE_ETH;     
173                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
174                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
175                case ARPHRD_PPP: return TRACE_TYPE_NONE;
176                case ARPHRD_NONE: return TRACE_TYPE_NONE;
177        }
178        printf("Unknown ARPHRD %08x\n",arphrd);
179        return ~0U;
180}
181
182unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
183        switch(linktype) {
184                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
185                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
186                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
187                default: break;
188        }
189        return ~0U;
190}
191
192/** Tinker with a packet
193 * packets that don't support direction tagging are annoying, especially
194 * when we have direction tagging information!  So this converts the packet
195 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
196 * pcap style packet for the reason that it means it works with bpf filters.
197 *
198 * @note this will copy the packet, so use sparingly if possible.
199 */
200void promote_packet(libtrace_packet_t *packet)
201{
202        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
203                char *tmpbuffer;
204                libtrace_sll_header_t *hdr;
205
206                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
207                        == TRACE_TYPE_LINUX_SLL) {
208                        /* This is already been promoted, so ignore it */
209                        return;
210                }
211
212                /* This should be easy, just prepend the header */
213                tmpbuffer= (char*)malloc(
214                                sizeof(libtrace_sll_header_t)
215                                +trace_get_capture_length(packet)
216                                +trace_get_framing_length(packet)
217                                );
218
219                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
220                        +trace_get_framing_length(packet));
221
222                hdr->halen=htons(6);
223                hdr->pkttype=TRACE_SLL_OUTGOING;
224
225                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
226                        case TRACE_TYPE_NONE:
227                                trace_get_layer3(packet, &hdr->protocol, NULL);
228                                hdr->hatype = htons(ARPHRD_PPP);
229                                hdr->protocol=htons(hdr->protocol);
230                                break;
231                        case TRACE_TYPE_ETH:
232                                hdr->hatype = htons(ARPHRD_ETHER);
233                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
234                                break;
235                        default:
236                                /* failed */
237                                return;
238                }
239                memcpy(tmpbuffer,packet->header,
240                                trace_get_framing_length(packet));
241                memcpy(tmpbuffer
242                                +sizeof(libtrace_sll_header_t)
243                                +trace_get_framing_length(packet),
244                                packet->payload,
245                                trace_get_capture_length(packet));
246                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
247                        packet->buf_control=TRACE_CTRL_PACKET;
248                }
249                else {
250                        free(packet->buffer);
251                }
252                packet->buffer=tmpbuffer;
253                packet->header=tmpbuffer;
254                packet->payload=tmpbuffer+trace_get_framing_length(packet);
255                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
256                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
257                        sizeof(libtrace_sll_header_t);
258                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
259                        sizeof(libtrace_sll_header_t);
260                return;
261        }
262}
263
264/* Try and simplify the packet one step, kinda the opposite to promote_packet
265 *
266 * returns true if demotion was possible, false if not.
267 */
268bool demote_packet(libtrace_packet_t *packet)
269{
270        uint8_t type;
271        uint32_t remaining = 0;
272        char *tmp;
273        struct timeval tv;
274        static libtrace_t *trace = NULL;
275        switch(trace_get_link_type(packet)) {
276                case TRACE_TYPE_ATM:
277                        remaining=trace_get_capture_length(packet);
278                        packet->payload=trace_get_payload_from_atm(
279                                packet->payload,&type,&remaining);
280                        if (!packet->payload)
281                                return false;
282                        tmp=(char*)malloc(
283                                trace_get_capture_length(packet)
284                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
285                                );
286
287                        tv=trace_get_timeval(packet);
288                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
289                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
290                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
291                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
292                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
293                                = remaining;
294
295                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
296                                        packet->payload,
297                                        (size_t)remaining);
298                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
299                                packet->buf_control=TRACE_CTRL_PACKET;
300                        }
301                        else {
302                                free(packet->buffer);
303                        }
304                        packet->buffer=tmp;
305                        packet->header=tmp;
306                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
307                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
308                       
309                        if (trace == NULL) {
310                                trace = trace_create_dead("pcapfile:-");
311                        }
312
313                        packet->trace=trace;
314
315                        /* Invalidate caches */
316                        packet->l3_header = NULL;
317                        packet->capture_length = -1;
318
319                        return true;
320
321                case TRACE_TYPE_LINUX_SLL:
322                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
323                                        ->hatype)) {
324                                case ARPHRD_PPP:
325                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
326                                        break;
327                                case ARPHRD_ETHER:
328                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
329                                        break;
330                                default:
331                                        /* Dunno how to demote this packet */
332                                        return false;
333                        }
334                        /* Skip the Linux SLL header */
335                        packet->payload=(void*)((char*)packet->payload
336                                        +sizeof(libtrace_sll_header_t));
337                        trace_set_capture_length(packet,
338                                trace_get_capture_length(packet)
339                                        -sizeof(libtrace_sll_header_t));
340
341                        /* Invalidate caches */
342                        packet->l3_header = NULL;
343                        packet->capture_length = -1;
344                        break;
345                default:
346                        return false;
347        }
348
349        /* Invalidate caches */
350        packet->l3_header = NULL;
351        packet->capture_length = -1;
352        return true;
353}
Note: See TracBrowser for help on using the repository browser.