source: lib/linktypes.c @ 73dd29f

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

Sooo, pcap has two types of DLT's "pure" DLT's that are platform dependant,
and "linktype" DLT's that are portable and are what are written to pcap files.

Instead of fudging the two concepts together so much, attempt to disintangle
this mess without exposing too much of the god awful mess to the end user.

  • Property mode set to 100644
File size: 9.1 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_linktype_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                case TRACE_TYPE_METADATA:
90                        break;
91        }
92        return ~0U;
93}
94
95libtrace_linktype_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
96{
97        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
98}
99
100static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
101{
102        switch (linktype) {
103                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
104                default:
105                                    return linktype;
106        }
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_linktype_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        }
129        return ~0U;
130}
131
132uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
133{
134        switch(linktype) {
135                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
136                case TRACE_TYPE_ETH:    return TYPE_ETH;
137                case TRACE_TYPE_ATM:    return TYPE_ATM;
138                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
139                /* Unsupported conversions */
140                case TRACE_TYPE_LLCSNAP:
141                case TRACE_TYPE_DUCK:
142                case TRACE_TYPE_80211_RADIO:
143                case TRACE_TYPE_80211_PRISM:
144                case TRACE_TYPE_80211:
145                case TRACE_TYPE_PFLOG:
146                case TRACE_TYPE_NONE:
147                case TRACE_TYPE_LINUX_SLL:
148                case TRACE_TYPE_PPP:
149                case TRACE_TYPE_POS:
150                case TRACE_TYPE_METADATA:
151                        break;
152        }
153        return 255;
154}
155
156libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
157        switch(arphrd) {
158                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
159                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
160                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
161        }
162        return ~0U;
163}
164
165unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
166        switch(linktype) {
167                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
168                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
169                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
170                default: break;
171        }
172        return ~0U;
173}
174
175/** Tinker with a packet
176 * packets that don't support direction tagging are annoying, especially
177 * when we have direction tagging information!  So this converts the packet
178 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
179 * pcap style packet for the reason that it means it works with bpf filters.
180 *
181 * @note this will copy the packet, so use sparingly if possible.
182 */
183void promote_packet(libtrace_packet_t *packet)
184{
185        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
186                char *tmpbuffer;
187                libtrace_sll_header_t *hdr;
188
189                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
190                        == TRACE_TYPE_LINUX_SLL) {
191                        /* This is already been promoted, so ignore it */
192                        return;
193                }
194
195                /* This should be easy, just prepend the header */
196                tmpbuffer= (char*)malloc(
197                                sizeof(libtrace_sll_header_t)
198                                +trace_get_capture_length(packet)
199                                +trace_get_framing_length(packet)
200                                );
201
202                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
203                        +trace_get_framing_length(packet));
204
205                hdr->halen=htons(6);
206                hdr->pkttype=TRACE_SLL_OUTGOING;
207
208                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
209                        case TRACE_TYPE_NONE:
210                                trace_get_payload_from_link(
211                                        trace_get_link(packet),
212                                        trace_get_link_type(packet),
213                                        &hdr->protocol,
214                                        NULL);
215                                hdr->hatype = htons(ARPHRD_PPP);
216                                hdr->protocol=htons(hdr->protocol);
217                                break;
218                        case TRACE_TYPE_ETH:
219                                hdr->hatype = htons(ARPHRD_ETHER);
220                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
221                                break;
222                        default:
223                                /* failed */
224                                return;
225                }
226                memcpy(tmpbuffer,packet->header,
227                                trace_get_framing_length(packet));
228                memcpy(tmpbuffer
229                                +sizeof(libtrace_sll_header_t)
230                                +trace_get_framing_length(packet),
231                                packet->payload,
232                                trace_get_capture_length(packet));
233                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
234                        packet->buf_control=TRACE_CTRL_PACKET;
235                }
236                else {
237                        free(packet->buffer);
238                }
239                packet->buffer=tmpbuffer;
240                packet->header=tmpbuffer;
241                packet->payload=tmpbuffer+trace_get_framing_length(packet);
242                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
243                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
244                        sizeof(libtrace_sll_header_t);
245                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
246                        sizeof(libtrace_sll_header_t);
247                return;
248        }
249}
250
251/* Try and simplify the packet one step, kinda the opposite to promote_packet
252 *
253 * returns true if demotion was possible, false if not.
254 */
255bool demote_packet(libtrace_packet_t *packet)
256{
257        uint8_t type;
258        uint32_t remaining;
259        char *tmp;
260        struct timeval tv;
261        static libtrace_t *trace = NULL;
262        switch(trace_get_link_type(packet)) {
263                case TRACE_TYPE_ATM:
264                        remaining=trace_get_capture_length(packet);
265                        packet->payload=trace_get_payload_from_atm(
266                                packet->payload,&type,&remaining);
267
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("pcap:-");
297                        }
298
299                        packet->trace=trace;
300
301                        return true;
302
303                case TRACE_TYPE_LINUX_SLL:
304                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
305                                        ->hatype)) {
306                                case ARPHRD_PPP:
307                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
308                                        break;
309                                case ARPHRD_ETHER:
310                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
311                                        break;
312                                default:
313                                        /* Dunno how to demote this packet */
314                                        return false;
315                        }
316                        /* Skip the Linux SLL header */
317                        packet->payload=(void*)((char*)packet->payload
318                                        +sizeof(libtrace_sll_header_t));
319                        trace_set_capture_length(packet,
320                                trace_get_capture_length(packet)
321                                        -sizeof(libtrace_sll_header_t));
322                        break;
323                default:
324                        return false;
325        }
326        return true;
327}
Note: See TracBrowser for help on using the repository browser.