source: lib/format_linux.c @ 411f3c7

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

Fixed the format module auditing code in trace.c to work with the new linked
list.
Did some more tidyups on format_linux, it now supports get_capture_length()
properly, does snapping and configurable promisc.

  • Property mode set to 100644
File size: 8.0 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2004 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *         
8 * All rights reserved.
9 *
10 * This code has been developed by the University of Waikato WAND
11 * research group. For further information please see http://www.wand.net.nz/
12 *
13 * libtrace is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * libtrace is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with libtrace; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
26 *
27 * $Id: format_template.c,v 1.13 2005/11/22 23:38:56 dlawson Exp $
28 *
29 */
30
31#include "libtrace.h"
32#include "libtrace_int.h"
33#include "format_helper.h"
34#include "config.h"
35#include "stdlib.h"
36
37#ifdef HAVE_INTTYPES_H
38#  include <inttypes.h>
39#else
40# error "Can't find inttypes.h"
41#endif
42
43#include <sys/socket.h>
44#include <netpacket/packet.h>
45#include <net/ethernet.h>
46#include <net/if_arp.h>
47
48#include <string.h>
49#include <net/if.h>
50#include <sys/ioctl.h>
51
52static struct libtrace_format_t linuxnative;
53
54struct libtrace_format_data_t {
55        int fd;
56        int snaplen;
57        int promisc;
58};
59
60struct libtrace_linuxnative_header {
61        struct timeval ts;
62        int wirelen;
63        int caplen;
64        struct sockaddr_ll hdr;
65};
66
67#define FORMAT(x) ((struct libtrace_format_data_t*)(x))
68
69static int linuxnative_init_input(libtrace_t *libtrace) 
70{
71        libtrace->format_data = (struct libtrace_format_data_t *)
72                malloc(sizeof(struct libtrace_format_data_t));
73        FORMAT(libtrace->format_data)->fd = -1;
74        FORMAT(libtrace->format_data)->promisc = 0;
75        FORMAT(libtrace->format_data)->snaplen = 65536;
76
77        return 0;
78}
79
80static int linuxnative_start_input(libtrace_t *libtrace)
81{
82        struct sockaddr_ll addr;
83        FORMAT(libtrace->format_data)->fd = 
84                                socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
85        if (FORMAT(libtrace->format_data)->fd==-1) {
86                free(libtrace->format_data);
87                return -1;
88        }
89        addr.sll_family = AF_PACKET;
90        addr.sll_protocol = htons(ETH_P_ALL);
91        if (strlen(libtrace->uridata)) {
92                addr.sll_ifindex = if_nametoindex(libtrace->uridata);
93                if (addr.sll_ifindex == 0) {
94                        close(FORMAT(libtrace->format_data)->fd);
95                        free(libtrace->format_data);
96                        return -1;
97                }
98        }
99        else {
100                addr.sll_ifindex = 0;
101        }
102        if (bind(FORMAT(libtrace->format_data)->fd,
103                                (struct sockaddr*)&addr,
104                                sizeof(addr))==-1) {
105                free(libtrace->format_data);
106                return -1;
107        }
108        /* enable promisc mode when listening on an interface */
109        if (addr.sll_ifindex!=0) {
110                struct packet_mreq mreq;
111                socklen_t socklen = sizeof(mreq);
112                mreq.mr_ifindex = addr.sll_ifindex;
113                mreq.mr_type = PACKET_MR_PROMISC;
114                setsockopt(FORMAT(libtrace->format_data)->fd,
115                                SOL_PACKET,
116                                PACKET_ADD_MEMBERSHIP,
117                                &mreq,
118                                socklen);
119        }
120
121        return 0;
122}
123
124static int linuxnative_pause_input(libtrace_t *libtrace)
125{
126        close(FORMAT(libtrace->format_data)->fd);
127        FORMAT(libtrace->format_data)->fd=-1;
128
129        return 0;
130}
131
132static int linuxnative_fin_input(libtrace_t *libtrace) 
133{
134        free(libtrace->format_data);
135        return 0;
136}
137
138static int linuxnative_config_input(libtrace_t *libtrace,
139                trace_option_t option,
140                void *data)
141{
142        switch(option) {
143                case TRACE_OPTION_SNAPLEN:
144                        FORMAT(libtrace->format_data)->snaplen=*(int*)data;
145                        return 0;
146                case TRACE_OPTION_PROMISC:
147                        FORMAT(libtrace->format_data)->promisc=*(int*)data;
148                        return 0;
149                case TRACE_OPTION_FILTER:
150                        /* We don't support bpf filters in any special way
151                         * so return an error and let libtrace deal with
152                         * emulating it
153                         */
154                        break;
155                /* Avoid default: so that future options will cause a warning
156                 * here to remind us to implement it, or flag it as
157                 * unimplementable
158                 */
159        }
160        trace_set_err(libtrace,TRACE_ERR_UNKNOWN_OPTION,
161                        "Unknown option %i", option);
162        return -1;
163}
164
165#define LIBTRACE_MIN(a,b) ((a)<(b) ? (a) : (b))
166
167static int linuxnative_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) {
168        struct libtrace_linuxnative_header *hdr;
169        socklen_t socklen;
170        int snaplen;
171        if (!packet->buffer || packet->buf_control == TRACE_CTRL_EXTERNAL) {
172                packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE);
173                packet->buf_control = TRACE_CTRL_PACKET;
174        }
175
176        packet->header = packet->buffer;
177        packet->type = RT_DATA_LINUX_NATIVE;
178        packet->payload = (char*)packet->buffer+sizeof(*hdr);
179
180        hdr=(void*)packet->buffer;
181        socklen=sizeof(hdr->hdr);
182        snaplen=LIBTRACE_MIN(
183                        (int)LIBTRACE_PACKET_BUFSIZE-(int)sizeof(*hdr),
184                        (int)FORMAT(libtrace->format_data)->snaplen);
185        hdr->wirelen = recvfrom(FORMAT(libtrace->format_data)->fd,
186                        (void*)packet->payload,
187                        snaplen,
188                        MSG_TRUNC,
189                        (void *)&hdr->hdr,
190                        &socklen);
191
192        if (hdr->wirelen==-1)
193                return -1;
194
195        hdr->caplen=LIBTRACE_MIN(snaplen,hdr->wirelen);
196
197        if (ioctl(FORMAT(libtrace->format_data)->fd,SIOCGSTAMP,&hdr->ts)==-1)
198                perror("ioctl(SIOCGSTAMP)");
199
200        return hdr->wirelen+sizeof(*hdr);
201}
202
203static libtrace_linktype_t linuxnative_get_link_type(const struct libtrace_packet_t *packet) {
204        switch (htons((((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_protocol))) {
205                case ETH_P_IP:
206                case ETH_P_IPV6:
207                case ETH_P_ARP:
208                        return TRACE_TYPE_ETH;
209                default: /* shrug, beyond me! */
210                        printf("unknown type %x\n",(((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_protocol));
211                        return -1;
212        }
213}
214
215static int8_t linuxnative_get_direction(const struct libtrace_packet_t *packet) {
216        switch (((struct libtrace_linuxnative_header*)(packet->buffer))->hdr.sll_pkttype) {
217                case PACKET_OUTGOING:
218                        return 0;
219                default:
220                        return 1;
221        }
222}
223
224static struct timeval linuxnative_get_timeval(const libtrace_packet_t *packet) 
225{
226        return ((struct libtrace_linuxnative_header*)(packet->buffer))->ts;
227}
228
229static int linuxnative_get_capture_length(const libtrace_packet_t *packet)
230{
231        return ((struct libtrace_linuxnative_header*)(packet->buffer))->caplen;
232}
233
234static int linuxnative_get_wire_length(const libtrace_packet_t *packet) 
235{
236        return ((struct libtrace_linuxnative_header*)(packet->buffer))->wirelen;
237}
238
239static int linuxnative_get_framing_length(const libtrace_packet_t *packet) 
240{
241        return sizeof(struct libtrace_linuxnative_header);
242}
243
244static int linuxnative_get_fd(const libtrace_t *trace) {
245        return FORMAT(trace->format_data)->fd;
246}
247
248static void linuxnative_help() {
249        printf("linuxnative format module: $Revision$\n");
250        printf("Supported input URIs:\n");
251        printf("\tint:\n");
252        printf("\n");
253        printf("Supported output URIs:\n");
254        printf("\tnone\n");
255        printf("\n");
256        return;
257}
258static struct libtrace_format_t linuxnative = {
259        "int",
260        "$Id: format_linuxnative.c,v 1.13 2005/11/22 23:38:56 dlawson Exp $",
261        TRACE_FORMAT_LINUX_NATIVE,
262        linuxnative_init_input,         /* init_input */
263        linuxnative_config_input,       /* config_input */
264        linuxnative_start_input,        /* start_input */
265        linuxnative_pause_input,        /* pause_input */
266        NULL,                           /* init_output */
267        NULL,                           /* config_output */
268        NULL,                           /* start_ouput */
269        linuxnative_fin_input,          /* fin_input */
270        NULL,                           /* fin_output */
271        linuxnative_read_packet,        /* read_packet */
272        NULL,                           /* fin_packet */
273        NULL,                           /* write_packet */
274        linuxnative_get_link_type,      /* get_link_type */
275        linuxnative_get_direction,      /* get_direction */
276        NULL,                           /* set_direction */
277        NULL,                           /* get_erf_timestamp */
278        linuxnative_get_timeval,        /* get_timeval */
279        NULL,                           /* get_seconds */
280        NULL,                           /* seek_erf */
281        NULL,                           /* seek_timeval */
282        NULL,                           /* seek_seconds */
283        linuxnative_get_capture_length, /* get_capture_length */
284        linuxnative_get_wire_length,    /* get_wire_length */
285        linuxnative_get_framing_length, /* get_framing_length */
286        NULL,                           /* set_capture_length */
287        linuxnative_get_fd,             /* get_fd */
288        trace_event_device,             /* trace_event */
289        linuxnative_help,               /* help */
290        NULL
291};
292
293void CONSTRUCTOR linuxnative_constructor() {
294        register_format(&linuxnative);
295}
Note: See TracBrowser for help on using the repository browser.