source: lib/linktypes.c @ dbdc23f

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

Endace POS traces are in fact PPP traces. Deal with this correctly, even when
converting between trace formats

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