source: lib/linktypes.c @ 50ce607

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 50ce607 was f7bcbfb, checked in by Shane Alcock <salcock@…>, 7 years ago

Fixed warnings that cropped up when building with clang

  • Added proper "unknown" or "error" values to some libtrace enums. This removes the need for the hideous ==~0U checks that we used to do to check for errors and should be a bit more robust.
  • Fixed potential strncat bugs in one of the libpacketdump decoders.
  • Changed some null-ops in ior-peek as our current method was triggering warnings.
  • Property mode set to 100644
File size: 12.5 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 "libtrace_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                case TRACE_DLT_OPENBSD_LOOP: return TRACE_TYPE_OPENBSD_LOOP;
68                /* Unhandled */
69                case TRACE_DLT_ERROR:
70                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
71                                         * header If you want raw L3 headers
72                                         * use TRACE_DLT_RAW
73                                         */
74                        break;
75        }
76        return TRACE_TYPE_UNKNOWN;
77}
78
79libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
80{
81        /* If pcap doesn't have a DLT, you can either ask pcap to register
82         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
83         * can add it to demote_packet
84         */
85        switch(type) {
86                case TRACE_TYPE_NONE: return TRACE_DLT_RAW; 
87                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
88                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
89                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
90                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
91                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
92                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
93                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
94                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
95                /* Theres more than one type of PPP.  Who knew? */
96                case TRACE_TYPE_POS:    return TRACE_DLT_PPP_SERIAL; 
97                case TRACE_TYPE_OPENBSD_LOOP: return TRACE_DLT_OPENBSD_LOOP;
98
99                /* Below here are unsupported conversions */
100                /* Despite hints to the contrary, there is no DLT
101                 * for 'raw atm packets that happen to be missing
102                 * the HEC' or even 'raw atm packets that have a hec'.
103                 *
104                 * The closest are DLT_ATM_RFC1483 but that doesn't
105                 * include the ATM header, only the LLCSNAP header.
106                 */
107                case TRACE_TYPE_ATM:
108                /* pcap has no DLT for DUCK */
109                case TRACE_TYPE_DUCK:
110                /* Used for test traces within WAND */
111                case TRACE_TYPE_80211_PRISM:   
112                /* Probably == PPP */
113                /* TODO: We haven't researched these yet */
114                case TRACE_TYPE_AAL5:
115                case TRACE_TYPE_METADATA:
116                case TRACE_TYPE_NONDATA:
117                        break;
118                case TRACE_TYPE_UNKNOWN:
119                        break;
120        }
121        return TRACE_DLT_ERROR;
122}
123
124static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
125{
126        switch (linktype) {
127                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
128                default:
129                                    return linktype;
130        }
131}
132
133libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
134{
135        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
136}
137
138libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
139{
140        /* For pcap the rt type is just the linktype + a fixed value */
141        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
142}
143
144libtrace_rt_types_t bpf_linktype_to_rt(libtrace_dlt_t linktype) {
145        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_BPF;
146
147}
148
149libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
150{
151       
152        if (rt_type >= TRACE_RT_DATA_DLT && rt_type < TRACE_RT_DATA_DLT_END) {
153                /* RT type is in the pcap range */
154                return rt_type - TRACE_RT_DATA_DLT;
155        } 
156        else if (rt_type >= TRACE_RT_DATA_BPF && rt_type < TRACE_RT_DATA_BPF_END) {
157                return rt_type - TRACE_RT_DATA_BPF;
158        }
159       
160        fprintf(stderr, "Error: RT type %u cannot be converted to a pcap DLT\n", rt_type);
161        assert(rt_type >= TRACE_RT_DATA_DLT && rt_type < TRACE_RT_DATA_BPF_END);
162        return 0;       /* satisfy warnings */
163}
164
165libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
166{
167        switch (erf) {
168                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
169                case TYPE_ETH:          return TRACE_TYPE_ETH;
170                case TYPE_ATM:          return TRACE_TYPE_ATM;
171                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
172                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
173                case TYPE_IPV4:         return TRACE_TYPE_NONE;
174                case TYPE_IPV6:         return TRACE_TYPE_NONE;
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               
187                /* Not technically correct! Could be IPv6 packet
188                 *
189                 * TODO: Maybe we want TRACE_TYPE_RAW_IPV4 and
190                 * TRACE_TYPE_RAW_IPV6 to replace TRACE_TYPE_NONE.
191                 * Still need a good way to figure out how to convert
192                 * TRACE_DLT_LINKTYPE_RAW into the correct type for the
193                 * IP version though :( */
194                case TRACE_TYPE_NONE:   return TYPE_IPV4;
195                /* Unsupported conversions */
196                case TRACE_TYPE_LLCSNAP:
197                case TRACE_TYPE_DUCK:
198                case TRACE_TYPE_80211_RADIO:
199                case TRACE_TYPE_80211_PRISM:
200                case TRACE_TYPE_80211:
201                case TRACE_TYPE_PFLOG:
202                case TRACE_TYPE_LINUX_SLL:
203                case TRACE_TYPE_PPP:
204                case TRACE_TYPE_POS:
205                case TRACE_TYPE_METADATA:
206                case TRACE_TYPE_NONDATA:
207                case TRACE_TYPE_OPENBSD_LOOP:
208                case TRACE_TYPE_UNKNOWN:
209                        break;
210        }
211        return 255;
212}
213
214libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
215        switch(arphrd) {
216                case LIBTRACE_ARPHRD_ETHER: return TRACE_TYPE_ETH;     
217                case LIBTRACE_ARPHRD_EETHER: return TRACE_TYPE_ETH;     
218                case LIBTRACE_ARPHRD_IEEE80211: return TRACE_TYPE_80211;
219                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
220                case LIBTRACE_ARPHRD_PPP: return TRACE_TYPE_NONE;
221                case LIBTRACE_ARPHRD_LOOPBACK: return TRACE_TYPE_ETH;
222                case LIBTRACE_ARPHRD_NONE: return TRACE_TYPE_NONE;
223        }
224        printf("Unknown ARPHRD %08x\n",arphrd);
225        return ~0U;
226}
227
228unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
229        switch(linktype) {
230                case TRACE_TYPE_ETH: return LIBTRACE_ARPHRD_ETHER;
231                case TRACE_TYPE_80211: return LIBTRACE_ARPHRD_IEEE80211;
232                case TRACE_TYPE_80211_RADIO: return LIBTRACE_ARPHRD_IEEE80211_RADIOTAP;
233                default: break;
234        }
235        return ~0U;
236}
237
238/** Prepends a Linux SLL header to the packet.
239 *
240 * Packets that don't support direction tagging are annoying, especially
241 * when we have direction tagging information!  So this converts the packet
242 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
243 * pcap style packet for the reason that it means it works with bpf filters.
244 *
245 * @note this will copy the packet, so use sparingly if possible.
246 */
247void promote_packet(libtrace_packet_t *packet)
248{
249        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
250                char *tmpbuffer;
251                libtrace_sll_header_t *hdr;
252
253                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
254                        == TRACE_TYPE_LINUX_SLL) {
255                        /* This is already been promoted, so ignore it */
256                        return;
257                }
258
259                /* This should be easy, just prepend the header */
260                tmpbuffer= (char*)malloc(
261                                sizeof(libtrace_sll_header_t)
262                                +trace_get_capture_length(packet)
263                                +trace_get_framing_length(packet)
264                                );
265
266                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
267                        +trace_get_framing_length(packet));
268
269                hdr->halen=htons(6);
270                hdr->pkttype=TRACE_SLL_OUTGOING;
271
272                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
273                        case TRACE_TYPE_NONE:
274                                trace_get_layer3(packet, &hdr->protocol, NULL);
275                                hdr->hatype = htons(LIBTRACE_ARPHRD_PPP);
276                                hdr->protocol=htons(hdr->protocol);
277                                break;
278                        case TRACE_TYPE_ETH:
279                                hdr->hatype = htons(LIBTRACE_ARPHRD_ETHER);
280                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
281                                break;
282                        default:
283                                /* failed */
284                                return;
285                }
286                memcpy(tmpbuffer,packet->header,
287                                trace_get_framing_length(packet));
288                memcpy(tmpbuffer
289                                +sizeof(libtrace_sll_header_t)
290                                +trace_get_framing_length(packet),
291                                packet->payload,
292                                trace_get_capture_length(packet));
293                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
294                        packet->buf_control=TRACE_CTRL_PACKET;
295                }
296                else {
297                        free(packet->buffer);
298                }
299                packet->buffer=tmpbuffer;
300                packet->header=tmpbuffer;
301                packet->payload=tmpbuffer+trace_get_framing_length(packet);
302                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
303                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
304                        sizeof(libtrace_sll_header_t);
305                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
306                        sizeof(libtrace_sll_header_t);
307                trace_clear_cache(packet);
308                return;
309        }
310}
311
312/* Try and remove any extraneous encapsulation that may have been added to
313 * a packet. Effectively the opposite to promote_packet.
314 *
315 * Returns true if demotion was possible, false if not.
316 */
317bool demote_packet(libtrace_packet_t *packet)
318{
319        uint8_t type;
320        uint16_t ha_type, next_proto;
321        libtrace_sll_header_t *sll = NULL;
322        uint32_t remaining = 0;
323        char *tmp;
324        struct timeval tv;
325        static libtrace_t *trace = NULL;
326        switch(trace_get_link_type(packet)) {
327                case TRACE_TYPE_ATM:
328                        remaining=trace_get_capture_length(packet);
329                        packet->payload=trace_get_payload_from_atm(
330                                packet->payload,&type,&remaining);
331                        if (!packet->payload)
332                                return false;
333                        tmp=(char*)malloc(
334                                trace_get_capture_length(packet)
335                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
336                                );
337
338                        tv=trace_get_timeval(packet);
339                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
340                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
341                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
342                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
343                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
344                                = remaining;
345
346                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
347                                        packet->payload,
348                                        (size_t)remaining);
349                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
350                                packet->buf_control=TRACE_CTRL_PACKET;
351                        }
352                        else {
353                                free(packet->buffer);
354                        }
355                        packet->buffer=tmp;
356                        packet->header=tmp;
357                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
358                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
359                       
360                        if (trace == NULL) {
361                                trace = trace_create_dead("pcapfile:-");
362                        }
363
364                        packet->trace=trace;
365
366                        /* Invalidate caches */
367                        trace_clear_cache(packet);
368                        return true;
369
370                case TRACE_TYPE_LINUX_SLL:
371                        sll = (libtrace_sll_header_t *)(packet->payload);
372
373                        ha_type = ntohs(sll->hatype);
374                        next_proto = ntohs(sll->protocol);
375               
376                        /* Preserved from older libtrace behaviour */
377                        if (ha_type == LIBTRACE_ARPHRD_PPP)
378                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
379                        /* Don't decide trace type based on ha_type,
380                         * decide based on the protocol header that is
381                         * coming up!
382                         */
383                        else if (next_proto == TRACE_ETHERTYPE_LOOPBACK)
384                                packet->type = pcap_linktype_to_rt(TRACE_DLT_EN10MB);
385                        else if (next_proto == TRACE_ETHERTYPE_IP) 
386                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
387                        else if (next_proto == TRACE_ETHERTYPE_IPV6)
388                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
389                        else
390                                return false;
391
392                        /* Skip the Linux SLL header */
393                        packet->payload=(void*)((char*)packet->payload
394                                        +sizeof(libtrace_sll_header_t));
395                        trace_set_capture_length(packet,
396                                trace_get_capture_length(packet)
397                                        -sizeof(libtrace_sll_header_t));
398
399                        /* Invalidate caches */
400                        trace_clear_cache(packet);
401                        break;
402                default:
403                        return false;
404        }
405
406        /* Invalidate caches */
407        trace_clear_cache(packet);
408        return true;
409}
Note: See TracBrowser for help on using the repository browser.