1 /* 2 * scamper_probe.h 3 * 4 * $Id: scamper_probe.h,v 1.47 2020/06/12 23:29:25 mjl Exp $ 5 * 6 * Copyright (C) 2005-2006 Matthew Luckie 7 * Copyright (C) 2006-2011 The University of Waikato 8 * Copyright (C) 2012 Matthew Luckie 9 * Copyright (C) 2012-2015 The Regents of the University of California 10 * Copyright (C) 2020 Matthew Luckie 11 * Author: Matthew Luckie 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation, version 2. 16 * 17 * This program is distributed in the hope that it will be useful, 18 * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 20 * GNU General Public License for more details. 21 * 22 * You should have received a copy of the GNU General Public License 23 * along with this program; if not, write to the Free Software 24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 25 * 26 */ 27 28 #ifndef __SCAMPER_PROBE_H 29 #define __SCAMPER_PROBE_H 30 31 /* 32 * scamper_probe_ipopt 33 * 34 * this structure is used to hold IPv4 options and IPv6 extension headers. 35 */ 36 typedef struct scamper_probe_ipopt 37 { 38 uint8_t type; 39 40 union 41 { 42 struct v4tsps 43 { 44 struct in_addr ips[4]; 45 uint8_t ipc; 46 } v4tsps; 47 48 struct v6rh0 49 { 50 struct in6_addr *ips; 51 uint8_t ipc; 52 } v6rh0; 53 54 struct v6frag 55 { 56 uint16_t off; 57 uint32_t id; 58 } v6frag; 59 60 struct quickstart 61 { 62 uint8_t func; 63 uint8_t rate; 64 uint8_t ttl; 65 uint32_t nonce; 66 } quickstart; 67 } un; 68 } scamper_probe_ipopt_t; 69 70 #define opt_v4tsps_ips un.v4tsps.ips 71 #define opt_v4tsps_ipc un.v4tsps.ipc 72 #define opt_v6rh0_ips un.v6rh0.ips 73 #define opt_v6rh0_ipc un.v6rh0.ipc 74 #define opt_v6frag_off un.v6frag.off 75 #define opt_v6frag_id un.v6frag.id 76 #define opt_qs_nonce un.quickstart.nonce 77 #define opt_qs_ttl un.quickstart.ttl 78 #define opt_qs_rate un.quickstart.rate 79 #define opt_qs_func un.quickstart.func 80 81 #define SCAMPER_PROBE_IPOPTS_V6ROUTE0 0 82 #define SCAMPER_PROBE_IPOPTS_V6FRAG 1 83 #define SCAMPER_PROBE_IPOPTS_V4RR 2 84 #define SCAMPER_PROBE_IPOPTS_V4TSPS 3 /* TS: prespecified interfaces */ 85 #define SCAMPER_PROBE_IPOPTS_V4TSO 4 /* TS: record only timestamps */ 86 #define SCAMPER_PROBE_IPOPTS_V4TSAA 5 /* TS: record IP and timestamps */ 87 #define SCAMPER_PROBE_IPOPTS_QUICKSTART 6 /* RFC 4782 */ 88 89 #define SCAMPER_PROBE_FLAG_IPID 0x0001 90 #define SCAMPER_PROBE_FLAG_NOFRAG 0x0002 91 #define SCAMPER_PROBE_FLAG_SPOOF 0x0004 92 #define SCAMPER_PROBE_FLAG_DL 0x0008 93 #define SCAMPER_PROBE_FLAG_RXERR 0x0010 /* socket is an rxerr variant */ 94 95 #define SCAMPER_PROBE_TCPOPT_SACK 0x01 96 #define SCAMPER_PROBE_TCPOPT_TS 0x02 97 #define SCAMPER_PROBE_TCPOPT_FO 0x04 98 #define SCAMPER_PROBE_TCPOPT_FO_EXP 0x08 99 100 #define SCAMPER_PROBE_IS_IPID(pr) ( \ 101 ((pr)->pr_flags & SCAMPER_PROBE_FLAG_IPID) != 0 && \ 102 (pr)->pr_ip_dst != NULL && SCAMPER_ADDR_TYPE_IS_IPV4((pr)->pr_ip_dst)) 103 104 /* 105 * scamper_probe 106 * 107 * this structure details how a probe should be formed and sent. 108 * it records any error code 109 */ 110 typedef struct scamper_probe 111 { 112 /* 113 * the following fields define the socket to use. note: they are optional 114 * (and ignored) if the scamper_probe_task function is called with a 115 * scamper_probe structure as it determines how to send the packet. 116 * if the caller requires the packet to be sent on a datalink socket, it 117 * must supply the datalink socket to use (in pr_dl) and a datalink header. 118 */ 119 int pr_fd; 120 scamper_dl_t *pr_dl; 121 uint8_t *pr_dl_buf; 122 uint16_t pr_dl_len; 123 124 /* flags set on input */ 125 uint16_t pr_flags; 126 127 /* IP address of router to send the packet to. null means default router */ 128 scamper_addr_t *pr_rtr; 129 130 /* IP header parameters */ 131 scamper_addr_t *pr_ip_src; 132 scamper_addr_t *pr_ip_dst; 133 uint8_t pr_ip_tos; 134 uint8_t pr_ip_ttl; 135 uint8_t pr_ip_proto; 136 uint16_t pr_ip_id; /* IPv4 ID */ 137 uint16_t pr_ip_off; 138 uint32_t pr_ip_flow; /* IPv6 flow id */ 139 140 /* IPv4 options / IPv6 extension headers */ 141 scamper_probe_ipopt_t *pr_ipopts; 142 int pr_ipoptc; 143 144 /* UDP header parameters */ 145 uint16_t pr_udp_sport; 146 uint16_t pr_udp_dport; 147 148 /* ICMP header parameters */ 149 uint8_t pr_icmp_type; 150 uint8_t pr_icmp_code; 151 uint16_t pr_icmp_sum; 152 uint16_t pr_icmp_id; 153 uint16_t pr_icmp_seq; 154 uint16_t pr_icmp_mtu; 155 156 /* TCP header parameters */ 157 uint16_t pr_tcp_sport; 158 uint16_t pr_tcp_dport; 159 uint32_t pr_tcp_seq; 160 uint32_t pr_tcp_ack; 161 uint8_t pr_tcp_flags; 162 uint8_t pr_tcp_opts; 163 uint8_t pr_tcp_wscale; 164 uint16_t pr_tcp_win; 165 uint16_t pr_tcp_mss; 166 uint32_t pr_tcp_tsval; 167 uint32_t pr_tcp_tsecr; 168 uint32_t pr_tcp_sack[8]; 169 uint8_t pr_tcp_sackb; 170 uint8_t *pr_tcp_fo_cookie; 171 uint8_t pr_tcp_fo_cookielen; 172 173 /* the contents of the packet's body */ 174 uint8_t *pr_data; 175 uint16_t pr_len; 176 177 /* the time immediately before the call to sendto was made */ 178 struct timeval pr_tx; 179 180 /* the actual transmitted packet, IP header and down, when datalink tx'd */ 181 uint8_t *pr_tx_raw; 182 uint16_t pr_tx_rawlen; 183 184 /* if an error occurs in the probe function, the errno is recorded */ 185 int pr_errno; 186 } scamper_probe_t; 187 188 int scamper_probe(scamper_probe_t *probe); 189 190 #ifdef __SCAMPER_TASK_H 191 int scamper_probe_task(scamper_probe_t *probe, scamper_task_t *task); 192 #endif 193 194 /* convenience macro to construct an ICMP echo packet */ 195 #define SCAMPER_PROBE_ICMP_ECHO(pr, id, seq) do { \ 196 assert((pr)->pr_ip_dst != NULL); \ 197 assert((pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4 || \ 198 (pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV6); \ 199 if((pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4) \ 200 { \ 201 (pr)->pr_ip_proto = IPPROTO_ICMP; \ 202 (pr)->pr_icmp_type = ICMP_ECHO; \ 203 } \ 204 else \ 205 { \ 206 (pr)->pr_ip_proto = IPPROTO_ICMPV6; \ 207 (pr)->pr_icmp_type = ICMP6_ECHO_REQUEST; \ 208 } \ 209 (pr)->pr_icmp_id = (id); \ 210 (pr)->pr_icmp_seq = (seq); \ 211 } while(0) 212 213 /* convenience macro to construct an ICMP timestamp request packet */ 214 #define SCAMPER_PROBE_ICMP_TIME(pr, id, seq) do { \ 215 assert((pr)->pr_ip_dst != NULL); \ 216 assert((pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4); \ 217 (pr)->pr_ip_proto = IPPROTO_ICMP; \ 218 (pr)->pr_icmp_type = ICMP_TSTAMP; \ 219 (pr)->pr_icmp_id = (id); \ 220 (pr)->pr_icmp_seq = (seq); \ 221 } while(0) 222 223 #define SCAMPER_PROBE_ICMP_PTB(pr, mtu) do { \ 224 assert((pr)->pr_ip_dst != NULL); \ 225 assert((pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4 || \ 226 (pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV6); \ 227 if((pr)->pr_ip_dst->type == SCAMPER_ADDR_TYPE_IPV4) \ 228 { \ 229 (pr)->pr_ip_proto = IPPROTO_ICMP; \ 230 (pr)->pr_icmp_type = ICMP_UNREACH; \ 231 (pr)->pr_icmp_code = ICMP_UNREACH_NEEDFRAG; \ 232 } \ 233 else \ 234 { \ 235 (pr)->pr_ip_proto = IPPROTO_ICMPV6; \ 236 (pr)->pr_icmp_type = ICMP6_PACKET_TOO_BIG; \ 237 } \ 238 (pr)->pr_icmp_mtu = (mtu); \ 239 } while(0) 240 241 /* 242 * scamper_probe_cleanup: 243 * cleanup any state kept inside the scamper_probe module 244 */ 245 int scamper_probe_init(void); 246 void scamper_probe_cleanup(void); 247 248 #endif /* __SCAMPER_PROBE_H */ 249