source: lib/linktypes.c @ a857389

cachetimestampsdevelopetsiliverc-4.0.3rc-4.0.4ringdecrementfixringperformance
Last change on this file since a857389 was a857389, checked in by Shane Alcock <salcock@…>, 3 years ago

Initial support for ERF provenance records

Update erftypes.h with TYPE_META (27).
Check for ERF_TYPE_MAX rather than some arbitrary type in ERF sanity checks. In Wireshark we recently completely removed these checks as there are only a few types before TYPE_PAD/ERF_TYPE_MAX, but leave them in for now.
Add TRACE_TYPE_ERF_META for provenance record payload.
Continue to use TRACE_RT_DATA_ERF as provenance is a valid ERF record. Note: this means that LIBTRACE_IS_META_PACKET() will currently return FALSE which may confuse some tools. Other places in the code also tend to check for TRACE_TYPE_NONDATA which isn't true here either.
Return zero for wire length of provenance records.
Don't allow snapping them (just return the same value).
Skip provenance records in l2 parsers and trace_get_payload_from_meta().
Return provenance payload for trace_get_packet_meta().

Also add support for a couple of missing ERF_TYPE_ETH_COLOR variants.

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