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, &params_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_dealias_write(const scamper_file_t *sf,
				     const scamper_dealias_t *dealias)
{
  static int (*const state[])(const scamper_file_t *, const void *,
			      warts_dealias_data_t *, warts_addrtable_t *,
			      uint32_t *) = {
    warts_dealias_mercator_state,
    warts_dealias_ally_state,    
    warts_dealias_radargun_state,
    warts_dealias_prefixscan_state,
    warts_dealias_bump_state,
  };
  static void (*const write[])(const void *, const scamper_file_t *,
			       warts_addrtable_t *, uint8_t *, uint32_t *,
			       const uint32_t, warts_dealias_data_t *) = {
    warts_dealias_mercator_write,
    warts_dealias_ally_write,
    warts_dealias_radargun_write,
    warts_dealias_prefixscan_write,
    warts_dealias_bump_write,
  };
  uint8_t                 *buf = NULL;
  uint8_t                  flags[dealias_vars_mfb];
  uint16_t                 flags_len, params_len;
  scamper_dealias_probe_t *probe;
  warts_dealias_data_t     data;
  warts_dealias_probe_t   *probes = NULL;
  uint32_t                 len, len2, off = 0;
  size_t                   size;
  uint32_t                 i;
  warts_addrtable_t        table;

  memset(&data, 0, sizeof(data));
  memset(&table, 0, sizeof(table));

  /* figure out which dealias data items we'll store in this record */
  warts_dealias_params(dealias, flags, &flags_len, &params_len);
  len = 8 + flags_len + params_len + 2;

  /* figure out the state that we have to allocate */
  if(state[dealias->method-1](sf, dealias->data, &data, &table, &len) != 0)
     {
       goto err;
     }

  /*
   * figure out the state that we have to allocate to store the
   * probes sent (and their responses)
   */
  if(dealias->probec > 0)
    {
      size = dealias->probec * sizeof(warts_dealias_probe_t);
      if((probes = (warts_dealias_probe_t *)malloc_zero(size)) == NULL)
	{
	  goto err;
	}

      for(i=0; i<dealias->probec; i++)
	{
	  probe = dealias->probes[i];
	  len2 = len;
	  if(warts_dealias_probe_state(sf,probe,&probes[i],&table,&len2) != 0)
	    goto err;
	  if(len2 < len)
	    goto err;
	  len = len2;
	}
    }

  if((buf = malloc(len)) == NULL)
    goto err;
  insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_DEALIAS);

  if(warts_dealias_params_write(dealias, sf, buf, &off, len,
				flags, flags_len, params_len) != 0)
    {
      goto err;
    }

  write[dealias->method-1](dealias->data, sf, &table, buf, &off, len, &data);

  if(data.probedefs != NULL)
    free(data.probedefs);
  data.probedefs = NULL;

  if(dealias->probec > 0)
    {
      for(i=0; i<dealias->probec; i++)
	{
	  probe = dealias->probes[i];
	  warts_dealias_probe_write(probe,sf,&table,buf,&off, len, &probes[i]);
	}
    }

  warts_dealias_probes_free(probes, dealias->probec);
  probes = 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(probes != NULL) warts_dealias_probes_free(probes, dealias->probec);
  if(data.probedefs != NULL) free(data.probedefs);
  if(buf != NULL) free(buf);
  return -1;
}
int scamper_file_warts_tracelb_write(const scamper_file_t *sf,
				     const scamper_tracelb_t *trace)
{
  const scamper_tracelb_node_t *node;
  const scamper_tracelb_link_t *link;
  uint8_t                      *buf = NULL;
  uint32_t                      off = 0, len, len2;
  uint8_t                       trace_flags[tracelb_vars_mfb];
  uint16_t                      trace_flags_len, trace_params_len;
  warts_tracelb_node_t         *node_state = NULL;
  warts_tracelb_link_t         *link_state = NULL;
  size_t                        size;
  int                           i;
  warts_addrtable_t             table;

  /* make sure the table is nulled out */
  memset(&table, 0, sizeof(table));

  /* figure out which tracelb data items we'll store in this record */
  warts_tracelb_params(trace, &table, trace_flags, &trace_flags_len,
		       &trace_params_len);

  /* this represents the length of the trace's flags and parameters */
  len = 8 + trace_flags_len + trace_params_len;
  if(trace_params_len != 0) len += 2;

  /* record the node records */
  if(trace->nodec > 0)
    {
      size = trace->nodec * sizeof(warts_tracelb_node_t);
      if((node_state = (warts_tracelb_node_t *)malloc_zero(size)) == NULL)
	{
	  goto err;
	}

      for(i=0; i<trace->nodec; i++)
	{
	  len2 = len;
	  node = trace->nodes[i];
	  if(warts_tracelb_node_state(sf, node, &table, &node_state[i],
				      &len2) != 0)
	    {
	      goto err;
	    }

	  /* check for wrapping */
	  if(len2 < len)
	    goto err;
	  len = len2;
	}
    }

  /* record the link records */
  if(trace->linkc > 0)
    {
      size = trace->linkc * sizeof(warts_tracelb_link_t);
      if((link_state = (warts_tracelb_link_t *)malloc_zero(size)) == NULL)
	{
	  goto err;
	}

      for(i=0; i<trace->linkc; i++)
	{
	  len2 = len;
	  link = trace->links[i];
	  if(warts_tracelb_link_state(sf, trace, link, &link_state[i],
				      &table, &len2) != 0)
	    {
	      goto err;
	    }

	  /* check for wrapping */
	  if(len2 < len)
	    goto err;
	  len = len2;
	}
    }

  if((buf = malloc_zero(len)) == NULL)
    {
      goto err;
    }

  insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_TRACELB);

  /* write trace params */
  if(warts_tracelb_params_write(trace, sf, &table, buf, &off, len, trace_flags,
				trace_flags_len, trace_params_len) != 0)
    {
      goto err;
    }

  /* write trace nodes */
  for(i=0; i<trace->nodec; i++)
    {
      warts_tracelb_node_write(trace->nodes[i], &node_state[i], &table,
			       buf, &off, len);
    }
  if(node_state != NULL)
    {
      free(node_state);
      node_state = NULL;
    }

  /* write trace links */
  for(i=0; i<trace->linkc; i++)
    {
      link = trace->links[i];
      warts_tracelb_link_write(link, &link_state[i], &table, buf, &off, len);
      warts_tracelb_link_free(&link_state[i]);
    }
  if(link_state != NULL)
    {
      free(link_state);
      link_state = NULL;
    }

  assert(off == len);

  if(warts_write(sf, buf, off) == -1)
    {
      goto err;
    }

  warts_addrtable_clean(&table);
  free(buf);
  return 0;

 err:
  warts_addrtable_clean(&table);
  if(node_state != NULL) free(node_state);
  if(link_state != NULL) free(link_state);
  if(buf != NULL) free(buf);
  return -1;
}
Exemple #4
0
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, &params_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;
}
int scamper_file_warts_neighbourdisc_write(const scamper_file_t *sf,
					   const scamper_neighbourdisc_t *nd)
{
  warts_addrtable_t table;
  warts_neighbourdisc_probe_t *probes = NULL;
  scamper_neighbourdisc_probe_t *probe;
  uint8_t *buf = NULL;
  uint8_t  flags[neighbourdisc_vars_mfb];
  uint16_t flags_len, params_len;
  uint32_t len, len2, off = 0;
  size_t   size;
  int      i;

  memset(&table, 0, sizeof(table));

  /* figure out which neighbourdisc items we'll store in this record */
  warts_neighbourdisc_params(nd, &table, flags, &flags_len, &params_len);
  len = 8 + flags_len + params_len + 2;

  if(nd->probec > 0)
    {
      size = nd->probec * sizeof(warts_neighbourdisc_probe_t);
      if((probes = (warts_neighbourdisc_probe_t *)malloc_zero(size)) == NULL)
	goto err;

      for(i=0; i<nd->probec; i++)
	{
	  probe = nd->probes[i];
	  len2 = len;
	  if(warts_neighbourdisc_probe_state(sf, probe, &probes[i], &table,
					     &len2) != 0)
	    goto err;
	  if(len2 < len)
	    goto err;
	  len = len2;
	}
    }

  if((buf = malloc(len)) == NULL)
    goto err;
  insert_wartshdr(buf, &off, len, SCAMPER_FILE_OBJ_NEIGHBOURDISC);

  if(warts_neighbourdisc_params_write(nd, sf, &table, buf, &off, len,
				      flags, flags_len, params_len) != 0)
    {
      goto err;
    }

  if(nd->probec > 0)
    {
      for(i=0; i<nd->probec; i++)
	{
	  probe = nd->probes[i];
	  warts_neighbourdisc_probe_write(probe, sf, &table, buf, &off, len,
					  &probes[i]);
	}
    }

  warts_neighbourdisc_probes_free(probes, nd->probec);
  probes = 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(probes != NULL) warts_neighbourdisc_probes_free(probes, nd->probec);
  if(buf != NULL) free(buf);
  return -1;
}