/*
* scamper_trace.c
*
* $Id: scamper_trace.c,v 1.62 2007/11/02 22:26:54 mjl Exp $
*
* Copyright (C) 2003-2007 The University of Waikato
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#if defined(__APPLE__)
#include <stdint.h>
#endif
#if defined(DMALLOC)
#include <dmalloc.h>
#endif
#include "scamper_addr.h"
#include "scamper_list.h"
#include "scamper_tlv.h"
#include "scamper_trace.h"
#include "utils.h"
int scamper_trace_pmtud_alloc(scamper_trace_t *trace)
{
if((trace->pmtud = malloc_zero(sizeof(scamper_trace_pmtud_t))) == NULL)
{
return -1;
}
return 0;
}
void scamper_trace_pmtud_free(scamper_trace_t *trace)
{
scamper_trace_hop_t *hop, *hop_next;
if(trace->pmtud != NULL)
{
hop = trace->pmtud->hops;
while(hop != NULL)
{
hop_next = hop->hop_next;
scamper_trace_hop_free(hop);
hop = hop_next;
}
if(trace->pmtud->tlvs != NULL)
{
scamper_tlv_free(trace->pmtud->tlvs);
}
free(trace->pmtud);
trace->pmtud = NULL;
}
return;
}
int scamper_trace_pmtud_hop_count(const scamper_trace_t *trace)
{
scamper_trace_hop_t *hop;
int count = 0;
if(trace == NULL || trace->pmtud == NULL)
{
return -1;
}
for(hop = trace->pmtud->hops; hop != NULL; hop = hop->hop_next)
{
count++;
}
return count;
}
int scamper_trace_hops_alloc(scamper_trace_t *trace, const int hops)
{
scamper_trace_hop_t **h;
size_t size;
size = sizeof(scamper_trace_hop_t *) * hops;
if(trace->hops == NULL)
{
h = (scamper_trace_hop_t **)malloc_zero(size);
}
else
{
h = (scamper_trace_hop_t **)realloc(trace->hops, size);
}
if(h != NULL)
{
trace->hops = h;
return 0;
}
return -1;
}
void scamper_trace_hop_free(scamper_trace_hop_t *hop)
{
if(hop != NULL)
{
scamper_tlv_free(hop->hop_tlvs);
scamper_addr_free(hop->hop_addr);
free(hop);
}
return;
}
scamper_trace_hop_t *scamper_trace_hop_alloc()
{
scamper_trace_hop_t *hop;
if((hop = malloc_zero(sizeof(struct scamper_trace_hop))) == NULL)
{
return NULL;
}
return hop;
}
int scamper_trace_hop_count(const scamper_trace_t *trace)
{
scamper_trace_hop_t *hop;
int i, hops = 0;
for(i=0; i<trace->hop_count; i++)
{
for(hop = trace->hops[i]; hop != NULL; hop = hop->hop_next)
{
hops++;
}
}
return hops;
}
/*
* scamper_trace_addr
*
* return the target address of the traceroute. the caller doesn't know
* that this is a trace structure, they merely get passed the address
* of this function.
*/
scamper_addr_t *scamper_trace_addr(const void *va)
{
return ((const scamper_trace_t *)va)->dst;
}
const char *scamper_trace_type_tostr(const scamper_trace_t *trace)
{
switch(trace->type)
{
case SCAMPER_TRACE_TYPE_UDP: return "udp";
case SCAMPER_TRACE_TYPE_UDP_PARIS: return "udp-paris";
case SCAMPER_TRACE_TYPE_ICMP_ECHO: return "icmp-echo";
case SCAMPER_TRACE_TYPE_ICMP_ECHO_PARIS: return "icmp-echo-paris";
case SCAMPER_TRACE_TYPE_TCP: return "tcp";
}
return NULL;
}
/*
* scamper_trace_probe_headerlen
*
* return the length of headers sent on probe packets with this trace
*/
int scamper_trace_probe_headerlen(const scamper_trace_t *trace)
{
int len;
switch(trace->dst->type)
{
case SCAMPER_ADDR_TYPE_IPV4:
len = 20;
break;
case SCAMPER_ADDR_TYPE_IPV6:
len = 40;
break;
default:
return -1;
}
switch(trace->type)
{
case SCAMPER_TRACE_TYPE_UDP:
case SCAMPER_TRACE_TYPE_UDP_PARIS:
len += 8;
break;
case SCAMPER_TRACE_TYPE_ICMP_ECHO:
case SCAMPER_TRACE_TYPE_ICMP_ECHO_PARIS:
len += (1 + 1 + 2 + 2 + 2);
break;
case SCAMPER_TRACE_TYPE_TCP:
len += 20;
break;
default:
return -1;
}
return len;
}
uint16_t scamper_trace_pathlength(const scamper_trace_t *trace)
{
uint16_t i=0, max = 0;
for(i=0; i != trace->hop_count; i++)
{
if(trace->hops[i] != NULL)
max = i;
}
return max;
}
/*
* scamper_trace_free
*
*/
void scamper_trace_free(scamper_trace_t *trace)
{
scamper_trace_hop_t *hop, *hop_next;
int i;
if(trace == NULL) return;
if(trace->hops != NULL)
{
for(i=0; i<trace->hop_count; i++)
{
hop = trace->hops[i];
while(hop != NULL)
{
hop_next = hop->hop_next;
scamper_trace_hop_free(hop);
hop = hop_next;
}
}
free(trace->hops);
}
scamper_trace_pmtud_free(trace);
if(trace->tlvs != NULL) scamper_tlv_free(trace->tlvs);
if(trace->dst != NULL) scamper_addr_free(trace->dst);
if(trace->src != NULL) scamper_addr_free(trace->src);
if(trace->cycle != NULL) scamper_cycle_free(trace->cycle);
if(trace->list != NULL) scamper_list_free(trace->list);
free(trace);
return;
}
/*
* scamper_trace_alloc
*
* allocate the trace and all the possibly necessary data fields
*/
scamper_trace_t *scamper_trace_alloc()
{
return (struct scamper_trace *)malloc_zero(sizeof(struct scamper_trace));
}
syntax highlighted by Code2HTML, v. 0.9.1