source: lib/format_rt.c @ fd87898

4.0.1-hotfixescachetimestampsdevelopdpdk-ndagetsilivegetfragoffhelplibtrace4ndag_formatpfringrc-4.0.1rc-4.0.2rc-4.0.3rc-4.0.4ringdecrementfixringperformanceringtimestampfixes
Last change on this file since fd87898 was fd87898, checked in by Shane Alcock <salcock@…>, 9 years ago
  • Fixed incorrect condition for checking if the RT type was BPF
  • Don't set "Unknown Option" in format_bpf if the option is in fact unsupported - wdcap relies on the error being unsupported in the case of META_FREQ
  • Property mode set to 100644
File size: 23.5 KB
Line 
1/*
2 * This file is part of libtrace
3 *
4 * Copyright (c) 2007,2008,2009,2010 The University of Waikato, Hamilton,
5 * New Zealand.
6 *
7 * Authors: Daniel Lawson
8 *          Perry Lorier
9 *          Shane Alcock
10 *         
11 * All rights reserved.
12 *
13 * This code has been developed by the University of Waikato WAND
14 * research group. For further information please see http://www.wand.net.nz/
15 *
16 * libtrace is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * libtrace is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with libtrace; if not, write to the Free Software
28 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29 *
30 * $Id$
31 *
32 */
33
34
35#define _GNU_SOURCE
36
37#include "config.h"
38#include "common.h"
39#include "libtrace.h"
40#include "libtrace_int.h"
41#include "format_helper.h"
42#include "rt_protocol.h"
43
44#include <sys/stat.h>
45#include <assert.h>
46#include <errno.h>
47#include <fcntl.h>
48#include <stdio.h>
49#include <string.h>
50#include <stdlib.h>
51#include <unistd.h>
52
53#ifndef WIN32
54# include <netdb.h>
55#endif
56
57#define RT_INFO ((struct rt_format_data_t*)libtrace->format_data)
58
59/* Convert the RT denial code into a nice printable and coherent string */
60static const char *rt_deny_reason(enum rt_conn_denied_t reason) 
61{
62        const char *string = 0;
63
64        switch(reason) {
65                case RT_DENY_WRAPPER:
66                        string = "Rejected by TCP Wrappers";
67                        break;
68                case RT_DENY_FULL:
69                        string = "Max connections reached on server";
70                        break;
71                case RT_DENY_AUTH:
72                        string = "Authentication failed";
73                        break;
74                default:
75                        string = "Unknown reason";
76        }
77
78        return string;
79}
80
81
82struct rt_format_data_t {
83        /* Name of the host to connect to */
84        char *hostname;
85        /* Buffer to store received packets into */
86        char *pkt_buffer;
87        /* Pointer to the next packet to be read from the buffer */
88        char *buf_current;
89        /* Amount of buffer space used */
90        size_t buf_filled;
91        /* The port to connect to */
92        int port;
93        /* The file descriptor for the RT connection */
94        int input_fd;
95        /* Flag indicating whether the server is doing reliable RT */
96        int reliable;
97
98        /* Header for the packet currently being received */
99        rt_header_t rt_hdr;
100       
101        /* Dummy traces that can be assigned to the received packets to ensure
102         * that the appropriate functions can be used to process them */
103        libtrace_t *dummy_duck;
104        libtrace_t *dummy_erf;
105        libtrace_t *dummy_pcap;
106        libtrace_t *dummy_linux;
107        libtrace_t *dummy_bpf;
108};
109
110/* Connects to an RT server
111 *
112 * Returns -1 if an error occurs
113 */
114static int rt_connect(libtrace_t *libtrace) {
115        struct hostent *he;
116        struct sockaddr_in remote;
117        rt_header_t connect_msg;
118        rt_deny_conn_t deny_hdr;       
119        rt_hello_t hello_opts;
120        uint8_t reason;
121       
122        if ((he=gethostbyname(RT_INFO->hostname)) == NULL) {
123                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
124                                "Failed to convert hostname %s to address",
125                                RT_INFO->hostname);
126                return -1;
127        }
128        if ((RT_INFO->input_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
129                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
130                                "Could not create socket");
131                return -1;
132        }
133
134        memset(&remote,0, sizeof(remote));
135        remote.sin_family = AF_INET;
136        remote.sin_port = htons(RT_INFO->port);
137        remote.sin_addr = *((struct in_addr *)he->h_addr);
138
139        if (connect(RT_INFO->input_fd, (struct sockaddr *)&remote,
140                                (socklen_t)sizeof(struct sockaddr)) == -1) {
141                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
142                                "Could not connect to host %s on port %d",
143                                RT_INFO->hostname, RT_INFO->port);
144                return -1;
145        }
146
147        /* We are connected, now receive message from server */
148       
149        if (recv(RT_INFO->input_fd, (void*)&connect_msg, sizeof(rt_header_t), 0) != sizeof(rt_header_t) ) {
150                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
151                                "Could not receive connection message from %s",
152                                RT_INFO->hostname);
153                return -1;
154        }
155       
156        switch (connect_msg.type) {
157                case TRACE_RT_DENY_CONN:
158                        /* Connection was denied */
159                       
160                        if (recv(RT_INFO->input_fd, (void*)&deny_hdr, 
161                                                sizeof(rt_deny_conn_t),
162                                                0) != sizeof(rt_deny_conn_t)) {
163                                reason = 0;
164                        }       
165                        reason = deny_hdr.reason;
166                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
167                                "Connection attempt is denied: %s",
168                                rt_deny_reason(reason));       
169                        return -1;
170                case TRACE_RT_HELLO:
171                        /* Hello message - read the options sent to us by the
172                         * server */
173                        if (recv(RT_INFO->input_fd, (void*)&hello_opts, 
174                                                sizeof(rt_hello_t), 0)
175                                        != sizeof(rt_hello_t)) {
176                                trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
177                                        "Failed to receive TRACE_RT_HELLO options");
178                                return -1;
179                        }
180                        RT_INFO->reliable = hello_opts.reliable;
181                       
182                        return 0;
183                default:
184                        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
185                                        "Unknown message type received: %d",
186                                        connect_msg.type);
187                        return -1;
188        }
189        trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,
190                        "Somehow you managed to reach this unreachable code");
191        return -1;
192}
193
194static void rt_init_format_data(libtrace_t *libtrace) {
195        libtrace->format_data = malloc(sizeof(struct rt_format_data_t));
196
197        RT_INFO->dummy_duck = NULL;
198        RT_INFO->dummy_erf = NULL;
199        RT_INFO->dummy_pcap = NULL;
200        RT_INFO->dummy_linux = NULL;
201        RT_INFO->dummy_bpf = NULL;
202        RT_INFO->pkt_buffer = NULL;
203        RT_INFO->buf_current = NULL;
204        RT_INFO->buf_filled = 0;
205        RT_INFO->hostname = NULL;
206        RT_INFO->port = 0;
207}
208
209static int rt_init_input(libtrace_t *libtrace) {
210        char *scan;
211        char *uridata = libtrace->uridata;
212
213        rt_init_format_data(libtrace);
214
215        /* If the user specifies "rt:" then assume localhost and the default
216         * port */     
217        if (strlen(uridata) == 0) {
218                RT_INFO->hostname =
219                        strdup("localhost");
220                RT_INFO->port =
221                        COLLECTOR_PORT;
222        } else {
223                /* If the user does not specify a port, assume the default
224                 * port */
225                if ((scan = strchr(uridata,':')) == NULL) {
226                        RT_INFO->hostname =
227                                strdup(uridata);
228                        RT_INFO->port =
229                                COLLECTOR_PORT;
230                } else {
231                        RT_INFO->hostname =
232                                (char *)strndup(uridata,
233                                                (size_t)(scan - uridata));
234                        RT_INFO->port =
235                                atoi(++scan);
236                }
237        }
238
239        return 0;
240}
241       
242static int rt_start_input(libtrace_t *libtrace) {
243        rt_header_t start_msg;
244
245        start_msg.type = TRACE_RT_START;
246        start_msg.length = 0; 
247
248        if (rt_connect(libtrace) == -1)
249                return -1;
250       
251        /* Need to send start message to server */
252        if (send(RT_INFO->input_fd, (void*)&start_msg, sizeof(rt_header_t) +
253                                start_msg.length, 0) != sizeof(rt_header_t)) {
254                printf("Failed to send start message to server\n");
255                return -1;
256        }
257        RT_INFO->rt_hdr.type = TRACE_RT_LAST;
258
259        return 0;
260}
261
262static int rt_pause_input(libtrace_t *libtrace) {
263        rt_header_t close_msg;
264
265        close_msg.type = TRACE_RT_CLOSE;
266        close_msg.length = 0; 
267       
268        /* Send a close message to the server */
269        if (send(RT_INFO->input_fd, (void*)&close_msg, sizeof(rt_header_t) + 
270                                close_msg.length, 0) != (int)sizeof(rt_header_t)
271                                + close_msg.length) {
272                printf("Failed to send close message to server\n");
273       
274        }
275
276        close(RT_INFO->input_fd);
277        return 0;
278}
279
280static int rt_fin_input(libtrace_t *libtrace) {
281        /* Make sure we clean up any dummy traces that we have been using */
282       
283        if (RT_INFO->dummy_duck)
284                trace_destroy_dead(RT_INFO->dummy_duck);
285
286        if (RT_INFO->dummy_erf) 
287                trace_destroy_dead(RT_INFO->dummy_erf);
288               
289        if (RT_INFO->dummy_pcap)
290                trace_destroy_dead(RT_INFO->dummy_pcap);
291
292        if (RT_INFO->dummy_linux)
293                trace_destroy_dead(RT_INFO->dummy_linux);
294
295        if (RT_INFO->dummy_bpf)
296                trace_destroy_dead(RT_INFO->dummy_bpf);
297        free(libtrace->format_data);
298        return 0;
299}
300
301
302/* I've upped this to 10K to deal with jumbo-grams that have not been snapped
303 * in any way. This means we have a much larger memory overhead per packet
304 * (which won't be used in the vast majority of cases), so we may want to think
305 * about doing something smarter, e.g. allocate a smaller block of memory and
306 * only increase it as required.
307 *
308 * XXX Capturing off int: can still lead to packets that are larger than 10K,
309 * in instances where the fragmentation is done magically by the NIC. This
310 * is pretty nasty, but also very rare.
311 */
312#define RT_BUF_SIZE 10000U
313
314/* Receives data from an RT server */
315static int rt_read(libtrace_t *libtrace, void **buffer, size_t len, int block) 
316{
317        int numbytes;
318       
319        assert(len <= RT_BUF_SIZE);
320       
321        if (!RT_INFO->pkt_buffer) {
322                RT_INFO->pkt_buffer = (char*)malloc((size_t)RT_BUF_SIZE);
323                RT_INFO->buf_current = RT_INFO->pkt_buffer;
324                RT_INFO->buf_filled = 0;
325        }
326
327#ifndef MSG_DONTWAIT
328#define MSG_DONTWAIT 0
329#endif
330
331        if (block)
332                block=0;
333        else
334                block=MSG_DONTWAIT;
335
336        /* If we don't have enough buffer space for the amount we want to
337         * read, move the current buffer contents to the front of the buffer
338         * to make room */
339        if (len > RT_INFO->buf_filled) {
340                memcpy(RT_INFO->pkt_buffer, RT_INFO->buf_current, 
341                                RT_INFO->buf_filled);
342                RT_INFO->buf_current = RT_INFO->pkt_buffer;
343#ifndef MSG_NOSIGNAL
344#  define MSG_NOSIGNAL 0
345#endif
346                /* Loop as long as we don't have all the data that we were
347                 * asked for */
348                while (len > RT_INFO->buf_filled) {
349                        if ((numbytes = recv(RT_INFO->input_fd,
350                                                RT_INFO->buf_current + 
351                                                RT_INFO->buf_filled,
352                                                RT_BUF_SIZE-RT_INFO->buf_filled,
353                                                MSG_NOSIGNAL|block)) <= 0) {
354                                if (numbytes == 0) {
355                                        trace_set_err(libtrace, TRACE_ERR_RT_FAILURE, 
356                                                        "No data received");
357                                        return -1;
358                                }
359                               
360                                if (errno == EINTR) {
361                                        /* ignore EINTR in case
362                                         * a caller is using signals
363                                         */
364                                        continue;
365                                }
366                                if (errno == EAGAIN) {
367                                        /* We asked for non-blocking mode, so
368                                         * we need to return now */
369                                        trace_set_err(libtrace,
370                                                        EAGAIN,
371                                                        "EAGAIN");
372                                        return -1;
373                                }
374                               
375                                perror("recv");
376                                trace_set_err(libtrace, errno,
377                                                "Failed to read data into rt recv buffer");
378                                return -1;
379                        }
380                        RT_INFO->buf_filled+=numbytes;
381                }
382
383        }
384        *buffer = RT_INFO->buf_current;
385        RT_INFO->buf_current += len;
386        RT_INFO->buf_filled -= len;
387        return len;
388}
389
390
391/* Sets the trace format for the packet to match the format it was originally
392 * captured in, rather than the RT format */
393static int rt_set_format(libtrace_t *libtrace, libtrace_packet_t *packet) 
394{
395
396        /* We need to assign the packet to a "dead" trace */
397
398        /* Try to minimize the number of corrupt packets that slip through
399         * while making it easy to identify new pcap DLTs */
400        if (packet->type > TRACE_RT_DATA_DLT && 
401                        packet->type < TRACE_RT_DATA_DLT_END) {
402                if (!RT_INFO->dummy_pcap) {
403                        RT_INFO->dummy_pcap = trace_create_dead("pcap:-");
404                }
405                packet->trace = RT_INFO->dummy_pcap;
406                return 0;       
407        }
408
409        if (packet->type > TRACE_RT_DATA_BPF &&
410                        packet->type < TRACE_RT_DATA_BPF_END) {
411
412                if (!RT_INFO->dummy_bpf) {
413                        RT_INFO->dummy_bpf = trace_create_dead("bpf:-");
414                        /* This may fail on a non-BSD machine */
415                        if (trace_is_err(RT_INFO->dummy_bpf)) {
416                                trace_perror(RT_INFO->dummy_bpf, "Creating dead bpf trace");
417                                return -1;
418                        }
419                }
420                packet->trace = RT_INFO->dummy_bpf;
421                return 0;
422        }
423
424        switch (packet->type) {
425                case TRACE_RT_DUCK_2_4:
426                case TRACE_RT_DUCK_2_5:
427                        if (!RT_INFO->dummy_duck) {
428                                RT_INFO->dummy_duck = trace_create_dead("duck:dummy");
429                        }
430                        packet->trace = RT_INFO->dummy_duck;
431                        break;
432                case TRACE_RT_DATA_ERF:
433                        if (!RT_INFO->dummy_erf) {
434                                RT_INFO->dummy_erf = trace_create_dead("erf:-");
435                        }
436                        packet->trace = RT_INFO->dummy_erf;
437                        break;
438                case TRACE_RT_DATA_LINUX_NATIVE:
439                        if (!RT_INFO->dummy_linux) {
440                                RT_INFO->dummy_linux = trace_create_dead("int:");
441                                /* This may fail on a non-Linux machine */
442                                if (trace_is_err(RT_INFO->dummy_linux)) {
443                                        trace_perror(RT_INFO->dummy_linux, "Creating dead bpf trace");
444                                        return -1;
445                                }
446                        }
447                        packet->trace = RT_INFO->dummy_linux;
448                        break;
449                case TRACE_RT_STATUS:
450                case TRACE_RT_METADATA:
451                        /* Just use the RT trace! */
452                        packet->trace = libtrace;
453                        break;
454                case TRACE_RT_DATA_LEGACY_ETH:
455                case TRACE_RT_DATA_LEGACY_ATM:
456                case TRACE_RT_DATA_LEGACY_POS:
457                        printf("Sending legacy over RT is currently not supported\n");
458                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Legacy packet cannot be sent over rt");
459                        return -1;
460                default:
461                        printf("Unrecognised format: %u\n", packet->type);
462                        trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unrecognised packet format");
463                        return -1;
464        }
465        return 0; /* success */
466}               
467
468/* Sends an RT ACK to the server to acknowledge receipt of packets */
469static int rt_send_ack(libtrace_t *libtrace, 
470                uint32_t seqno)  {
471       
472        static char *ack_buffer = 0;
473        char *buf_ptr;
474        int numbytes = 0;
475        size_t to_write = 0;
476        rt_header_t *hdr;
477        rt_ack_t *ack_hdr;
478       
479        if (!ack_buffer) {
480                ack_buffer = (char*)malloc(sizeof(rt_header_t) 
481                                                        + sizeof(rt_ack_t));
482        }
483       
484        hdr = (rt_header_t *) ack_buffer;
485        ack_hdr = (rt_ack_t *) (ack_buffer + sizeof(rt_header_t));
486       
487        hdr->type = TRACE_RT_ACK;
488        hdr->length = sizeof(rt_ack_t);
489
490        ack_hdr->sequence = seqno;
491       
492        to_write = hdr->length + sizeof(rt_header_t);
493        buf_ptr = ack_buffer;
494
495        /* Keep trying until we write the entire ACK */
496        while (to_write > 0) {
497                numbytes = send(RT_INFO->input_fd, buf_ptr, to_write, 0); 
498                if (numbytes == -1) {
499                        if (errno == EINTR || errno == EAGAIN) {
500                                continue;
501                        }
502                        else {
503                                printf("Error sending ack\n");
504                                perror("send");
505                                trace_set_err(libtrace, TRACE_ERR_RT_FAILURE, 
506                                                "Error sending ack");
507                                return -1;
508                        }
509                }
510                to_write = to_write - numbytes;
511                buf_ptr = buf_ptr + to_write;
512               
513        }
514
515        return 1;
516}
517
518/* Shouldn't need to call this too often */
519static int rt_prepare_packet(libtrace_t *libtrace, libtrace_packet_t *packet,
520                void *buffer, libtrace_rt_types_t rt_type, uint32_t flags) {
521
522        if (packet->buffer != buffer &&
523                        packet->buf_control == TRACE_CTRL_PACKET) {
524                free(packet->buffer);
525        }
526
527        if ((flags & TRACE_PREP_OWN_BUFFER) == TRACE_PREP_OWN_BUFFER) {
528                packet->buf_control = TRACE_CTRL_PACKET;
529        } else
530                packet->buf_control = TRACE_CTRL_EXTERNAL;
531
532
533        packet->buffer = buffer;
534        packet->header = NULL;
535        packet->type = rt_type;
536        packet->payload = buffer;
537
538        if (libtrace->format_data == NULL) {
539                rt_init_format_data(libtrace);
540        }
541
542        return 0;
543}       
544
545/* Reads the body of an RT packet from the network */
546static int rt_read_data_packet(libtrace_t *libtrace,
547                libtrace_packet_t *packet, int blocking) {
548        uint32_t prep_flags = 0;
549
550        prep_flags |= TRACE_PREP_DO_NOT_OWN_BUFFER;
551
552        /* The stored RT header will tell us how much data we need to read */
553        if (rt_read(libtrace, &packet->buffer, (size_t)RT_INFO->rt_hdr.length, 
554                                blocking) != RT_INFO->rt_hdr.length) {
555                return -1;
556        }
557
558        /* Send an ACK if required */
559        if (RT_INFO->reliable > 0 && packet->type >= TRACE_RT_DATA_SIMPLE) {
560                if (rt_send_ack(libtrace, RT_INFO->rt_hdr.sequence) == -1)
561                                return -1;
562        }
563       
564        /* Convert to the original capture format */
565        if (rt_set_format(libtrace, packet) < 0) {
566                return -1;
567        }
568               
569        /* Update payload pointers and packet type to match the original
570         * format */
571        if (trace_prepare_packet(packet->trace, packet, packet->buffer,
572                                packet->type, prep_flags)) {
573                return -1;
574        }
575
576        return 0;
577}
578
579/* Reads an RT packet from the network. Will block if the "blocking" flag is
580 * set to 1, otherwise will return if insufficient data is available */
581static int rt_read_packet_versatile(libtrace_t *libtrace,
582                libtrace_packet_t *packet,int blocking) {
583        rt_header_t *pkt_hdr = NULL;
584        void *void_hdr;
585        libtrace_rt_types_t switch_type;
586       
587        if (packet->buf_control == TRACE_CTRL_PACKET) {
588                packet->buf_control = TRACE_CTRL_EXTERNAL;
589                free(packet->buffer);
590                packet->buffer = NULL;
591        }
592
593        /* RT_LAST indicates that we need to read the RT header for the next
594         * packet. This is a touch hax, I admit */
595        if (RT_INFO->rt_hdr.type == TRACE_RT_LAST) {
596                void_hdr = (void *)pkt_hdr;
597                /* FIXME: Better error handling required */
598                if (rt_read(libtrace, &void_hdr, 
599                                sizeof(rt_header_t),blocking) !=
600                                sizeof(rt_header_t)) {
601                        return -1;
602                }
603                pkt_hdr = (rt_header_t *)void_hdr;
604               
605                /* Need to store these in case the next rt_read overwrites
606                 * the buffer they came from! */
607                RT_INFO->rt_hdr.type = pkt_hdr->type;
608                RT_INFO->rt_hdr.length = pkt_hdr->length;
609                RT_INFO->rt_hdr.sequence = pkt_hdr->sequence;
610        }
611        packet->type = RT_INFO->rt_hdr.type;
612       
613        /* All data-bearing packets (as opposed to RT internal messages)
614         * should be treated the same way when it comes to reading the rest
615         * of the packet */
616        if (packet->type >= TRACE_RT_DATA_SIMPLE) {
617                switch_type = TRACE_RT_DATA_SIMPLE;
618        } else {
619                switch_type = packet->type;
620        }
621
622        switch(switch_type) {
623                case TRACE_RT_DATA_SIMPLE:
624                case TRACE_RT_DUCK_2_4:
625                case TRACE_RT_DUCK_2_5:
626                case TRACE_RT_STATUS:
627                case TRACE_RT_METADATA:
628                        if (rt_read_data_packet(libtrace, packet, blocking))
629                                return -1;
630                        break;
631                case TRACE_RT_END_DATA:
632                case TRACE_RT_KEYCHANGE:
633                case TRACE_RT_LOSTCONN:
634                case TRACE_RT_CLIENTDROP:
635                case TRACE_RT_SERVERSTART:
636                        /* All these have no payload */
637                        break;
638                case TRACE_RT_PAUSE_ACK:
639                        /* XXX: Add support for this */
640                        break;
641                case TRACE_RT_OPTION:
642                        /* XXX: Add support for this */
643                        break;
644                default:
645                        printf("Bad rt type for client receipt: %d\n",
646                                        switch_type);
647                        return -1;
648        }
649                               
650                       
651               
652        /* Return the number of bytes read from the stream */
653        RT_INFO->rt_hdr.type = TRACE_RT_LAST;
654        return RT_INFO->rt_hdr.length + sizeof(rt_header_t);
655}
656
657/* Reads the next available packet in a blocking fashion */
658static int rt_read_packet(libtrace_t *libtrace,
659                libtrace_packet_t *packet) {
660        return rt_read_packet_versatile(libtrace,packet,1);
661}
662
663
664/* This should only get called for RT messages - RT-encapsulated data records
665 * should be converted to the appropriate capture format */
666static int rt_get_capture_length(const libtrace_packet_t *packet) {
667        rt_metadata_t *rt_md_hdr;
668        switch (packet->type) {
669                case TRACE_RT_STATUS:
670                        return sizeof(rt_status_t);
671                case TRACE_RT_HELLO:
672                        return sizeof(rt_hello_t);
673                case TRACE_RT_START:
674                        return 0;
675                case TRACE_RT_ACK:
676                        return sizeof(rt_ack_t);
677                case TRACE_RT_END_DATA:
678                        return 0;
679                case TRACE_RT_CLOSE:
680                        return 0;
681                case TRACE_RT_DENY_CONN:
682                        return sizeof(rt_deny_conn_t);
683                case TRACE_RT_PAUSE:
684                        return 0; 
685                case TRACE_RT_PAUSE_ACK:
686                        return 0;
687                case TRACE_RT_OPTION:
688                        return 0; /* FIXME */
689                case TRACE_RT_KEYCHANGE:
690                        return 0;
691                case TRACE_RT_LOSTCONN:
692                        return 0;
693                case TRACE_RT_SERVERSTART:
694                        return 0;
695                case TRACE_RT_CLIENTDROP:
696                        return 0;
697                case TRACE_RT_METADATA:
698                        /* This is a little trickier to work out */
699                        rt_md_hdr = (rt_metadata_t *)packet->buffer;
700                        return rt_md_hdr->label_len + rt_md_hdr->value_len + 
701                                sizeof(rt_metadata_t);
702                default:
703                        printf("Unknown type: %d\n", packet->type);
704                       
705        }
706        return 0;
707}
708
709/* RT messages do not have a wire length because they were not captured from
710 * the wire - they were generated by the capture process */
711static int rt_get_wire_length(UNUSED const libtrace_packet_t *packet) {
712        return 0;
713}
714
715/* Although RT messages do contain "framing", this framing is considered to be
716 * stripped as soon as the packet is read by the RT client */                   
717static int rt_get_framing_length(UNUSED const libtrace_packet_t *packet) {
718        return 0;
719}
720
721
722static libtrace_linktype_t rt_get_link_type(UNUSED const libtrace_packet_t *packet)
723{
724        /* RT messages don't have a link type */
725        return TRACE_TYPE_NONDATA;
726}
727
728static int rt_get_fd(const libtrace_t *trace) {
729        return ((struct rt_format_data_t *)trace->format_data)->input_fd;
730}
731
732static libtrace_eventobj_t trace_event_rt(libtrace_t *trace,
733                                        libtrace_packet_t *packet) 
734{
735        libtrace_eventobj_t event = {0,0,0.0,0};
736        libtrace_err_t read_err;
737
738        assert(trace);
739        assert(packet);
740       
741        if (trace->format->get_fd) {
742                event.fd = trace->format->get_fd(trace);
743        } else {
744                event.fd = 0;
745        }
746
747        do {
748
749                event.size = rt_read_packet_versatile(trace, packet, 0);
750                if (event.size == -1) {
751                        read_err = trace_get_err(trace);
752                        if (read_err.err_num == EAGAIN) {
753                                /* No data available - do an IOWAIT */
754                                event.type = TRACE_EVENT_IOWAIT;
755                        }
756                        else {
757                                trace_perror(trace, "Error doing a non-blocking read from rt");
758                                event.type = TRACE_EVENT_PACKET;
759                                break;
760                        }
761                } else if (event.size == 0) {
762                        /* RT gives us a specific indicator that there will be
763                         * no more packets. */
764                        if (packet->type == TRACE_RT_END_DATA)
765                                event.type = TRACE_EVENT_TERMINATE;
766                        else
767                                /* Since several RT messages can have zero-byte
768                                 * length (once the framing is removed), an
769                                 * event size of zero can still indicate a
770                                 * PACKET event */
771                                event.type = TRACE_EVENT_PACKET;
772
773                }       
774                else {
775                        event.type = TRACE_EVENT_PACKET;
776                }
777
778                if (trace->filter && event.type == TRACE_EVENT_PACKET) {
779                        if (!trace_apply_filter(trace->filter, packet)) {
780                                trace_clear_cache(packet);
781                                continue;
782                        }
783                }
784
785                break; 
786        } while (1);
787
788        return event;
789}
790
791static void rt_help(void) {
792        printf("rt format module\n");
793        printf("Supported input URIs:\n");
794        printf("\trt:hostname:port\n");
795        printf("\trt:hostname (connects on default port)\n");
796        printf("\n");
797        printf("\te.g.: rt:localhost\n");
798        printf("\te.g.: rt:localhost:32500\n");
799        printf("\n");
800
801}
802
803
804static struct libtrace_format_t rt = {
805        "rt",
806        "$Id$",
807        TRACE_FORMAT_RT,
808        NULL,                           /* probe filename */
809        NULL,                           /* probe magic */
810        rt_init_input,                  /* init_input */
811        NULL,                           /* config_input */
812        rt_start_input,                 /* start_input */
813        rt_pause_input,                 /* pause */
814        NULL,                           /* init_output */
815        NULL,                           /* config_output */
816        NULL,                           /* start_output */
817        rt_fin_input,                   /* fin_input */
818        NULL,                           /* fin_output */
819        rt_read_packet,                 /* read_packet */
820        rt_prepare_packet,              /* prepare_packet */
821        NULL,                           /* fin_packet */
822        NULL,                           /* write_packet */
823        rt_get_link_type,               /* get_link_type */
824        NULL,                           /* get_direction */
825        NULL,                           /* set_direction */
826        NULL,                           /* get_erf_timestamp */
827        NULL,                           /* get_timeval */
828        NULL,                           /* get_timespec */
829        NULL,                           /* get_seconds */
830        NULL,                           /* seek_erf */
831        NULL,                           /* seek_timeval */
832        NULL,                           /* seek_seconds */
833        rt_get_capture_length,          /* get_capture_length */
834        rt_get_wire_length,                     /* get_wire_length */
835        rt_get_framing_length,          /* get_framing_length */
836        NULL,                           /* set_capture_length */
837        NULL,                           /* get_received_packets */
838        NULL,                           /* get_filtered_packets */
839        NULL,                           /* get_dropped_packets */
840        NULL,                           /* get_captured_packets */
841        rt_get_fd,                      /* get_fd */
842        trace_event_rt,             /* trace_event */
843        rt_help,                        /* help */
844        NULL                            /* next pointer */
845};
846
847void rt_constructor(void) {
848        register_format(&rt);
849}
Note: See TracBrowser for help on using the repository browser.