1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
|
/*
* scamper_icmp_resp.h
*
* $Id: scamper_icmp_resp.h,v 1.14.2.1 2008/02/22 20:23:31 mjl Exp $
*
* Copyright (C) 2005-2008 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_ICMP_RESP_H
#define __SCAMPER_ICMP_RESP_H
#define SCAMPER_ICMP_RESP_FLAG_KERNRX (0x01)
#define SCAMPER_ICMP_RESP_FLAG_INNER_IP (0x02)
#define SCAMPER_ICMP_RESP_IS_ECHO_REPLY(ir) ( \
(ir->ir_af == AF_INET && ir->ir_icmp_type == 0) || \
(ir->ir_af == AF_INET6 && ir->ir_icmp_type == 129))
#define SCAMPER_ICMP_RESP_IS_TTL_EXP(ir) ( \
(ir->ir_af == AF_INET && ir->ir_icmp_type == 11) || \
(ir->ir_af == AF_INET6 && ir->ir_icmp_type == 3))
#define SCAMPER_ICMP_RESP_IS_UNREACH(ir) ( \
(ir->ir_af == AF_INET && ir->ir_icmp_type == 3) || \
(ir->ir_af == AF_INET6 && ir->ir_icmp_type == 1))
#define SCAMPER_ICMP_RESP_IS_UNREACH_PORT(ir) ( \
(ir->ir_af == AF_INET && ir->ir_icmp_type == 3 && ir->ir_icmp_code == 3) || \
(ir->ir_af == AF_INET6 && ir->ir_icmp_type == 1 && ir->ir_icmp_code == 4))
#define SCAMPER_ICMP_RESP_IS_PACKET_TOO_BIG(ir) ( \
(ir->ir_af == AF_INET && ir->ir_icmp_type == 3 && ir->ir_icmp_code == 4) || \
(ir->ir_af == AF_INET6 && ir->ir_icmp_type == 2))
/* this macro checks to see if the inner structs are valid */
#define SCAMPER_ICMP_RESP_INNER_IS_SET(ir) ( \
((ir->ir_flags & SCAMPER_ICMP_RESP_FLAG_INNER_IP) != 0))
#define SCAMPER_ICMP_RESP_INNER_IS_ICMP(ir) ( \
(ir->ir_af == AF_INET && ir->ir_inner_ip_proto == 1) || \
(ir->ir_af == AF_INET6 && ir->ir_inner_ip_proto == 58))
#define SCAMPER_ICMP_RESP_INNER_IS_ICMP_ECHO_REQ(ir) ( \
(ir->ir_af == AF_INET && \
ir->ir_inner_ip_proto == 1 && ir->ir_icmp_type == 0) || \
(ir->ir_af == AF_INET6 && \
ir->ir_inner_ip_proto == 58 && ir->ir_icmp_type == 129))
/*
* an ICMP response may consist of up to four pieces. when an ICMP
* packet is received, scamper parses the packet and records values of
* interest in this structure.
*
* the four pieces of interesting information can be broken up into the
* following categories:
*
* 1. the IP header
* 2. the ICMP header
* 3. [optional] IP header of probe that caused this message
* 4. [optional] transport header of probe that caused this message
*
* the optional pieces - the 'inner' IP and transport headers are found
* depending on the type / code of the ICMP message. they are always
* found in 'destination unreachable' type messages, but obviously
* are not found in echo replies or the like.
*/
typedef struct scamper_icmp_resp
{
/* the address family (AF_INET / AF_INET6) of the response */
int ir_af;
/* when the ICMP response was received */
struct timeval ir_rx;
/* flags, whose meanings are defined above */
uint8_t ir_flags;
/*
* category 1: the IP header;
*
* scamper records the source of the ICMP message but not the destination,
* as that is the host scamper is running on, and that is not interesting.
*
* scamper also records the size, ttl, ipid, and tos fields of the
* response
*/
union
{
struct in_addr v4;
struct in6_addr v6;
} ir_ip_src;
uint16_t ir_ip_size;
uint16_t ir_ip_id;
uint8_t ir_ip_tos;
int16_t ir_ip_ttl; /* ir_ip_hlim; -1 if unavailable */
/*
* category 2: the ICMP header;
*
* scamper records the type and code of the ICMP message. depending on
* the type of the message, optional ICMP id and sequence fields are
* also recorded. if the message
*/
uint8_t ir_icmp_type;
uint8_t ir_icmp_code;
union
{
struct ir_idseq
{
uint16_t id;
uint16_t seq;
} idseq;
uint16_t nhmtu;
} ir_icmp_un;
/*
* category 3: the inner IP header;
*
* if the ICMP type/code hints that a portion of the probe is included
* in the ICMP response, then scamper records interesting portions of the
* IP header. we don't record the source address, as that is the host
* that scamper is running on, and that does not seem to be interesting.
*/
union
{
struct in_addr v4;
struct in6_addr v6;
} ir_inner_ip_dst;
uint16_t ir_inner_ip_size;
uint16_t ir_inner_ip_id; /* IPv4 ID */
uint32_t ir_inner_ip_flow; /* IPv6 flow */
uint8_t ir_inner_ip_tos;
uint8_t ir_inner_ip_ttl; /* ir_inner_ip_hlim */
uint8_t ir_inner_ip_proto;
/*
* category 4: details of the transport header
*
* the IPv4 ICMP RFC says that if an ICMP error message
*/
union
{
struct irt_udp
{
uint16_t sport;
uint16_t dport;
uint16_t sum;
} irit_udp;
struct irt_tcp
{
uint16_t sport;
uint16_t dport;
uint32_t seq;
} irit_tcp;
struct irt_icmp
{
uint8_t type;
uint8_t code;
uint16_t id;
uint16_t seq;
} irit_icmp;
} ir_inner_trans_un;
uint8_t *ir_ext;
uint16_t ir_extlen;
} scamper_icmp_resp_t;
#define ir_ip_hlim ir_ip_ttl
#define ir_icmp_id ir_icmp_un.idseq.id
#define ir_icmp_seq ir_icmp_un.idseq.seq
#define ir_icmp_nhmtu ir_icmp_un.nhmtu
#define ir_inner_ip_hlim ir_inner_ip_ttl
#define ir_inner_udp_sport ir_inner_trans_un.irit_udp.sport
#define ir_inner_udp_dport ir_inner_trans_un.irit_udp.dport
#define ir_inner_udp_sum ir_inner_trans_un.irit_udp.sum
#define ir_inner_tcp_sport ir_inner_trans_un.irit_tcp.sport
#define ir_inner_tcp_dport ir_inner_trans_un.irit_tcp.dport
#define ir_inner_tcp_seq ir_inner_trans_un.irit_tcp.seq
#define ir_inner_icmp_type ir_inner_trans_un.irit_icmp.type
#define ir_inner_icmp_code ir_inner_trans_un.irit_icmp.code
#define ir_inner_icmp_id ir_inner_trans_un.irit_icmp.id
#define ir_inner_icmp_seq ir_inner_trans_un.irit_icmp.seq
int scamper_icmp_resp_src(scamper_icmp_resp_t *resp, scamper_addr_t *addr);
int scamper_icmp_resp_inner_dst(scamper_icmp_resp_t *resp, scamper_addr_t *a);
void scamper_icmp_resp_handle(scamper_icmp_resp_t *resp);
/* scamper only uses this function if it is built in debug mode */
#ifndef NDEBUG
void scamper_icmp_resp_print(const scamper_icmp_resp_t *resp);
#else
#define scamper_icmp_resp_print(resp) ((void)0)
#endif
#endif /* __SCAMPER_ICMP_RESP_H */
|