source: lib/linktypes.c @ dcbc330

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

The packet size has increased -- bump the wirelen too

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