source: lib/linktypes.c @ 34cab5b

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

Understand ARPHRD_NONE

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