source: lib/linktypes.c @ 15e9390

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

Squash unused item warning

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