source: lib/linktypes.c @ 121b7e2

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 121b7e2 was 121b7e2, checked in by Shane Alcock <salcock@…>, 14 years ago
  • Updated format_dag25 to support multiple streams - the new uri format for dag is "dag:/dev/dagX,<stream number>"
  • As each dag card can only be opened by a single process, thread-safety is now incorporated to allow separate threads to read from each dag stream
  • format_dag24 also supports the new uri format, although the stream number is ignored because old dags only have the one stream
  • Updated dagformat.h to include a whole bunch of new erf types
  • Added explicit support for the DSM Coloured Ethernet record type which will be required to deal with streamed packets
  • Fixed erf_get_padding() code that was comparing the return value of trace_get_link_type against an erf type rather than a libtrace link type
  • 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_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                /* Unhandled */
47                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
48                                         * header If you want raw L3 headers
49                                         * use TRACE_DLT_RAW
50                                         */
51                        break;
52        }
53        return ~0U;
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                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
72                /* Below here are unsupported conversions */
73                /* Dispite hints to the contrary, there is no DLT
74                 * for 'raw atm packets that happen to be missing
75                 * the HEC' or even 'raw atm packets that have a hec'.
76                 *
77                 * The closest are DLT_ATM_RFC1483 but that doesn't
78                 * include the ATM header, only the LLCSNAP header.
79                 */
80                case TRACE_TYPE_ATM:
81                /* pcap has no DLT for DUCK */
82                case TRACE_TYPE_DUCK:
83                /* Used for test traces within WAND */
84                case TRACE_TYPE_80211_PRISM:   
85                /* Probably == PPP */
86                case TRACE_TYPE_POS:
87                /* TODO: We haven't researched these yet */
88                case TRACE_TYPE_AAL5:
89                case TRACE_TYPE_METADATA:
90                        break;
91        }
92        return ~0U;
93}
94
95static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
96{
97        switch (linktype) {
98                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
99                default:
100                                    return linktype;
101        }
102}
103
104libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
105{
106        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
107}
108
109libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
110{
111        /* For pcap the rt type is just the linktype + a fixed value */
112        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
113}
114
115libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
116{
117        assert(rt_type >= TRACE_RT_DATA_DLT);
118        return rt_type - TRACE_RT_DATA_DLT;
119}
120
121libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
122{
123        switch (erf) {
124                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
125                case TYPE_ETH:          return TRACE_TYPE_ETH;
126                case TYPE_ATM:          return TRACE_TYPE_ATM;
127                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
128                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
129        }
130        return ~0U;
131}
132
133uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
134{
135        switch(linktype) {
136                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
137                case TRACE_TYPE_ETH:    return TYPE_ETH;
138                case TRACE_TYPE_ATM:    return TYPE_ATM;
139                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
140                /* Unsupported conversions */
141                case TRACE_TYPE_LLCSNAP:
142                case TRACE_TYPE_DUCK:
143                case TRACE_TYPE_80211_RADIO:
144                case TRACE_TYPE_80211_PRISM:
145                case TRACE_TYPE_80211:
146                case TRACE_TYPE_PFLOG:
147                case TRACE_TYPE_NONE:
148                case TRACE_TYPE_LINUX_SLL:
149                case TRACE_TYPE_PPP:
150                case TRACE_TYPE_POS:
151                case TRACE_TYPE_METADATA:
152                        break;
153        }
154        return 255;
155}
156
157libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
158        switch(arphrd) {
159                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
160                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
161                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
162                case ARPHRD_PPP: return TRACE_TYPE_NONE;
163        }
164        printf("Unknown ARPHRD %08x\n",arphrd);
165        return ~0U;
166}
167
168unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
169        switch(linktype) {
170                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
171                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
172                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
173                default: break;
174        }
175        return ~0U;
176}
177
178/** Tinker with a packet
179 * packets that don't support direction tagging are annoying, especially
180 * when we have direction tagging information!  So this converts the packet
181 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
182 * pcap style packet for the reason that it means it works with bpf filters.
183 *
184 * @note this will copy the packet, so use sparingly if possible.
185 */
186void promote_packet(libtrace_packet_t *packet)
187{
188        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
189                char *tmpbuffer;
190                libtrace_sll_header_t *hdr;
191
192                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
193                        == TRACE_TYPE_LINUX_SLL) {
194                        /* This is already been promoted, so ignore it */
195                        return;
196                }
197
198                /* This should be easy, just prepend the header */
199                tmpbuffer= (char*)malloc(
200                                sizeof(libtrace_sll_header_t)
201                                +trace_get_capture_length(packet)
202                                +trace_get_framing_length(packet)
203                                );
204
205                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
206                        +trace_get_framing_length(packet));
207
208                hdr->halen=htons(6);
209                hdr->pkttype=TRACE_SLL_OUTGOING;
210
211                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
212                        case TRACE_TYPE_NONE:
213                                trace_get_layer3(packet, &hdr->protocol, NULL);
214                                hdr->hatype = htons(ARPHRD_PPP);
215                                hdr->protocol=htons(hdr->protocol);
216                                break;
217                        case TRACE_TYPE_ETH:
218                                hdr->hatype = htons(ARPHRD_ETHER);
219                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
220                                break;
221                        default:
222                                /* failed */
223                                return;
224                }
225                memcpy(tmpbuffer,packet->header,
226                                trace_get_framing_length(packet));
227                memcpy(tmpbuffer
228                                +sizeof(libtrace_sll_header_t)
229                                +trace_get_framing_length(packet),
230                                packet->payload,
231                                trace_get_capture_length(packet));
232                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
233                        packet->buf_control=TRACE_CTRL_PACKET;
234                }
235                else {
236                        free(packet->buffer);
237                }
238                packet->buffer=tmpbuffer;
239                packet->header=tmpbuffer;
240                packet->payload=tmpbuffer+trace_get_framing_length(packet);
241                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
242                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
243                        sizeof(libtrace_sll_header_t);
244                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
245                        sizeof(libtrace_sll_header_t);
246                return;
247        }
248}
249
250/* Try and simplify the packet one step, kinda the opposite to promote_packet
251 *
252 * returns true if demotion was possible, false if not.
253 */
254bool demote_packet(libtrace_packet_t *packet)
255{
256        uint8_t type;
257        uint32_t remaining = 0;
258        char *tmp;
259        struct timeval tv;
260        static libtrace_t *trace = NULL;
261        switch(trace_get_link_type(packet)) {
262                case TRACE_TYPE_ATM:
263                        remaining=trace_get_capture_length(packet);
264                        packet->payload=trace_get_payload_from_atm(
265                                packet->payload,&type,&remaining);
266                        if (!packet->payload)
267                                return false;
268                        tmp=(char*)malloc(
269                                trace_get_capture_length(packet)
270                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
271                                );
272
273                        tv=trace_get_timeval(packet);
274                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
275                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
276                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
277                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
278                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
279                                = remaining;
280
281                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
282                                        packet->payload,
283                                        (size_t)remaining);
284                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
285                                packet->buf_control=TRACE_CTRL_PACKET;
286                        }
287                        else {
288                                free(packet->buffer);
289                        }
290                        packet->buffer=tmp;
291                        packet->header=tmp;
292                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
293                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
294                       
295                        if (trace == NULL) {
296                                trace = trace_create_dead("pcapfile:-");
297                        }
298
299                        packet->trace=trace;
300
301                        /* Invalidate caches */
302                        packet->l3_header = NULL;
303                        packet->capture_length = -1;
304
305                        return true;
306
307                case TRACE_TYPE_LINUX_SLL:
308                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
309                                        ->hatype)) {
310                                case ARPHRD_PPP:
311                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
312                                        break;
313                                case ARPHRD_ETHER:
314                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
315                                        break;
316                                default:
317                                        /* Dunno how to demote this packet */
318                                        return false;
319                        }
320                        /* Skip the Linux SLL header */
321                        packet->payload=(void*)((char*)packet->payload
322                                        +sizeof(libtrace_sll_header_t));
323                        trace_set_capture_length(packet,
324                                trace_get_capture_length(packet)
325                                        -sizeof(libtrace_sll_header_t));
326
327                        /* Invalidate caches */
328                        packet->l3_header = NULL;
329                        packet->capture_length = -1;
330                        break;
331                default:
332                        return false;
333        }
334
335        /* Invalidate caches */
336        packet->l3_header = NULL;
337        packet->capture_length = -1;
338        return true;
339}
Note: See TracBrowser for help on using the repository browser.