source: lib/format_erf.c @ 4dedc28

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since 4dedc28 was 4dedc28, checked in by Daniel Lawson <dlawson@…>, 15 years ago

isplit input formats out

  • Property mode set to 100644
File size: 11.5 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$
28 *
29 */
30
31#include "libtrace.h"
32#include "format.h"
33
34#ifdef HAVE_INTTYPES_H
35#  include <inttypes.h>
36#else
37#  error "Can't find inttypes.h - this needs to be fixed"
38#endif
39
40#ifdef HAVE_STDDEF_H
41#  include <stddef.h>
42#else
43# error "Can't find stddef.h - do you define ptrdiff_t elsewhere?"
44#endif
45#include <sys/types.h>
46#include <sys/socket.h>
47#include <sys/un.h>
48#include <sys/mman.h>
49#include <sys/stat.h>
50#include <unistd.h>
51#include <assert.h>
52#include <errno.h>
53#include <netdb.h>
54
55/* Catch undefined O_LARGEFILE on *BSD etc */
56#ifndef O_LARGEFILE
57#  define O_LARGEFILE 0
58#endif
59static int dag_init_input(struct libtrace_t *libtrace) {
60        struct stat buf;
61        if (stat(libtrace->conn_info.path,&buf) == -1) {
62                perror("stat");
63                return 0;
64        } 
65        if (S_ISCHR(buf.st_mode)) {
66                // DEVICE
67                if((libtrace->input.fd = 
68                                dag_open(libtrace->conn_info.path)) < 0) {
69                        fprintf(stderr,"Cannot open DAG %s: %m\n", 
70                                        libtrace->conn_info.path,errno);
71                        exit(0);
72                }
73                if((libtrace->dag.buf = (void *)
74                                dag_mmap(libtrace->input.fd)) == MAP_FAILED) {
75                        fprintf(stderr,"Cannot mmap DAG %s: %m\n", 
76                                        libtrace->conn_info.path,errno);
77                        exit(0);
78                }
79                if(dag_start(libtrace->input.fd) < 0) {
80                        fprintf(stderr,"Cannot start DAG %s: %m\n", 
81                                        libtrace->conn_info.path,errno);
82                        exit(0);
83                }
84        } else {
85                fprintf(stderr,"%s isn't a valid char device, exiting\n",
86                                libtrace->conn_info.path);
87                return 0;
88        }
89}
90
91static int erf_init_input(struct libtrace_t *libtrace) {
92        struct stat buf;
93        struct hostent *he;
94        struct sockaddr_in remote;
95        struct sockaddr_un unix_sock;
96        if (!strncmp(libtrace->conn_info.path,"-",1)) {
97                // STDIN
98#if HAVE_ZLIB
99                libtrace->input.file = gzdopen(STDIN, "r");
100#else   
101                libtrace->input.file = stdin;
102#endif
103
104        } else {
105                if (stat(libtrace->conn_info.path,&buf) == -1 ) {
106                        perror("stat");
107                        return 0;
108                }
109                if (S_ISSOCK(buf.st_mode)) {
110                        // SOCKET
111                        if ((libtrace->input.fd = socket(
112                                        AF_UNIX, SOCK_STREAM, 0)) == -1) {
113                                perror("socket");
114                                return 0;
115                        }
116                        unix_sock.sun_family = AF_UNIX;
117                        bzero(unix_sock.sun_path,108);
118                        snprintf(unix_sock.sun_path,
119                                        108,"%s"
120                                        ,libtrace->conn_info.path);
121
122                        if (connect(libtrace->input.fd, 
123                                        (struct sockaddr *)&unix_sock,
124                                        sizeof(struct sockaddr)) == -1) {
125                                perror("connect (unix)");
126                                return 0;
127                        }
128                } else { 
129                        // TRACE
130#if HAVE_ZLIB
131                        // using gzdopen means we can set O_LARGEFILE
132                        // ourselves. However, this way is messy and
133                        // we lose any error checking on "open"
134                        libtrace->input.file = 
135                                gzdopen(open(
136                                        libtrace->conn_info.path,
137                                        O_LARGEFILE), "r");
138#else
139                        libtrace->input.file = 
140                                fdopen(open(
141                                        libtrace->conn_info.path,
142                                        O_LARGEFILE), "r");
143#endif
144
145                }
146        }
147}
148
149static int rtclient_init_input(struct libtrace_t *libtrace) {
150        char *scan;
151        char *uridata = libtrace->conn_info.path;
152        struct hostent *he;
153        struct sockaddr_in remote;
154
155        if (strlen(uridata) == 0) {
156                libtrace->conn_info.rt.hostname = 
157                        strdup("localhost");
158                libtrace->conn_info.rt.port = 
159                        COLLECTOR_PORT;
160        } else {
161                if ((scan = strchr(uridata,':')) == NULL) {
162                        libtrace->conn_info.rt.hostname = 
163                                strdup(uridata);
164                        libtrace->conn_info.rt.port =
165                                COLLECTOR_PORT;
166                } else {
167                        libtrace->conn_info.rt.hostname = 
168                                (char *)strndup(uridata,
169                                                (scan - uridata));
170                        libtrace->conn_info.rt.port = 
171                                atoi(++scan);
172                }
173        }
174       
175        if ((he=gethostbyname(libtrace->conn_info.rt.hostname)) == NULL) { 
176                perror("gethostbyname");
177                return 0;
178        } 
179        if ((libtrace->input.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
180                perror("socket");
181                return 0;
182        }
183
184        remote.sin_family = AF_INET;   
185        remote.sin_port = htons(libtrace->conn_info.rt.port);
186        remote.sin_addr = *((struct in_addr *)he->h_addr);
187        bzero(&(remote.sin_zero), 8);
188
189        if (connect(libtrace->input.fd, (struct sockaddr *)&remote,
190                                sizeof(struct sockaddr)) == -1) {
191                perror("connect (inet)");
192                return 0;
193        }
194}
195
196static int dag_fin_input(struct libtrace_t *libtrace) {
197        dag_stop(libtrace->input.fd);
198}
199
200static int erf_fin_input(struct libtrace_t *libtrace) {
201#if HAVE_ZLIB
202        gzclose(libtrace->input.file);
203#else   
204        fclose(libtrace->input.file);   
205#endif
206}
207
208static int rtclient_fin_input(struct libtrace_t *libtrace) {
209        close(libtrace->input.fd);
210}
211
212static int erf_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
213        return -1;
214}
215
216static int dag_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
217        int numbytes;
218        int size;
219        char buf[RP_BUFSIZE];
220        dag_record_t *erfptr;
221        void *buffer = packet->buffer;
222        void *buffer2 = buffer;
223        int rlen;
224       
225        if (libtrace->dag.diff == 0) {
226                if ((numbytes = trace_read(libtrace,buf,RP_BUFSIZE)) <= 0) 
227                        return numbytes;
228        }
229
230        //DAG always gives us whole packets
231        erfptr = (dag_record_t *) ((void *)libtrace->dag.buf + 
232                        (libtrace->dag.bottom + libtrace->dag.offset));
233        size = ntohs(erfptr->rlen);
234
235        if ( size  > LIBTRACE_PACKET_BUFSIZE) {
236                printf("%d\n",size);
237                assert( size < LIBTRACE_PACKET_BUFSIZE);
238        }
239
240        // have to copy it out of the memory hole at this stage:
241        memcpy(packet->buffer, erfptr, size);
242
243        packet->size = size;
244        libtrace->dag.offset += size;
245        libtrace->dag.diff -= size;
246
247        assert(libtrace->dag.diff >= 0);
248
249        return (size);
250
251}
252
253static int erf_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
254        int numbytes;
255        int size;
256        char buf[RP_BUFSIZE];
257        dag_record_t *erfptr;
258        void *buffer = packet->buffer;
259        void *buffer2 = buffer;
260        int rlen;
261       
262        if ((numbytes=gzread(libtrace->input.file,
263                                        buffer,
264                                        dag_record_size)) == -1) {
265                perror("gzread");
266                return -1;
267        }
268        if (numbytes == 0) {
269                return 0;
270        }
271        rlen = ntohs(((dag_record_t *)buffer)->rlen);
272        size = rlen - dag_record_size;
273        assert(size < LIBTRACE_PACKET_BUFSIZE);
274        buffer2 = buffer + dag_record_size;
275       
276        // read in the rest of the packet
277        if ((numbytes=gzread(libtrace->input.file,
278                                        buffer2,
279                                        size)) == -1) {
280                perror("gzread");
281                return -1;
282        }
283        packet->size = rlen;
284        return rlen;
285}
286
287static int rtclient_read(struct libtrace_t *libtrace, void *buffer, size_t len) {
288        int numbytes;
289        static short lctr = 0;
290        struct dag_record_t *erfptr = 0;
291        int rlen;
292
293        if (buffer == 0)
294                buffer = malloc(len);
295        while(1) {
296#ifndef MSG_NOSIGNAL
297#  define MSG_NOSIGNAL 0
298#endif
299                if ((numbytes = recv(libtrace->input.fd,
300                                                buffer,
301                                                len,
302                                                MSG_NOSIGNAL)) == -1) {
303                        if (errno == EINTR) {
304                                //ignore EINTR in case
305                                // a caller is using signals
306                                continue;
307                        }
308                        perror("recv");
309                        return -1;
310                }
311                break;
312
313        }
314        return numbytes;
315}
316
317static int rtclient_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) {
318        int numbytes;
319        int size;
320        char buf[RP_BUFSIZE];
321        dag_record_t *erfptr;
322        int read_required = 0;
323       
324        void *buffer = 0;
325        buffer = packet->buffer;
326
327        do {
328                if (fifo_out_available(libtrace->fifo) == 0 || read_required) {
329                        if ((numbytes = trace_read(
330                                                libtrace,buf,RP_BUFSIZE))<=0) {
331                                return numbytes;
332                        }
333                        assert(libtrace->fifo);
334                        fifo_write(libtrace->fifo,buf,numbytes);
335                        read_required = 0;
336                }
337                if (fifo_out_read(libtrace->fifo,
338                                &packet->status, sizeof(int)) == 0) {
339                        read_required = 1;
340                        continue;
341                }
342                fifo_out_update(libtrace->fifo,sizeof(int));
343
344                if ((numbytes = fifo_out_read(libtrace->fifo, buffer,
345                                                sizeof(dag_record_t))) == 0) {
346                        fifo_out_reset(libtrace->fifo);
347                        read_required = 1;
348                        continue;
349                }
350                size = ntohs(((dag_record_t *)buffer)->rlen);
351
352                // read in the full packet
353                if ((numbytes = fifo_out_read(libtrace->fifo, 
354                                                buffer, size)) == 0) {
355                        fifo_out_reset(libtrace->fifo);
356                        read_required = 1;
357                        continue;
358                }
359
360                // got in our howle packet, so...
361                fifo_out_update(libtrace->fifo,size);
362
363                fifo_ack_update(libtrace->fifo,size + sizeof(int));
364
365                packet->size = numbytes;
366                return numbytes;
367        } while(1);
368}
369
370static void *erf_get_link(const struct libtrace_packet_t *packet) {
371        dag_record_t *erfptr = 0;
372        erfptr = (dag_record_t *)packet->buffer;
373        const void *ethptr = 0;
374
375        if (erfptr->flags.rxerror == 1) {
376                return NULL;
377        }
378        ethptr = ((uint8_t *)packet->buffer +
379                        dag_record_size + 2);
380}
381
382static libtrace_linktype_t erf_get_link_type(const struct libtrace_packet_t *packet) {
383        dag_record_t *erfptr = 0;
384        erfptr = (dag_record_t *)packet->buffer;
385        switch (erfptr->type) {
386                case TYPE_ETH: return TRACE_TYPE_ETH;
387                case TYPE_ATM: return TRACE_TYPE_ATM;
388                default: assert(0);
389        }
390}
391
392static int8_t erf_get_direction(const struct libtrace_packet_t *packet) {
393        dag_record_t *erfptr = 0;
394        erfptr = (dag_record_t *)packet->buffer;
395        return erfptr->flags.iface;
396}
397
398static int8_t erf_set_direction(const struct libtrace_packet_t *packet, int8_t direction) {
399        dag_record_t *erfptr = 0;
400        erfptr = (dag_record_t *)packet->buffer;
401        erfptr->flags.iface = direction;
402        return erfptr->flags.iface;
403}
404
405static uint64_t erf_get_erf_timestamp(const struct libtrace_packet_t *packet) {
406        dag_record_t *erfptr = 0;
407        erfptr = (dag_record_t *)packet->buffer;
408        return erfptr->ts;
409}
410
411static int erf_get_capture_length(const struct libtrace_packet_t *packet) {
412        dag_record_t *erfptr = 0;
413        erfptr = (dag_record_t *)packet->buffer;
414        return ntohs(erfptr->rlen);
415}
416
417static int erf_get_wire_length(const struct libtrace_packet_t *packet) {
418        dag_record_t *erfptr = 0;
419        erfptr = (dag_record_t *)packet->buffer;
420        return ntohs(erfptr->wlen);
421}
422
423static size_t erf_truncate_packet(struct libtrace_packet_t *packet, const size_t size) {
424        dag_record_t *erfptr = 0;
425        assert(packet);
426        if(size > packet->size) {
427                // can't make a packet larger
428                return packet->size;
429        }
430        erfptr = (dag_record_t *)packet->buffer;
431        erfptr->rlen = ntohs(size + sizeof(dag_record_t));
432        packet->size = size + sizeof(dag_record_t);
433        return packet->size;
434}
435
436static struct format_t erf = {
437        "erf",
438        "$Id$",
439        erf_init_input,
440        NULL,
441        erf_fin_input,
442        NULL,
443        erf_read_packet,
444        NULL,
445        erf_get_link,
446        erf_get_link_type,
447        erf_get_direction,
448        erf_set_direction,
449        erf_get_erf_timestamp,
450        NULL,
451        NULL,
452        erf_get_capture_length,
453        erf_get_wire_length,
454        erf_truncate_packet
455};
456
457static struct format_t dag = {
458        "dag",
459        "$Id$",
460        dag_init_input,
461        NULL,
462        dag_fin_input,
463        NULL,
464        dag_read_packet,
465        NULL,
466        erf_get_link,
467        erf_get_link_type,
468        erf_get_direction,
469        erf_set_direction,
470        erf_get_erf_timestamp,
471        NULL,
472        NULL,
473        erf_get_capture_length,
474        erf_get_wire_length,
475        erf_truncate_packet
476};
477
478static struct format_t rtclient = {
479        "rtclient",
480        "$Id$",
481        rtclient_init_input,
482        NULL,
483        rtclient_fin_input,
484        rtclient_read,
485        rtclient_read_packet,
486        NULL,
487        erf_get_link,
488        erf_get_link_type,
489        erf_get_direction,
490        erf_set_direction,
491        erf_get_erf_timestamp,
492        NULL,
493        NULL,
494        erf_get_capture_length,
495        erf_get_wire_length,
496        erf_truncate_packet
497};
498
499void __attribute__((constructor)) erf_constructor() {
500        register_format(&erf);
501        register_format(&dag);
502}
Note: See TracBrowser for help on using the repository browser.