source: lib/linktypes.c @ 1ab9849

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

Correctly generate/parse LINUX_SLL headers

  • Property mode set to 100644
File size: 5.9 KB
Line 
1#include "libtrace.h"
2#include "config.h"
3
4#include "rt_protocol.h"
5#include <assert.h>
6#include "libtrace_int.h"
7#include <stdlib.h>
8#include <string.h>
9
10#ifndef WIN32
11#include <net/if_arp.h>
12#endif
13
14#ifndef ARPHRD_ETHER
15#define ARPHRD_ETHER    1               /* Ethernet 10/100Mbps.  */
16#endif
17
18#ifndef ARPHRD_PPP
19#define ARPHRD_PPP      512
20#endif
21
22#ifndef ARPHRD_IEEE80211
23#define ARPHRD_IEEE80211        801
24#endif
25
26
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
34libtrace_linktype_t pcap_dlt_to_libtrace(libtrace_dlt_t dlt)
35{
36        switch(dlt) {
37                case TRACE_DLT_NULL: return TRACE_TYPE_NONE;
38                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
39                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_ATM;
40                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
41                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
42                case TRACE_DLT_PFLOG:
43                                        return TRACE_TYPE_PFLOG;
44                case TRACE_DLT_IEEE802_11_RADIO:
45                                        return TRACE_TYPE_80211_RADIO;
46        }
47        return ~0;
48}
49
50libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
51{
52        switch(type) {
53                case TRACE_TYPE_NONE: return TRACE_DLT_NULL;
54                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
55                case TRACE_TYPE_ATM: return TRACE_DLT_ATM_RFC1483;
56                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
57                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
58                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
59        case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
60        }
61        return ~0;
62}
63
64enum rt_field_t pcap_dlt_to_rt(libtrace_dlt_t dlt) 
65{
66        /* For pcap the rt type is just the dlt + a fixed value */
67        return dlt + RT_DATA_PCAP;
68}
69
70libtrace_dlt_t rt_to_pcap_dlt(enum rt_field_t rt_type)
71{
72        assert(rt_type >= RT_DATA_PCAP);
73        return rt_type - RT_DATA_PCAP;
74}
75
76libtrace_linktype_t erf_type_to_libtrace(char erf)
77{
78        switch (erf) {
79                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
80                case TYPE_ETH:          return TRACE_TYPE_ETH;
81                case TYPE_ATM:          return TRACE_TYPE_ATM;
82                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
83        }
84        return ~0;
85}
86
87char libtrace_to_erf_type(libtrace_linktype_t linktype)
88{
89        switch(linktype) {
90                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
91                case TRACE_TYPE_ETH:    return TYPE_ETH;
92                case TRACE_TYPE_ATM:    return TYPE_ATM;
93                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
94        }
95        return -1;
96}
97
98libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
99        switch(arphrd) {
100                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
101                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
102                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
103        }
104        return ~0;
105}
106
107unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
108        switch(linktype) {
109                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
110                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
111                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
112        }
113        return -1;
114}
115
116/** Tinker with a packet
117 * packets that don't support direction tagging are annoying, especially
118 * when we have direction tagging information!  So this converts the packet
119 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
120 * pcap style packet for the reason that it means it works with bpf filters.
121 *
122 * @note this will copy the packet, so use sparingly if possible.
123 */
124void promote_packet(libtrace_packet_t *packet)
125{
126        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
127                char *tmpbuffer;
128                libtrace_sll_header_t *hdr;
129
130                if (pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))
131                        == TRACE_TYPE_LINUX_SLL) {
132                        /* This is already been promoted, so ignore it */
133                        return;
134                }
135
136                /* This should be easy, just prepend the header */
137                tmpbuffer= (char*)malloc(
138                                sizeof(libtrace_sll_header_t)
139                                +trace_get_capture_length(packet)
140                                +trace_get_framing_length(packet)
141                                );
142
143                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
144                        +trace_get_framing_length(packet));
145
146                hdr->halen=htons(6);
147                hdr->pkttype=TRACE_SLL_OUTGOING;
148
149                switch(pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))) {
150                        case TRACE_TYPE_NONE:
151                                trace_get_payload_from_link(
152                                        trace_get_link(packet),
153                                        trace_get_link_type(packet),
154                                        &hdr->protocol,
155                                        NULL);
156                                hdr->hatype = htons(ARPHRD_PPP);
157                                hdr->protocol=htons(hdr->protocol);
158                                break;
159                        case TRACE_TYPE_ETH:
160                                hdr->hatype = htons(ARPHRD_ETHER);
161                                hdr->protocol=htons(0x0060); /* ETH_P_LOOP */
162                                break;
163                        default:
164                                /* failed */
165                                return;
166                }
167                memcpy(tmpbuffer,packet->header,
168                                trace_get_framing_length(packet));
169                memcpy(tmpbuffer
170                                +sizeof(libtrace_sll_header_t)
171                                +trace_get_framing_length(packet),
172                                packet->payload,
173                                trace_get_capture_length(packet));
174                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
175                        packet->buf_control=TRACE_CTRL_PACKET;
176                }
177                else {
178                        free(packet->buffer);
179                }
180                packet->buffer=tmpbuffer;
181                packet->header=tmpbuffer;
182                packet->payload=tmpbuffer+trace_get_framing_length(packet);
183                packet->type=pcap_dlt_to_rt(TRACE_DLT_LINUX_SLL);
184                ((struct pcap_pkthdr*) packet->header)->caplen+=
185                        sizeof(libtrace_sll_header_t);
186                ((struct pcap_pkthdr*) packet->header)->len+=
187                        sizeof(libtrace_sll_header_t);
188                return;
189        }
190}
191
192/* Try and simplify the packet one step, kinda the opposite to promote_packet
193 *
194 * returns true if demotion was possible, false if not.
195 */
196bool demote_packet(libtrace_packet_t *packet)
197{
198        switch(trace_get_link_type(packet)) {
199                case TRACE_TYPE_LINUX_SLL:
200                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
201                                        ->hatype)) {
202                                case ARPHRD_PPP:
203                                        packet->type=pcap_dlt_to_rt(DLT_NULL);
204                                        break;
205                                case ARPHRD_ETHER:
206                                        packet->type=pcap_dlt_to_rt(DLT_EN10MB);
207                                        break;
208                                default:
209                                        /* Dunno how to demote this packet */
210                                        return false;
211                        }
212                        /* Skip the Linux SLL header */
213                        packet->payload=(void*)((char*)packet->payload
214                                        +sizeof(libtrace_sll_header_t));
215                        trace_set_capture_length(packet,
216                                trace_get_capture_length(packet)
217                                        -sizeof(libtrace_sll_header_t));
218                        break;
219                default:
220                        return false;
221        }
222        return true;
223}
Note: See TracBrowser for help on using the repository browser.