source: lib/format_rt.c @ f2fae49

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

Add new "loss" framework

  • Property mode set to 100644
File size: 18.9 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007 The University of Waikato, Hamilton, New Zealand.
5 * Authors: Daniel Lawson
6 *          Perry Lorier
7 *          Shane Alcock
8 *
9 * All rights reserved.
10 *
11 * This code has been developed by the University of Waikato WAND
12 * research group. For further information please see http://www.wand.net.nz/
13 *
14 * libtrace is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
18 *
19 * libtrace is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with libtrace; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
27 *
28 * $Id$
29 *
30 */
31
32#define _GNU_SOURCE
33
34#include "config.h"
35#include "common.h"
36#include "libtrace.h"
37#include "libtrace_int.h"
38#include "format_helper.h"
39#include "rt_protocol.h"
40
41#include <sys/stat.h>
42#include <assert.h>
43#include <errno.h>
44#include <fcntl.h>
45#include <stdio.h>
46#include <string.h>
47#include <stdlib.h>
48
49#ifndef WIN32
50# include <netdb.h>
51#endif
52
53#define RT_INFO ((struct rt_format_data_t*)libtrace->format_data)
54
55static const char *rt_deny_reason(enum rt_conn_denied_t reason) 
56{
57        const char *string = 0;
58
59        switch(reason) {
60                case RT_DENY_WRAPPER:
61                        string = "Rejected by TCP Wrappers";
62                        break;
63                case RT_DENY_FULL:
64                        string = "Max connections reached on server";
65                        break;
66                case RT_DENY_AUTH:
67                        string = "Authentication failed";
68                        break;
69                default:
70                        string = "Unknown reason";
71        }
72
73        return string;
74}
75
76
77struct rt_format_data_t {
78        char *hostname;
79        int port;
80        int input_fd;
81        int reliable;
82        char *pkt_buffer;
83        char *buf_current;
84        size_t buf_filled;
85        rt_header_t rt_hdr;
86       
87        libtrace_t *dummy_duck;
88        libtrace_t *dummy_erf;
89        libtrace_t *dummy_pcap;
90        libtrace_t *dummy_linux;
91};
92
93static int rt_connect(libtrace_t *libtrace) {
94        struct hostent *he;
95        struct sockaddr_in remote;
96        rt_header_t connect_msg;
97        rt_deny_conn_t deny_hdr;       
98        rt_hello_t hello_opts;
99        uint8_t reason;
100       
101        if ((he=gethostbyname(RT_INFO->hostname)) == NULL) {
102                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
103                                "Failed to convert hostname %s to address",
104                                RT_INFO->hostname);
105                return -1;
106        }
107        if ((RT_INFO->input_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
108                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
109                                "Could not create socket");
110                return -1;
111        }
112
113        memset(&remote,0, sizeof(remote));
114        remote.sin_family = AF_INET;
115        remote.sin_port = htons(RT_INFO->port);
116        remote.sin_addr = *((struct in_addr *)he->h_addr);
117
118        if (connect(RT_INFO->input_fd, (struct sockaddr *)&remote,
119                                (socklen_t)sizeof(struct sockaddr)) == -1) {
120                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
121                                "Could not connect to host %s on port %d",
122                                RT_INFO->hostname, RT_INFO->port);
123                return -1;
124        }
125
126       
127#if 0
128        oldflags = fcntl(RT_INFO->input_fd, F_GETFL, 0);
129        if (oldflags == -1) {
130                trace_set_err(libtrace, errno,
131                                "Could not get fd flags from fd %d\n",
132                                RT_INFO->input_fd);
133                return -1;
134        }
135        oldflags |= O_NONBLOCK;
136        if (fcntl(RT_INFO->input_fd, F_SETFL, oldflags) == -1) {
137                trace_set_err(libtrace, errno,
138                                "Could not set fd flags for fd %d\n",
139                                RT_INFO->input_fd);
140                return -1;
141        }
142#endif
143       
144       
145        /* We are connected, now receive message from server */
146       
147        if (recv(RT_INFO->input_fd, (void*)&connect_msg, sizeof(rt_header_t), 0) != sizeof(rt_header_t) ) {
148                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
149                                "Could not receive connection message from %s",
150                                RT_INFO->hostname);
151                return -1;
152        }
153       
154        switch (connect_msg.type) {
155                case TRACE_RT_DENY_CONN:
156                       
157                        if (recv(RT_INFO->input_fd, (void*)&deny_hdr, 
158                                                sizeof(rt_deny_conn_t),
159                                                0) != sizeof(rt_deny_conn_t)) {
160                                reason = 0;
161                        }       
162                        reason = deny_hdr.reason;
163                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
164                                "Connection attempt is denied: %s",
165                                rt_deny_reason(reason));       
166                        return -1;
167                case TRACE_RT_HELLO:
168                        /* do something with options */
169                        if (recv(RT_INFO->input_fd, (void*)&hello_opts, 
170                                                sizeof(rt_hello_t), 0)
171                                        != sizeof(rt_hello_t)) {
172                                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
173                                        "Failed to receive TRACE_RT_HELLO options");
174                                return -1;
175                        }
176                        RT_INFO->reliable = hello_opts.reliable;
177                       
178                        return 0;
179                default:
180                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
181                                        "Unknown message type received: %d",
182                                        connect_msg.type);
183                        return -1;
184        }
185        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
186                        "Somehow you managed to reach this unreachable code");
187        return -1;
188}
189
190
191static int rt_init_input(libtrace_t *libtrace) {
192        char *scan;
193        char *uridata = libtrace->uridata;
194        libtrace->format_data = malloc(sizeof(struct rt_format_data_t));
195
196        RT_INFO->dummy_duck = NULL;
197        RT_INFO->dummy_erf = NULL;
198        RT_INFO->dummy_pcap = NULL;
199        RT_INFO->dummy_linux = NULL;
200        RT_INFO->pkt_buffer = NULL;
201        RT_INFO->buf_current = NULL;
202        RT_INFO->buf_filled = 0;
203       
204        if (strlen(uridata) == 0) {
205                RT_INFO->hostname =
206                        strdup("localhost");
207                RT_INFO->port =
208                        COLLECTOR_PORT;
209        } else {
210                if ((scan = strchr(uridata,':')) == NULL) {
211                        RT_INFO->hostname =
212                                strdup(uridata);
213                        RT_INFO->port =
214                                COLLECTOR_PORT;
215                } else {
216                        RT_INFO->hostname =
217                                (char *)strndup(uridata,
218                                                (size_t)(scan - uridata));
219                        RT_INFO->port =
220                                atoi(++scan);
221                }
222        }
223
224        return 0;
225}
226       
227static int rt_start_input(libtrace_t *libtrace) {
228        rt_header_t start_msg;
229
230        start_msg.type = TRACE_RT_START;
231        start_msg.length = 0; 
232
233        if (rt_connect(libtrace) == -1)
234                return -1;
235       
236        /* Need to send start message to server */
237        if (send(RT_INFO->input_fd, (void*)&start_msg, sizeof(rt_header_t) +
238                                start_msg.length, 0) != sizeof(rt_header_t)) {
239                printf("Failed to send start message to server\n");
240                return -1;
241        }
242        RT_INFO->rt_hdr.type = TRACE_RT_LAST;
243
244        return 0;
245}
246
247static int rt_pause_input(libtrace_t *libtrace) {
248        rt_header_t close_msg;
249
250        close_msg.type = TRACE_RT_CLOSE;
251        close_msg.length = 0; 
252       
253        /* Send a close message to the server */
254        if (send(RT_INFO->input_fd, (void*)&close_msg, sizeof(rt_header_t) + 
255                                close_msg.length, 0) != (int)sizeof(rt_header_t)
256                                + close_msg.length) {
257                printf("Failed to send close message to server\n");
258       
259        }
260
261        close(RT_INFO->input_fd);
262        return 0;
263}
264
265static int rt_fin_input(libtrace_t *libtrace) {
266        if (RT_INFO->dummy_duck)
267                trace_destroy_dead(RT_INFO->dummy_duck);
268
269        if (RT_INFO->dummy_erf) 
270                trace_destroy_dead(RT_INFO->dummy_erf);
271               
272        if (RT_INFO->dummy_pcap)
273                trace_destroy_dead(RT_INFO->dummy_pcap);
274
275        if (RT_INFO->dummy_linux)
276                trace_destroy_dead(RT_INFO->dummy_linux);
277        free(libtrace->format_data);
278        return 0;
279}
280
281#define RT_BUF_SIZE 4000U
282
283static int rt_read(libtrace_t *libtrace, void **buffer, size_t len, int block) 
284{
285        int numbytes;
286       
287        assert(len <= RT_BUF_SIZE);
288       
289        if (!RT_INFO->pkt_buffer) {
290                RT_INFO->pkt_buffer = (char*)malloc((size_t)RT_BUF_SIZE);
291                RT_INFO->buf_current = RT_INFO->pkt_buffer;
292                RT_INFO->buf_filled = 0;
293        }
294
295#ifndef MSG_DONTWAIT
296#define MSG_DONTWAIT 0
297#endif
298
299        if (block)
300                block=0;
301        else
302                block=MSG_DONTWAIT;
303
304       
305        if (len > RT_INFO->buf_filled) {
306                memcpy(RT_INFO->pkt_buffer, RT_INFO->buf_current, 
307                                RT_INFO->buf_filled);
308                RT_INFO->buf_current = RT_INFO->pkt_buffer;
309#ifndef MSG_NOSIGNAL
310#  define MSG_NOSIGNAL 0
311#endif
312                while (len > RT_INFO->buf_filled) {
313                        if ((numbytes = recv(RT_INFO->input_fd,
314                                                RT_INFO->buf_current + 
315                                                RT_INFO->buf_filled,
316                                                RT_BUF_SIZE-RT_INFO->buf_filled,
317                                                MSG_NOSIGNAL|block)) <= 0) {
318                                if (numbytes == 0) {
319                                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
320                                                        "No data received");
321                                        return -1;
322                                }
323                               
324                                if (errno == EINTR) {
325                                        /* ignore EINTR in case
326                                         * a caller is using signals
327                                         */
328                                        continue;
329                                }
330                                if (errno == EAGAIN) {
331                                        trace_set_err(libtrace,
332                                                        EAGAIN,
333                                                        "EAGAIN");
334                                        return -1;
335                                }
336                               
337                                perror("recv");
338                                trace_set_err(libtrace, errno,
339                                                "Failed to read data into rt recv buffer");
340                                return -1;
341                        }
342                        /*
343                        buf_ptr = RT_INFO->pkt_buffer;
344                        for (i = 0; i < RT_BUF_SIZE ; i++) {
345                                       
346                                printf("%02x", (unsigned char)*buf_ptr);
347                                buf_ptr ++;
348                        }
349                        printf("\n");
350                        */
351                        RT_INFO->buf_filled+=numbytes;
352                }
353
354        }
355        *buffer = RT_INFO->buf_current;
356        RT_INFO->buf_current += len;
357        RT_INFO->buf_filled -= len;
358        return len;
359}
360
361
362static int rt_set_format(libtrace_t *libtrace, libtrace_packet_t *packet) 
363{
364
365        /* Try to minimize the number of corrupt packets that slip through
366         * while making it easy to identify new pcap DLTs */
367        if (packet->type > TRACE_RT_DATA_DLT && 
368                        packet->type < TRACE_RT_DATA_DLT_END) {
369                if (!RT_INFO->dummy_pcap) {
370                        RT_INFO->dummy_pcap = trace_create_dead("pcap:-");
371                }
372                packet->trace = RT_INFO->dummy_pcap;
373                return 0;       
374        }
375
376        switch (packet->type) {
377                case TRACE_RT_DUCK_2_4:
378                case TRACE_RT_DUCK_2_5:
379                        if (!RT_INFO->dummy_duck) {
380                                RT_INFO->dummy_duck = trace_create_dead("duck:dummy");
381                        }
382                        packet->trace = RT_INFO->dummy_duck;
383                        break;
384                case TRACE_RT_DATA_ERF:
385                        if (!RT_INFO->dummy_erf) {
386                                RT_INFO->dummy_erf = trace_create_dead("erf:-");
387                        }
388                        packet->trace = RT_INFO->dummy_erf;
389                        break;
390                case TRACE_RT_DATA_LINUX_NATIVE:
391                        if (!RT_INFO->dummy_linux) {
392                                RT_INFO->dummy_linux = trace_create_dead("int:");
393                        }
394                        packet->trace = RT_INFO->dummy_linux;
395                        break;
396                case TRACE_RT_DATA_LEGACY_ETH:
397                case TRACE_RT_DATA_LEGACY_ATM:
398                case TRACE_RT_DATA_LEGACY_POS:
399                        printf("Sending legacy over RT is currently not supported\n");
400                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Legacy packet cannot be sent over rt");
401                        return -1;
402                default:
403                        printf("Unrecognised format: %u\n", packet->type);
404                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unrecognised packet format");
405                        return -1;
406        }
407        return 0; /* success */
408}               
409
410static void rt_set_payload(libtrace_packet_t *packet) {
411        dag_record_t *erfptr;
412       
413        switch (packet->type) {
414                case TRACE_RT_DATA_ERF:
415                        erfptr = (dag_record_t *)packet->header;
416                       
417                        if (erfptr->flags.rxerror == 1) {
418                                packet->payload = NULL;
419                                break;
420                        }
421                        /* else drop into the default case */
422                default:
423                        packet->payload = (char *)packet->buffer +
424                                trace_get_framing_length(packet);
425                        break;
426        }
427}
428
429static int rt_send_ack(libtrace_t *libtrace, 
430                uint32_t seqno)  {
431       
432        static char *ack_buffer = 0;
433        char *buf_ptr;
434        int numbytes = 0;
435        size_t to_write = 0;
436        rt_header_t *hdr;
437        rt_ack_t *ack_hdr;
438       
439        if (!ack_buffer) {
440                ack_buffer = (char*)malloc(sizeof(rt_header_t) 
441                                                        + sizeof(rt_ack_t));
442        }
443       
444        hdr = (rt_header_t *) ack_buffer;
445        ack_hdr = (rt_ack_t *) (ack_buffer + sizeof(rt_header_t));
446       
447        hdr->type = TRACE_RT_ACK;
448        hdr->length = sizeof(rt_ack_t);
449
450        ack_hdr->sequence = seqno;
451       
452        to_write = hdr->length + sizeof(rt_header_t);
453        buf_ptr = ack_buffer;
454
455        while (to_write > 0) {
456                numbytes = send(RT_INFO->input_fd, buf_ptr, to_write, 0); 
457                if (numbytes == -1) {
458                        if (errno == EINTR || errno == EAGAIN) {
459                                continue;
460                        }
461                        else {
462                                printf("Error sending ack\n");
463                                perror("send");
464                                trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, 
465                                                "Error sending ack");
466                                return -1;
467                        }
468                }
469                to_write = to_write - numbytes;
470                buf_ptr = buf_ptr + to_write;
471               
472        }
473
474        return 1;
475}
476
477       
478static int rt_read_packet_versatile(libtrace_t *libtrace,
479                libtrace_packet_t *packet,int blocking) {
480        rt_header_t *pkt_hdr = NULL;
481        void *void_hdr;
482       
483        if (packet->buf_control == TRACE_CTRL_PACKET) {
484                packet->buf_control = TRACE_CTRL_EXTERNAL;
485                free(packet->buffer);
486                packet->buffer = NULL;
487        }
488
489        /* RT_LAST means that the next bytes received should be a
490         * rt header - I know it's hax and maybe I'll fix it later on */
491        if (RT_INFO->rt_hdr.type == TRACE_RT_LAST) {
492                void_hdr = (void *)pkt_hdr;
493                /* FIXME: Better error handling required */
494                if (rt_read(libtrace, &void_hdr, 
495                                sizeof(rt_header_t),blocking) !=
496                                sizeof(rt_header_t)) {
497                        return -1;
498                }
499                pkt_hdr = (rt_header_t *)void_hdr;
500               
501                /* Need to salvage these in case the next rt_read overwrites
502                 * the buffer they came from! */
503                RT_INFO->rt_hdr.type = pkt_hdr->type;
504                RT_INFO->rt_hdr.length = pkt_hdr->length;
505                RT_INFO->rt_hdr.sequence = pkt_hdr->sequence;
506        }
507        packet->type = RT_INFO->rt_hdr.type;
508
509       
510        if (packet->type >= TRACE_RT_DATA_SIMPLE) {
511                if (rt_read(libtrace, 
512                                        &packet->buffer,
513                                        (size_t)RT_INFO->rt_hdr.length,
514                                        blocking) != RT_INFO->rt_hdr.length) {
515                        return -1;
516                }
517                packet->header = packet->buffer;
518               
519                if (RT_INFO->reliable > 0) {
520                        if (rt_send_ack(libtrace, RT_INFO->rt_hdr.sequence) 
521                                        == -1)
522                        {
523                                return -1;
524                        }
525                }
526               
527                       
528                if (rt_set_format(libtrace, packet) < 0) {
529                        return -1;
530                }
531                rt_set_payload(packet);
532        } else {
533                switch(packet->type) {
534                        case TRACE_RT_STATUS:
535                        case TRACE_RT_METADATA:
536                                if (rt_read(libtrace, &packet->buffer, 
537                                        (size_t)RT_INFO->rt_hdr.length,
538                                        blocking) != 
539                                                RT_INFO->rt_hdr.length) {
540                                        return -1;
541                                }
542                                packet->header = 0;
543                                packet->payload = packet->buffer;
544                                break;
545                        case TRACE_RT_DUCK_2_4:
546                        case TRACE_RT_DUCK_2_5:
547                                if (rt_read(libtrace, &packet->buffer,
548                                        (size_t)RT_INFO->rt_hdr.length,
549                                        blocking) != 
550                                                RT_INFO->rt_hdr.length) {
551                                        return -1;
552                                }
553                                if (rt_set_format(libtrace, packet) < 0) {
554                                        return -1;
555                                }
556                                packet->header = 0;
557                                packet->payload = packet->buffer;
558                                break;
559                        case TRACE_RT_END_DATA:
560                                break;
561                        case TRACE_RT_PAUSE_ACK:
562                                /* FIXME: Do something useful */
563                                break;
564                        case TRACE_RT_OPTION:
565                                /* FIXME: Do something useful here as well */
566                                break;
567                        case TRACE_RT_KEYCHANGE:
568                                break;
569                        case TRACE_RT_LOSTCONN:
570                                break;
571                        case TRACE_RT_SERVERSTART:
572                                break;
573                        case TRACE_RT_CLIENTDROP:
574                                break;
575                        default:
576                                printf("Bad rt type for client receipt: %d\n",
577                                        packet->type);
578                                return -1;
579                }
580        }
581        /* Return the number of bytes read from the stream */
582        RT_INFO->rt_hdr.type = TRACE_RT_LAST;
583        return RT_INFO->rt_hdr.length + sizeof(rt_header_t);
584}
585
586static int rt_read_packet(libtrace_t *libtrace,
587                libtrace_packet_t *packet) {
588        return rt_read_packet_versatile(libtrace,packet,1);
589}
590
591
592static int rt_get_capture_length(const libtrace_packet_t *packet) {
593        rt_metadata_t *rt_md_hdr;
594        switch (packet->type) {
595                case TRACE_RT_STATUS:
596                        return sizeof(rt_status_t);
597                case TRACE_RT_HELLO:
598                        return sizeof(rt_hello_t);
599                case TRACE_RT_START:
600                        return 0;
601                case TRACE_RT_ACK:
602                        return sizeof(rt_ack_t);
603                case TRACE_RT_END_DATA:
604                        return 0;
605                case TRACE_RT_CLOSE:
606                        return 0;
607                case TRACE_RT_DENY_CONN:
608                        return sizeof(rt_deny_conn_t);
609                case TRACE_RT_PAUSE:
610                        return 0; 
611                case TRACE_RT_PAUSE_ACK:
612                        return 0;
613                case TRACE_RT_OPTION:
614                        return 0; /* FIXME */
615                case TRACE_RT_KEYCHANGE:
616                        return 0;
617                case TRACE_RT_LOSTCONN:
618                        return 0;
619                case TRACE_RT_SERVERSTART:
620                        return 0;
621                case TRACE_RT_CLIENTDROP:
622                        return 0;
623                case TRACE_RT_METADATA:
624                        /* This is a little trickier to work out */
625                        rt_md_hdr = (rt_metadata_t *)packet->buffer;
626                        return rt_md_hdr->label_len + rt_md_hdr->value_len + 
627                                sizeof(rt_metadata_t);
628                default:
629                        printf("Unknown type: %d\n", packet->type);
630                       
631        }
632        return 0;
633}
634
635static int rt_get_wire_length(UNUSED const libtrace_packet_t *packet) {
636        return 0;
637}
638                       
639static int rt_get_framing_length(UNUSED const libtrace_packet_t *packet) {
640        return 0;
641}
642
643static int rt_get_fd(const libtrace_t *trace) {
644        return ((struct rt_format_data_t *)trace->format_data)->input_fd;
645}
646
647static libtrace_eventobj_t trace_event_rt(libtrace_t *trace,
648                                        libtrace_packet_t *packet) 
649{
650        libtrace_eventobj_t event = {0,0,0.0,0};
651        libtrace_err_t read_err;
652
653        assert(trace);
654        assert(packet);
655       
656        if (trace->format->get_fd) {
657                event.fd = trace->format->get_fd(trace);
658        } else {
659                event.fd = 0;
660        }
661
662        event.size = rt_read_packet_versatile(trace, packet, 0);
663        if (event.size == -1) {
664                read_err = trace_get_err(trace);
665                if (read_err.err_num == EAGAIN) {
666                        event.type = TRACE_EVENT_IOWAIT;
667                }
668                else {
669                        event.type = TRACE_EVENT_PACKET;
670                }
671        } else if (event.size == 0) {
672                if (packet->type == TRACE_RT_END_DATA)
673                        event.type = TRACE_EVENT_TERMINATE;
674                else
675                        event.type = TRACE_EVENT_PACKET;
676               
677        }       
678        else {
679                event.type = TRACE_EVENT_PACKET;
680        }
681
682       
683        return event;
684}
685
686static void rt_help(void) {
687        printf("rt format module\n");
688        printf("Supported input URIs:\n");
689        printf("\trt:hostname:port\n");
690        printf("\trt:hostname (connects on default port)\n");
691        printf("\n");
692        printf("\te.g.: rt:localhost\n");
693        printf("\te.g.: rt:localhost:32500\n");
694        printf("\n");
695
696}
697
698
699static struct libtrace_format_t rt = {
700        "rt",
701        "$Id$",
702        TRACE_FORMAT_RT,
703        rt_init_input,                  /* init_input */
704        NULL,                           /* config_input */
705        rt_start_input,                 /* start_input */
706        rt_pause_input,                 /* pause */
707        NULL,                           /* init_output */
708        NULL,                           /* config_output */
709        NULL,                           /* start_output */
710        rt_fin_input,                   /* fin_input */
711        NULL,                           /* fin_output */
712        rt_read_packet,                 /* read_packet */
713        NULL,                           /* fin_packet */
714        NULL,                           /* write_packet */
715        NULL,                           /* get_link_type */
716        NULL,                           /* get_direction */
717        NULL,                           /* set_direction */
718        NULL,                           /* get_erf_timestamp */
719        NULL,                           /* get_timeval */
720        NULL,                           /* get_seconds */
721        NULL,                           /* seek_erf */
722        NULL,                           /* seek_timeval */
723        NULL,                           /* seek_seconds */
724        rt_get_capture_length,          /* get_capture_length */
725        rt_get_wire_length,                     /* get_wire_length */
726        rt_get_framing_length,          /* get_framing_length */
727        NULL,                           /* set_capture_length */
728        NULL,                           /* get_received_packets */
729        NULL,                           /* get_filtered_packets */
730        NULL,                           /* get_dropped_packets */
731        NULL,                           /* get_captured_packets */
732        rt_get_fd,                      /* get_fd */
733        trace_event_rt,             /* trace_event */
734        rt_help,                        /* help */
735        NULL                            /* next pointer */
736};
737
738void rt_constructor(void) {
739        register_format(&rt);
740}
Note: See TracBrowser for help on using the repository browser.