source: lib/linktypes.c @ a7d1914

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

Remove packet->size as noone really knew what it held anyway, and disagreements
were more easily settled by removing it than standardising one way or the other.

  • 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                ((struct pcap_pkthdr*) packet->header)->caplen+=
176                        sizeof(libtrace_sll_header_t);
177                ((struct pcap_pkthdr*) packet->header)->len+=
178                        sizeof(libtrace_sll_header_t);
179                return;
180        }
181}
182
183/* Try and simplify the packet one step, kinda the opposite to promote_packet
184 *
185 * returns true if demotion was possible, false if not.
186 */
187bool demote_packet(libtrace_packet_t *packet)
188{
189        switch(trace_get_link_type(packet)) {
190                case TRACE_TYPE_LINUX_SLL:
191                        switch(ntohs(((libtrace_sll_header_t*)packet->payload)
192                                        ->hatype)) {
193                                case ARPHRD_PPP:
194                                        packet->type=pcap_dlt_to_rt(DLT_NULL);
195                                        break;
196                                case ARPHRD_ETHER:
197                                        packet->type=pcap_dlt_to_rt(DLT_EN10MB);
198                                        break;
199                                default:
200                                        /* Dunno how to demote this packet */
201                                        return false;
202                        }
203                        /* Skip the Linux SLL header */
204                        packet->payload=(void*)((char*)packet->payload
205                                        +sizeof(libtrace_sll_header_t));
206                        trace_set_capture_length(packet,
207                                trace_get_capture_length(packet)
208                                        -sizeof(libtrace_sll_header_t));
209                        break;
210                default:
211                        return false;
212        }
213        return true;
214}
Note: See TracBrowser for help on using the repository browser.