source: lib/linktypes.c @ e1868fb

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

Cleanup a gazillion warnings

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