source: lib/linktypes.c @ 8889370

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 8889370 was 8889370, checked in by Scott Raynel <smr26@…>, 15 years ago

trace_get_payload_from_linux_sll now returns a pointer to the start of the next header intead of trying to jump through the next one. It also returns the hardware address type instead of the protocol type now. trace_get_payload_from_link has been updated to recurse to step through the protocols. This makes _from_linux_sll more like the rest of the functions in protocols.c.
We also now have arphrd_type_to_libtrace() and libtrace_to_arphrd_type() functions to help with this.

  • 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/* This file maps libtrace types to/from pcap DLT and erf types
23 *
24 * When adding a new linktype to libtrace, add the mapping(s) here,
25 * and add the understanding of the type to get_ip(), and perhaps
26 * get_{source,destination}_mac (if your linklayer has mac's)
27 */
28
29libtrace_linktype_t pcap_dlt_to_libtrace(libtrace_dlt_t dlt)
30{
31        switch(dlt) {
32                case TRACE_DLT_NULL: return TRACE_TYPE_NONE;
33                case TRACE_DLT_EN10MB: return TRACE_TYPE_ETH;
34                case TRACE_DLT_ATM_RFC1483: return TRACE_TYPE_ATM;
35                case TRACE_DLT_IEEE802_11: return TRACE_TYPE_80211;
36                case TRACE_DLT_LINUX_SLL: return TRACE_TYPE_LINUX_SLL;
37                case TRACE_DLT_PFLOG: return TRACE_TYPE_PFLOG;
38        case TRACE_DLT_IEEE802_11_RADIO: return TRACE_TYPE_80211_RADIO;
39        }
40        return ~0;
41}
42
43libtrace_dlt_t libtrace_to_pcap_dlt(libtrace_linktype_t type)
44{
45        switch(type) {
46                case TRACE_TYPE_NONE: return TRACE_DLT_NULL;
47                case TRACE_TYPE_ETH: return TRACE_DLT_EN10MB;
48                case TRACE_TYPE_ATM: return TRACE_DLT_ATM_RFC1483;
49                case TRACE_TYPE_80211: return TRACE_DLT_IEEE802_11;
50                case TRACE_TYPE_LINUX_SLL: return TRACE_DLT_LINUX_SLL;
51                case TRACE_TYPE_PFLOG: return TRACE_DLT_PFLOG;
52        case TRACE_TYPE_80211_RADIO: return TRACE_DLT_IEEE802_11_RADIO;
53        }
54        return ~0;
55}
56
57enum rt_field_t pcap_dlt_to_rt(libtrace_dlt_t dlt) 
58{
59        /* For pcap the rt type is just the dlt + a fixed value */
60        return dlt + RT_DATA_PCAP;
61}
62
63libtrace_dlt_t rt_to_pcap_dlt(enum rt_field_t rt_type)
64{
65        assert(rt_type >= RT_DATA_PCAP);
66        return rt_type - RT_DATA_PCAP;
67}
68
69libtrace_linktype_t erf_type_to_libtrace(char erf)
70{
71        switch (erf) {
72                case TYPE_HDLC_POS:     return TRACE_TYPE_HDLC_POS;
73                case TYPE_ETH:          return TRACE_TYPE_ETH;
74                case TYPE_ATM:          return TRACE_TYPE_ATM;
75                case TYPE_AAL5:         return TRACE_TYPE_AAL5;
76        }
77        return ~0;
78}
79
80char libtrace_to_erf_type(libtrace_linktype_t linktype)
81{
82        switch(linktype) {
83                case TRACE_TYPE_HDLC_POS: return TYPE_HDLC_POS;
84                case TRACE_TYPE_ETH:    return TYPE_ETH;
85                case TRACE_TYPE_ATM:    return TYPE_ATM;
86                case TRACE_TYPE_AAL5:   return TYPE_AAL5;
87        }
88        return -1;
89}
90
91libtrace_linktype_t arphrd_type_to_libtrace(unsigned int arphrd) {
92        switch(arphrd) {
93                case ARPHRD_ETHER: return TRACE_TYPE_ETH;       
94                case ARPHRD_IEEE80211: return TRACE_TYPE_80211;
95                case ARPHRD_80211_RADIOTAP: return TRACE_TYPE_80211_RADIO;
96        }
97        return ~0;
98}
99
100unsigned int libtrace_to_arphrd_type(libtrace_linktype_t linktype) {
101        switch(linktype) {
102                case TRACE_TYPE_ETH: return ARPHRD_ETHER;
103                case TRACE_TYPE_80211: return ARPHRD_IEEE80211;
104                case TRACE_TYPE_80211_RADIO: return ARPHRD_80211_RADIOTAP;
105        }
106        return -1;
107}
108
109/** Tinker with a packet
110 * packets that don't support direction tagging are annoying, especially
111 * when we have direction tagging information!  So this converts the packet
112 * to TRACE_TYPE_LINUX_SLL which does support direction tagging.  This is a
113 * pcap style packet for the reason that it means it works with bpf filters.
114 *
115 * @note this will copy the packet, so use sparingly if possible.
116 */
117void promote_packet(libtrace_packet_t *packet)
118{
119        if (packet->trace->format->type == TRACE_FORMAT_PCAP) {
120                char *tmpbuffer;
121                libtrace_sll_header_t *hdr;
122
123                switch(pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))) {
124                        case TRACE_TYPE_LINUX_SLL:
125                                return; /* Unnecessary */
126
127                        case TRACE_TYPE_NONE:
128                        case TRACE_TYPE_ETH:
129                                /* This should be easy, just prepend the header */
130                                tmpbuffer= (char*)malloc(
131                                                sizeof(libtrace_sll_header_t)
132                                                +trace_get_capture_length(packet)
133                                                +trace_get_framing_length(packet)
134                                                );
135
136                                hdr=(libtrace_sll_header_t*)((char*)tmpbuffer
137                                        +trace_get_framing_length(packet));
138
139                                hdr->pkttype=TRACE_SLL_OUTGOING;
140                                if (pcap_dlt_to_libtrace(rt_to_pcap_dlt(packet->type))==TRACE_TYPE_ETH)
141                                        hdr->hatype = htons(ARPHRD_ETHER);
142                                else
143                                        hdr->hatype = htons(ARPHRD_PPP);
144                                trace_get_payload_from_link(
145                                        trace_get_link(packet),
146                                        trace_get_link_type(packet),
147                                        &hdr->protocol,
148                                        NULL);
149                                /* Linux SLL appears to have the protocol
150                                 * field in /host/ byte order.
151                                 */
152                                hdr->protocol=ntohs(hdr->protocol);
153                                break;
154                        default:
155                                /* failed */
156                                return;
157                }
158                memcpy(tmpbuffer,packet->header,
159                                trace_get_framing_length(packet));
160                memcpy(tmpbuffer
161                                +sizeof(libtrace_sll_header_t)
162                                +trace_get_framing_length(packet),
163                                packet->payload,
164                                trace_get_capture_length(packet));
165                if (packet->buf_control == TRACE_CTRL_EXTERNAL) {
166                        packet->buf_control=TRACE_CTRL_PACKET;
167                }
168                else {
169                        free(packet->buffer);
170                }
171                packet->buffer=tmpbuffer;
172                packet->header=tmpbuffer;
173                packet->payload=tmpbuffer+trace_get_framing_length(packet);
174                packet->type=pcap_dlt_to_rt(TRACE_DLT_LINUX_SLL);
175                packet->size+=sizeof(libtrace_sll_header_t);
176                ((struct pcap_pkthdr*) packet->header)->caplen+=
177                        sizeof(libtrace_sll_header_t);
178                ((struct pcap_pkthdr*) packet->header)->len+=
179                        sizeof(libtrace_sll_header_t);
180                return;
181        }
182}
183
184/* Try and simplify the packet one step, kinda the opposite to promote_packet
185 *
186 * returns true if demotion was possible, false if not.
187 */
188bool demote_packet(libtrace_packet_t *packet)
189{
190        switch(trace_get_link_type(packet)) {
191                case TRACE_TYPE_LINUX_SLL:
192                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
193                                        ->hatype)) {
194                                case ARPHRD_PPP:
195                                        packet->type=pcap_dlt_to_rt(DLT_NULL);
196                                        break;
197                                case ARPHRD_ETHER:
198                                        packet->type=pcap_dlt_to_rt(DLT_EN10MB);
199                                        break;
200                                default:
201                                        /* Dunno how to demote this packet */
202                                        return false;
203                        }
204                        /* Skip the Linux SLL header */
205                        packet->payload=(void*)((char*)packet->payload
206                                        +sizeof(libtrace_sll_header_t));
207                        trace_set_capture_length(packet,
208                                trace_get_capture_length(packet)
209                                        -sizeof(libtrace_sll_header_t));
210                        break;
211                default:
212                        return false;
213        }
214        return true;
215}
Note: See TracBrowser for help on using the repository browser.