/* * scamper_icmp_resp.h * * $Id: scamper_icmp_resp.h,v 1.14 2007/05/03 23:25:11 mjl Exp $ * * Copyright (C) 2005-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_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; } 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 */