static int ip6_ext_quickstart(struct ip6_hdr *ip6, const scamper_probe_ipopt_t *opt, uint8_t *buf, size_t *len) { size_t off = 1; if(*len < 16) { *len = 16; return -1; } buf[off++] = 1; /* length of hop-by-hop options : 16 bytes */ /* two Pad1 options */ buf[off++] = 0; buf[off++] = 0; /* quickstart option */ buf[off++] = 0x26; buf[off++] = 6; buf[off++] = (opt->opt_qs_func << 4) | opt->opt_qs_rate; buf[off++] = opt->opt_qs_ttl; bytes_htonl(&buf[off], opt->opt_qs_nonce << 2); off += 4; /* PadN option, length 4 */ buf[off++] = 1; buf[off++] = 2; buf[off++] = 0; buf[off++] = 0; *len = off; return 0; }
static int ip6_ext_frag(struct ip6_hdr *ip6, const scamper_probe_ipopt_t *opt, uint8_t *buf, size_t *len) { /* make sure the pktbuf has at least enough space left for this */ if(*len < 8) { *len = 8; return -1; } /* the length of this header is set to zero since it is of fixed size */ buf[1] = 0; /* copy in the fragmentation value */ bytes_htons(buf+2, opt->opt_v6frag_off); bytes_htonl(buf+4, opt->opt_v6frag_id); *len = 8; return 0; }
int scamper_ip4_build(scamper_probe_t *pr, uint8_t *buf, size_t *len) { scamper_probe_ipopt_t *opt; struct ip *ip; size_t off, ip4hlen; int i, j; if(scamper_ip4_hlen(pr, &ip4hlen) != 0) return -1; if(ip4hlen > *len) { *len = ip4hlen; return -1; } ip = (struct ip *)buf; off = sizeof(struct ip); #ifndef _WIN32 ip->ip_v = 4; ip->ip_hl = (ip4hlen / 4); #else ip->ip_vhl = 0x40 | (ip4hlen / 4); #endif if((pr->pr_ip_off & IP_OFFMASK) != 0 || pr->pr_no_trans) ip->ip_len = htons(ip4hlen + pr->pr_len); else if(pr->pr_ip_proto == IPPROTO_ICMP || pr->pr_ip_proto == IPPROTO_UDP) ip->ip_len = htons(ip4hlen + 8 + pr->pr_len); else if(pr->pr_ip_proto == IPPROTO_TCP) ip->ip_len = htons(ip4hlen + scamper_tcp4_hlen(pr) + pr->pr_len); else { scamper_debug(__func__, "unimplemented pr %d", pr->pr_ip_proto); return -1; } ip->ip_tos = pr->pr_ip_tos; ip->ip_id = htons(pr->pr_ip_id); ip->ip_off = htons(pr->pr_ip_off); ip->ip_ttl = pr->pr_ip_ttl; ip->ip_p = pr->pr_ip_proto; ip->ip_sum = 0; memcpy(&ip->ip_src, pr->pr_ip_src->addr, sizeof(ip->ip_src)); memcpy(&ip->ip_dst, pr->pr_ip_dst->addr, sizeof(ip->ip_dst)); for(i=0; i<pr->pr_ipoptc; i++) { opt = &pr->pr_ipopts[i]; if(opt->type == SCAMPER_PROBE_IPOPTS_V4RR) { memset(buf+off+3, 0, 37); buf[off+0] = 7; buf[off+1] = 39; buf[off+2] = 4; off = 60; } else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSPS || opt->type == SCAMPER_PROBE_IPOPTS_V4TSO || opt->type == SCAMPER_PROBE_IPOPTS_V4TSAA) { buf[off+0] = 68; buf[off+2] = 5; if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSPS) { buf[off+1] = (opt->opt_v4tsps_ipc * 4 * 2) + 4; buf[off+3] = 3; off += 4; for(j=0; j<opt->opt_v4tsps_ipc; j++) { memcpy(buf+off, &opt->opt_v4tsps_ips[j], 4); off += 4; memset(buf+off, 0, 4); off += 4; } } else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSO) { buf[off+1] = 40; memset(buf+off+3, 0, 41); off += 40; } else if(opt->type == SCAMPER_PROBE_IPOPTS_V4TSAA) { buf[off+1] = 36; buf[off+3] = 1; memset(buf+off+4, 0, 36); off += 36; } } else if(opt->type == SCAMPER_PROBE_IPOPTS_QUICKSTART) { assert(opt->opt_qs_func <= 0xf); assert(opt->opt_qs_rate <= 0xf); buf[off+0] = 25; buf[off+1] = 8; buf[off+2] = (opt->opt_qs_func << 4) | opt->opt_qs_rate; buf[off+3] = opt->opt_qs_ttl; bytes_htonl(&buf[off+4], opt->opt_qs_nonce << 2); off += 8; } else return -1; } assert(off == ip4hlen); ip->ip_sum = in_cksum(ip, ip4hlen); *len = off; return 0; }
/** Dump the given vector to the plugin output file in binary * * @param corsaro The corsaro object associated with the vector * @param vector The vector to dump * @return 0 if the vector is dumped successfully, -1 if an error occurs */ static int binary_dump(corsaro_t *corsaro, attack_vector_t *vector) { uint8_t av_bytes[CORSARO_DOS_ATTACK_VECTOR_BYTECNT]; uint8_t *ptr = &av_bytes[0]; /* uint8_t *pkt_buf = NULL; libtrace_linktype_t linktype; uint32_t pkt_length; */ /* dump the attack vector details */ bytes_htonl(ptr, vector->target_ip); ptr+=4; bytes_htonl(ptr, kh_size(vector->attack_ip_hash)); ptr+=4; bytes_htonl(ptr, kh_size(vector->attack_ip_hash)-vector->attack_ip_cnt); ptr+=4; bytes_htonl(ptr, kh_size(vector->attack_port_hash)); ptr+=4; bytes_htonl(ptr, kh_size(vector->target_port_hash)); ptr+=4; bytes_htonll(ptr, vector->packet_cnt); ptr+=8; bytes_htonl(ptr, vector->interval_packet_cnt); ptr+=4; bytes_htonll(ptr, vector->byte_cnt); ptr+=8; bytes_htonl(ptr, vector->interval_byte_cnt); ptr+=4; bytes_htonll(ptr, vector->ppm_window.max_ppm); ptr+=8; bytes_htonl(ptr, vector->start_time.tv_sec); ptr+=4; bytes_htonl(ptr, vector->start_time.tv_usec); ptr+=4; bytes_htonl(ptr, vector->latest_time.tv_sec); ptr+=4; bytes_htonl(ptr, vector->latest_time.tv_usec); ptr+=4; /* dump the initial packet using trace_get_packet_buffer */ /* if((pkt_buf = trace_get_packet_buffer(vector->initial_packet, &linktype, NULL)) == NULL || (pkt_length = trace_get_capture_length(vector->initial_packet)) == 0) { corsaro_log(__func__, "could not get packet buffer"); return -1; } */ /* add the size of the packet to the byte array before we dump it */ bytes_htonl(ptr, vector->initial_packet_len); if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, &av_bytes[0], CORSARO_DOS_ATTACK_VECTOR_BYTECNT) != CORSARO_DOS_ATTACK_VECTOR_BYTECNT) { corsaro_log(__func__, corsaro, "could not dump vector byte array to file"); return -1; } if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, vector->initial_packet, vector->initial_packet_len) != vector->initial_packet_len) { corsaro_log(__func__, corsaro, "could not dump packet to file"); return -1; } return 0; }
/** Implements the end_interval function of the plugin API */ int corsaro_dos_end_interval(corsaro_t *corsaro, corsaro_interval_t *int_end) { int this_interval = int_end->time-STATE(corsaro)->first_interval; khiter_t i; attack_vector_t *vector; attack_vector_t **attack_arr = NULL; int attack_arr_cnt = 0; uint8_t gbuf[12]; uint8_t cntbuf[4]; if(this_interval < CORSARO_DOS_INTERVAL) { /* we haven't run for long enough to dump */ return 0; } else { /* we either have hit exactly the right amount of time, or we have gone for too long, dump now and reset the counter */ STATE(corsaro)->first_interval = int_end->time; /* fall through and continue to dump */ } /* this is an interval we care about */ /* malloc an array big enough to hold the entire hash even though we wont need it to be that big */ if((attack_arr = malloc(sizeof(attack_vector_t *)* kh_size(STATE(corsaro)->attack_hash))) == NULL) { corsaro_log(__func__, corsaro, "could not malloc array for attack vectors"); return -1; } /* classify the flows and dump the attack ones */ for(i = kh_begin(STATE(corsaro)->attack_hash); i != kh_end(STATE(corsaro)->attack_hash); ++i) { if(kh_exist(STATE(corsaro)->attack_hash, i)) { vector = kh_key(STATE(corsaro)->attack_hash, i); if(attack_vector_is_expired(vector, int_end->time) != 0) { kh_del(av, STATE(corsaro)->attack_hash, i); attack_vector_free(vector); vector = NULL; } else if(attack_vector_is_attack(corsaro, vector, int_end->time) != 0) { /* this is an attack */ /* add it to the attack array so we can know how many before we dump it */ attack_arr[attack_arr_cnt] = vector; attack_arr_cnt++; } else { attack_vector_reset(vector); } } } corsaro_io_write_interval_start(corsaro, STATE(corsaro)->outfile, &corsaro->interval_start); if(corsaro->global_file != NULL) { corsaro_io_write_plugin_start(corsaro, corsaro->global_file, PLUGIN(corsaro)); } if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_ASCII) { if(corsaro->global_file != NULL) { /* global stats */ /* dump the number of mismatched packets and vectors */ corsaro_file_printf(corsaro, corsaro->global_file, "mismatch: %"PRIu32"\n" "attack_vectors: %"PRIu32"\n" "non-attack_vectors: %"PRIu32"\n", STATE(corsaro)->number_mismatched_packets, attack_arr_cnt, kh_size(STATE(corsaro)->attack_hash) -attack_arr_cnt); } /* dump the number of vectors */ corsaro_file_printf(corsaro, STATE(corsaro)->outfile, "%"PRIu32"\n", attack_arr_cnt); /* dump the vectors */ for(i = 0; i < attack_arr_cnt; i++) { if(ascii_dump(corsaro, attack_arr[i]) != 0) { corsaro_log(__func__, corsaro, "could not dump hash"); return -1; } /* reset the interval stats */ attack_vector_reset(attack_arr[i]); } } else if(CORSARO_FILE_MODE(STATE(corsaro)->outfile) == CORSARO_FILE_MODE_BINARY) { if(corsaro->global_file != NULL) { /* global stats */ bytes_htonl(&gbuf[0], STATE(corsaro)->number_mismatched_packets); bytes_htonl(&gbuf[4], attack_arr_cnt); bytes_htonl(&gbuf[8], kh_size(STATE(corsaro)->attack_hash)-attack_arr_cnt); if(corsaro_file_write(corsaro, corsaro->global_file, &gbuf[0], 12) != 12) { corsaro_log(__func__, corsaro, "could not dump global stats to file"); return -1; } } /* dump the number of vectors */ bytes_htonl(&cntbuf[0], attack_arr_cnt); if(corsaro_file_write(corsaro, STATE(corsaro)->outfile, &cntbuf[0], 4) != 4) { corsaro_log(__func__, corsaro, "could not dump vector count to file"); return -1; } /* dump the vectors */ for(i = 0; i < attack_arr_cnt; i++) { if(binary_dump(corsaro, attack_arr[i]) != 0) { corsaro_log(__func__, corsaro, "could not dump hash"); return -1; } attack_vector_reset(attack_arr[i]); } } else { corsaro_log(__func__, corsaro, "invalid mode"); return -1; } if(corsaro->global_file != NULL) { corsaro_io_write_plugin_end(corsaro, corsaro->global_file, PLUGIN(corsaro)); } corsaro_io_write_interval_end(corsaro, STATE(corsaro)->outfile, int_end); STATE(corsaro)->number_mismatched_packets = 0; free(attack_arr); /* if we are rotating, now is when we should do it */ if(corsaro_is_rotate_interval(corsaro)) { /* close the current file */ if(STATE(corsaro)->outfile != NULL) { corsaro_file_close(corsaro, STATE(corsaro)->outfile); STATE(corsaro)->outfile = NULL; } } return 0; }