static void warts_trace_pmtud_write(const scamper_trace_t *trace, uint8_t *buf, uint32_t *off, uint32_t len, warts_trace_pmtud_t *state, warts_addrtable_t *table) { warts_param_writer_t handlers[] = { {&trace->pmtud->ifmtu, (wpw_t)insert_uint16, NULL}, {&trace->pmtud->pmtu, (wpw_t)insert_uint16, NULL}, {&trace->pmtud->outmtu, (wpw_t)insert_uint16, NULL}, {&trace->pmtud->ver, (wpw_t)insert_byte, NULL}, {&trace->pmtud->notec, (wpw_t)insert_byte, NULL}, }; const int handler_cnt = sizeof(handlers)/sizeof(warts_param_writer_t); uint16_t u16; uint8_t u8; warts_params_write(buf, off, len, state->flags, state->flags_len, state->params_len, handlers, handler_cnt); /* write the number of hop records */ insert_uint16(buf, off, len, &state->hopc, NULL); /* write the hop records */ for(u16=0; u16<state->hopc; u16++) warts_trace_hop_write(&state->hops[u16], table, buf, off, len); /* write the notes */ for(u8=0; u8<trace->pmtud->notec; u8++) warts_trace_pmtud_n_write(trace->pmtud->notes[u8], buf, off, len, &state->notes[u8]); return; }
static void insert_dealias_prefixscan_xs(uint8_t *buf, uint32_t *off, const uint32_t len, const scamper_dealias_prefixscan_t *p, void *param) { uint16_t i; i = htons(p->xc); insert_uint16(buf, off, len, &i, NULL); for(i=0; i<p->xc; i++) insert_addr(buf, off, len, p->xs[i], param); return; }
int scamper_file_warts_ping_write(const scamper_file_t *sf, const scamper_ping_t *ping) { warts_addrtable_t table; warts_ping_reply_t *reply_state = NULL; scamper_ping_reply_t *reply; uint8_t *buf = NULL; uint8_t flags[ping_vars_mfb]; uint16_t flags_len, params_len; uint32_t len, off = 0; uint16_t reply_count; size_t size; int i, j; memset(&table, 0, sizeof(table)); /* figure out which ping data items we'll store in this record */ warts_ping_params(ping, &table, flags, &flags_len, ¶ms_len); /* length of the ping's flags, parameters, and number of reply records */ len = 8 + flags_len + 2 + params_len + 2; if((reply_count = scamper_ping_reply_count(ping)) > 0) { size = reply_count * sizeof(warts_ping_reply_t); if((reply_state = (warts_ping_reply_t *)malloc_zero(size)) == NULL) { goto err; } for(i=0, j=0; i<ping->ping_sent; i++) { for(reply=ping->ping_replies[i]; reply != NULL; reply = reply->next) { if(warts_ping_reply_state(sf, ping, reply, &reply_state[j++], &table, &len) == -1) { goto err; } } } } if((buf = malloc(len)) == NULL) { goto err; } insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_PING); if(warts_ping_params_write(ping, sf, &table, buf, &off, len, flags, flags_len, params_len) == -1) { goto err; } /* reply record count */ insert_uint16(buf, &off, len, &reply_count, NULL); /* write each ping reply record */ for(i=0; i<reply_count; i++) { warts_ping_reply_write(&reply_state[i], &table, buf, &off, len); } if(reply_state != NULL) { free(reply_state); reply_state = NULL; } assert(off == len); if(warts_write(sf, buf, len) == -1) { goto err; } warts_addrtable_clean(&table); free(buf); return 0; err: warts_addrtable_clean(&table); if(reply_state != NULL) free(reply_state); if(buf != NULL) free(buf); return -1; }
int scamper_file_warts_trace_write(const scamper_file_t *sf, const scamper_trace_t *trace) { scamper_trace_hop_t *hop; uint8_t *buf = NULL; uint8_t trace_flags[trace_vars_mfb]; uint16_t trace_flags_len, trace_params_len; warts_trace_hop_t *hop_state = NULL; uint16_t hop_recs; warts_trace_pmtud_t *pmtud = NULL; warts_trace_hop_t *ld_state = NULL; uint16_t ld_recs = 0; uint32_t ld_len = 0; warts_trace_dtree_t dtree_state; uint16_t u16; uint8_t u8; uint32_t off = 0, len, len2; size_t size; int i, j; warts_addrtable_t *table = NULL; memset(&dtree_state, 0, sizeof(dtree_state)); if((table = warts_addrtable_alloc_byaddr()) == NULL) goto err; /* figure out which trace data items we'll store in this record */ warts_trace_params(trace, table, trace_flags, &trace_flags_len, &trace_params_len); /* * this represents the length of the trace's flags and parameters, and the * 2-byte field that records the number of hop records that follow */ len = 8 + trace_flags_len + trace_params_len + 2; if(trace_params_len != 0) len += 2; /* for each hop, figure out what is going to be stored in this record */ if((hop_recs = scamper_trace_hop_count(trace)) > 0) { size = hop_recs * sizeof(warts_trace_hop_t); if((hop_state = (warts_trace_hop_t *)malloc_zero(size)) == NULL) { goto err; } for(i=0, j=0; i<trace->hop_count; i++) { for(hop = trace->hops[i]; hop != NULL; hop = hop->hop_next) { /* record basic hop state */ len2 = len; warts_trace_hop_state(trace,hop,&hop_state[j++],table,&len2); if(len2 < len) goto err; len = len2; } } } /* figure out how much space we need for PMTUD data, if we have it */ if(trace->pmtud != NULL) { if((pmtud = malloc_zero(sizeof(warts_trace_pmtud_t))) == NULL) goto err; if(warts_trace_pmtud_state(trace, pmtud, table) != 0) goto err; len += (2 + pmtud->len); /* 2 = size of attribute header */ } if(trace->lastditch != NULL) { /* count the number of last-ditch hop records */ ld_recs = scamper_trace_lastditch_hop_count(trace); /* allocate an array of hop state structs for the lastditch hops */ size = ld_recs * sizeof(warts_trace_hop_t); if((ld_state = (warts_trace_hop_t *)malloc_zero(size)) == NULL) goto err; /* need to record count of lastditch hops and a single zero flags byte */ ld_len = 3; /* record hop state for each lastditch reply */ for(hop = trace->lastditch, j=0; hop != NULL; hop = hop->hop_next) warts_trace_hop_state(trace, hop, &ld_state[j++], table, &ld_len); len += (2 + ld_len); /* 2 = size of attribute header */ } if(trace->dtree != NULL) { /* figure out what the structure of the dtree header looks like */ if(warts_trace_dtree_params(sf, trace, table, &dtree_state) != 0) goto err; /* 2 = size of attribute header */ len += (2 + dtree_state.len); } len += 2; /* EOF */ if((buf = malloc_zero(len)) == NULL) { goto err; } insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_TRACE); /* write trace parameters */ if(warts_trace_params_write(trace, sf, table, buf, &off, len, trace_flags, trace_flags_len, trace_params_len) == -1) { goto err; } /* hop record count */ insert_uint16(buf, &off, len, &hop_recs, NULL); /* write each traceroute hop record */ for(i=0; i<hop_recs; i++) warts_trace_hop_write(&hop_state[i], table, buf, &off, len); if(hop_state != NULL) free(hop_state); hop_state = NULL; /* write the PMTUD data */ if(pmtud != NULL) { /* write the attribute header */ u16 = WARTS_TRACE_ATTR_HDR(WARTS_TRACE_ATTR_PMTUD, pmtud->len); insert_uint16(buf, &off, len, &u16, NULL); /* write details of the pmtud measurement */ warts_trace_pmtud_write(trace, buf, &off, len, pmtud, table); warts_trace_pmtud_free(pmtud); pmtud = NULL; } /* write the last-ditch data */ if(trace->lastditch != NULL) { /* write the attribute header */ u16 = WARTS_TRACE_ATTR_HDR(WARTS_TRACE_ATTR_LASTDITCH, ld_len); insert_uint16(buf, &off, len, &u16, NULL); /* write the last-ditch flags: currently zero */ u8 = 0; insert_byte(buf, &off, len, &u8, NULL); /* write the number of hop records */ insert_uint16(buf, &off, len, &ld_recs, NULL); for(i=0; i<ld_recs; i++) warts_trace_hop_write(&ld_state[i], table, buf, &off, len); free(ld_state); ld_state = NULL; } /* write doubletree data */ if(trace->dtree != NULL) { u16 = WARTS_TRACE_ATTR_HDR(WARTS_TRACE_ATTR_DTREE, dtree_state.len); insert_uint16(buf, &off, len, &u16, NULL); /* write details of the pmtud measurement */ warts_trace_dtree_write(trace, table, buf, &off, len, &dtree_state); } /* write the end of trace attributes header */ u16 = WARTS_TRACE_ATTR_EOF; insert_uint16(buf, &off, len, &u16, NULL); assert(off == len); if(warts_write(sf, buf, len) == -1) { goto err; } warts_addrtable_free(table); free(buf); return 0; err: if(table != NULL) warts_addrtable_free(table); if(buf != NULL) free(buf); if(hop_state != NULL) free(hop_state); if(pmtud != NULL) warts_trace_pmtud_free(pmtud); if(ld_state != NULL) free(ld_state); return -1; }
/* Write data from a scamper tbit object to a warts file */ int scamper_file_warts_tbit_write(const scamper_file_t *sf, const scamper_tbit_t *tbit) { warts_addrtable_t table; warts_tbit_pkt_t *pkts = NULL; warts_tbit_pmtud_t pmtud; warts_tbit_null_t null; warts_tbit_app_http_t http; uint8_t *buf = NULL; uint8_t flags[tbit_vars_mfb]; uint16_t junk16; uint16_t flags_len, params_len; uint32_t len, i, off = 0; size_t size; memset(&table, 0, sizeof(table)); /* Set the tbit data (not including the packets) */ warts_tbit_params(tbit, &table, flags, &flags_len, ¶ms_len); len = 8 + flags_len + params_len + 2; if(tbit->pktc > 0) { /* Allocate memory for the state */ size = tbit->pktc * sizeof(warts_tbit_pkt_t); if((pkts = (warts_tbit_pkt_t *)malloc_zero(size)) == NULL) goto err; for(i=0; i<tbit->pktc; i++) warts_tbit_pkt_params(tbit->pkts[i], &pkts[i], &len); } if(tbit->data != NULL) { switch(tbit->type) { case SCAMPER_TBIT_TYPE_PMTUD: warts_tbit_pmtud_params(tbit, &table, &pmtud); len += (2 + 4 + pmtud.len); break; case SCAMPER_TBIT_TYPE_NULL: warts_tbit_null_params(tbit, &null); len += (2 + 4 + null.len); break; default: goto err; } } if(tbit->app_data != NULL) { if(tbit->app_proto == SCAMPER_TBIT_APP_HTTP) { warts_tbit_app_http_params(tbit, &http); len += (2 + 4 + http.len); } else goto err; } /* struct eof */ len += 2; /* Allocate memory to store all of the data (including packets) */ if((buf = malloc(len)) == NULL) goto err; insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_TBIT); /* Write the tbit data (excluding packets) to the buffer */ if(warts_tbit_params_write(tbit, sf, &table, buf, &off, len, flags, flags_len, params_len) != 0) { goto err; } if(tbit->pktc > 0) { for(i=0; i<tbit->pktc; i++) warts_tbit_pkt_write(tbit->pkts[i], sf, buf, &off, len, &pkts[i]); free(pkts); pkts = NULL; } if(tbit->data != NULL) { junk16 = WARTS_TBIT_STRUCT_TYPE; insert_uint16(buf, &off, len, &junk16, NULL); switch(tbit->type) { case SCAMPER_TBIT_TYPE_PMTUD: insert_uint32(buf, &off, len, &pmtud.len, NULL); warts_tbit_pmtud_write(tbit, buf, &off, len, &table, &pmtud); break; case SCAMPER_TBIT_TYPE_NULL: insert_uint32(buf, &off, len, &null.len, NULL); warts_tbit_null_write(tbit, buf, &off, len, &null); break; default: goto err; } } if(tbit->app_data != NULL) { junk16 = WARTS_TBIT_STRUCT_APP; insert_uint16(buf, &off, len, &junk16, NULL); if(tbit->app_proto == SCAMPER_TBIT_APP_HTTP) { insert_uint32(buf, &off, len, &http.len, NULL); warts_tbit_app_http_write(tbit, buf, &off, len, &http); } else goto err; } junk16 = WARTS_TBIT_STRUCT_EOF; insert_uint16(buf, &off, len, &junk16, NULL); assert(off == len); /* Write the whole buffer to a warts file */ if(warts_write(sf, buf, len) == -1) goto err; warts_addrtable_clean(&table); free(buf); return 0; err: warts_addrtable_clean(&table); if(pkts != NULL) free(pkts); if(buf != NULL) free(buf); return -1; }