/*
* scamper_trace.h
*
* $Id: scamper_trace.h,v 1.87 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
*
*/
#ifndef __SCAMPER_TRACE_H
#define __SCAMPER_TRACE_H
#define SCAMPER_TRACE_STOP_NONE 0x00 /* null reason */
#define SCAMPER_TRACE_STOP_COMPLETED 0x01 /* got an ICMP port unreach */
#define SCAMPER_TRACE_STOP_UNREACH 0x02 /* got an other ICMP unreach code */
#define SCAMPER_TRACE_STOP_ICMP 0x03 /* got an ICMP msg, not unreach */
#define SCAMPER_TRACE_STOP_LOOP 0x04 /* loop detected */
#define SCAMPER_TRACE_STOP_DEAD 0x05 /* unresponsive target */
#define SCAMPER_TRACE_STOP_ERROR 0x06 /* sendto error */
#define SCAMPER_TRACE_STOP_HOPLIMIT 0x07 /* hoplimit reached */
#define SCAMPER_TRACE_FLAG_ALLATTEMPTS 0x01 /* send all allotted attempts */
#define SCAMPER_TRACE_FLAG_PMTUD 0x02 /* conduct PMTU discovery */
#define SCAMPER_TRACE_FLAG_DL 0x04 /* datalink for TX timestamps */
#define SCAMPER_TRACE_FLAG_GAPCONT 0x08 /* continue probing past gap */
#define SCAMPER_TRACE_TYPE_ICMP_ECHO 0x01 /* ICMP echo requests */
#define SCAMPER_TRACE_TYPE_UDP 0x02 /* UDP to unused ports */
#define SCAMPER_TRACE_TYPE_TCP 0x03 /* TCP SYN packets */
#define SCAMPER_TRACE_TYPE_ICMP_ECHO_PARIS 0x04 /* paris traceroute */
#define SCAMPER_TRACE_TYPE_UDP_PARIS 0x05 /* paris traceroute */
#define SCAMPER_TRACE_HOP_IS_ICMP_TTL_EXP(hop) ( \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 11) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 3))
#define SCAMPER_TRACE_HOP_IS_ICMP_TTL_EXP_TRANS(hop) ( \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 11 && hop->hop_icmp_code == 0) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 3 && hop->hop_icmp_code == 0))
#define SCAMPER_TRACE_HOP_IS_ICMP_PACKET_TOO_BIG(hop) (\
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 3 && hop->hop_icmp_code == 4) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 2))
#define SCAMPER_TRACE_HOP_IS_ICMP_UNREACH(hop) ( \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 3) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 1))
#define SCAMPER_TRACE_HOP_IS_ICMP_UNREACH_PORT(hop) ( \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 3 && hop->hop_icmp_code == 3) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 1 && hop->hop_icmp_code == 4))
#define SCAMPER_TRACE_HOP_IS_ICMP_ECHO_REPLY(hop) ( \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV4 && \
hop->hop_icmp_type == 0) || \
(hop->hop_addr->type == SCAMPER_ADDR_TYPE_IPV6 && \
hop->hop_icmp_type == 129))
/*
* hop TLV types:
* these items are stored conditionally in the hop data structure as needed.
*/
#define SCAMPER_TRACE_HOP_TLV_REPLY_IPID 0x01 /* 2 bytes */
#define SCAMPER_TRACE_HOP_TLV_REPLY_IPTOS 0x02 /* 1 byte */
#define SCAMPER_TRACE_HOP_TLV_NHMTU 0x03 /* 2 bytes */
#define SCAMPER_TRACE_HOP_TLV_INNER_IPLEN 0x04 /* 2 bytes */
#define SCAMPER_TRACE_HOP_TLV_INNER_IPTTL 0x05 /* 1 byte */
/*
* scamper hop flags:
* these flags give extra meaning to fields found in the hop structure
* by default.
*/
#define SCAMPER_TRACE_HOP_FLAG_TS_SOCK_RX 0x01 /* socket rx timestamp */
#define SCAMPER_TRACE_HOP_FLAG_TS_DL_TX 0x02 /* datalink tx timestamp */
#define SCAMPER_TRACE_HOP_FLAG_TS_DL_RX 0x04 /* datalink rx timestamp */
#define SCAMPER_TRACE_HOP_FLAG_TS_TSC 0x08 /* rtt computed w/ tsc clock */
#define SCAMPER_TRACE_HOP_FLAG_REPLY_TTL 0x10 /* reply ttl included */
#define SCAMPER_TRACE_HOP_FLAG_TCP 0x20 /* reply is TCP */
/*
* this macro is a more convenient way to check that the hop record
* has both the tx and rx timestamps from the datalink for computing the
* RTT
*/
#define SCAMPER_TRACE_HOP_FLAG_DL_RTT(hop) \
((hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_TX) && \
(hop->hop_flags & SCAMPER_TRACE_HOP_FLAG_TS_DL_RX))
/*
* pmtud TLV types:
* these items are stored conditionally in the PMTUD data structure as
* needed.
*/
#define SCAMPER_TRACE_PMTUD_TLV_OUTMTU 0x01 /* 2 bytes */
/* forward declare the TLV structure */
struct scamper_tlv;
/*
* scamper_trace_hop:
*/
typedef struct scamper_trace_hop
{
/* the address of the hop that responded */
scamper_addr_t *hop_addr;
/* flags defined by SCAMPER_TRACE_HOP_FLAG_* */
uint8_t hop_flags;
/*
* probe_id: the attempt # this probe is in response to [count from 0]
* probe_ttl: the ttl that we sent to the trace->dst
* probe_size: the size of the probe we sent
* reply_size: the size of the icmp response we received
* reply_ttl: the ttl of the reply packet
*/
uint8_t hop_probe_id;
uint8_t hop_probe_ttl;
uint8_t hop_reply_ttl;
uint16_t hop_probe_size;
uint16_t hop_reply_size;
/* icmp type / code returned by this hop */
union
{
struct hop_icmp
{
uint8_t hop_icmp_type;
uint8_t hop_icmp_code;
} icmp;
struct hop_tcp
{
uint8_t hop_tcp_flags;
} tcp;
} hop_un;
/* time elapsed between sending the probe and receiving this resp */
struct timeval hop_rtt;
/* any data items to store conditionally */
struct scamper_tlv *hop_tlvs;
struct scamper_trace_hop *hop_next;
} scamper_trace_hop_t;
#define hop_icmp_type hop_un.icmp.hop_icmp_type
#define hop_icmp_code hop_un.icmp.hop_icmp_code
#define hop_tcp_flags hop_un.tcp.hop_tcp_flags
typedef struct scamper_trace_pmtud
{
uint16_t ifmtu; /* the outgoing interface's MTU */
uint16_t pmtu; /* the packet size we reached the target with */
scamper_trace_hop_t *hops; /* list of hops that returned icmp messages */
struct scamper_tlv *tlvs; /* any data items to store conditionally */
} scamper_trace_pmtud_t;
/*
* scamper_trace:
* a trace structure contains enough state for scamper to probe a series
* of traces concurrently.
*/
typedef struct scamper_trace
{
/* the current list, cycle, and defaults */
scamper_list_t *list;
scamper_cycle_t *cycle;
/* source and destination addresses of the trace */
scamper_addr_t *src;
scamper_addr_t *dst;
/* when the trace commenced */
struct timeval start;
/* hops array, number of valid hops specified by hop_count */
scamper_trace_hop_t **hops;
uint16_t hop_count;
/* why the trace finished */
uint8_t stop_reason;
uint8_t stop_data;
/* trace parameters */
uint8_t type;
uint8_t flags;
uint8_t attempts;
uint8_t hoplimit;
uint8_t gaplimit;
uint8_t firsthop;
uint8_t tos;
uint8_t wait;
uint8_t loops;
uint16_t probe_size;
uint16_t sport;
uint16_t dport;
/* anything optional to store with the trace */
struct scamper_tlv *tlvs;
/* if we perform PMTU discovery on the trace, then record the data here */
scamper_trace_pmtud_t *pmtud;
} scamper_trace_t;
/*
* scamper_trace_alloc:
* allocate a brand new scamper trace object, empty of any data
*
* scamper_trace_hops_alloc:
* allocate an array of hop records to the trace object
*
* scamper_trace_free:
* free the memory used by this trace object.
* this function assumes that any memory that would be dynamically
* allocated can be freed with free()
*
* scamper_trace_probe_headerlen:
* return the size of headers sent with each probe for the trace
*
* scamper_trace_addr:
* return the address of the trace -- caller doesn't know that it is a trace.
*/
scamper_trace_t *scamper_trace_alloc(void);
int scamper_trace_hops_alloc(scamper_trace_t *trace, const int hops);
void scamper_trace_free(scamper_trace_t *trace);
uint16_t scamper_trace_pathlength(const scamper_trace_t *trace);
int scamper_trace_probe_headerlen(const scamper_trace_t *trace);
scamper_addr_t *scamper_trace_addr(const void *va);
const char *scamper_trace_type_tostr(const scamper_trace_t *trace);
/*
* scamper_trace_hop_alloc:
* allocate a blank hop record
*
* scamper_trace_hop_free:
* free the memory used by a hop structure
*
* scamper_trace_hop_count:
* return the total number of hops attached to the trace structure
*/
scamper_trace_hop_t *scamper_trace_hop_alloc(void);
void scamper_trace_hop_free(scamper_trace_hop_t *hop);
int scamper_trace_hop_count(const scamper_trace_t *trace);
/*
* scamper_trace_pmtud_alloc:
* allocate a blank pmtud record for the trace structure
*
* scamper_trace_pmtud_free:
* free the attached pmtud record from the trace structure
*
* scamper_trace_pmtud_hop_count:
* return the total number of hops attached to the pmtud structure
*/
int scamper_trace_pmtud_alloc(scamper_trace_t *trace);
void scamper_trace_pmtud_free(scamper_trace_t *trace);
int scamper_trace_pmtud_hop_count(const scamper_trace_t *trace);
/*
* Utility macros
*
*
*/
#define SCAMPER_TRACE_PMTUD_GET_OUTMTU(pmtud, outmtu) \
do \
{ \
const scamper_tlv_t *tlv; \
if((tlv=scamper_tlv_get(pmtud->tlvs, \
SCAMPER_TRACE_PMTUD_TLV_OUTMTU)) == NULL) \
{ \
outmtu = pmtud->ifmtu; \
} \
else \
{ \
outmtu = tlv->tlv_val_16; \
} \
} \
while(0)
#define SCAMPER_TRACE_HOP_GET_TURN_TTL(hop, turn_ttl) \
do \
{ \
const scamper_tlv_t *tlv; \
if((tlv=scamper_tlv_get(hop->hop_tlvs, \
SCAMPER_TRACE_HOP_TLV_INNER_IPTTL)) == NULL) \
{ \
turn_ttl = 1; \
} \
else \
{ \
turn_ttl = tlv->tlv_val_8; \
} \
} \
while(0)
#define SCAMPER_TRACE_HOP_GET_NHMTU(hop, nhmtu) \
do \
{ \
const scamper_tlv_t *tlv; \
if((tlv=scamper_tlv_get(hop->hop_tlvs, \
SCAMPER_TRACE_HOP_TLV_NHMTU)) != NULL) \
{ \
nhmtu = tlv->tlv_val_16; \
} \
else \
{ \
nhmtu = 0; \
} \
} \
while(0)
#endif /* __SCAMPER_TRACE_H */
syntax highlighted by Code2HTML, v. 0.9.1