source: lib/linktypes.c @ 1326d5f

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 1326d5f was 1326d5f, checked in by Shane Alcock <salcock@…>, 11 years ago
  • OpenSolaris? also doesn't like it if you redefine FILE_OFFSET_BITS after it has defined it itself. The solution: make sure our definition occurs beforehand, e.g. moving config.h to the top of the include list
  • Property mode set to 100644
File size: 11.1 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34#include "config.h"
35#include "libtrace.h"
36
37#include "rt_protocol.h"
38#include <assert.h>
39#include "libtrace_int.h"
40#include <stdlib.h>
41#include <string.h>
42
43#ifndef WIN32
44#include <net/if_arp.h>
45#endif
46
47#ifndef ARPHRD_ETHER
48#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
49#endif
50
51#ifndef ARPHRD_EETHER
52#define ARPHRD_EETHER    2               /* Experimental Ethernet 10/100Mbps.  */
53#endif
54
55#ifndef ARPHRD_PPP
56#define ARPHRD_PPP      512
57#endif
58
59#ifndef ARPHRD_IEEE80211
60#define ARPHRD_IEEE80211        801
61#endif
62
63#ifndef ARPHRD_NONE
64#define ARPHRD_NONE     0xFFFE
65#endif
66
67
68/* This file maps libtrace types to/from pcap DLT and erf types
69 *
70 * When adding a new linktype to libtrace, add the mapping(s) here,
71 * and add the understanding of the type to get_ip(), and perhaps
72 * get_{source,destination}_mac (if your linklayer has mac's)
73 */
74
75libtrace_linktype_t pcap_linktype_to_libtrace(libtrace_dlt_t linktype)
76{
77        switch(linktype) {
78                case TRACE_DLT_RAW:
79                case TRACE_DLT_LINKTYPE_RAW: return TRACE_TYPE_NONE;
80                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
81                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
82                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
83                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
84                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
85                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
86                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
87                case TRACE_DLT_PPP_SERIAL: return TRACE_TYPE_POS;
88                case TRACE_DLT_C_HDLC: return TRACE_TYPE_HDLC_POS;
89                /* Unhandled */
90                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
91                                         * header If you want raw L3 headers
92                                         * use TRACE_DLT_RAW
93                                         */
94                        break;
95        }
96        return ~0U;
97}
98
99libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
100{
101        /* If pcap doesn't have a DLT, you can either ask pcap to register
102         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
103         * can add it to demote_packet
104         */
105        switch(type) {
106                case TRACE_TYPE_NONE: return TRACE_DLT_RAW; 
107                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
108                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
109                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
110                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
111                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
112                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
113                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
114                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
115                /* Theres more than one type of PPP.  Who knew? */
116                case TRACE_TYPE_POS:    return TRACE_DLT_PPP_SERIAL; 
117
118                /* Below here are unsupported conversions */
119                /* Despite hints to the contrary, there is no DLT
120                 * for 'raw atm packets that happen to be missing
121                 * the HEC' or even 'raw atm packets that have a hec'.
122                 *
123                 * The closest are DLT_ATM_RFC1483 but that doesn't
124                 * include the ATM header, only the LLCSNAP header.
125                 */
126                case TRACE_TYPE_ATM:
127                /* pcap has no DLT for DUCK */
128                case TRACE_TYPE_DUCK:
129                /* Used for test traces within WAND */
130                case TRACE_TYPE_80211_PRISM:   
131                /* Probably == PPP */
132                /* TODO: We haven't researched these yet */
133                case TRACE_TYPE_AAL5:
134                case TRACE_TYPE_METADATA:
135                case TRACE_TYPE_NONDATA:
136                        break;
137        }
138        return ~0U;
139}
140
141static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
142{
143        switch (linktype) {
144                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
145                default:
146                                    return linktype;
147        }
148}
149
150libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
151{
152        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
153}
154
155libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
156{
157        /* For pcap the rt type is just the linktype + a fixed value */
158        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
159}
160
161libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
162{
163        assert(rt_type >= TRACE_RT_DATA_DLT);
164        return rt_type - TRACE_RT_DATA_DLT;
165}
166
167libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
168{
169        switch (erf) {
170                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
171                case TYPE_ETH:          return TRACE_TYPE_ETH;
172                case TYPE_ATM:          return TRACE_TYPE_ATM;
173                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
174                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
175        }
176        return ~0U;
177}
178
179uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
180{
181        switch(linktype) {
182                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
183                case TRACE_TYPE_ETH:    return TYPE_ETH;
184                case TRACE_TYPE_ATM:    return TYPE_ATM;
185                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
186                /* Unsupported conversions */
187                case TRACE_TYPE_LLCSNAP:
188                case TRACE_TYPE_DUCK:
189                case TRACE_TYPE_80211_RADIO:
190                case TRACE_TYPE_80211_PRISM:
191                case TRACE_TYPE_80211:
192                case TRACE_TYPE_PFLOG:
193                case TRACE_TYPE_NONE:
194                case TRACE_TYPE_LINUX_SLL:
195                case TRACE_TYPE_PPP:
196                case TRACE_TYPE_POS:
197                case TRACE_TYPE_METADATA:
198                case TRACE_TYPE_NONDATA:
199                        break;
200        }
201        return 255;
202}
203
204libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
205        switch(arphrd) {
206                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
207                case ARPHRD_EETHER: return TRACE_TYPE_ETH;     
208                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
209                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
210                case ARPHRD_PPP: return TRACE_TYPE_NONE;
211                case ARPHRD_NONE: return TRACE_TYPE_NONE;
212        }
213        printf("Unknown ARPHRD %08x\n",arphrd);
214        return ~0U;
215}
216
217unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
218        switch(linktype) {
219                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
220                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
221                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
222                default: break;
223        }
224        return ~0U;
225}
226
227/** Prepends a Linux SLL header to the packet.
228 *
229 * Packets that don't support direction tagging are annoying, especially
230 * when we have direction tagging information!  So this converts the packet
231 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
232 * pcap style packet for the reason that it means it works with bpf filters.
233 *
234 * @note this will copy the packet, so use sparingly if possible.
235 */
236void promote_packet(libtrace_packet_t *packet)
237{
238        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
239                char *tmpbuffer;
240                libtrace_sll_header_t *hdr;
241
242                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
243                        == TRACE_TYPE_LINUX_SLL) {
244                        /* This is already been promoted, so ignore it */
245                        return;
246                }
247
248                /* This should be easy, just prepend the header */
249                tmpbuffer= (char*)malloc(
250                                sizeof(libtrace_sll_header_t)
251                                +trace_get_capture_length(packet)
252                                +trace_get_framing_length(packet)
253                                );
254
255                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
256                        +trace_get_framing_length(packet));
257
258                hdr->halen=htons(6);
259                hdr->pkttype=TRACE_SLL_OUTGOING;
260
261                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
262                        case TRACE_TYPE_NONE:
263                                trace_get_layer3(packet, &hdr->protocol, NULL);
264                                hdr->hatype = htons(ARPHRD_PPP);
265                                hdr->protocol=htons(hdr->protocol);
266                                break;
267                        case TRACE_TYPE_ETH:
268                                hdr->hatype = htons(ARPHRD_ETHER);
269                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
270                                break;
271                        default:
272                                /* failed */
273                                return;
274                }
275                memcpy(tmpbuffer,packet->header,
276                                trace_get_framing_length(packet));
277                memcpy(tmpbuffer
278                                +sizeof(libtrace_sll_header_t)
279                                +trace_get_framing_length(packet),
280                                packet->payload,
281                                trace_get_capture_length(packet));
282                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
283                        packet->buf_control=TRACE_CTRL_PACKET;
284                }
285                else {
286                        free(packet->buffer);
287                }
288                packet->buffer=tmpbuffer;
289                packet->header=tmpbuffer;
290                packet->payload=tmpbuffer+trace_get_framing_length(packet);
291                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
292                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
293                        sizeof(libtrace_sll_header_t);
294                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
295                        sizeof(libtrace_sll_header_t);
296                return;
297        }
298}
299
300/* Try and remove any extraneous encapsulation that may have been added to
301 * a packet. Effectively the opposite to promote_packet.
302 *
303 * Returns true if demotion was possible, false if not.
304 */
305bool demote_packet(libtrace_packet_t *packet)
306{
307        uint8_t type;
308        uint32_t remaining = 0;
309        char *tmp;
310        struct timeval tv;
311        static libtrace_t *trace = NULL;
312        switch(trace_get_link_type(packet)) {
313                case TRACE_TYPE_ATM:
314                        remaining=trace_get_capture_length(packet);
315                        packet->payload=trace_get_payload_from_atm(
316                                packet->payload,&type,&remaining);
317                        if (!packet->payload)
318                                return false;
319                        tmp=(char*)malloc(
320                                trace_get_capture_length(packet)
321                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
322                                );
323
324                        tv=trace_get_timeval(packet);
325                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
326                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
327                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
328                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
329                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
330                                = remaining;
331
332                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
333                                        packet->payload,
334                                        (size_t)remaining);
335                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
336                                packet->buf_control=TRACE_CTRL_PACKET;
337                        }
338                        else {
339                                free(packet->buffer);
340                        }
341                        packet->buffer=tmp;
342                        packet->header=tmp;
343                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
344                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
345                       
346                        if (trace == NULL) {
347                                trace = trace_create_dead("pcapfile:-");
348                        }
349
350                        packet->trace=trace;
351
352                        /* Invalidate caches */
353                        packet->l3_header = NULL;
354                        packet->capture_length = -1;
355
356                        return true;
357
358                case TRACE_TYPE_LINUX_SLL:
359                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
360                                        ->hatype)) {
361                                case ARPHRD_PPP:
362                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
363                                        break;
364                                case ARPHRD_ETHER:
365                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
366                                        break;
367                                default:
368                                        /* Dunno how to demote this packet */
369                                        return false;
370                        }
371                        /* Skip the Linux SLL header */
372                        packet->payload=(void*)((char*)packet->payload
373                                        +sizeof(libtrace_sll_header_t));
374                        trace_set_capture_length(packet,
375                                trace_get_capture_length(packet)
376                                        -sizeof(libtrace_sll_header_t));
377
378                        /* Invalidate caches */
379                        packet->l3_header = NULL;
380                        packet->capture_length = -1;
381                        break;
382                default:
383                        return false;
384        }
385
386        /* Invalidate caches */
387        packet->l3_header = NULL;
388        packet->capture_length = -1;
389        return true;
390}
Note: See TracBrowser for help on using the repository browser.