Changeset 4dedc28 for lib/trace.c
- Timestamp:
- 07/29/05 09:26:57 (17 years ago)
- Branches:
- 4.0.1-hotfixes, cachetimestamps, develop, dpdk-ndag, etsilive, getfragoff, help, libtrace4, master, ndag_format, pfring, rc-4.0.1, rc-4.0.2, rc-4.0.3, rc-4.0.4, ringdecrementfix, ringperformance, ringtimestampfixes
- Children:
- 7050c10
- Parents:
- dd6e168
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
lib/trace.c
rdd6e168 r4dedc28 42 42 #include "common.h" 43 43 #include "config.h" 44 #include "format.h" 44 45 #include <assert.h> 45 46 #include <errno.h> … … 132 133 #endif 133 134 135 #include "format.h" 136 //#include "format/format_list.h" 134 137 #include <err.h> 135 138 136 typedef enum {SOCKET, TRACE, STDIN, DEVICE, INTERFACE, RT } source_t;137 138 typedef enum {ERF, PCAP, PCAPINT, DAG, RTCLIENT, WAG, WAGINT } format_t;139 //typedef enum {SOCKET, TRACE, STDIN, DEVICE, INTERFACE, RT } source_t; 140 141 //typedef enum {ERF, PCAP, PCAPINT, DAG, RTCLIENT, WAG, WAGINT } format_e_t; 139 142 140 143 typedef enum {RTSERVER, GZERF } output_t; … … 176 179 177 180 struct fifo_t *fifo; 178 179 // rtserver stuff180 181 /** fd that watches for incoming connections */182 int connect_fd;183 /** fds that represent connected clients */184 fd_set rt_fds;185 /** fds that are listening for connections (this should only contain connect_fd) */186 fd_set listen;187 int max_rtfds;188 /** Used for creating new fds as required */189 struct sockaddr_in * remote;190 181 }; 191 182 192 /** The information about traces that are open 193 * @internal 194 */ 195 struct libtrace_t { 196 format_t format; /**< The format that this trace is in */ 197 source_t sourcetype; /**< The type (device,file, etc */ 198 199 union { 200 /** Information about rtclients */ 201 struct { 202 char *hostname; 203 short port; 204 } rt; 205 char *path; /**< information for local sockets */ 206 char *interface; /**< intormation for reading of network 207 interfaces */ 208 } conn_info; 209 /** Information about the current state of the input device */ 210 union { 211 int fd; 212 #if HAVE_ZLIB 213 gzFile *file; 214 #else 215 FILE *file; 216 #endif 217 #if HAVE_PCAP 218 pcap_t *pcap; 219 #endif 220 } input; 221 222 struct fifo_t *fifo; 223 struct { 224 void *buf; 225 unsigned bottom; 226 unsigned top; 227 unsigned diff; 228 unsigned curr; 229 unsigned offset; 230 } dag; 231 struct { 232 void *buffer; 233 int size; 234 } packet; 235 double tdelta; 236 double trace_start_ts; 237 double real_start_ts; 238 double trace_last_ts; 239 240 double last_ts; 241 double start_ts; 242 }; 243 244 struct trace_sll_header_t { 245 uint16_t pkttype; /* packet type */ 246 uint16_t hatype; /* link-layer address type */ 247 uint16_t halen; /* link-layer address length */ 248 char addr[8]; /* link-layer address */ 249 uint16_t protocol; /* protocol */ 250 }; 251 252 #ifndef PF_RULESET_NAME_SIZE 253 #define PF_RULESET_NAME_SIZE 16 254 #endif 255 256 #ifndef IFNAMSIZ 257 #define IFNAMSIZ 16 258 #endif 259 260 struct trace_pflog_header_t { 261 uint8_t length; 262 sa_family_t af; 263 uint8_t action; 264 uint8_t reason; 265 char ifname[IFNAMSIZ]; 266 char ruleset[PF_RULESET_NAME_SIZE]; 267 uint32_t rulenr; 268 uint32_t subrulenr; 269 uint8_t dir; 270 uint8_t pad[3]; 271 }; 183 184 185 struct format_t **format_list = 0; 186 int format_size = 0; 187 int nformats = 0; 188 189 void register_format(struct format_t *f) { 190 fprintf(stderr,"Registering input format %s\n",f->name); 191 if (format_list == 0) { 192 format_size = 10; 193 format_list = malloc(sizeof(struct format_t *) * format_size); 194 } else if (format_size == nformats) { 195 format_size = format_size + 10; 196 format_list = realloc(format_list, 197 sizeof(struct format_t *) * format_size); 198 } 199 format_list[nformats] = f; 200 nformats++; 201 } 202 272 203 273 204 #define RP_BUFSIZE 65536 … … 277 208 char *scan = calloc(sizeof(char),URI_PROTO_LINE); 278 209 char *uridata = 0; 210 int i = 0; 279 211 struct stat buf; 280 212 … … 296 228 (*libtrace)->tdelta = 0.0; 297 229 298 if (!strncasecmp(scan,"erf",3)) { 299 (*libtrace)->format=ERF; 300 #if HAVE_PCAP 301 } else if (!strncasecmp(scan,"pcapint",7)) { 302 (*libtrace)->format=PCAPINT; 303 } else if (!strncasecmp(scan,"pcap",4)) { 304 (*libtrace)->format=PCAP; 305 #else 306 } else if (!strncasecmp(scan,"pcap",4)) { // also catches pcapint 307 fprintf(stderr,"This version of libtrace has been compiled without PCAP support\n"); 230 231 (*libtrace)->format = 0; 232 for (i = 0; i < nformats; i++) { 233 if (strlen(scan) == strlen(format_list[i]->name) && 234 !strncasecmp(scan, 235 format_list[i]->name, 236 strlen(scan))) { 237 (*libtrace)->format=format_list[i]; 238 break; 239 } 240 } 241 if ((*libtrace)->format == 0) { 242 fprintf(stderr, 243 "libtrace has no support for this format (%s)\n",scan); 308 244 return 0; 309 #endif 310 311 #if HAVE_DAG 312 } else if (!strncasecmp(scan,"dag",3)) { 313 (*libtrace)->format=DAG; 314 #else 315 } else if (!strncasecmp(scan,"dag",3)) { 316 fprintf(stderr,"This version of libtrace has been compiled without DAG support\n"); 317 return 0; 318 #endif 319 } else if (!strncasecmp(scan,"rtclient",7)) { 320 (*libtrace)->format=RTCLIENT; 321 } else if (!strncasecmp(scan,"wagint",6)) { 322 struct ports_t *port; 323 (*libtrace)->format=WAGINT; 324 } else if (!strncasecmp(scan,"wag",3)) { 325 (*libtrace)->format=WAG; 326 } else { 327 //badly formed URI 328 return 0; 329 } 330 245 } 246 331 247 // push uridata past the delimiter 332 248 uridata++; 333 249 (*libtrace)->conn_info.path = strdup(uridata); 250 334 251 // libtrace->format now contains the type of uri 335 252 // libtrace->uridata contains the appropriate data for this 336 253 337 switch((*libtrace)->format) { 338 #if HAVE_PCAP 339 case PCAPINT: 340 #endif 341 case WAGINT: 342 /* Can have uridata of the following format 343 * eth0 344 * etc 345 */ 346 // We basically assume this is correct. 347 (*libtrace)->sourcetype = INTERFACE; 348 (*libtrace)->conn_info.path = strdup(uridata); 349 break; 350 #if HAVE_PCAP 351 case PCAP: 352 #endif 353 case ERF: 354 case WAG: 355 /* 356 * Can have uridata of the following format 357 * /path/to/socket (probably not PCAP) 358 * /path/to/file 359 * /path/to/file.gz (not PCAP) 360 * /dev/device (use PCAPINT) 361 * - 362 */ 363 if (!strncmp(uridata,"-",1)) { 364 (*libtrace)->sourcetype = STDIN; 365 } else { 366 if (stat(uridata,&buf) == -1) { 367 perror("stat"); 368 return 0; 369 } 370 if (S_ISSOCK(buf.st_mode)) { 371 (*libtrace)->sourcetype = SOCKET; 372 } else if (S_ISCHR(buf.st_mode)) { 373 (*libtrace)->sourcetype = DEVICE; 374 } else { 375 (*libtrace)->sourcetype = TRACE; 376 } 377 (*libtrace)->conn_info.path = strdup(uridata); 378 } 379 break; 380 case DAG: 381 #if HAVE_DAG 382 /* 383 * Can have uridata of the following format: 384 * /dev/device 385 */ 386 if (stat(uridata,&buf) == -1) { 387 perror("stat"); 388 return 0; 389 } 390 if (S_ISCHR(buf.st_mode)) { 391 (*libtrace)->sourcetype = DEVICE; 392 } else { 393 fprintf(stderr,"%s isn't a valid char device, exiting\n",uridata); 394 exit(1); 395 } 396 (*libtrace)->conn_info.path = strdup(uridata); 397 #endif 398 break; 399 400 case RTCLIENT: 401 /* 402 * Can have the uridata in the format 403 * hostname 404 * hostname:port 405 */ 406 (*libtrace)->sourcetype = RT; 407 if (strlen(uridata) == 0) { 408 (*libtrace)->conn_info.rt.hostname = 409 strdup("localhost"); 410 (*libtrace)->conn_info.rt.port = 411 COLLECTOR_PORT; 412 break; 413 } 414 if ((scan = strchr(uridata,':')) == NULL) { 415 (*libtrace)->conn_info.rt.hostname = 416 strdup(uridata); 417 (*libtrace)->conn_info.rt.port = 418 COLLECTOR_PORT; 419 } else { 420 (*libtrace)->conn_info.rt.hostname = 421 (char *)strndup(uridata,(scan - uridata)); 422 423 (*libtrace)->conn_info.rt.port = 424 atoi(++scan); 425 } 426 break; 427 } 428 254 if ((*libtrace)->format->init_input) { 255 (*libtrace)->format->init_input( (*libtrace)); 256 } else { 257 fprintf(stderr, 258 "No init function for format %s\n",scan); 259 return 0; 260 } 261 429 262 430 263 (*libtrace)->fifo = create_fifo(1048576); … … 554 387 } 555 388 556 switch(libtrace->sourcetype) {557 case RT:558 if ((he=gethostbyname(libtrace->conn_info.rt.hostname)) == NULL) {559 perror("gethostbyname");560 return 0;561 }562 if ((libtrace->input.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {563 perror("socket");564 return 0;565 }566 567 remote.sin_family = AF_INET;568 remote.sin_port = htons(libtrace->conn_info.rt.port);569 remote.sin_addr = *((struct in_addr *)he->h_addr);570 bzero(&(remote.sin_zero), 8);571 572 if (connect(libtrace->input.fd, (struct sockaddr *)&remote,573 sizeof(struct sockaddr)) == -1) {574 perror("connect (inet)");575 return 0;576 }577 break;578 case TRACE:579 #if HAVE_PCAP580 if (libtrace->format == PCAP) {581 if ((libtrace->input.pcap = pcap_open_offline(libtrace->conn_info.path, errbuf)) == NULL) {582 fprintf(stderr,"%s\n",errbuf);583 return 0;584 }585 } else {586 #else587 {588 #endif589 590 /* Catch undefined O_LARGEFILE on *BSD etc */591 #ifndef O_LARGEFILE592 # define O_LARGEFILE 0593 #endif594 595 #if HAVE_ZLIB596 // using gzdopen means we can set O_LARGEFILE597 // ourselves. However, this way is messy and598 // we lose any error checking on "open"599 libtrace->input.file = gzdopen(open(libtrace->conn_info.path,O_LARGEFILE), "r");600 #else601 libtrace->input.file = fdopen(open(libtrace->conn_info.path,O_LARGEFILE), "r");602 #endif603 }604 break;605 case STDIN:606 #if HAVE_PCAP607 if (libtrace->format == PCAP) {608 libtrace->input.pcap = pcap_open_offline("-",errbuf);609 } else {610 #else611 {612 #endif613 #if HAVE_ZLIB614 libtrace->input.file = gzdopen(STDIN, "r");615 #else616 libtrace->input.file = stdin;617 #endif618 }619 break;620 case SOCKET:621 /* Pcap doesn't work */622 if (libtrace->format != PCAP) {623 if ((libtrace->input.fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {624 perror("socket");625 return 0;626 }627 unix_sock.sun_family = AF_UNIX;628 bzero(unix_sock.sun_path,108);629 snprintf(unix_sock.sun_path,108,"%s",libtrace->conn_info.path);630 631 if (connect(libtrace->input.fd, (struct sockaddr *)&unix_sock,632 sizeof(struct sockaddr)) == -1) {633 perror("connect (unix)");634 return 0;635 }636 }637 break;638 case DEVICE:639 case INTERFACE:640 switch (libtrace->format) {641 #if HAVE_PCAP642 case PCAPINT:643 case PCAP:644 libtrace->input.pcap = pcap_open_live(645 libtrace->conn_info.path,646 4096,647 1,648 1,649 errbuf);650 break;651 #endif652 case WAGINT:653 case WAG:654 libtrace->input.fd = open(655 libtrace->conn_info.path,656 O_RDONLY);657 break;658 #if HAVE_DAG659 case DAG:660 if((libtrace->input.fd = dag_open(libtrace->conn_info.path)) < 0) {661 fprintf(stderr,"Cannot open DAG %s: %m\n", libtrace->conn_info.path,errno);662 exit(0);663 }664 if((libtrace->dag.buf = dag_mmap(libtrace->input.fd)) == MAP_FAILED) {665 fprintf(stderr,"Cannot mmap DAG %s: %m\n", libtrace->conn_info.path,errno);666 exit(0);667 }668 if(dag_start(libtrace->input.fd) < 0) {669 fprintf(stderr,"Cannot start DAG %s: %m\n", libtrace->conn_info.path,errno);670 exit(0);671 }672 break;673 #endif674 default:675 fprintf(stderr,"Unknown format trace, hoping I can just read\n");676 break;677 678 }679 break;680 default:681 fprintf(stderr,"Unsupported source type for libtrace, terminating (%i)\n",libtrace->sourcetype);682 exit(0);683 684 }685 389 return libtrace; 686 390 } … … 689 393 * 690 394 * @param uri the uri string describing the output format and the destination 691 * @returns the newly created libtrace_out_t structure , or NULL if an error occurs395 * @returns the newly created libtrace_out_t structure 692 396 * 693 397 * @author Shane Alcock … … 695 399 struct libtrace_out_t *trace_output_create(char *uri) { 696 400 struct libtrace_out_t *libtrace = malloc(sizeof(struct libtrace_out_t)); 697 struct sockaddr_in listener; 401 struct sockaddr_in remote, client; 402 int client_fd, clilen; 698 403 struct hostent *he; 699 int yes = 1;700 404 701 405 if (init_output(&libtrace, uri) == 0) … … 704 408 switch(libtrace->outputformat) { 705 409 case RTSERVER: 706 FD_ZERO(&libtrace->listen);707 FD_ZERO(&libtrace->rt_fds);708 709 410 if ((he=gethostbyname(libtrace->conn_info.rt.hostname)) == NULL) { 710 411 perror("gethostbyname"); 711 412 return 0; 712 413 } 713 if ((libtrace-> connect_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {414 if ((libtrace->output.fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { 714 415 perror("socket"); 715 416 return 0; 716 417 } 717 if (setsockopt(libtrace->connect_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int)) == -1) {718 perror("setsockopt");719 return 0;720 }721 libtrace->remote = calloc(1,sizeof(struct sockaddr_in));722 418 // Need to set up a listening server here 723 bzero((char *) libtrace->remote, sizeof(libtrace->remote));724 libtrace->remote->sin_family = AF_INET;725 libtrace->remote->sin_addr.s_addr = INADDR_ANY;726 libtrace->remote->sin_port = htons(libtrace->conn_info.rt.port);727 728 if (bind(libtrace-> connect_fd, (struct sockaddr *) libtrace->remote, sizeof(struct sockaddr_in)) < 0) {419 bzero((char *) &remote, sizeof(remote)); 420 remote.sin_family = AF_INET; 421 remote.sin_addr.s_addr = INADDR_ANY; 422 remote.sin_port = htons(libtrace->conn_info.rt.port); 423 424 if (bind(libtrace->output.fd, (struct sockaddr *) &remote, sizeof(remote)) < 0) { 729 425 perror("bind"); 730 426 return 0; 731 427 } 732 // fprintf(stderr, "Waiting for client to connect\n"); 733 734 if (listen(libtrace->connect_fd, 10) == -1) { 735 perror("listen"); 736 return 0; 737 } 738 739 FD_SET(libtrace->connect_fd, &libtrace->listen); 740 libtrace->max_rtfds = libtrace->connect_fd; 741 /* 428 fprintf(stderr, "Waiting for client to connect\n"); 429 430 listen(libtrace->output.fd, 5); 742 431 clilen = sizeof(client); 743 432 if ((client_fd = accept(libtrace->output.fd, (struct sockaddr *) &client, &clilen)) < 0) { … … 747 436 libtrace->output.fd = client_fd; 748 437 fprintf(stderr, "Client connected\n"); 749 */750 438 break; 751 439 … … 782 470 void trace_destroy(struct libtrace_t *libtrace) { 783 471 assert(libtrace); 784 #if HAVE_PCAP 785 if (libtrace->format == PCAP || libtrace->format == PCAPINT) { 786 pcap_close(libtrace->input.pcap); 787 #else 788 if (0) { 789 #endif 790 } else if (libtrace->sourcetype == SOCKET || libtrace->sourcetype == RT) { 791 close(libtrace->input.fd); 792 #if HAVE_DAG 793 } else if (libtrace->format == DAG) { 794 dag_stop(libtrace->input.fd); 795 #endif 796 } else { 797 #if HAVE_ZLIB 798 gzclose(libtrace->input.file); 799 #else 800 fclose(libtrace->input.file); 801 #endif 802 } 472 libtrace->format->fin_input(libtrace); 803 473 // need to free things! 804 474 destroy_fifo(libtrace->fifo); … … 826 496 } 827 497 destroy_fifo(libtrace->fifo); 828 free(libtrace->remote);829 498 free(libtrace); 830 499 } … … 864 533 break; 865 534 case DEVICE: 866 switch(libtrace->format) { 867 #if HAVE_DAG 868 case DAG: 869 870 libtrace->dag.bottom = libtrace->dag.top; 871 libtrace->dag.top = dag_offset( 872 libtrace->input.fd, 873 &(libtrace->dag.bottom), 874 0); 875 libtrace->dag.diff = libtrace->dag.top - 876 libtrace->dag.bottom; 877 878 numbytes=libtrace->dag.diff; 879 libtrace->dag.offset = 0; 880 881 break; 882 #endif 883 default: 884 if ((numbytes=read(libtrace->input.fd, 535 if (libtrace->format->read) { 536 libtrace->format->read(libtrace,buffer,len); 537 } else { 538 if ((numbytes=read(libtrace->input.fd, 885 539 buffer, 886 540 len)) == -1) { 887 541 perror("read"); 888 542 return -1; 889 543 } 890 544 } 891 545 break; … … 939 593 */ 940 594 int trace_read_packet(struct libtrace_t *libtrace, struct libtrace_packet_t *packet) { 941 int numbytes; 942 int size; 943 char buf[RP_BUFSIZE]; 944 #if HAVE_PCAP 945 //struct pcap_pkthdr *pcaphdr = malloc(sizeof(struct pcap_pkthdr)); 946 const u_char *pcappkt; 947 int pcapbytes = 0; 948 #endif 949 dag_record_t *erfptr; 950 int read_required = 0; 951 952 void *buffer = 0; 595 953 596 if (!libtrace) { 954 597 fprintf(stderr,"Oi! You called trace_read_packet() with a NULL libtrace parameter!\n"); … … 961 604 packet->trace = libtrace; 962 605 963 buffer = packet->buffer; 964 #if HAVE_PCAP 965 /* PCAP gives us it's own per-packet interface. Let's use it */ 966 if (libtrace->format == PCAP || libtrace->format == PCAPINT) { 967 /* pcap_next doesn't return enough information for us 968 * newer libpcap has pcap_next_ex, which does, but we'd 969 * really rather have it all the time. */ 970 971 //if ((pcappkt = pcap_next(libtrace->input.pcap, &pcaphdr)) == NULL) { 972 /* 973 if ((pcapbytes = pcap_next_ex(libtrace->input.pcap, 974 &pcaphdr, 975 &pcappkt)) < 0 ) { 976 */ 977 /* Instead of pcap_next/pcap_next_ex, we do this ourselves 978 * with a trivial callback function. This lets us 979 * catch the same errors as pcap_next_ex, but removes 980 * the requirement for libpcap >= 0.8.x 981 */ 982 while ((pcapbytes = pcap_dispatch(libtrace->input.pcap, 983 1, /* number of packets */ 984 &trace_pcap_handler, 985 (u_char *)packet)) == 0); 986 987 if (pcapbytes < 0 ) { 988 return -1; 989 } 990 return (packet->size - sizeof(struct pcap_pkthdr)); 991 //memcpy(buffer,&pcaphdr,sizeof(struct pcap_pkthdr)); 992 //numbytes = pcaphdr->len; 993 //memcpy(buffer + sizeof(struct pcap_pkthdr),pcappkt,numbytes); 994 995 //packet->size = numbytes + sizeof(struct pcap_pkthdr); 996 //return numbytes; 997 } 998 #endif 999 1000 /* If we're reading from an ERF input, it's an offline trace. We can make some assumptions */ 1001 if (libtrace->format == ERF) { 1002 void *buffer2 = buffer; 1003 int rlen; 1004 // read in the trace header 1005 if ((numbytes=gzread(libtrace->input.file, 1006 buffer, 1007 dag_record_size)) == -1) { 1008 perror("gzread"); 1009 return -1; 1010 } 1011 if (numbytes == 0) { 1012 return 0; 1013 } 1014 rlen = ntohs(((dag_record_t *)buffer)->rlen); 1015 size = rlen - dag_record_size; 1016 assert(size < LIBTRACE_PACKET_BUFSIZE); 1017 buffer2 = buffer + dag_record_size; 1018 1019 // read in the rest of the packet 1020 if ((numbytes=gzread(libtrace->input.file, 1021 buffer2, 1022 size)) == -1) { 1023 perror("gzread"); 1024 return -1; 1025 } 1026 //if ((numbytes + dag_record_size) != rlen) { 1027 // printf("read %d wanted %d\n",numbytes +dag_record_size, rlen); 1028 //} 1029 packet->size = rlen; 1030 1031 return rlen; 1032 } 1033 1034 #if HAVE_DAG 1035 if (libtrace->format == DAG) { 1036 if (libtrace->dag.diff == 0) { 1037 if ((numbytes = trace_read(libtrace,buf,RP_BUFSIZE)) <= 0) 1038 return numbytes; 1039 } 1040 // DAG always gives us whole packets. 1041 1042 erfptr = (dag_record_t *) ((void *)libtrace->dag.buf + (libtrace->dag.bottom + libtrace->dag.offset)); 1043 size = ntohs(erfptr->rlen); 1044 1045 if ( size > LIBTRACE_PACKET_BUFSIZE) { 1046 printf("%d\n",size); 1047 assert( size < LIBTRACE_PACKET_BUFSIZE); 1048 } 1049 1050 // have to copy it out of the memory hole at this stage: 1051 memcpy(packet->buffer, erfptr, size); 1052 1053 packet->size = size; 1054 libtrace->dag.offset += size; 1055 libtrace->dag.diff -= size; 1056 1057 assert(libtrace->dag.diff >= 0); 1058 //assert(libtrace->dag.offset <= libtrace->dag.top); 1059 return (size); 1060 1061 } 1062 #endif 1063 do { 1064 if (fifo_out_available(libtrace->fifo) == 0 || read_required) { 1065 if ((numbytes = trace_read(libtrace,buf,RP_BUFSIZE))<=0){ 1066 return numbytes; 1067 } 1068 assert(libtrace->fifo); 1069 fifo_write(libtrace->fifo,buf,numbytes); 1070 1071 read_required = 0; 1072 } 1073 1074 switch (libtrace->format) { 1075 case RTCLIENT: 1076 // only do this if we're reading from the RT interface 1077 if (fifo_out_read(libtrace->fifo, &packet->status, sizeof(int)) == 0) { 1078 read_required = 1; 1079 continue; 1080 } 1081 1082 fifo_out_update(libtrace->fifo,sizeof(int)); 1083 1084 /* FALL THRU */ 1085 case ERF: 1086 //case DAG: 1087 // read in the erf header 1088 if ((numbytes = fifo_out_read(libtrace->fifo, buffer, sizeof(dag_record_t))) == 0) { 1089 fifo_out_reset(libtrace->fifo); 1090 read_required = 1; 1091 continue; 1092 } 1093 1094 size = ntohs(((dag_record_t *)buffer)->rlen); 1095 break; 1096 case WAG: 1097 if ((numbytes = fifo_out_read(libtrace->fifo, 1098 &size, 1099 sizeof(size))) 1100 == 0) { 1101 fifo_out_reset(libtrace->fifo); 1102 read_required = 1; 1103 continue; 1104 } 1105 size*=4; 1106 break; 1107 default: 1108 fprintf(stderr,"Unknown type in _read()\n"); 1109 assert(0); 1110 } 1111 1112 assert(size < LIBTRACE_PACKET_BUFSIZE); 1113 // read in the full packet 1114 if ((numbytes = fifo_out_read(libtrace->fifo, buffer, size)) == 0) { 1115 fifo_out_reset(libtrace->fifo); 1116 read_required = 1; 1117 continue; 1118 } 1119 1120 // got in our whole packet, so... 1121 fifo_out_update(libtrace->fifo,size); 1122 1123 if (libtrace->sourcetype == SOCKET || libtrace->sourcetype == RT) { 1124 fifo_ack_update(libtrace->fifo,size + sizeof(int)); 1125 } else { 1126 fifo_ack_update(libtrace->fifo,size); 1127 } 1128 1129 packet->size = numbytes; 1130 return numbytes; 1131 1132 } while (1); 606 if (libtrace->format->read_packet) { 607 return libtrace->format->read_packet(libtrace,packet); 608 } 1133 609 } 1134 610 … … 1202 678 void *buffer = &buf[intsize]; 1203 679 int write_required = 0; 1204 struct timeval tv; 1205 int i; 1206 int rt_fd; 1207 int sin_size = sizeof(struct sockaddr_in); 1208 1209 fd_set current; 1210 680 1211 681 assert(libtrace); 1212 682 assert(packet); … … 1224 694 if (libtrace->outputformat == RTSERVER) { 1225 695 do { 1226 // check for incoming connections NOTE: Should this be inside the do { }1227 tv.tv_sec = 0;1228 tv.tv_usec = 10;1229 current = libtrace->listen;1230 do {1231 if (select(libtrace->max_rtfds + 1, ¤t, NULL, NULL,&tv) >=0 ) {1232 break;1233 }1234 }1235 while (errno == EINTR);1236 for (i = 0; i <= libtrace->max_rtfds; i++) {1237 if (FD_ISSET(i, ¤t)) {1238 // Got something on the listening socket1239 if (i == libtrace->connect_fd) {1240 if ((rt_fd = accept(i, (struct sockaddr *) libtrace->remote,1241 &sin_size)) == -1) {1242 perror("accept");1243 } else {1244 printf("Client connected\n");1245 FD_SET(rt_fd, &libtrace->rt_fds);1246 if (rt_fd > libtrace->max_rtfds)1247 libtrace->max_rtfds = rt_fd;1248 }1249 }1250 }1251 }1252 1253 696 assert(libtrace->fifo); 1254 697 … … 1279 722 continue; 1280 723 } 1281 current = libtrace->rt_fds;724 fifo_out_update(libtrace->fifo, size); 1282 725 // Sort out the protocol header 1283 726 memcpy(buf, &packet->status, intsize); 1284 if (select(libtrace->max_rtfds + 1, NULL, ¤t, NULL, &tv) == -1 ) { 1285 perror("select"); 1286 write_required = 0; 1287 continue; 727 728 729 // Send the buffer out on the wire 730 if ((numbytes = trace_write(libtrace, buf, size + sizeof(int))) <=0 ) { 731 return numbytes; 1288 732 } 1289 1290 // Send the data to each ready client 1291 for (i = 0; i <= libtrace->max_rtfds; i++) { 1292 if (FD_ISSET(i, ¤t)) { 1293 libtrace->output.fd = i; 1294 if ((numbytes = trace_write(libtrace, buf, size + sizeof(int))) <=0 ) { 1295 // close rt_client 1296 FD_CLR(i, &libtrace->rt_fds); 1297 close(i); 1298 numbytes = 0; 1299 continue; 1300 } 1301 } 1302 } 1303 1304 fifo_out_update(libtrace->fifo, size); 733 1305 734 // Need an ack to come back 1306 735 // TODO: Obviously this is a little unfinished … … 1327 756 void *trace_get_link(const struct libtrace_packet_t *packet) { 1328 757 const void *ethptr = 0; 1329 dag_record_t *erfptr = 0;1330 struct wag_event_t *event = (struct wag_event_t *)packet->buffer;1331 struct wag_data_event_t *data_event;1332 758 1333 1334 switch(packet->trace->format) { 1335 case ERF: 1336 case DAG: 1337 case RTCLIENT: 1338 erfptr = (dag_record_t *)packet->buffer; 1339 if (erfptr->flags.rxerror == 1) { 1340 return NULL; 1341 } 1342 if (trace_get_link_type(packet)==TRACE_TYPE_ETH) 1343 ethptr = ((uint8_t *)packet->buffer + 1344 dag_record_size + 2); 1345 else 1346 ethptr = ((uint8_t *)packet->buffer + 1347 dag_record_size + 2); 1348 break; 1349 #if HAVE_PCAP 1350 case PCAPINT: 1351 case PCAP: 1352 ethptr = (packet->buffer + sizeof(struct pcap_pkthdr)); 1353 break; 1354 #endif 1355 case WAGINT: 1356 case WAG: 1357 switch (event->type) { 1358 case 0x0: 1359 data_event = (void*)&(event->payload); 1360 return data_event->data; 1361 default: 1362 fprintf(stderr,"Unknown WAG Event (0x%08x)\n",event->type); 1363 return NULL; 1364 } 1365 1366 default: 1367 fprintf(stderr,"Don't know this trace format\n"); 1368 assert(0); 1369 } 759 if (packet->trace->format->get_link) { 760 ethptr = packet->trace->format->get_link(packet); 761 } 1370 762 return (void *)ethptr; 1371 763 } … … 1659 1051 uint64_t trace_get_erf_timestamp(const struct libtrace_packet_t *packet) { 1660 1052 uint64_t timestamp = 0; 1661 dag_record_t *erfptr = 0; 1662 struct pcap_pkthdr *pcapptr = 0; 1663 struct wag_event_t *wagptr = 0; 1664 switch (packet->trace->format) { 1665 case DAG: 1666 case ERF: 1667 case RTCLIENT: 1668 erfptr = (dag_record_t *)packet->buffer; 1669 timestamp = erfptr->ts; 1670 break; 1671 #if HAVE_PCAP 1672 case PCAPINT: 1673 case PCAP: 1674 pcapptr = (struct pcap_pkthdr *)packet->buffer; 1675 timestamp = ((((uint64_t)pcapptr->ts.tv_sec) << 32) + \ 1676 (((uint64_t)pcapptr->ts.tv_usec*UINT_MAX)/1000000)); 1677 break; 1678 #endif 1679 case WAGINT: 1680 case WAG: 1681 wagptr = (struct wag_event_t *)packet->buffer; 1682 timestamp = wagptr->timestamp_lo; 1683 timestamp |= (uint64_t)wagptr->timestamp_hi<<32; 1684 timestamp = ((timestamp%44000000)*(UINT_MAX/44000000)) 1685 | ((timestamp/44000000)<<32); 1686 break; 1687 default: 1688 fprintf(stderr,"Unknown format in trace_get_erf_timestamp\n"); 1689 timestamp = 0; 1690 } 1691 return timestamp; 1053 struct timeval ts; 1054 1055 if (packet->trace->format->get_erf_timestamp) { 1056 timestamp = packet->trace->format->get_erf_timestamp(packet); 1057 } else if (packet->trace->format->get_timeval) { 1058 ts = packet->trace->format->get_timeval(packet); 1059 timestamp = ((((uint64_t)ts.tv_sec) << 32) + \ 1060 (((uint64_t)ts.tv_usec * UINT_MAX)/1000000)); 1061 } 1062 return timestamp; 1692 1063 } 1693 1064 … … 1701 1072 struct timeval trace_get_timeval(const struct libtrace_packet_t *packet) { 1702 1073 struct timeval tv; 1703 #if HAVE_PCAP 1704 struct pcap_pkthdr *pcapptr = 0; 1705 #endif 1706 uint64_t ts; 1707 //uint32_t seconds; 1708 switch (packet->trace->format) { 1709 #if HAVE_PCAP 1710 case PCAPINT: 1711 case PCAP: 1712 pcapptr = (struct pcap_pkthdr *)packet->buffer; 1713 // ick. FIXME 1714 tv = pcapptr->ts; 1715 break; 1716 #endif 1717 case WAGINT: 1718 case WAG: 1719 case DAG: 1720 case ERF: 1721 case RTCLIENT: 1722 default: 1723 // FIXME: This isn't portable to big-endian machines 1724 ts = trace_get_erf_timestamp(packet); 1074 uint64_t ts = 0; 1075 1076 if (packet->trace->format->get_timeval) { 1077 tv = packet->trace->format->get_timeval(packet); 1078 } else if (packet->trace->format->get_erf_timestamp) { 1079 ts = packet->trace->format->get_erf_timestamp(packet); 1725 1080 #if __BYTE_ORDER == __BIG_ENDIAN 1726 1081 tv.tv_sec = ts & 0xFFFFFFFF; 1727 1082 #elif __BYTE_ORDER == __LITTLE_ENDIAN 1728 1083 tv.tv_sec = ts >> 32; 1729 1084 #else 1730 1085 #error "What on earth are you running this on?" 1731 1086 #endif 1732 1733 1734 1735 1736 1737 1738 1739 break;1740 } 1087 ts = (1000000 * (ts & 0xffffffffULL)); 1088 ts += (ts & 0x80000000ULL) << 1; 1089 tv.tv_usec = ts >> 32; 1090 if (tv.tv_usec >= 1000000) { 1091 tv.tv_usec -= 1000000; 1092 tv.tv_sec += 1; 1093 } 1094 } 1095 1741 1096 return tv; 1742 1097 } … … 1748 1103 */ 1749 1104 double trace_get_seconds(const struct libtrace_packet_t *packet) { 1105 double seconds; 1750 1106 uint64_t ts; 1751 ts = trace_get_erf_timestamp(packet); 1752 return (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX); 1107 1108 if (packet->trace->format->get_seconds) { 1109 seconds = packet->trace->format->get_seconds(packet); 1110 } else if (packet->trace->format->get_erf_timestamp) { 1111 ts = packet->trace->format->get_erf_timestamp(packet); 1112 seconds = (ts>>32) + ((ts & UINT_MAX)*1.0 / UINT_MAX); 1113 } 1114 return seconds; 1753 1115 } 1754 1116 … … 1765 1127 */ 1766 1128 int trace_get_capture_length(const struct libtrace_packet_t *packet) { 1767 dag_record_t *erfptr = 0; 1768 #if HAVE_PCAP 1769 struct pcap_pkthdr *pcapptr = 0; 1770 #endif 1771 struct wag_event_t *wag_event; 1772 switch (packet->trace->format) { 1773 case DAG: 1774 case ERF: 1775 case RTCLIENT: 1776 erfptr = (dag_record_t *)packet->buffer; 1777 return ntohs(erfptr->rlen); 1778 #if HAVE_PCAP 1779 case PCAPINT: 1780 case PCAP: 1781 pcapptr = (struct pcap_pkthdr *)packet->buffer; 1782 //return ntohs(pcapptr->caplen); 1783 return pcapptr->caplen; 1784 #endif 1785 case WAGINT: 1786 case WAG: 1787 wag_event = (struct wag_event_t *)packet->buffer; 1788 switch(wag_event->type) { 1789 case 0: 1790 return wag_event->length*4-( 1791 sizeof(struct wag_event_t)+ 1792 sizeof(struct wag_data_event_t) 1793 ); 1794 default: 1795 assert(0); 1796 } 1797 default: 1798 assert(0); 1129 1130 if (packet->trace->format->get_capture_length) { 1131 return packet->trace->format->get_capture_length(packet); 1799 1132 } 1800 1133 return -1; … … 1811 1144 */ 1812 1145 int trace_get_wire_length(const struct libtrace_packet_t *packet){ 1813 dag_record_t *erfptr = 0; 1814 #if HAVE_PCAP 1815 struct pcap_pkthdr *pcapptr = 0; 1816 #endif 1817 struct wag_event_t *wag_event = 0; 1818 switch (packet->trace->format) { 1819 case DAG: 1820 case ERF: 1821 case RTCLIENT: 1822 erfptr = (dag_record_t *)packet->buffer; 1823 return ntohs(erfptr->wlen); 1824 break; 1825 #if HAVE_PCAP 1826 case PCAPINT: 1827 case PCAP: 1828 pcapptr = (struct pcap_pkthdr *)packet->buffer; 1829 return ntohs(pcapptr->len); 1830 break; 1831 #endif 1832 case WAGINT: 1833 case WAG: 1834 wag_event = (struct wag_event_t *)packet->buffer; 1835 switch(wag_event->type) { 1836 case 0: 1837 return ((struct wag_data_event_t *)(&wag_event->payload))->frame_length; 1838 default: 1839 assert(0); 1840 } 1146 if (packet->trace->format->get_wire_length) { 1147 return packet->trace->format->get_wire_length(packet); 1841 1148 } 1842 1149 return -1; … … 1851 1158 */ 1852 1159 libtrace_linktype_t trace_get_link_type(const struct libtrace_packet_t *packet ) { 1853 dag_record_t *erfptr = 0; 1854 #if HAVE_PCAP 1855 struct pcap_pkthdr *pcapptr = 0; 1856 #endif 1857 int linktype = 0; 1858 switch (packet->trace->format) { 1859 case DAG: 1860 case ERF: 1861 case RTCLIENT: 1862 erfptr = (dag_record_t *)packet->buffer; 1863 switch (erfptr->type) { 1864 case TYPE_ETH: return TRACE_TYPE_ETH; 1865 case TYPE_ATM: return TRACE_TYPE_ATM; 1866 default: assert(0); 1867 } 1868 return erfptr->type; 1869 1870 break; 1871 #if HAVE_PCAP 1872 case PCAPINT: 1873 case PCAP: 1874 pcapptr = (struct pcap_pkthdr *)packet->buffer; 1875 linktype = pcap_datalink(packet->trace->input.pcap); 1876 switch (linktype) { 1877 case DLT_NULL: 1878 return TRACE_TYPE_NONE; 1879 case DLT_EN10MB: 1880 return TRACE_TYPE_ETH; 1881 case DLT_ATM_RFC1483: 1882 return TRACE_TYPE_ATM; 1883 case DLT_IEEE802_11: 1884 return TRACE_TYPE_80211; 1885 #ifdef DLT_LINUX_SLL 1886 case DLT_LINUX_SLL: 1887 return TRACE_TYPE_LINUX_SLL; 1888 #endif 1889 #ifdef DLT_PFLOG 1890 case DLT_PFLOG: 1891 return TRACE_TYPE_PFLOG; 1892 #endif 1893 } 1894 break; 1895 #endif 1896 case WAGINT: 1897 case WAG: 1898 return TRACE_TYPE_80211; 1160 if (packet->trace->format->get_link_type) { 1161 return packet->trace->format->get_link_type(packet); 1899 1162 } 1900 1163 return -1; … … 2158 1421 */ 2159 1422 int8_t trace_set_direction(struct libtrace_packet_t *packet, int8_t direction) { 2160 2161 dag_record_t *erfptr = 0; 2162 assert(packet); 2163 2164 switch(packet->trace->format) { 2165 case DAG: 2166 case ERF: 2167 case RTCLIENT: 2168 erfptr = (dag_record_t *)packet->buffer; 2169 erfptr->flags.iface = direction; 2170 break; 2171 default: 2172 direction = -1; 2173 } 2174 2175 return direction; 2176 2177 1423 1424 1425 if (packet->trace->format->set_direction) { 1426 return packet->trace->format->set_direction(packet,direction); 1427 } 1428 return -1; 2178 1429 } 2179 1430 … … 2189 1440 int8_t trace_get_direction(const struct libtrace_packet_t *packet) { 2190 1441 2191 int8_t direction;2192 dag_record_t *erfptr = 0;2193 1442 assert(packet); 2194 direction = -1; 2195 2196 switch(packet->trace->format) { 2197 case DAG: 2198 case ERF: 2199 case RTCLIENT: 2200 erfptr = (dag_record_t *)packet->buffer; 2201 direction = erfptr->flags.iface; 2202 break; 2203 case PCAP: 2204 case PCAPINT: 2205 switch (trace_get_link_type(packet)) { 2206 case TRACE_TYPE_LINUX_SLL: 2207 { 2208 struct trace_sll_header_t *sll; 2209 sll = trace_get_link(packet); 2210 if (!sll) { 2211 return -1; 2212 } 2213 /* 0 == LINUX_SLL_HOST */ 2214 /* the Waikato Capture point defines "packets 2215 * originating locally" (ie, outbound), with a 2216 * direction of 0, and "packets destined locally" 2217 * (ie, inbound), with a direction of 1. 2218 * This is kind-of-opposite to LINUX_SLL. 2219 * We return consistent values here, however 2220 * 2221 * Note that in recent versions of pcap, you can 2222 * use "inbound" and "outbound" on ppp in linux 2223 */ 2224 if (ntohs(sll->pkttype==0)) { 2225 2226 direction = 1; 2227 } 2228 else { 2229 direction = 0; 2230 } 2231 break; 2232 } 2233 case TRACE_TYPE_PFLOG: 2234 { 2235 struct trace_pflog_header_t *pflog; 2236 pflog = trace_get_link(packet); 2237 if (!pflog) { 2238 return -1; 2239 } 2240 /* enum { PF_IN=0, PF_OUT=1 }; */ 2241 if (ntohs(pflog->dir==0)) { 2242 2243 direction = 1; 2244 } 2245 else { 2246 direction = 0; 2247 } 2248 break; 2249 } 2250 default: 2251 /* pass */ 2252 break; 2253 } 2254 default: 2255 /* pass */ 2256 break; 2257 } 2258 2259 return direction; 2260 1443 1444 if (packet->trace->format->get_direction) { 1445 return packet->trace->format->get_direction(packet); 1446 } 1447 return -1; 2261 1448 2262 1449 } … … 2439 1626 return packet->size; 2440 1627 } 2441 switch (packet->trace->format) { 2442 #if HAVE_PCAP 2443 case PCAPINT: 2444 case PCAP: 2445 pcaphdr = (struct pcap_pkthdr *)packet->buffer; 2446 pcaphdr->caplen = size + sizeof(struct pcap_pkthdr); 2447 packet->size = pcaphdr->caplen; 2448 break; 2449 #endif 2450 case ERF: 2451 case DAG: 2452 case RTCLIENT: 2453 erfptr = (dag_record_t *)packet->buffer; 2454 erfptr->rlen = ntohs(size + sizeof(dag_record_t)); 2455 packet->size = size + sizeof(dag_record_t); 2456 break; 2457 case WAGINT: 2458 case WAG: 2459 // don't know how to do this? 2460 break; 2461 } 2462 return packet->size; 2463 } 2464 1628 if (packet->trace->format->truncate_packet) { 1629 return packet->trace->format->truncate_packet(packet,size); 1630 } 1631 return -1; 1632 } 1633
Note: See TracChangeset
for help on using the changeset viewer.