static int pcap_start_input(libtrace_t *libtrace) { char errbuf[PCAP_ERRBUF_SIZE]; /* Check if the file is already open */ if (INPUT.pcap) return 0; /* success */ /* Open the trace file for reading */ if ((INPUT.pcap = pcap_open_offline(libtrace->uridata, errbuf)) == NULL) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s", errbuf); return -1; } /* If a filter has been configured, compile and apply it */ if (DATA(libtrace)->filter) { if (DATA(libtrace)->filter->flag == 0) { pcap_compile(INPUT.pcap, &DATA(libtrace)->filter->filter, DATA(libtrace)->filter->filterstring, 1, 0); DATA(libtrace)->filter->flag = 1; } if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter) == -1) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s", pcap_geterr(INPUT.pcap)); return -1; } } return 0; }
/* Initialises a DAG input trace */ static int dag_init_input(libtrace_t *libtrace) { struct stat buf; char *dag_dev_name = NULL; char *scan = NULL; /* Since DAG 2.5 has been changed to support a slightly different URI * format, it's probably a good idea to deal with URIs specified in * such a fashion even if we just end up ignoring the stream number */ if ((scan = strchr(libtrace->uridata,',')) == NULL) { dag_dev_name = strdup(libtrace->uridata); } else { dag_dev_name = (char *)strndup(libtrace->uridata, (size_t)(scan - libtrace->uridata)); } /* Make sure a DAG device with the right name exists */ if (stat(dag_dev_name, &buf) == -1) { trace_set_err(libtrace,errno,"stat(%s)",dag_dev_name); free(dag_dev_name); return -1; } dag_init_format_data(libtrace); if (S_ISCHR(buf.st_mode)) { /* DEVICE */ if((FORMAT_DATA->fd = dag_open(dag_dev_name)) < 0) { trace_set_err(libtrace,errno,"Cannot open DAG %s", dag_dev_name); free(dag_dev_name); return -1; } /* Memory-map ourselves a pointer to the DAG memory hole */ if((FORMAT_DATA->buf = (void *)dag_mmap(FORMAT_DATA->fd)) == MAP_FAILED) { trace_set_err(libtrace,errno,"Cannot mmap DAG %s", dag_dev_name); free(dag_dev_name); return -1; } } else { trace_set_err(libtrace,errno,"Not a valid dag device: %s", dag_dev_name); free(dag_dev_name); return -1; } free(dag_dev_name); return 0; }
/* Extracts DUCK information from the DAG card and produces a DUCK packet */ static int dag_get_duckinfo(libtrace_t *libtrace, libtrace_packet_t *packet) { dag_inf lt_dag_inf; /* Allocate memory for the DUCK data */ if (packet->buf_control == TRACE_CTRL_EXTERNAL || !packet->buffer) { packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE); packet->buf_control = TRACE_CTRL_PACKET; if (!packet->buffer) { trace_set_err(libtrace, errno, "Cannot allocate packet buffer"); return -1; } } /* DUCK doesn't actually have a format header, as such */ packet->header = 0; packet->payload = packet->buffer; /* Check that the DAG card supports DUCK */ if ((ioctl(FORMAT_DATA->fd, DAG_IOINF, <_dag_inf) < 0)) { trace_set_err(libtrace, errno, "Error using DAG_IOINF"); return -1; } if (!IsDUCK(<_dag_inf)) { printf("WARNING: %s does not have modern clock support - No DUCK information will be gathered\n", libtrace->uridata); return 0; } /* Get the DUCK information from the card */ if ((ioctl(FORMAT_DATA->fd, DAG_IOGETDUCK, (duck_inf *)packet->payload) < 0)) { trace_set_err(libtrace, errno, "Error using DAG_IOGETDUCK"); return -1; } /* Set the type */ packet->type = TRACE_RT_DUCK_2_4; /* Set the packet's trace to point at a DUCK trace, so that the * DUCK format functions will be called on the packet rather than the * DAG ones */ if (!DUCK.dummy_duck) DUCK.dummy_duck = trace_create_dead("duck:dummy"); packet->trace = DUCK.dummy_duck; return sizeof(duck_inf); }
static int pcapint_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) { int err; if (trace_get_link_type(packet) == TRACE_TYPE_NONDATA) return 0; if (!OUTPUT.trace.pcap) { OUTPUT.trace.pcap = (pcap_t *)pcap_open_live( libtrace->uridata,65536,0,0,NULL); } #ifdef HAVE_PCAP_INJECT err=pcap_inject(OUTPUT.trace.pcap, packet->payload, trace_get_capture_length(packet)); if (err!=(int)trace_get_capture_length(packet)) err=-1; #else #ifdef HAVE_PCAP_SENDPACKET err=pcap_sendpacket(OUTPUT.trace.pcap, packet->payload, trace_get_capture_length(packet)); #else trace_set_err(packet->trace,TRACE_ERR_UNSUPPORTED,"writing is not supported on this platform"); return -1; #endif #endif return err; }
static int pcapfile_init_input(libtrace_t *libtrace) { libtrace->format_data = malloc(sizeof(struct pcapfile_format_data_t)); if (!libtrace->format_data) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unable to allocate memory for " "format data inside pcapfile_init_input()"); return -1; } IN_OPTIONS.real_time = 0; DATA(libtrace)->started = false; return 0; }
static int pcapfile_start_input(libtrace_t *libtrace) { int err; if (!libtrace->io) { libtrace->io=trace_open_file(libtrace); DATA(libtrace)->started=false; } if (!DATA(libtrace)->started) { if (!libtrace->io) { trace_set_err(libtrace, TRACE_ERR_BAD_IO, "Trace cannot start IO in pcapfile_start_input()"); return -1; } err=wandio_read(libtrace->io, &DATA(libtrace)->header, sizeof(DATA(libtrace)->header)); DATA(libtrace)->started = true; if (!(sizeof(DATA(libtrace)->header) > 0)) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Trace is missing header in pcapfile_start_input()"); return -1; } if (err<1) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Error while reading pcap file header\n"); return -1; } if (err != (int)sizeof(DATA(libtrace)->header)) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Incomplete pcap file header"); return -1; } if (!header_is_magic(&(DATA(libtrace)->header))) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED, "Not a pcap tracefile (magic=%08x)\n",swapl(libtrace,DATA(libtrace)->header.magic_number)); return -1; /* Not a pcap file */ } if (swaps(libtrace,DATA(libtrace)->header.version_major)!=2 && swaps(libtrace,DATA(libtrace)->header.version_minor)!=4) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED, "Unknown pcap tracefile version %d.%d\n", swaps(libtrace, DATA(libtrace)->header.version_major), swaps(libtrace, DATA(libtrace)->header.version_minor)); return -1; } } return 0; }
/* Starts a DAG input trace */ static int dag_start_input(libtrace_t *libtrace) { if(dag_start(FORMAT_DATA->fd) < 0) { trace_set_err(libtrace,errno,"Cannot start DAG %s", libtrace->uridata); return -1; } /* Flush the memory hole */ while(dag_available(libtrace) != 0) FORMAT_DATA->diff = 0; FORMAT_DATA->drops = 0; return 0; }
static uint64_t pcap_get_dropped_packets(libtrace_t *trace) { struct pcap_stat stats; if (pcap_stats(DATA(trace)->input.pcap,&stats)==-1) { char *errmsg = pcap_geterr(DATA(trace)->input.pcap); trace_set_err(trace,TRACE_ERR_UNSUPPORTED, "Failed to retreive stats: %s\n", errmsg ? errmsg : "Unknown pcap error"); return ~0; } return stats.ps_drop; }
/* Sends an RT ACK to the server to acknowledge receipt of packets */ static int rt_send_ack(libtrace_t *libtrace, uint32_t seqno) { static char *ack_buffer = 0; char *buf_ptr; int numbytes = 0; size_t to_write = 0; rt_header_t *hdr; rt_ack_t *ack_hdr; if (!ack_buffer) { ack_buffer = (char*)malloc(sizeof(rt_header_t) + sizeof(rt_ack_t)); } hdr = (rt_header_t *) ack_buffer; ack_hdr = (rt_ack_t *) (ack_buffer + sizeof(rt_header_t)); hdr->type = TRACE_RT_ACK; hdr->length = sizeof(rt_ack_t); ack_hdr->sequence = seqno; to_write = hdr->length + sizeof(rt_header_t); buf_ptr = ack_buffer; /* Keep trying until we write the entire ACK */ while (to_write > 0) { numbytes = send(RT_INFO->input_fd, buf_ptr, to_write, 0); if (numbytes == -1) { if (errno == EINTR || errno == EAGAIN) { continue; } else { printf("Error sending ack\n"); perror("send"); trace_set_err(libtrace, TRACE_ERR_RT_FAILURE, "Error sending ack"); return -1; } } to_write = to_write - numbytes; buf_ptr = buf_ptr + to_write; } return 1; }
/* Starts a BPF input trace */ static int bpf_start_input(libtrace_t *libtrace) { int bpfid=0; struct bpf_version bv; struct ifreq ifr; unsigned int v; /* Find and open a bpf device */ do { char buffer[64]; snprintf(buffer,sizeof(buffer),"/dev/bpf%d", bpfid); bpfid++; FORMATIN(libtrace)->fd = open(buffer, O_RDONLY); } while(FORMATIN(libtrace)->fd == -1 && errno == EBUSY); if (FORMATIN(libtrace)->fd == -1) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED, "No free bpf devices"); return -1; } /* Check the BPF Version is ok */ if (ioctl(FORMATIN(libtrace)->fd, BIOCVERSION, &bv) == -1) { trace_set_err(libtrace,errno, "Failed to read the bpf version"); close(FORMATIN(libtrace)->fd); return -1; } if (bv.bv_major != BPF_MAJOR_VERSION) { trace_set_err(libtrace,errno, "Unknown kernel BPF version (%d.%d, libtrace requires at least %d.%d)", bv.bv_major, bv.bv_minor, BPF_MAJOR_VERSION, BPF_MINOR_VERSION); close(FORMATIN(libtrace)->fd); return -1; } if (bv.bv_minor < BPF_MINOR_VERSION) { trace_set_err(libtrace,errno, "Kernel version too old (%d.%d, libtrace requires at least %d.%d)", bv.bv_major, bv.bv_minor, BPF_MAJOR_VERSION, BPF_MINOR_VERSION); close(FORMATIN(libtrace)->fd); return -1; } /* We assume the default kernel buffer size is sufficient. */ if (ioctl(FORMATIN(libtrace)->fd, BIOCGBLEN, &FORMATIN(libtrace)->buffersize)==-1) { trace_set_err(libtrace,errno,"Failed to find buffer length"); close(FORMATIN(libtrace)->fd); return -1; } FORMATIN(libtrace)->buffer = NULL; FORMATIN(libtrace)->bufptr = NULL; FORMATIN(libtrace)->remaining = 0; /* Attach to the device */ strncpy(ifr.ifr_name, libtrace->uridata, sizeof(ifr.ifr_name)); if (ioctl(FORMATIN(libtrace)->fd, BIOCSETIF, &ifr) == -1) { trace_set_err(libtrace,errno,"Failed to attach"); close(FORMATIN(libtrace)->fd); return -1; } /* Set the link type */ if (ioctl(FORMATIN(libtrace)->fd, BIOCGDLT, &FORMATIN(libtrace)->linktype) == -1) { trace_set_err(libtrace,errno,"Failed to retrieve link type"); close(FORMATIN(libtrace)->fd); return -1; } /* TODO: If BIOCGDLTLIST exists then we should perhaps do something * with it. We don't have the same concept of multiple DLT's * as pcap does. We grab the rawest possible thing and then * decode packets by understanding the protocols. So perhaps * we should setup a rating of DLT's that we'll prefer in order. * For example we should try and get 802.11 frames rather than * 802.3 frames. The general rule should be "whatever actually * went over the air", although of course if we don't support * what went over the air we should fall back to something we * /do/ support. */ /* Using timeouts seems sucky. We'll always use immediate mode. We * pray the kernel is smart enough that if a another packet arrives * while we're processing this one that it will buffer them into it's * kernel buffer so we can receive packets later. (It'll need to do this * to deal with us spending time processing the last 'n' packets anyway) */ v=1; if (ioctl(FORMATIN(libtrace)->fd, BIOCIMMEDIATE, &v) == -1) { trace_set_err(libtrace,errno,"Failed to set immediate mode"); close(FORMATIN(libtrace)->fd); return -1; } /* Set promiscous mode, if the user has asked us to do so */ if (FORMATIN(libtrace)->promisc) { if (ioctl(FORMATIN(libtrace)->fd, BIOCPROMISC, NULL) == -1) { trace_set_err(libtrace,errno, "Failed to set promisc mode"); close(FORMATIN(libtrace)->fd); return -1; } } FORMATIN(libtrace)->stats_valid = 0; /* TODO: we should always set a bpf filter for snapping */ /* We're done! */ return 0; }
/* Sets the trace format for the packet to match the format it was originally * captured in, rather than the RT format */ static int rt_set_format(libtrace_t *libtrace, libtrace_packet_t *packet) { /* We need to assign the packet to a "dead" trace */ /* Try to minimize the number of corrupt packets that slip through * while making it easy to identify new pcap DLTs */ if (packet->type > TRACE_RT_DATA_DLT && packet->type < TRACE_RT_DATA_DLT_END) { if (!RT_INFO->dummy_pcap) { RT_INFO->dummy_pcap = trace_create_dead("pcap:-"); } packet->trace = RT_INFO->dummy_pcap; return 0; } if (packet->type > TRACE_RT_DATA_BPF && packet->type < TRACE_RT_DATA_BPF_END) { if (!RT_INFO->dummy_bpf) { RT_INFO->dummy_bpf = trace_create_dead("bpf:-"); /* This may fail on a non-BSD machine */ if (trace_is_err(RT_INFO->dummy_bpf)) { trace_perror(RT_INFO->dummy_bpf, "Creating dead bpf trace"); return -1; } } packet->trace = RT_INFO->dummy_bpf; return 0; } switch (packet->type) { case TRACE_RT_DUCK_2_4: case TRACE_RT_DUCK_2_5: if (!RT_INFO->dummy_duck) { RT_INFO->dummy_duck = trace_create_dead("duck:dummy"); } packet->trace = RT_INFO->dummy_duck; break; case TRACE_RT_DATA_ERF: if (!RT_INFO->dummy_erf) { RT_INFO->dummy_erf = trace_create_dead("erf:-"); } packet->trace = RT_INFO->dummy_erf; break; case TRACE_RT_DATA_LINUX_NATIVE: if (!RT_INFO->dummy_linux) { RT_INFO->dummy_linux = trace_create_dead("int:"); /* This may fail on a non-Linux machine */ if (trace_is_err(RT_INFO->dummy_linux)) { trace_perror(RT_INFO->dummy_linux, "Creating dead int trace"); return -1; } } packet->trace = RT_INFO->dummy_linux; break; case TRACE_RT_DATA_LINUX_RING: if (!RT_INFO->dummy_ring) { RT_INFO->dummy_ring = trace_create_dead("ring:"); /* This may fail on a non-Linux machine */ if (trace_is_err(RT_INFO->dummy_ring)) { trace_perror(RT_INFO->dummy_ring, "Creating dead int trace"); return -1; } } packet->trace = RT_INFO->dummy_ring; break; case TRACE_RT_STATUS: case TRACE_RT_METADATA: /* Just use the RT trace! */ packet->trace = libtrace; break; case TRACE_RT_DATA_LEGACY_ETH: case TRACE_RT_DATA_LEGACY_ATM: case TRACE_RT_DATA_LEGACY_POS: printf("Sending legacy over RT is currently not supported\n"); trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Legacy packet cannot be sent over rt"); return -1; default: printf("Unrecognised format: %u\n", packet->type); trace_set_err(libtrace, TRACE_ERR_BAD_PACKET, "Unrecognised packet format"); return -1; } return 0; /* success */ }
/* Receives data from an RT server */ static int rt_read(libtrace_t *libtrace, void **buffer, size_t len, int block) { int numbytes; assert(len <= RT_BUF_SIZE); if (!RT_INFO->pkt_buffer) { RT_INFO->pkt_buffer = (char*)malloc((size_t)RT_BUF_SIZE); RT_INFO->buf_current = RT_INFO->pkt_buffer; RT_INFO->buf_filled = 0; } #ifndef MSG_DONTWAIT #define MSG_DONTWAIT 0 #endif if (block) block=0; else block=MSG_DONTWAIT; /* If we don't have enough buffer space for the amount we want to * read, move the current buffer contents to the front of the buffer * to make room */ if (len > RT_INFO->buf_filled) { memcpy(RT_INFO->pkt_buffer, RT_INFO->buf_current, RT_INFO->buf_filled); RT_INFO->buf_current = RT_INFO->pkt_buffer; #ifndef MSG_NOSIGNAL # define MSG_NOSIGNAL 0 #endif /* Loop as long as we don't have all the data that we were * asked for */ while (len > RT_INFO->buf_filled) { if ((numbytes = recv(RT_INFO->input_fd, RT_INFO->buf_current + RT_INFO->buf_filled, RT_BUF_SIZE-RT_INFO->buf_filled, MSG_NOSIGNAL|block)) <= 0) { if (numbytes == 0) { trace_set_err(libtrace, TRACE_ERR_RT_FAILURE, "No data received"); return -1; } if (errno == EINTR) { /* ignore EINTR in case * a caller is using signals */ continue; } if (errno == EAGAIN) { /* We asked for non-blocking mode, so * we need to return now */ trace_set_err(libtrace, EAGAIN, "EAGAIN"); return -1; } perror("recv"); trace_set_err(libtrace, errno, "Failed to read data into rt recv buffer"); return -1; } RT_INFO->buf_filled+=numbytes; } } *buffer = RT_INFO->buf_current; RT_INFO->buf_current += len; RT_INFO->buf_filled -= len; return len; }
/* Connects to an RT server * * Returns -1 if an error occurs */ static int rt_connect(libtrace_t *libtrace) { struct hostent *he; struct sockaddr_in remote; rt_header_t connect_msg; rt_deny_conn_t deny_hdr; rt_hello_t hello_opts; uint8_t reason; if ((he=gethostbyname(RT_INFO->hostname)) == NULL) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to convert hostname %s to address", RT_INFO->hostname); return -1; } if ((RT_INFO->input_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Could not create socket"); return -1; } memset(&remote,0, sizeof(remote)); remote.sin_family = AF_INET; remote.sin_port = htons(RT_INFO->port); remote.sin_addr = *((struct in_addr *)he->h_addr); if (connect(RT_INFO->input_fd, (struct sockaddr *)&remote, (socklen_t)sizeof(struct sockaddr)) == -1) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Could not connect to host %s on port %d", RT_INFO->hostname, RT_INFO->port); return -1; } /* We are connected, now receive message from server */ if (recv(RT_INFO->input_fd, (void*)&connect_msg, sizeof(rt_header_t), 0) != sizeof(rt_header_t) ) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Could not receive connection message from %s", RT_INFO->hostname); return -1; } switch (connect_msg.type) { case TRACE_RT_DENY_CONN: /* Connection was denied */ if (recv(RT_INFO->input_fd, (void*)&deny_hdr, sizeof(rt_deny_conn_t), 0) != sizeof(rt_deny_conn_t)) { reason = 0; } reason = deny_hdr.reason; trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Connection attempt is denied: %s", rt_deny_reason(reason)); return -1; case TRACE_RT_HELLO: /* Hello message - read the options sent to us by the * server */ if (recv(RT_INFO->input_fd, (void*)&hello_opts, sizeof(rt_hello_t), 0) != sizeof(rt_hello_t)) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Failed to receive TRACE_RT_HELLO options"); return -1; } RT_INFO->reliable = hello_opts.reliable; return 0; default: trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Unknown message type received: %d", connect_msg.type); return -1; } trace_set_err(libtrace, TRACE_ERR_INIT_FAILED, "Somehow you managed to reach this unreachable code"); return -1; }
static libtrace_direction_t pcap_get_direction(const libtrace_packet_t *packet) { libtrace_direction_t direction = -1; switch(pcap_get_link_type(packet)) { /* Only packets encapsulated in Linux SLL or PFLOG have any * direction information */ case TRACE_TYPE_LINUX_SLL: { libtrace_sll_header_t *sll; sll = trace_get_packet_buffer(packet, NULL, NULL); /* TODO: should check remaining>=sizeof(*sll) */ if (!sll) { trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET, "Bad or missing packet"); return -1; } /* 0 == LINUX_SLL_HOST */ /* the Waikato Capture point defines "packets * originating locally" (ie, outbound), with a * direction of 0, and "packets destined locally" * (ie, inbound), with a direction of 1. * This is kind-of-opposite to LINUX_SLL. * We return consistent values here, however * * Note that in recent versions of pcap, you can * use "inbound" and "outbound" on ppp in linux */ if (sll->pkttype == TRACE_SLL_OUTGOING) { direction = TRACE_DIR_OUTGOING; } else { direction = TRACE_DIR_INCOMING; } break; } case TRACE_TYPE_PFLOG: { libtrace_pflog_header_t *pflog; pflog = trace_get_packet_buffer(packet, NULL, NULL); /* TODO: should check remaining >= sizeof(*pflog) */ if (!pflog) { trace_set_err(packet->trace, TRACE_ERR_BAD_PACKET, "Bad or missing packet"); return -1; } /* enum { PF_IN=0, PF_OUT=1 }; */ if (ntohs(pflog->dir==0)) { direction = TRACE_DIR_INCOMING; } else { direction = TRACE_DIR_OUTGOING; } break; } default: break; } return direction; }
static int pcap_read_packet(libtrace_t *libtrace, libtrace_packet_t *packet) { int ret = 0; int linktype; uint32_t flags = 0; assert(libtrace->format_data); linktype = pcap_datalink(DATA(libtrace)->input.pcap); packet->type = pcap_linktype_to_rt(linktype); /* If we're using the replacement pcap_next_ex() we need to * make sure we have a buffer to *shudder* memcpy into */ if (!packet->buffer) { packet->buffer = malloc(LIBTRACE_PACKET_BUFSIZE); if (!packet->buffer) { trace_set_err(libtrace, errno, "Cannot allocate memory"); return -1; } packet->header = packet->buffer; packet->payload = (char *)packet->buffer+sizeof(struct pcap_pkthdr); } flags |= TRACE_PREP_OWN_BUFFER; for(;;) { struct pcap_pkthdr *pcap_hdr = NULL; u_char *pcap_payload = NULL; ret = pcap_next_ex(INPUT.pcap, &pcap_hdr, (const u_char **)&pcap_payload); packet->header = pcap_hdr; packet->payload = pcap_payload; switch(ret) { case 1: break; /* no error */ case 0: if (libtrace_halt) return 0; continue; /* timeout expired */ case -1: trace_set_err(libtrace,TRACE_ERR_BAD_PACKET, "%s",pcap_geterr(INPUT.pcap)); return -1; /* Error */ case -2: return 0; /* EOF */ } /* * pcap is nasty in that the header and payload aren't * necessarily located sequentially in memory, but most * sensible uses of pcap_prepare_packet will involve a * buffer where header and payload are sequential. * * Basically, don't call pcap_prepare_packet here! * if (pcap_prepare_packet(libtrace, packet, packet->buffer, packet->type, flags)) { return -1; } */ return ((struct pcap_pkthdr*)packet->header)->len +sizeof(struct pcap_pkthdr); } }
static int pcapint_start_input(libtrace_t *libtrace) { char errbuf[PCAP_ERRBUF_SIZE]; #ifdef HAVE_PCAP_CREATE int ret = 0; if ((INPUT.pcap = pcap_create(libtrace->uridata, errbuf)) == NULL) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf); return -1; /* failure */ } if ((pcap_set_snaplen(INPUT.pcap, DATA(libtrace)->snaplen) == PCAP_ERROR_ACTIVATED)) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf); return -1; /* failure */ } if ((pcap_set_promisc(INPUT.pcap, DATA(libtrace)->promisc) == PCAP_ERROR_ACTIVATED)) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf); return -1; /* failure */ } if ((pcap_set_timeout(INPUT.pcap, 1) == PCAP_ERROR_ACTIVATED)) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf); return -1; /* failure */ } if ((ret = pcap_activate(INPUT.pcap)) != 0) { if (ret == PCAP_WARNING_PROMISC_NOTSUP) { trace_set_err(libtrace, TRACE_ERR_INIT_FAILED,"Promiscuous mode unsupported"); return -1; } if (ret == PCAP_WARNING) { pcap_perror(INPUT.pcap, "Pcap Warning:"); } else { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s", pcap_geterr(INPUT.pcap)); return -1; } } #else /* Open the live device */ if ((INPUT.pcap = pcap_open_live(libtrace->uridata, DATA(libtrace)->snaplen, DATA(libtrace)->promisc, 1, errbuf)) == NULL) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s",errbuf); return -1; /* failure */ } #endif /* Set a filter if one is defined */ if (DATA(libtrace)->filter) { if (DATA(libtrace)->filter->flag == 0) { pcap_compile(INPUT.pcap, &DATA(libtrace)->filter->filter, DATA(libtrace)->filter->filterstring, 1, 0); DATA(libtrace)->filter->flag = 1; } if (pcap_setfilter(INPUT.pcap,&DATA(libtrace)->filter->filter) == -1) { trace_set_err(libtrace,TRACE_ERR_INIT_FAILED,"%s", pcap_geterr(INPUT.pcap)); return -1; /* failure */ } } #ifdef HAVE_PCAP_SETNONBLOCK pcap_setnonblock(INPUT.pcap,0,errbuf); #endif return 0; /* success */ }