source: lib/linktypes.c @ eb1aab2

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

Fixed all the warnings about cases that weren't being dealt with by our switch statements - the original code was fine, but the warnings were annoying

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