DLLEXPORT uint16_t *trace_checksum_transport(libtrace_packet_t *packet, uint16_t *csum) { void *header = NULL; uint16_t ethertype; uint32_t remaining; uint32_t sum = 0; uint8_t proto = 0; uint16_t *csum_ptr = NULL; int plen = 0; uint8_t safety[65536]; uint8_t *ptr = safety; header = trace_get_layer3(packet, ðertype, &remaining); if (header == NULL) return NULL; if (ethertype == TRACE_ETHERTYPE_IP) { libtrace_ip_t *ip = (libtrace_ip_t *)header; if (remaining < sizeof(libtrace_ip_t)) return NULL; sum = ipv4_pseudo_checksum(ip); } else if (ethertype == TRACE_ETHERTYPE_IPV6) { libtrace_ip6_t *ip = (libtrace_ip6_t *)header; if (remaining < sizeof(libtrace_ip6_t)) return 0; sum = ipv6_pseudo_checksum(ip); } header = trace_get_transport(packet, &proto, &remaining); if (proto == TRACE_IPPROTO_TCP) { libtrace_tcp_t *tcp = (libtrace_tcp_t *)header; header = trace_get_payload_from_tcp(tcp, &remaining); csum_ptr = &tcp->check; memcpy(ptr, tcp, tcp->doff * 4); tcp = (libtrace_tcp_t *)ptr; tcp->check = 0; ptr += (tcp->doff * 4); } else if (proto == TRACE_IPPROTO_UDP) { libtrace_udp_t *udp = (libtrace_udp_t *)header; header = trace_get_payload_from_udp(udp, &remaining); csum_ptr = &udp->check; memcpy(ptr, udp, sizeof(libtrace_udp_t)); udp = (libtrace_udp_t *)ptr; udp->check = 0; ptr += sizeof(libtrace_udp_t); } else if (proto == TRACE_IPPROTO_ICMP) { /* ICMP doesn't use the pseudo header */ sum = 0; libtrace_icmp_t *icmp = (libtrace_icmp_t *)header; header = trace_get_payload_from_icmp(icmp, &remaining); csum_ptr = &icmp->checksum; memcpy(ptr, icmp, sizeof(libtrace_icmp_t)); icmp = (libtrace_icmp_t *)ptr; icmp->checksum = 0; ptr += sizeof(libtrace_icmp_t); } else { return NULL; } sum += add_checksum(safety, (uint16_t)(ptr - safety)); plen = trace_get_payload_length(packet); if (plen < 0) return NULL; if (remaining < (uint32_t)plen) return NULL; if (header == NULL) return NULL; sum += add_checksum(header, (uint16_t)plen); *csum = ntohs(finish_checksum(sum)); //assert(0); return csum_ptr; }
/** 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; }