source: lib/linktypes.c @ 1935565

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 1935565 was 64d4398, checked in by Shane Alcock <salcock@…>, 9 years ago

Fixed bugs when converting packets from Linux SLL (pcap) to ERF - thanks to Simon Wadsworth for reporting this problem

  • Raw IP packets (e.g. captured using pcapint:any) are now treated as TRACE_TYPE_NONE internally.
  • TRACE_TYPE_NONE maps to the ERF type TYPE_IPV4 - distinguishing between IPv4 and IPv6 within the current API is a bit tricky so that's on the TODO list
  • Wire length calculation for Ethernet encapsulated inside Linux SLL now includes the FCS, just like every other libtrace packet format.
  • Property mode set to 100644
File size: 11.6 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#include "arphrd.h"
44
45
46/* This file maps libtrace types to/from pcap DLT and erf types
47 *
48 * When adding a new linktype to libtrace, add the mapping(s) here,
49 * and add the understanding of the type to get_ip(), and perhaps
50 * get_{source,destination}_mac (if your linklayer has mac's)
51 */
52
53libtrace_linktype_t pcap_linktype_to_libtrace(libtrace_dlt_t linktype)
54{
55        switch(linktype) {
56                case TRACE_DLT_RAW:
57                case TRACE_DLT_LINKTYPE_RAW: return TRACE_TYPE_NONE;
58                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
59                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
60                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
61                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
62                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
63                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
64                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
65                case TRACE_DLT_PPP_SERIAL: return TRACE_TYPE_POS;
66                case TRACE_DLT_C_HDLC: return TRACE_TYPE_HDLC_POS;
67                /* Unhandled */
68                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
69                                         * header If you want raw L3 headers
70                                         * use TRACE_DLT_RAW
71                                         */
72                        break;
73        }
74        return ~0U;
75}
76
77libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
78{
79        /* If pcap doesn't have a DLT, you can either ask pcap to register
80         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
81         * can add it to demote_packet
82         */
83        switch(type) {
84                case TRACE_TYPE_NONE: return TRACE_DLT_RAW; 
85                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
86                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
87                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
88                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
89                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
90                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
91                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
92                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
93                /* Theres more than one type of PPP.  Who knew? */
94                case TRACE_TYPE_POS:    return TRACE_DLT_PPP_SERIAL; 
95
96                /* Below here are unsupported conversions */
97                /* Despite hints to the contrary, there is no DLT
98                 * for 'raw atm packets that happen to be missing
99                 * the HEC' or even 'raw atm packets that have a hec'.
100                 *
101                 * The closest are DLT_ATM_RFC1483 but that doesn't
102                 * include the ATM header, only the LLCSNAP header.
103                 */
104                case TRACE_TYPE_ATM:
105                /* pcap has no DLT for DUCK */
106                case TRACE_TYPE_DUCK:
107                /* Used for test traces within WAND */
108                case TRACE_TYPE_80211_PRISM:   
109                /* Probably == PPP */
110                /* TODO: We haven't researched these yet */
111                case TRACE_TYPE_AAL5:
112                case TRACE_TYPE_METADATA:
113                case TRACE_TYPE_NONDATA:
114                        break;
115        }
116        return ~0U;
117}
118
119static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
120{
121        switch (linktype) {
122                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
123                default:
124                                    return linktype;
125        }
126}
127
128libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
129{
130        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
131}
132
133libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
134{
135        /* For pcap the rt type is just the linktype + a fixed value */
136        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
137}
138
139libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
140{
141        assert(rt_type >= TRACE_RT_DATA_DLT);
142        return rt_type - TRACE_RT_DATA_DLT;
143}
144
145libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
146{
147        switch (erf) {
148                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
149                case TYPE_ETH:          return TRACE_TYPE_ETH;
150                case TYPE_ATM:          return TRACE_TYPE_ATM;
151                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
152                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
153                case TYPE_IPV4:         return TRACE_TYPE_NONE;
154                case TYPE_IPV6:         return TRACE_TYPE_NONE;
155        }
156        return ~0U;
157}
158
159uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
160{
161        switch(linktype) {
162                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
163                case TRACE_TYPE_ETH:    return TYPE_ETH;
164                case TRACE_TYPE_ATM:    return TYPE_ATM;
165                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
166                case TRACE_TYPE_NONE:   return TYPE_IPV4;
167                /* Unsupported conversions */
168                case TRACE_TYPE_LLCSNAP:
169                case TRACE_TYPE_DUCK:
170                case TRACE_TYPE_80211_RADIO:
171                case TRACE_TYPE_80211_PRISM:
172                case TRACE_TYPE_80211:
173                case TRACE_TYPE_PFLOG:
174                case TRACE_TYPE_LINUX_SLL:
175                case TRACE_TYPE_PPP:
176                case TRACE_TYPE_POS:
177                case TRACE_TYPE_METADATA:
178                case TRACE_TYPE_NONDATA:
179                        break;
180        }
181        return 255;
182}
183
184libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
185        switch(arphrd) {
186                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
187                case ARPHRD_EETHER: return TRACE_TYPE_ETH;     
188                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
189                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
190                case ARPHRD_PPP: return TRACE_TYPE_NONE;
191                case ARPHRD_LOOPBACK: return TRACE_TYPE_ETH;
192                case ARPHRD_NONE: return TRACE_TYPE_NONE;
193        }
194        printf("Unknown ARPHRD %08x\n",arphrd);
195        return ~0U;
196}
197
198unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
199        switch(linktype) {
200                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
201                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
202                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
203                default: break;
204        }
205        return ~0U;
206}
207
208/** Prepends a Linux SLL header to the packet.
209 *
210 * Packets that don't support direction tagging are annoying, especially
211 * when we have direction tagging information!  So this converts the packet
212 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
213 * pcap style packet for the reason that it means it works with bpf filters.
214 *
215 * @note this will copy the packet, so use sparingly if possible.
216 */
217void promote_packet(libtrace_packet_t *packet)
218{
219        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
220                char *tmpbuffer;
221                libtrace_sll_header_t *hdr;
222
223                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
224                        == TRACE_TYPE_LINUX_SLL) {
225                        /* This is already been promoted, so ignore it */
226                        return;
227                }
228
229                /* This should be easy, just prepend the header */
230                tmpbuffer= (char*)malloc(
231                                sizeof(libtrace_sll_header_t)
232                                +trace_get_capture_length(packet)
233                                +trace_get_framing_length(packet)
234                                );
235
236                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
237                        +trace_get_framing_length(packet));
238
239                hdr->halen=htons(6);
240                hdr->pkttype=TRACE_SLL_OUTGOING;
241
242                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
243                        case TRACE_TYPE_NONE:
244                                trace_get_layer3(packet, &hdr->protocol, NULL);
245                                hdr->hatype = htons(ARPHRD_PPP);
246                                hdr->protocol=htons(hdr->protocol);
247                                break;
248                        case TRACE_TYPE_ETH:
249                                hdr->hatype = htons(ARPHRD_ETHER);
250                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
251                                break;
252                        default:
253                                /* failed */
254                                return;
255                }
256                memcpy(tmpbuffer,packet->header,
257                                trace_get_framing_length(packet));
258                memcpy(tmpbuffer
259                                +sizeof(libtrace_sll_header_t)
260                                +trace_get_framing_length(packet),
261                                packet->payload,
262                                trace_get_capture_length(packet));
263                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
264                        packet->buf_control=TRACE_CTRL_PACKET;
265                }
266                else {
267                        free(packet->buffer);
268                }
269                packet->buffer=tmpbuffer;
270                packet->header=tmpbuffer;
271                packet->payload=tmpbuffer+trace_get_framing_length(packet);
272                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
273                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
274                        sizeof(libtrace_sll_header_t);
275                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
276                        sizeof(libtrace_sll_header_t);
277                trace_clear_cache(packet);
278                return;
279        }
280}
281
282/* Try and remove any extraneous encapsulation that may have been added to
283 * a packet. Effectively the opposite to promote_packet.
284 *
285 * Returns true if demotion was possible, false if not.
286 */
287bool demote_packet(libtrace_packet_t *packet)
288{
289        uint8_t type;
290        uint16_t ha_type, next_proto;
291        libtrace_sll_header_t *sll = NULL;
292        uint32_t remaining = 0;
293        char *tmp;
294        struct timeval tv;
295        static libtrace_t *trace = NULL;
296        switch(trace_get_link_type(packet)) {
297                case TRACE_TYPE_ATM:
298                        remaining=trace_get_capture_length(packet);
299                        packet->payload=trace_get_payload_from_atm(
300                                packet->payload,&type,&remaining);
301                        if (!packet->payload)
302                                return false;
303                        tmp=(char*)malloc(
304                                trace_get_capture_length(packet)
305                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
306                                );
307
308                        tv=trace_get_timeval(packet);
309                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
310                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
311                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
312                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
313                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
314                                = remaining;
315
316                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
317                                        packet->payload,
318                                        (size_t)remaining);
319                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
320                                packet->buf_control=TRACE_CTRL_PACKET;
321                        }
322                        else {
323                                free(packet->buffer);
324                        }
325                        packet->buffer=tmp;
326                        packet->header=tmp;
327                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
328                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
329                       
330                        if (trace == NULL) {
331                                trace = trace_create_dead("pcapfile:-");
332                        }
333
334                        packet->trace=trace;
335
336                        /* Invalidate caches */
337                        trace_clear_cache(packet);
338                        return true;
339
340                case TRACE_TYPE_LINUX_SLL:
341                        sll = (libtrace_sll_header_t *)(packet->payload);
342
343                        ha_type = ntohs(sll->hatype);
344                        next_proto = ntohs(sll->protocol);
345               
346                        /* Preserved from older libtrace behaviour */
347                        if (ha_type == ARPHRD_PPP)
348                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
349                        /* Don't decide trace type based on ha_type,
350                         * decide based on the protocol header that is
351                         * coming up!
352                         */
353                        else if (next_proto == TRACE_ETHERTYPE_LOOPBACK)
354                                packet->type = pcap_linktype_to_rt(TRACE_DLT_EN10MB);
355                        else if (next_proto == TRACE_ETHERTYPE_IP) 
356                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
357                        else if (next_proto == TRACE_ETHERTYPE_IPV6)
358                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
359                        else
360                                return false;
361
362#if 0
363                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
364                                        ->hatype)) {
365                                case ARPHRD_PPP:
366                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
367                                        break;
368                                case ARPHRD_ETHER:
369                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
370                                        break;
371                                default:
372                                        /* Dunno how to demote this packet */
373                                        return false;
374                        }
375#endif
376                        /* Skip the Linux SLL header */
377                        packet->payload=(void*)((char*)packet->payload
378                                        +sizeof(libtrace_sll_header_t));
379                        trace_set_capture_length(packet,
380                                trace_get_capture_length(packet)
381                                        -sizeof(libtrace_sll_header_t));
382
383                        /* Invalidate caches */
384                        trace_clear_cache(packet);
385                        break;
386                default:
387                        return false;
388        }
389
390        /* Invalidate caches */
391        trace_clear_cache(packet);
392        return true;
393}
Note: See TracBrowser for help on using the repository browser.