source: lib/linktypes.c @ be22b51

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

Other libtrace programs don't like meta-data so added a new trace_type that would allow them to ignore it without having to do anything special

  • Property mode set to 100644
File size: 8.6 KB
RevLine 
[643105b]1#include "libtrace.h"
[97e39a7]2#include "config.h"
[e5f1431]3
[7ac9705]4#include "rt_protocol.h"
5#include <assert.h>
[81f9b6e]6#include "libtrace_int.h"
7#include <stdlib.h>
8#include <string.h>
[643105b]9
[b721834]10#ifndef WIN32
11#include <net/if_arp.h>
[77285d9]12#endif
13
14#ifndef ARPHRD_ETHER
[b721834]15#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
[77285d9]16#endif
17
18#ifndef ARPHRD_PPP
[fe4ab68]19#define ARPHRD_PPP      512
[b721834]20#endif
21
[742a332]22#ifndef ARPHRD_IEEE80211
23#define ARPHRD_IEEE80211        801
24#endif
25
26
[643105b]27/* This file maps libtrace types to/from pcap DLT and erf types
28 *
29 * When adding a new linktype to libtrace, add the mapping(s) here,
30 * and add the understanding of the type to get_ip(), and perhaps
31 * get_{source,destination}_mac (if your linklayer has mac's)
32 */
33
[114b8d6]34libtrace_linktype_t pcap_dlt_to_libtrace(libtrace_dlt_t dlt)
[643105b]35{
36        switch(dlt) {
[2f3a25e]37                case TRACE_DLT_RAW: return TRACE_TYPE_NONE;
[114b8d6]38                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
39                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
40                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
[d5e1796]41                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
42                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
43                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
[4a207b8]44                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
[e7d66bf]45                /* Unhandled */
46                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
47                                         * header If you want raw L3 headers
48                                         * use TRACE_DLT_RAW
49                                         */
50                        break;
[643105b]51        }
[33d83d4]52        return ~0U;
[643105b]53}
54
[d5e1796]55
[81f9b6e]56libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
[643105b]57{
[d5e1796]58        /* If pcap doesn't have a DLT, you can either ask pcap to register
59         * you a DLT, (and perhaps write a tcpdump decoder for it), or you
60         * can add it to demote_packet
61         */
[643105b]62        switch(type) {
[2f3a25e]63                case TRACE_TYPE_NONE: return TRACE_DLT_RAW;
[114b8d6]64                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
65                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
66                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
67                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
[d5e1796]68                case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
69                case TRACE_TYPE_LLCSNAP: return TRACE_DLT_ATM_RFC1483;
[4a207b8]70                case TRACE_TYPE_PPP:    return TRACE_DLT_PPP;
[e7d66bf]71                /* Below here are unsupported conversions */
72                /* Dispite hints to the contrary, there is no DLT
73                 * for 'raw atm packets that happen to be missing
74                 * the HEC' or even 'raw atm packets that have a hec'.
75                 *
76                 * The closest are DLT_ATM_RFC1483 but that doesn't
77                 * include the ATM header, only the LLCSNAP header.
78                 */
79                case TRACE_TYPE_ATM:
80                /* pcap has no DLT for DUCK */
81                case TRACE_TYPE_DUCK:
82                /* Used for test traces within WAND */
83                case TRACE_TYPE_80211_PRISM:   
[4a207b8]84                /* Probably == PPP */
[e7d66bf]85                case TRACE_TYPE_POS:
[4a207b8]86                /* TODO: We haven't researched these yet */
[e7d66bf]87                case TRACE_TYPE_AAL5:
[4a207b8]88                case TRACE_TYPE_HDLC_POS:
[be22b51]89                case TRACE_TYPE_METADATA:
[e7d66bf]90                        break;
[643105b]91        }
[33d83d4]92        return ~0U;
[643105b]93}
94
[cab58c5]95libtrace_rt_types_t pcap_dlt_to_rt(libtrace_dlt_t dlt) 
[7ac9705]96{
97        /* For pcap the rt type is just the dlt + a fixed value */
[cab58c5]98        return dlt + TRACE_RT_DATA_DLT;
[7ac9705]99}
100
[cab58c5]101libtrace_dlt_t rt_to_pcap_dlt(libtrace_rt_types_t rt_type)
[7ac9705]102{
[cab58c5]103        assert(rt_type >= TRACE_RT_DATA_DLT);
104        return rt_type - TRACE_RT_DATA_DLT;
[7ac9705]105}
106
[4bd8a5b]107libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
[643105b]108{
109        switch (erf) {
[67a14d4]110                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
[643105b]111                case TYPE_ETH:          return TRACE_TYPE_ETH;
112                case TYPE_ATM:          return TRACE_TYPE_ATM;
[67a14d4]113                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
[643105b]114        }
[33d83d4]115        return ~0U;
[643105b]116}
117
[4bd8a5b]118uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
[643105b]119{
120        switch(linktype) {
[751531a]121                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
[643105b]122                case TRACE_TYPE_ETH:    return TYPE_ETH;
123                case TRACE_TYPE_ATM:    return TYPE_ATM;
[751531a]124                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
[e7d66bf]125                /* Unsupported conversions */
126                case TRACE_TYPE_LLCSNAP:
127                case TRACE_TYPE_DUCK:
128                case TRACE_TYPE_80211_RADIO:
129                case TRACE_TYPE_80211_PRISM:
130                case TRACE_TYPE_80211:
131                case TRACE_TYPE_PFLOG:
132                case TRACE_TYPE_NONE:
133                case TRACE_TYPE_LINUX_SLL:
[4a207b8]134                case TRACE_TYPE_PPP:
135                case TRACE_TYPE_POS:
[be22b51]136                case TRACE_TYPE_METADATA:
[e7d66bf]137                        break;
[643105b]138        }
[4bd8a5b]139        return 255;
[643105b]140}
[81f9b6e]141
[8889370]142libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
143        switch(arphrd) {
144                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
145                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
146                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
147        }
[33d83d4]148        return ~0U;
[8889370]149}
150
151unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
152        switch(linktype) {
153                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
154                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
155                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
[eb1aab2]156                default: break;
[8889370]157        }
[33d83d4]158        return ~0U;
[8889370]159}
160
[81f9b6e]161/** Tinker with a packet
162 * packets that don't support direction tagging are annoying, especially
163 * when we have direction tagging information!  So this converts the packet
164 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
165 * pcap style packet for the reason that it means it works with bpf filters.
166 *
167 * @note this will copy the packet, so use sparingly if possible.
168 */
169void promote_packet(libtrace_packet_t *packet)
170{
171        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
172                char *tmpbuffer;
173                libtrace_sll_header_t *hdr;
174
[1ab9849]175                if (pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))
176                        == TRACE_TYPE_LINUX_SLL) {
177                        /* This is already been promoted, so ignore it */
178                        return;
179                }
180
181                /* This should be easy, just prepend the header */
182                tmpbuffer= (char*)malloc(
183                                sizeof(libtrace_sll_header_t)
184                                +trace_get_capture_length(packet)
185                                +trace_get_framing_length(packet)
186                                );
187
188                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
189                        +trace_get_framing_length(packet));
190
191                hdr->halen=htons(6);
192                hdr->pkttype=TRACE_SLL_OUTGOING;
[81f9b6e]193
[1ab9849]194                switch(pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))) {
[d4c8b343]195                        case TRACE_TYPE_NONE:
196                                trace_get_payload_from_link(
197                                        trace_get_link(packet),
198                                        trace_get_link_type(packet),
199                                        &hdr->protocol,
200                                        NULL);
[1ab9849]201                                hdr->hatype = htons(ARPHRD_PPP);
202                                hdr->protocol=htons(hdr->protocol);
203                                break;
204                        case TRACE_TYPE_ETH:
205                                hdr->hatype = htons(ARPHRD_ETHER);
206                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
[81f9b6e]207                                break;
208                        default:
209                                /* failed */
210                                return;
211                }
212                memcpy(tmpbuffer,packet->header,
213                                trace_get_framing_length(packet));
214                memcpy(tmpbuffer
215                                +sizeof(libtrace_sll_header_t)
216                                +trace_get_framing_length(packet),
217                                packet->payload,
218                                trace_get_capture_length(packet));
219                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
220                        packet->buf_control=TRACE_CTRL_PACKET;
221                }
222                else {
223                        free(packet->buffer);
224                }
225                packet->buffer=tmpbuffer;
226                packet->header=tmpbuffer;
227                packet->payload=tmpbuffer+trace_get_framing_length(packet);
[d4c8b343]228                packet->type=pcap_dlt_to_rt(TRACE_DLT_LINUX_SLL);
[5551415]229                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
[404210e]230                        sizeof(libtrace_sll_header_t);
[5551415]231                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
[dcbc330]232                        sizeof(libtrace_sll_header_t);
[81f9b6e]233                return;
234        }
235}
[0ff6ddf]236
237/* Try and simplify the packet one step, kinda the opposite to promote_packet
238 *
239 * returns true if demotion was possible, false if not.
240 */
241bool demote_packet(libtrace_packet_t *packet)
242{
[d5e1796]243        uint8_t type;
244        uint32_t remaining;
245        char *tmp;
246        struct timeval tv;
247        static libtrace_t *trace = NULL;
[0ff6ddf]248        switch(trace_get_link_type(packet)) {
[d5e1796]249                case TRACE_TYPE_ATM:
250                        remaining=trace_get_capture_length(packet);
251                        packet->payload=trace_get_payload_from_atm(
252                                packet->payload,&type,&remaining);
253
[4746c71]254                        tmp=(char*)malloc(
[d5e1796]255                                trace_get_capture_length(packet)
256                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
257                                );
258
259                        tv=trace_get_timeval(packet);
260                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
261                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
[bb75d10]262                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
263                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
[d5e1796]264                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
265                                = remaining;
266
267                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
268                                        packet->payload,
[4bd8a5b]269                                        (size_t)remaining);
[d5e1796]270                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
271                                packet->buf_control=TRACE_CTRL_PACKET;
272                        }
273                        else {
274                                free(packet->buffer);
275                        }
276                        packet->buffer=tmp;
277                        packet->header=tmp;
278                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
279                        packet->type=pcap_dlt_to_rt(TRACE_DLT_ATM_RFC1483);
280                       
281                        if (trace == NULL) {
282                                trace = trace_create_dead("pcap:-");
283                        }
284
285                        packet->trace=trace;
286
287                        return true;
288
[0ff6ddf]289                case TRACE_TYPE_LINUX_SLL:
[8889370]290                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
291                                        ->hatype)) {
[0ff6ddf]292                                case ARPHRD_PPP:
[2f3a25e]293                                        packet->type=pcap_dlt_to_rt(TRACE_DLT_RAW);
[0ff6ddf]294                                        break;
295                                case ARPHRD_ETHER:
[5551415]296                                        packet->type=pcap_dlt_to_rt(TRACE_DLT_EN10MB);
[0ff6ddf]297                                        break;
298                                default:
299                                        /* Dunno how to demote this packet */
300                                        return false;
301                        }
[dcbc330]302                        /* Skip the Linux SLL header */
[0ff6ddf]303                        packet->payload=(void*)((char*)packet->payload
304                                        +sizeof(libtrace_sll_header_t));
305                        trace_set_capture_length(packet,
306                                trace_get_capture_length(packet)
307                                        -sizeof(libtrace_sll_header_t));
308                        break;
309                default:
310                        return false;
311        }
[1c1e4a2]312        return true;
[0ff6ddf]313}
Note: See TracBrowser for help on using the repository browser.