source: lib/linktypes.c @ 2193905

develop
Last change on this file since 2193905 was 2193905, checked in by Jacob Van Walraven <jcv9@…>, 3 years ago

Apply changes required for pull request #81

  • Property mode set to 100644
File size: 13.1 KB
RevLine 
[ebf8071]1/*
2 *
[ee6e802]3 * Copyright (c) 2007-2016 The University of Waikato, Hamilton, New Zealand.
[ebf8071]4 * All rights reserved.
5 *
[ee6e802]6 * This file is part of libtrace.
7 *
8 * This code has been developed by the University of Waikato WAND
[ebf8071]9 * research group. For further information please see http://www.wand.net.nz/
10 *
11 * libtrace is free software; you can redistribute it and/or modify
[ee6e802]12 * it under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 3 of the License, or
[ebf8071]14 * (at your option) any later version.
15 *
16 * libtrace is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
[ee6e802]19 * GNU Lesser General Public License for more details.
[ebf8071]20 *
[ee6e802]21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
[ebf8071]23 *
24 *
25 */
[97e39a7]26#include "config.h"
[1326d5f]27#include "libtrace.h"
[e5f1431]28
[7ac9705]29#include "rt_protocol.h"
[81f9b6e]30#include "libtrace_int.h"
31#include <stdlib.h>
32#include <string.h>
[643105b]33
[528eb6e]34#include "libtrace_arphrd.h"
[34cab5b]35
[742a332]36
[643105b]37/* This file maps libtrace types to/from pcap DLT and erf types
38 *
39 * When adding a new linktype to libtrace, add the mapping(s) here,
40 * and add the understanding of the type to get_ip(), and perhaps
41 * get_{source,destination}_mac (if your linklayer has mac's)
42 */
43
[73dd29f]44libtrace_linktype_t pcap_linktype_to_libtrace(libtrace_dlt_t linktype)
[643105b]45{
[73dd29f]46        switch(linktype) {
47                case TRACE_DLT_RAW:
48                case TRACE_DLT_LINKTYPE_RAW: return TRACE_TYPE_NONE;
[114b8d6]49                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
50                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
51                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
[d5e1796]52                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
53                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
54                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
[4a207b8]55                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
[29c8666]56                case TRACE_DLT_PPP_SERIAL: return TRACE_TYPE_POS;
[bd94246]57                case TRACE_DLT_C_HDLC: return TRACE_TYPE_HDLC_POS;
[77f79c7]58                case TRACE_DLT_OPENBSD_LOOP: return TRACE_TYPE_OPENBSD_LOOP;
[e7d66bf]59                /* Unhandled */
[f7bcbfb]60                case TRACE_DLT_ERROR:
[e7d66bf]61                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
62                                         * header If you want raw L3 headers
63                                         * use TRACE_DLT_RAW
64                                         */
65                        break;
[643105b]66        }
[f7bcbfb]67        return TRACE_TYPE_UNKNOWN;
[643105b]68}
69
[4c00a35]70libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
[643105b]71{
[d5e1796]72        /* If pcap doesn't have a DLT, you can either ask pcap to register
73         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
74         * can add it to demote_packet
75         */
[643105b]76        switch(type) {
[73dd29f]77                case TRACE_TYPE_NONE: return TRACE_DLT_RAW; 
[114b8d6]78                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
79                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
80                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
81                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
[d5e1796]82                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
83                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
[4a207b8]84                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
[dd06159]85                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
[29c8666]86                /* Theres more than one type of PPP.  Who knew? */
87                case TRACE_TYPE_POS:    return TRACE_DLT_PPP_SERIAL; 
[77f79c7]88                case TRACE_TYPE_OPENBSD_LOOP: return TRACE_DLT_OPENBSD_LOOP;
[29c8666]89
[e7d66bf]90                /* Below here are unsupported conversions */
[ebf8071]91                /* Despite hints to the contrary, there is no DLT
[e7d66bf]92                 * for 'raw atm packets that happen to be missing
93                 * the HEC' or even 'raw atm packets that have a hec'.
94                 *
95                 * The closest are DLT_ATM_RFC1483 but that doesn't
96                 * include the ATM header, only the LLCSNAP header.
97                 */
98                case TRACE_TYPE_ATM:
99                /* pcap has no DLT for DUCK */
100                case TRACE_TYPE_DUCK:
101                /* Used for test traces within WAND */
102                case TRACE_TYPE_80211_PRISM:   
[a857389]103                /* Could use DLT_ERF, but would only really make sense with PCAP-NG */
104                case TRACE_TYPE_ERF_META:
[4a207b8]105                /* Probably == PPP */
106                /* TODO: We haven't researched these yet */
[e7d66bf]107                case TRACE_TYPE_AAL5:
[be22b51]108                case TRACE_TYPE_METADATA:
[3ed3ed3]109                case TRACE_TYPE_NONDATA:
[b663d33]110                case TRACE_TYPE_ETSILI:
[e7d66bf]111                        break;
[f7bcbfb]112                case TRACE_TYPE_UNKNOWN:
[37ee856]113                case TRACE_TYPE_CONTENT_INVALID:
[f7bcbfb]114                        break;
[643105b]115        }
[f7bcbfb]116        return TRACE_DLT_ERROR;
[643105b]117}
118
[73dd29f]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
[d36a8c6]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
[73dd29f]133libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
[7ac9705]134{
[73dd29f]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;
[7ac9705]137}
138
[f00c146]139libtrace_rt_types_t bpf_linktype_to_rt(libtrace_dlt_t linktype) {
140        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_BPF;
141
142}
143
[ed5b2ce]144libtrace_rt_types_t pcapng_linktype_to_rt(libtrace_dlt_t linktype) {
145
146        return TRACE_RT_DATA_PCAPNG + pcap_dlt_to_pcap_linktype(linktype);
147}
148
[4c00a35]149libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
[7ac9705]150{
[ed5b2ce]151
[f00c146]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;
[ed5b2ce]155        }
[f00c146]156        else if (rt_type >= TRACE_RT_DATA_BPF && rt_type < TRACE_RT_DATA_BPF_END) {
157                return rt_type - TRACE_RT_DATA_BPF;
[ed5b2ce]158        } else if (rt_type >= TRACE_RT_DATA_PCAPNG && rt_type < TRACE_RT_DATA_PCAPNG_END) {
159                return rt_type - TRACE_RT_DATA_PCAPNG;
160        }
161
[f00c146]162        fprintf(stderr, "Error: RT type %u cannot be converted to a pcap DLT\n", rt_type);
[e1f3b6b]163        return 0;       /* satisfy warnings */
[7ac9705]164}
165
[4bd8a5b]166libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
[643105b]167{
168        switch (erf) {
[67a14d4]169                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
[643105b]170                case TYPE_ETH:          return TRACE_TYPE_ETH;
171                case TYPE_ATM:          return TRACE_TYPE_ATM;
[67a14d4]172                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
[a857389]173                case TYPE_COLOR_ETH:return TRACE_TYPE_ETH;
[121b7e2]174                case TYPE_DSM_COLOR_ETH:return TRACE_TYPE_ETH;
[a857389]175                case TYPE_COLOR_HASH_ETH:return TRACE_TYPE_ETH;
[64d4398]176                case TYPE_IPV4:         return TRACE_TYPE_NONE;
177                case TYPE_IPV6:         return TRACE_TYPE_NONE;
[a857389]178                case TYPE_META:         return TRACE_TYPE_ERF_META;
[643105b]179        }
[33d83d4]180        return ~0U;
[643105b]181}
182
[4bd8a5b]183uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
[643105b]184{
185        switch(linktype) {
[751531a]186                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
[643105b]187                case TRACE_TYPE_ETH:    return TYPE_ETH;
188                case TRACE_TYPE_ATM:    return TYPE_ATM;
[751531a]189                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
[a857389]190                case TRACE_TYPE_ERF_META: return TYPE_META;
[2627439]191               
192                /* Not technically correct! Could be IPv6 packet
193                 *
194                 * TODO: Maybe we want TRACE_TYPE_RAW_IPV4 and
195                 * TRACE_TYPE_RAW_IPV6 to replace TRACE_TYPE_NONE.
196                 * Still need a good way to figure out how to convert
197                 * TRACE_DLT_LINKTYPE_RAW into the correct type for the
198                 * IP version though :( */
[64d4398]199                case TRACE_TYPE_NONE:   return TYPE_IPV4;
[e7d66bf]200                /* Unsupported conversions */
201                case TRACE_TYPE_LLCSNAP:
202                case TRACE_TYPE_DUCK:
203                case TRACE_TYPE_80211_RADIO:
204                case TRACE_TYPE_80211_PRISM:
205                case TRACE_TYPE_80211:
206                case TRACE_TYPE_PFLOG:
207                case TRACE_TYPE_LINUX_SLL:
[4a207b8]208                case TRACE_TYPE_PPP:
209                case TRACE_TYPE_POS:
[be22b51]210                case TRACE_TYPE_METADATA:
[3ed3ed3]211                case TRACE_TYPE_NONDATA:
[77f79c7]212                case TRACE_TYPE_OPENBSD_LOOP:
[b663d33]213                case TRACE_TYPE_ETSILI:
[f7bcbfb]214                case TRACE_TYPE_UNKNOWN:
[37ee856]215                case TRACE_TYPE_CONTENT_INVALID:
[e7d66bf]216                        break;
[643105b]217        }
[4bd8a5b]218        return 255;
[643105b]219}
[81f9b6e]220
[8889370]221libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
222        switch(arphrd) {
[528eb6e]223                case LIBTRACE_ARPHRD_ETHER: return TRACE_TYPE_ETH;     
224                case LIBTRACE_ARPHRD_EETHER: return TRACE_TYPE_ETH;     
225                case LIBTRACE_ARPHRD_IEEE80211: return TRACE_TYPE_80211;
226                case LIBTRACE_ARPHRD_IEEE80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
227                case LIBTRACE_ARPHRD_PPP: return TRACE_TYPE_NONE;
[4697684]228                case LIBTRACE_ARPHRD_IPGRE: return TRACE_TYPE_NONE;
[528eb6e]229                case LIBTRACE_ARPHRD_LOOPBACK: return TRACE_TYPE_ETH;
[4b64a045]230                case LIBTRACE_ARPHRD_SIT: return TRACE_TYPE_ETH;
[528eb6e]231                case LIBTRACE_ARPHRD_NONE: return TRACE_TYPE_NONE;
[8889370]232        }
[7c72e4d]233        printf("Unknown ARPHRD %08x\n",arphrd);
[33d83d4]234        return ~0U;
[8889370]235}
236
237unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
238        switch(linktype) {
[528eb6e]239                case TRACE_TYPE_ETH: return LIBTRACE_ARPHRD_ETHER;
240                case TRACE_TYPE_80211: return LIBTRACE_ARPHRD_IEEE80211;
241                case TRACE_TYPE_80211_RADIO: return LIBTRACE_ARPHRD_IEEE80211_RADIOTAP;
[eb1aab2]242                default: break;
[8889370]243        }
[33d83d4]244        return ~0U;
[8889370]245}
246
[ebf8071]247/** Prepends a Linux SLL header to the packet.
248 *
249 * Packets that don't support direction tagging are annoying, especially
[81f9b6e]250 * when we have direction tagging information!  So this converts the packet
251 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
252 * pcap style packet for the reason that it means it works with bpf filters.
253 *
254 * @note this will copy the packet, so use sparingly if possible.
255 */
256void promote_packet(libtrace_packet_t *packet)
257{
258        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
259                char *tmpbuffer;
260                libtrace_sll_header_t *hdr;
261
[73dd29f]262                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
[1ab9849]263                        == TRACE_TYPE_LINUX_SLL) {
264                        /* This is already been promoted, so ignore it */
265                        return;
266                }
267
268                /* This should be easy, just prepend the header */
269                tmpbuffer= (char*)malloc(
270                                sizeof(libtrace_sll_header_t)
271                                +trace_get_capture_length(packet)
272                                +trace_get_framing_length(packet)
273                                );
274
275                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
276                        +trace_get_framing_length(packet));
277
278                hdr->halen=htons(6);
279                hdr->pkttype=TRACE_SLL_OUTGOING;
[81f9b6e]280
[73dd29f]281                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
[d4c8b343]282                        case TRACE_TYPE_NONE:
[9bc4689]283                                trace_get_layer3(packet, &hdr->protocol, NULL);
[528eb6e]284                                hdr->hatype = htons(LIBTRACE_ARPHRD_PPP);
[1ab9849]285                                hdr->protocol=htons(hdr->protocol);
286                                break;
287                        case TRACE_TYPE_ETH:
[528eb6e]288                                hdr->hatype = htons(LIBTRACE_ARPHRD_ETHER);
[1ab9849]289                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
[81f9b6e]290                                break;
291                        default:
292                                /* failed */
293                                return;
294                }
295                memcpy(tmpbuffer,packet->header,
296                                trace_get_framing_length(packet));
297                memcpy(tmpbuffer
298                                +sizeof(libtrace_sll_header_t)
299                                +trace_get_framing_length(packet),
300                                packet->payload,
301                                trace_get_capture_length(packet));
302                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
303                        packet->buf_control=TRACE_CTRL_PACKET;
304                }
305                else {
306                        free(packet->buffer);
307                }
308                packet->buffer=tmpbuffer;
309                packet->header=tmpbuffer;
310                packet->payload=tmpbuffer+trace_get_framing_length(packet);
[73dd29f]311                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
[5551415]312                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
[404210e]313                        sizeof(libtrace_sll_header_t);
[5551415]314                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
[dcbc330]315                        sizeof(libtrace_sll_header_t);
[48d72f8]316                trace_clear_cache(packet);
[81f9b6e]317                return;
318        }
319}
[0ff6ddf]320
[ebf8071]321/* Try and remove any extraneous encapsulation that may have been added to
322 * a packet. Effectively the opposite to promote_packet.
[0ff6ddf]323 *
[ebf8071]324 * Returns true if demotion was possible, false if not.
[0ff6ddf]325 */
326bool demote_packet(libtrace_packet_t *packet)
327{
[d5e1796]328        uint8_t type;
[64d4398]329        uint16_t ha_type, next_proto;
330        libtrace_sll_header_t *sll = NULL;
[e1fdc05]331        uint32_t remaining = 0;
[d5e1796]332        char *tmp;
333        struct timeval tv;
334        static libtrace_t *trace = NULL;
[37ee856]335
[0ff6ddf]336        switch(trace_get_link_type(packet)) {
[d5e1796]337                case TRACE_TYPE_ATM:
338                        remaining=trace_get_capture_length(packet);
339                        packet->payload=trace_get_payload_from_atm(
340                                packet->payload,&type,&remaining);
[e1fdc05]341                        if (!packet->payload)
342                                return false;
[4746c71]343                        tmp=(char*)malloc(
[d5e1796]344                                trace_get_capture_length(packet)
345                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
346                                );
347
348                        tv=trace_get_timeval(packet);
349                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
350                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
[bb75d10]351                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
352                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
[d5e1796]353                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
354                                = remaining;
355
356                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
357                                        packet->payload,
[4bd8a5b]358                                        (size_t)remaining);
[d5e1796]359                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
360                                packet->buf_control=TRACE_CTRL_PACKET;
361                        }
362                        else {
363                                free(packet->buffer);
364                        }
365                        packet->buffer=tmp;
366                        packet->header=tmp;
367                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
[73dd29f]368                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
[d5e1796]369                       
370                        if (trace == NULL) {
[6ba9d7b]371                                trace = trace_create_dead("pcapfile:-");
[d5e1796]372                        }
373
[37ee856]374                        trace->startcount = packet->trace->startcount;
[d5e1796]375                        packet->trace=trace;
376
[7c72e4d]377                        /* Invalidate caches */
[9cc1266]378                        trace_clear_cache(packet);
[d5e1796]379                        return true;
380
[0ff6ddf]381                case TRACE_TYPE_LINUX_SLL:
[64d4398]382                        sll = (libtrace_sll_header_t *)(packet->payload);
383
384                        ha_type = ntohs(sll->hatype);
385                        next_proto = ntohs(sll->protocol);
386               
387                        /* Preserved from older libtrace behaviour */
[528eb6e]388                        if (ha_type == LIBTRACE_ARPHRD_PPP)
[64d4398]389                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
390                        /* Don't decide trace type based on ha_type,
391                         * decide based on the protocol header that is
392                         * coming up!
393                         */
394                        else if (next_proto == TRACE_ETHERTYPE_LOOPBACK)
395                                packet->type = pcap_linktype_to_rt(TRACE_DLT_EN10MB);
396                        else if (next_proto == TRACE_ETHERTYPE_IP) 
397                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
398                        else if (next_proto == TRACE_ETHERTYPE_IPV6)
399                                packet->type = pcap_linktype_to_rt(TRACE_DLT_RAW);
400                        else
401                                return false;
402
[dcbc330]403                        /* Skip the Linux SLL header */
[0ff6ddf]404                        packet->payload=(void*)((char*)packet->payload
405                                        +sizeof(libtrace_sll_header_t));
406                        trace_set_capture_length(packet,
407                                trace_get_capture_length(packet)
408                                        -sizeof(libtrace_sll_header_t));
[7c72e4d]409
410                        /* Invalidate caches */
[9cc1266]411                        trace_clear_cache(packet);
[0ff6ddf]412                        break;
413                default:
414                        return false;
415        }
[7c72e4d]416
417        /* Invalidate caches */
[9cc1266]418        trace_clear_cache(packet);
[1c1e4a2]419        return true;
[0ff6ddf]420}
Note: See TracBrowser for help on using the repository browser.