source: lib/linktypes.c @ a81d2fc

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since a81d2fc was dd06159, checked in by Perry Lorier <perry@…>, 14 years ago

Add support for cisco hdlc over pos

  • Property mode set to 100644
File size: 9.4 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
[73dd29f]34libtrace_linktype_t pcap_linktype_to_libtrace(libtrace_dlt_t linktype)
[643105b]35{
[73dd29f]36        switch(linktype) {
37                case TRACE_DLT_RAW:
38                case TRACE_DLT_LINKTYPE_RAW: return TRACE_TYPE_NONE;
[114b8d6]39                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
40                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
41                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
[d5e1796]42                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
43                case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
44                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_LLCSNAP;
[4a207b8]45                case TRACE_DLT_PPP: return TRACE_TYPE_PPP;
[e7d66bf]46                /* Unhandled */
47                case TRACE_DLT_NULL:    /* Raw IP frame with a BSD specific
48                                         * header If you want raw L3 headers
49                                         * use TRACE_DLT_RAW
50                                         */
51                        break;
[643105b]52        }
[33d83d4]53        return ~0U;
[643105b]54}
55
[4c00a35]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) {
[73dd29f]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;
[dd06159]71                case TRACE_TYPE_HDLC_POS: return TRACE_DLT_C_HDLC;
[e7d66bf]72                /* Below here are unsupported conversions */
73                /* Dispite hints to the contrary, there is no DLT
74                 * for 'raw atm packets that happen to be missing
75                 * the HEC' or even 'raw atm packets that have a hec'.
76                 *
77                 * The closest are DLT_ATM_RFC1483 but that doesn't
78                 * include the ATM header, only the LLCSNAP header.
79                 */
80                case TRACE_TYPE_ATM:
81                /* pcap has no DLT for DUCK */
82                case TRACE_TYPE_DUCK:
83                /* Used for test traces within WAND */
84                case TRACE_TYPE_80211_PRISM:   
[4a207b8]85                /* Probably == PPP */
[e7d66bf]86                case TRACE_TYPE_POS:
[4a207b8]87                /* TODO: We haven't researched these yet */
[e7d66bf]88                case TRACE_TYPE_AAL5:
[be22b51]89                case TRACE_TYPE_METADATA:
[e7d66bf]90                        break;
[643105b]91        }
[33d83d4]92        return ~0U;
[643105b]93}
94
[73dd29f]95static libtrace_dlt_t pcap_dlt_to_pcap_linktype(libtrace_dlt_t linktype)
96{
97        switch (linktype) {
98                case TRACE_DLT_RAW: return TRACE_DLT_LINKTYPE_RAW;
99                default:
100                                    return linktype;
101        }
102}
103
[d36a8c6]104libtrace_dlt_t libtrace_to_pcap_linktype(libtrace_linktype_t type)
105{
106        return pcap_dlt_to_pcap_linktype(libtrace_to_pcap_dlt(type));
107}
108
[73dd29f]109libtrace_rt_types_t pcap_linktype_to_rt(libtrace_dlt_t linktype) 
[7ac9705]110{
[73dd29f]111        /* For pcap the rt type is just the linktype + a fixed value */
112        return pcap_dlt_to_pcap_linktype(linktype) + TRACE_RT_DATA_DLT;
[7ac9705]113}
114
[4c00a35]115libtrace_dlt_t rt_to_pcap_linktype(libtrace_rt_types_t rt_type)
[7ac9705]116{
[cab58c5]117        assert(rt_type >= TRACE_RT_DATA_DLT);
118        return rt_type - TRACE_RT_DATA_DLT;
[7ac9705]119}
120
[4bd8a5b]121libtrace_linktype_t erf_type_to_libtrace(uint8_t erf)
[643105b]122{
123        switch (erf) {
[67a14d4]124                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
[643105b]125                case TYPE_ETH:          return TRACE_TYPE_ETH;
126                case TYPE_ATM:          return TRACE_TYPE_ATM;
[67a14d4]127                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
[643105b]128        }
[33d83d4]129        return ~0U;
[643105b]130}
131
[4bd8a5b]132uint8_t libtrace_to_erf_type(libtrace_linktype_t linktype)
[643105b]133{
134        switch(linktype) {
[751531a]135                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
[643105b]136                case TRACE_TYPE_ETH:    return TYPE_ETH;
137                case TRACE_TYPE_ATM:    return TYPE_ATM;
[751531a]138                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
[e7d66bf]139                /* Unsupported conversions */
140                case TRACE_TYPE_LLCSNAP:
141                case TRACE_TYPE_DUCK:
142                case TRACE_TYPE_80211_RADIO:
143                case TRACE_TYPE_80211_PRISM:
144                case TRACE_TYPE_80211:
145                case TRACE_TYPE_PFLOG:
146                case TRACE_TYPE_NONE:
147                case TRACE_TYPE_LINUX_SLL:
[4a207b8]148                case TRACE_TYPE_PPP:
149                case TRACE_TYPE_POS:
[be22b51]150                case TRACE_TYPE_METADATA:
[e7d66bf]151                        break;
[643105b]152        }
[4bd8a5b]153        return 255;
[643105b]154}
[81f9b6e]155
[8889370]156libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
157        switch(arphrd) {
158                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
159                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
160                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
[f93f0b3]161                case ARPHRD_PPP: return TRACE_TYPE_NONE;
[8889370]162        }
[7c72e4d]163        printf("Unknown ARPHRD %08x\n",arphrd);
[33d83d4]164        return ~0U;
[8889370]165}
166
167unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
168        switch(linktype) {
169                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
170                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
171                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
[eb1aab2]172                default: break;
[8889370]173        }
[33d83d4]174        return ~0U;
[8889370]175}
176
[81f9b6e]177/** Tinker with a packet
178 * packets that don't support direction tagging are annoying, especially
179 * when we have direction tagging information!  So this converts the packet
180 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
181 * pcap style packet for the reason that it means it works with bpf filters.
182 *
183 * @note this will copy the packet, so use sparingly if possible.
184 */
185void promote_packet(libtrace_packet_t *packet)
186{
187        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
188                char *tmpbuffer;
189                libtrace_sll_header_t *hdr;
190
[73dd29f]191                if (pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))
[1ab9849]192                        == TRACE_TYPE_LINUX_SLL) {
193                        /* This is already been promoted, so ignore it */
194                        return;
195                }
196
197                /* This should be easy, just prepend the header */
198                tmpbuffer= (char*)malloc(
199                                sizeof(libtrace_sll_header_t)
200                                +trace_get_capture_length(packet)
201                                +trace_get_framing_length(packet)
202                                );
203
204                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
205                        +trace_get_framing_length(packet));
206
207                hdr->halen=htons(6);
208                hdr->pkttype=TRACE_SLL_OUTGOING;
[81f9b6e]209
[73dd29f]210                switch(pcap_linktype_to_libtrace(rt_to_pcap_linktype(packet->type))) {
[d4c8b343]211                        case TRACE_TYPE_NONE:
[9bc4689]212                                trace_get_layer3(packet, &hdr->protocol, NULL);
[1ab9849]213                                hdr->hatype = htons(ARPHRD_PPP);
214                                hdr->protocol=htons(hdr->protocol);
215                                break;
216                        case TRACE_TYPE_ETH:
217                                hdr->hatype = htons(ARPHRD_ETHER);
218                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
[81f9b6e]219                                break;
220                        default:
221                                /* failed */
222                                return;
223                }
224                memcpy(tmpbuffer,packet->header,
225                                trace_get_framing_length(packet));
226                memcpy(tmpbuffer
227                                +sizeof(libtrace_sll_header_t)
228                                +trace_get_framing_length(packet),
229                                packet->payload,
230                                trace_get_capture_length(packet));
231                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
232                        packet->buf_control=TRACE_CTRL_PACKET;
233                }
234                else {
235                        free(packet->buffer);
236                }
237                packet->buffer=tmpbuffer;
238                packet->header=tmpbuffer;
239                packet->payload=tmpbuffer+trace_get_framing_length(packet);
[73dd29f]240                packet->type=pcap_linktype_to_rt(TRACE_DLT_LINUX_SLL);
[5551415]241                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->caplen+=
[404210e]242                        sizeof(libtrace_sll_header_t);
[5551415]243                ((struct libtrace_pcapfile_pkt_hdr_t*) packet->header)->wirelen+=
[dcbc330]244                        sizeof(libtrace_sll_header_t);
[81f9b6e]245                return;
246        }
247}
[0ff6ddf]248
249/* Try and simplify the packet one step, kinda the opposite to promote_packet
250 *
251 * returns true if demotion was possible, false if not.
252 */
253bool demote_packet(libtrace_packet_t *packet)
254{
[d5e1796]255        uint8_t type;
[e1fdc05]256        uint32_t remaining = 0;
[d5e1796]257        char *tmp;
258        struct timeval tv;
259        static libtrace_t *trace = NULL;
[0ff6ddf]260        switch(trace_get_link_type(packet)) {
[d5e1796]261                case TRACE_TYPE_ATM:
262                        remaining=trace_get_capture_length(packet);
263                        packet->payload=trace_get_payload_from_atm(
264                                packet->payload,&type,&remaining);
[e1fdc05]265                        if (!packet->payload)
266                                return false;
[4746c71]267                        tmp=(char*)malloc(
[d5e1796]268                                trace_get_capture_length(packet)
269                                +sizeof(libtrace_pcapfile_pkt_hdr_t)
270                                );
271
272                        tv=trace_get_timeval(packet);
273                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_sec=tv.tv_sec;
274                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->ts_usec=tv.tv_usec;
[bb75d10]275                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->wirelen
276                                = trace_get_wire_length(packet)-(trace_get_capture_length(packet)-remaining);
[d5e1796]277                        ((libtrace_pcapfile_pkt_hdr_t*)tmp)->caplen
278                                = remaining;
279
280                        memcpy(tmp+sizeof(libtrace_pcapfile_pkt_hdr_t),
281                                        packet->payload,
[4bd8a5b]282                                        (size_t)remaining);
[d5e1796]283                        if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
284                                packet->buf_control=TRACE_CTRL_PACKET;
285                        }
286                        else {
287                                free(packet->buffer);
288                        }
289                        packet->buffer=tmp;
290                        packet->header=tmp;
291                        packet->payload=tmp+sizeof(libtrace_pcapfile_pkt_hdr_t);
[73dd29f]292                        packet->type=pcap_linktype_to_rt(TRACE_DLT_ATM_RFC1483);
[d5e1796]293                       
294                        if (trace == NULL) {
[6ba9d7b]295                                trace = trace_create_dead("pcapfile:-");
[d5e1796]296                        }
297
298                        packet->trace=trace;
299
[7c72e4d]300                        /* Invalidate caches */
301                        packet->l3_header = NULL;
302                        packet->capture_length = -1;
303
[d5e1796]304                        return true;
305
[0ff6ddf]306                case TRACE_TYPE_LINUX_SLL:
[8889370]307                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
308                                        ->hatype)) {
[0ff6ddf]309                                case ARPHRD_PPP:
[73dd29f]310                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_RAW);
[0ff6ddf]311                                        break;
312                                case ARPHRD_ETHER:
[73dd29f]313                                        packet->type=pcap_linktype_to_rt(TRACE_DLT_EN10MB);
[0ff6ddf]314                                        break;
315                                default:
316                                        /* Dunno how to demote this packet */
317                                        return false;
318                        }
[dcbc330]319                        /* Skip the Linux SLL header */
[0ff6ddf]320                        packet->payload=(void*)((char*)packet->payload
321                                        +sizeof(libtrace_sll_header_t));
322                        trace_set_capture_length(packet,
323                                trace_get_capture_length(packet)
324                                        -sizeof(libtrace_sll_header_t));
[7c72e4d]325
326                        /* Invalidate caches */
327                        packet->l3_header = NULL;
328                        packet->capture_length = -1;
[0ff6ddf]329                        break;
330                default:
331                        return false;
332        }
[7c72e4d]333
334        /* Invalidate caches */
335        packet->l3_header = NULL;
336        packet->capture_length = -1;
[1c1e4a2]337        return true;
[0ff6ddf]338}
Note: See TracBrowser for help on using the repository browser.