void error_per_packet(struct libtrace_packet_t *packet) { struct libtrace_ip *ip = trace_get_ip(packet); struct libtrace_tcp *tcp = trace_get_tcp(packet); void *link = trace_get_packet_buffer(packet,NULL,NULL); if (!link) { ++rx_errors; } /* This isn't quite as simple as it seems. * * If the packets were captured via wdcap's anonymisation module, * the checksum is set to 0 when it is correct and 1 if incorrect. * * If a different capture method is used, there's a good chance the * checksum has not been altered */ if (ip) { if (ntohs(ip->ip_sum)!=0) ++ip_errors; } if (tcp) { if (ntohs(tcp->check)!=0) ++tcp_errors; } }
static gboolean qfTraceHandlePacket(qfTraceSource_t *lts, yfPBuf_t *pbuf, qfContext_t *ctx) { yfIPFragInfo_t fraginfo_buf, *fraginfo = ctx->fragtab ? &fraginfo_buf : NULL; libtrace_linktype_t linktype; uint8_t *pkt; uint32_t caplen; struct timeval tv; /* extract data from libtrace */ tv = trace_get_timeval(lts->packet); pkt = trace_get_packet_buffer(lts->packet, &linktype, &caplen); /* Decode packet into packet buffer */ if (!yfDecodeToPBuf(ctx->dectx, linktype, yfDecodeTimeval(&tv), trace_get_capture_length(lts->packet), pkt, fraginfo, pbuf)) { /* Couldn't decode packet; counted in dectx. Skip. */ return FALSE; } #if QOF_ENABLE_DETUNE /* Signal drop if detune says so */ if (ctx->ictx.detune) { if (!qfDetunePacket(ctx->ictx.detune, &pbuf->ptime, pbuf->iplen)) { return FALSE; } } #endif /* Handle fragmentation if necessary */ if (fraginfo && fraginfo->frag) { yfDefragPBuf(ctx->fragtab, fraginfo, pbuf, pkt, caplen); } /* signal packet processed */ return TRUE; }
off_t corsaro_file_write_packet(corsaro_t *corsaro, corsaro_file_t *file, libtrace_packet_t *packet) { uint8_t *pkt_buf = NULL; libtrace_linktype_t linktype; switch(file->mode) { case CORSARO_FILE_MODE_ASCII: assert(file->wand_io != NULL); #ifdef HAVE_LIBPACKETDUMP corsaro_log(__func__, corsaro, "libpacketdump currently does not support dumping " "to a file"); return 0; #else corsaro_log(__func__, corsaro, "corsaro must be built with libpacketdump to dump " "a packet to ASCII"); return 0; #endif break; case CORSARO_FILE_MODE_BINARY: assert(file->wand_io != NULL); if((pkt_buf = trace_get_packet_buffer(packet, &linktype, NULL)) == NULL) { corsaro_log(__func__, corsaro, "could not get packet buffer"); return -1; } return corsaro_file_write(corsaro, file, pkt_buf, trace_get_capture_length(packet)); case CORSARO_FILE_MODE_TRACE: assert(file->trace_io != NULL); return trace_write_packet(file->trace_io, packet); default: corsaro_log(__func__, corsaro, "invalid corsaro file mode %d", file->mode); return -1; } return -1; }
static int pcap_get_wire_length(const libtrace_packet_t *packet) { struct pcap_pkthdr *pcapptr = 0; pcapptr = (struct pcap_pkthdr *)packet->header; if (packet->type==pcap_linktype_to_rt(TRACE_DLT_EN10MB)) return pcapptr->len+4; /* Include the missing FCS */ else if (packet->type==pcap_linktype_to_rt(TRACE_DLT_IEEE802_11_RADIO)) { libtrace_linktype_t linktype; void *link = trace_get_packet_buffer(packet,&linktype,NULL); /* If the packet is Radiotap and the flags field indicates * that the FCS is not included in the 802.11 frame, then * we need to add 4 to the wire-length to account for it. */ uint8_t flags; trace_get_wireless_flags(link, linktype, &flags); if ((flags & TRACE_RADIOTAP_F_FCS) == 0) return pcapptr->len + 4; } return pcapptr->len; }
/** Implements the process_packet function of the plugin API */ int corsaro_dos_process_packet(corsaro_t *corsaro, corsaro_packet_t *packet) { libtrace_packet_t *ltpacket = LT_PKT(packet); void *temp = NULL; uint8_t proto; uint32_t remaining; libtrace_ip_t *ip_hdr = NULL; libtrace_icmp_t *icmp_hdr = NULL; libtrace_ip_t *inner_ip_hdr = NULL; /* borrowed from libtrace's protocols.h (used by trace_get_*_port) */ struct ports_t { uint16_t src; /**< Source port */ uint16_t dst; /**< Destination port */ }; uint16_t attacker_port = 0; uint16_t target_port = 0; attack_vector_t findme; int khret; khiter_t khiter; attack_vector_t *vector = NULL; uint8_t *pkt_buf = NULL; libtrace_linktype_t linktype; struct timeval tv; if((packet->state.flags & CORSARO_PACKET_STATE_FLAG_BACKSCATTER) == 0) { /* not a backscatter packet */ return 0; } /* backscatter packet, lets find the flow */ /* check for ipv4 */ /* 10/19/12 ak replaced much more verbose code to get header with this */ if((ip_hdr = trace_get_ip(ltpacket)) == NULL) { /* non-ipv4 packet */ return 0; } /* get the transport header */ if((temp = trace_get_transport(ltpacket, &proto, &remaining)) == NULL) { /* not enough payload */ return 0; } findme.target_ip = 0; if(ip_hdr->ip_p == TRACE_IPPROTO_ICMP && remaining >= 2) { icmp_hdr = (libtrace_icmp_t *)temp; if((icmp_hdr->type == 3 || icmp_hdr->type == 4 || icmp_hdr->type == 5 || icmp_hdr->type == 11 || icmp_hdr->type == 12) && ((temp = trace_get_payload_from_icmp(icmp_hdr, &remaining)) != NULL && remaining >= 20 && (inner_ip_hdr = (libtrace_ip_t *)temp) && inner_ip_hdr->ip_v == 4)) { /* icmp error message */ if(inner_ip_hdr->ip_src.s_addr != ip_hdr->ip_dst.s_addr) { STATE(corsaro)->number_mismatched_packets++; } findme.target_ip = ntohl(inner_ip_hdr->ip_dst.s_addr); /* just extract the first four bytes of payload as ports */ if((temp = trace_get_payload_from_ip(inner_ip_hdr, NULL, &remaining)) != NULL && remaining >= 4) { attacker_port = ntohs(((struct ports_t *)temp)->src); target_port = ntohs(((struct ports_t *)temp)->dst); } } else { findme.target_ip = ntohl(ip_hdr->ip_src.s_addr); attacker_port = ntohs(icmp_hdr->code); target_port = ntohs(icmp_hdr->type); } } else if((ip_hdr->ip_p == TRACE_IPPROTO_TCP || ip_hdr->ip_p == TRACE_IPPROTO_UDP) && remaining >= 4) { findme.target_ip = ntohl(ip_hdr->ip_src.s_addr); attacker_port = trace_get_destination_port(ltpacket); target_port = trace_get_source_port(ltpacket); } if(findme.target_ip == 0) { /* the packet is none of ICMP, TCP or UDP */ return 0; } tv = trace_get_timeval(ltpacket); /* is this vector in the hash? */ assert(STATE(corsaro)->attack_hash != NULL); if((khiter = kh_get(av, STATE(corsaro)->attack_hash, &findme)) != kh_end(STATE(corsaro)->attack_hash)) { /* the vector is in the hash */ vector = kh_key(STATE(corsaro)->attack_hash, khiter); if(attack_vector_is_expired(vector, tv.tv_sec) != 0) { kh_del(av, STATE(corsaro)->attack_hash, khiter); attack_vector_free(vector); vector = NULL; } } if(vector == NULL) { /* create a new vector and fill it */ if((vector = attack_vector_init(corsaro)) == NULL) { corsaro_log(__func__, corsaro, "failed to create new attack vector"); return -1; } /* i think this may be buggy. do it the safe way for now vector->initial_packet = corsaro_mincopy_packet(packet); */ vector->initial_packet_len = trace_get_capture_length(ltpacket); if((vector->initial_packet = malloc(vector->initial_packet_len)) == NULL) { corsaro_log(__func__, corsaro, "could not malloc initial packet"); return -1; } if((pkt_buf = trace_get_packet_buffer(ltpacket, &linktype, NULL)) == NULL) { corsaro_log(__func__, corsaro, "could not get packet buffer"); return -1; } memcpy(vector->initial_packet, pkt_buf, vector->initial_packet_len); vector->attacker_ip = ntohl(ip_hdr->ip_dst.s_addr); vector->responder_ip = ntohl(ip_hdr->ip_src.s_addr); vector->target_ip = findme.target_ip; vector->start_time = tv; vector->ppm_window.window_start = tv.tv_sec; /* add to the hash */ khiter = kh_put(av, STATE(corsaro)->attack_hash, vector, &khret); } assert(vector != NULL); vector->packet_cnt++; vector->interval_packet_cnt++; vector->byte_cnt += ntohs(ip_hdr->ip_len); vector->interval_byte_cnt += ntohs(ip_hdr->ip_len); vector->latest_time = tv; /* update the pps window */ attack_vector_update_ppm_window(vector, tv); /* add the attacker ip to the hash */ kh_put(32xx, vector->attack_ip_hash, ntohl(ip_hdr->ip_dst.s_addr), &khret); /* add the ports to the hashes */ kh_put(32xx, vector->attack_port_hash, attacker_port, &khret); kh_put(32xx, vector->target_port_hash, target_port, &khret); return 0; }
DLLEXPORT void *trace_get_layer2(const libtrace_packet_t *packet, libtrace_linktype_t *linktype, uint32_t *remaining) { uint32_t dummyrem; void *meta = NULL; assert(packet != NULL); assert(linktype != NULL); if (remaining == NULL) remaining = &dummyrem; if (packet->l2_header) { /* Use cached values */ *linktype = packet->link_type; *remaining = packet->l2_remaining; return packet->l2_header; } /* Code looks a bit inefficient, but I'm actually trying to avoid * calling trace_get_packet_buffer more than once like we used to. */ meta = trace_get_packet_buffer(packet, linktype, remaining); /* If there are no meta-data headers, we just return the start of the * packet buffer, along with the linktype, etc. */ switch(*linktype) { /* meta points to a layer 2 header! */ case TRACE_TYPE_HDLC_POS: case TRACE_TYPE_ETH: case TRACE_TYPE_ATM: case TRACE_TYPE_80211: case TRACE_TYPE_NONE: case TRACE_TYPE_POS: case TRACE_TYPE_AAL5: case TRACE_TYPE_DUCK: case TRACE_TYPE_LLCSNAP: case TRACE_TYPE_PPP: case TRACE_TYPE_METADATA: case TRACE_TYPE_NONDATA: case TRACE_TYPE_OPENBSD_LOOP: ((libtrace_packet_t*)packet)->l2_header = meta; ((libtrace_packet_t*)packet)->l2_remaining = *remaining; return meta; case TRACE_TYPE_LINUX_SLL: case TRACE_TYPE_80211_RADIO: case TRACE_TYPE_80211_PRISM: case TRACE_TYPE_PFLOG: break; case TRACE_TYPE_UNKNOWN: return NULL; } /* If there are meta-data headers, we need to skip over them until we * find a non-meta data header and return that. */ for(;;) { void *nexthdr = trace_get_payload_from_meta(meta, linktype, remaining); if (nexthdr == NULL) { switch (*linktype) { /* meta points to a layer 2 header! */ case TRACE_TYPE_HDLC_POS: case TRACE_TYPE_ETH: case TRACE_TYPE_ATM: case TRACE_TYPE_80211: case TRACE_TYPE_NONE: case TRACE_TYPE_POS: case TRACE_TYPE_AAL5: case TRACE_TYPE_DUCK: case TRACE_TYPE_LLCSNAP: case TRACE_TYPE_PPP: case TRACE_TYPE_METADATA: case TRACE_TYPE_NONDATA: case TRACE_TYPE_OPENBSD_LOOP: ((libtrace_packet_t*)packet)->l2_header = meta; ((libtrace_packet_t*)packet)->l2_remaining = *remaining; return meta; case TRACE_TYPE_LINUX_SLL: case TRACE_TYPE_80211_RADIO: case TRACE_TYPE_80211_PRISM: case TRACE_TYPE_PFLOG: break; case TRACE_TYPE_UNKNOWN: return NULL; } /* Otherwise, we must have hit the end of the packet */ return NULL; } meta = nexthdr; } }
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_write_packet(libtrace_out_t *libtrace, libtrace_packet_t *packet) { struct pcap_pkthdr pcap_pkt_hdr; void *link; libtrace_linktype_t linktype; uint32_t remaining; link = trace_get_packet_buffer(packet,&linktype,&remaining); /* We may have to convert this packet into a suitable PCAP packet */ /* If this packet cannot be converted to a pcap linktype then * pop off the top header until it can be converted */ while (libtrace_to_pcap_linktype(linktype)==TRACE_DLT_ERROR) { if (!demote_packet(packet)) { trace_set_err_out(libtrace, TRACE_ERR_NO_CONVERSION, "pcap does not support this format"); return -1; } link = trace_get_packet_buffer(packet,&linktype,&remaining); } if (!OUTPUT.trace.pcap) { int linktype=libtrace_to_pcap_dlt(trace_get_link_type(packet)); OUTPUT.trace.pcap = pcap_open_dead(linktype,65536); if (!OUTPUT.trace.pcap) { trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED, "Failed to open dead trace: %s\n", pcap_geterr(OUTPUT.trace.pcap)); } OUTPUT.trace.dump = pcap_dump_open(OUTPUT.trace.pcap, libtrace->uridata); if (!OUTPUT.trace.dump) { char *errmsg = pcap_geterr(OUTPUT.trace.pcap); trace_set_err_out(libtrace,TRACE_ERR_INIT_FAILED,"Failed to open output file: %s\n", errmsg ? errmsg : "Unknown error"); return -1; } } /* Corrupt packet, or other "non data" packet, so skip it */ if (link == NULL) { /* Return "success", but nothing written */ return 0; } /* Check if the packet was captured using one of the PCAP formats */ if (packet->trace->format == &pcap || packet->trace->format == &pcapint) { /* Yes - this means we can write it straight out */ pcap_dump((u_char*)OUTPUT.trace.dump, (struct pcap_pkthdr *)packet->header, packet->payload); } else { /* No - need to fill in a PCAP header with the appropriate * values */ /* Leave the manual copy as it is, as it gets around * some OS's having different structures in pcap_pkt_hdr */ struct timeval ts = trace_get_timeval(packet); pcap_pkt_hdr.ts.tv_sec = ts.tv_sec; pcap_pkt_hdr.ts.tv_usec = ts.tv_usec; pcap_pkt_hdr.caplen = remaining; /* trace_get_wire_length includes FCS, while pcap doesn't */ if (trace_get_link_type(packet)==TRACE_TYPE_ETH) if (trace_get_wire_length(packet) >= 4) { pcap_pkt_hdr.len = trace_get_wire_length(packet)-4; } else { pcap_pkt_hdr.len = 0; } else pcap_pkt_hdr.len = trace_get_wire_length(packet); assert(pcap_pkt_hdr.caplen<65536); assert(pcap_pkt_hdr.len<65536); pcap_dump((u_char*)OUTPUT.trace.dump, &pcap_pkt_hdr, packet->payload); } return 0; }