1 /*
2  * icmp.h
3  *
4  * Internet Control Message Protocol.
5  * RFC 792, 950, 1256, 1393, 1475, 2002, 2521
6  *
7  * Copyright (c) 2000 Dug Song <dugsong@monkey.org>
8  *
9  * $Id: icmp.h 416 2003-03-16 17:39:18Z dugsong $
10  */
11 
12 #ifndef DNET_ICMP_H
13 #define DNET_ICMP_H
14 
15 #define ICMP_HDR_LEN	4	/* base ICMP header length */
16 #define ICMP_LEN_MIN	8	/* minimum ICMP message size, with header */
17 
18 #ifndef __GNUC__
19 #ifndef __attribute__
20 # define __attribute__(x)
21 #endif
22 # pragma pack(1)
23 #endif
24 
25 /*
26  * ICMP header
27  */
28 struct icmp_hdr {
29 	uint8_t		icmp_type;	/* type of message, see below */
30 	uint8_t		icmp_code;	/* type sub code */
31 	uint16_t	icmp_cksum;	/* ones complement cksum of struct */
32 };
33 
34 /*
35  * Types (icmp_type) and codes (icmp_code) -
36  * http://www.iana.org/assignments/icmp-parameters
37  */
38 #define		ICMP_CODE_NONE		0	/* for types without codes */
39 #define	ICMP_ECHOREPLY		0		/* echo reply */
40 #define	ICMP_UNREACH		3		/* dest unreachable, codes: */
41 #define		ICMP_UNREACH_NET		0	/* bad net */
42 #define		ICMP_UNREACH_HOST		1	/* bad host */
43 #define		ICMP_UNREACH_PROTO		2	/* bad protocol */
44 #define		ICMP_UNREACH_PORT		3	/* bad port */
45 #define		ICMP_UNREACH_NEEDFRAG		4	/* IP_DF caused drop */
46 #define		ICMP_UNREACH_SRCFAIL		5	/* src route failed */
47 #define		ICMP_UNREACH_NET_UNKNOWN	6	/* unknown net */
48 #define		ICMP_UNREACH_HOST_UNKNOWN	7	/* unknown host */
49 #define		ICMP_UNREACH_ISOLATED		8	/* src host isolated */
50 #define		ICMP_UNREACH_NET_PROHIB		9	/* for crypto devs */
51 #define		ICMP_UNREACH_HOST_PROHIB	10	/* ditto */
52 #define		ICMP_UNREACH_TOSNET		11	/* bad tos for net */
53 #define		ICMP_UNREACH_TOSHOST		12	/* bad tos for host */
54 #define		ICMP_UNREACH_FILTER_PROHIB	13	/* prohibited access */
55 #define		ICMP_UNREACH_HOST_PRECEDENCE	14	/* precedence error */
56 #define		ICMP_UNREACH_PRECEDENCE_CUTOFF	15	/* precedence cutoff */
57 #define	ICMP_SRCQUENCH		4		/* packet lost, slow down */
58 #define	ICMP_REDIRECT		5		/* shorter route, codes: */
59 #define		ICMP_REDIRECT_NET		0	/* for network */
60 #define		ICMP_REDIRECT_HOST		1	/* for host */
61 #define		ICMP_REDIRECT_TOSNET		2	/* for tos and net */
62 #define		ICMP_REDIRECT_TOSHOST		3	/* for tos and host */
63 #define	ICMP_ALTHOSTADDR	6		/* alternate host address */
64 #define	ICMP_ECHO		8		/* echo service */
65 #define	ICMP_RTRADVERT		9		/* router advertise, codes: */
66 #define		ICMP_RTRADVERT_NORMAL		0	/* normal */
67 #define		ICMP_RTRADVERT_NOROUTE_COMMON 16	/* selective routing */
68 #define	ICMP_RTRSOLICIT		10		/* router solicitation */
69 #define	ICMP_TIMEXCEED		11		/* time exceeded, code: */
70 #define		ICMP_TIMEXCEED_INTRANS		0	/* ttl==0 in transit */
71 #define		ICMP_TIMEXCEED_REASS		1	/* ttl==0 in reass */
72 #define	ICMP_PARAMPROB		12		/* ip header bad */
73 #define		ICMP_PARAMPROB_ERRATPTR		0	/* req. opt. absent */
74 #define		ICMP_PARAMPROB_OPTABSENT	1	/* req. opt. absent */
75 #define		ICMP_PARAMPROB_LENGTH		2	/* bad length */
76 #define	ICMP_TSTAMP		13		/* timestamp request */
77 #define	ICMP_TSTAMPREPLY	14		/* timestamp reply */
78 #define	ICMP_INFO		15		/* information request */
79 #define	ICMP_INFOREPLY		16		/* information reply */
80 #define	ICMP_MASK		17		/* address mask request */
81 #define	ICMP_MASKREPLY		18		/* address mask reply */
82 #define ICMP_TRACEROUTE		30		/* traceroute */
83 #define ICMP_DATACONVERR	31		/* data conversion error */
84 #define ICMP_MOBILE_REDIRECT	32		/* mobile host redirect */
85 #define ICMP_IPV6_WHEREAREYOU	33		/* IPv6 where-are-you */
86 #define ICMP_IPV6_IAMHERE	34		/* IPv6 i-am-here */
87 #define ICMP_MOBILE_REG		35		/* mobile registration req */
88 #define ICMP_MOBILE_REGREPLY	36		/* mobile registration reply */
89 #define ICMP_DNS		37		/* domain name request */
90 #define ICMP_DNSREPLY		38		/* domain name reply */
91 #define ICMP_SKIP		39		/* SKIP */
92 #define ICMP_PHOTURIS		40		/* Photuris */
93 #define		ICMP_PHOTURIS_UNKNOWN_INDEX	0	/* unknown sec index */
94 #define		ICMP_PHOTURIS_AUTH_FAILED	1	/* auth failed */
95 #define		ICMP_PHOTURIS_DECOMPRESS_FAILED	2	/* decompress failed */
96 #define		ICMP_PHOTURIS_DECRYPT_FAILED	3	/* decrypt failed */
97 #define		ICMP_PHOTURIS_NEED_AUTHN	4	/* no authentication */
98 #define		ICMP_PHOTURIS_NEED_AUTHZ	5	/* no authorization */
99 #define	ICMP_TYPE_MAX		40
100 
101 #define	ICMP_INFOTYPE(type)						\
102 	((type) == ICMP_ECHOREPLY || (type) == ICMP_ECHO ||		\
103 	(type) == ICMP_RTRADVERT || (type) == ICMP_RTRSOLICIT ||	\
104 	(type) == ICMP_TSTAMP || (type) == ICMP_TSTAMPREPLY ||		\
105 	(type) == ICMP_INFO || (type) == ICMP_INFOREPLY ||		\
106 	(type) == ICMP_MASK || (type) == ICMP_MASKREPLY)
107 
108 /*
109  * Echo message data
110  */
111 struct icmp_msg_echo {
112 	uint16_t	icmp_id;
113 	uint16_t	icmp_seq;
114 	uint8_t		icmp_data __flexarr;	/* optional data */
115 };
116 
117 /*
118  * Fragmentation-needed (unreachable) message data
119  */
120 struct icmp_msg_needfrag {
121 	uint16_t	icmp_void;		/* must be zero */
122 	uint16_t	icmp_mtu;		/* MTU of next-hop network */
123 	uint8_t		icmp_ip __flexarr;	/* IP hdr + 8 bytes of pkt */
124 };
125 
126 /*
127  *  Unreachable, source quench, redirect, time exceeded,
128  *  parameter problem message data
129  */
130 struct icmp_msg_quote {
131 	uint32_t	icmp_void;		/* must be zero */
132 #define icmp_gwaddr	icmp_void		/* router IP address to use */
133 #define icmp_pptr	icmp_void		/* ptr to bad octet field */
134 	uint8_t		icmp_ip __flexarr;	/* IP hdr + 8 bytes of pkt */
135 };
136 
137 /*
138  * Router advertisement message data, RFC 1256
139  */
140 struct icmp_msg_rtradvert {
141 	uint8_t		icmp_num_addrs;		/* # of address / pref pairs */
142 	uint8_t		icmp_wpa;		/* words / address == 2 */
143 	uint16_t	icmp_lifetime;		/* route lifetime in seconds */
144 	struct icmp_msg_rtr_data {
145 		uint32_t	icmp_void;
146 #define icmp_gwaddr		icmp_void	/* router IP address */
147 		uint32_t	icmp_pref;	/* router preference (usu 0) */
148 	} icmp_rtr __flexarr;			/* variable # of routers */
149 };
150 #define ICMP_RTR_PREF_NODEFAULT	0x80000000	/* do not use as default gw */
151 
152 /*
153  * Timestamp message data
154  */
155 struct icmp_msg_tstamp {
156 	uint32_t	icmp_id;		/* identifier */
157 	uint32_t	icmp_seq;		/* sequence number */
158 	uint32_t	icmp_ts_orig;		/* originate timestamp */
159 	uint32_t	icmp_ts_rx;		/* receive timestamp */
160 	uint32_t	icmp_ts_tx;		/* transmit timestamp */
161 };
162 
163 /*
164  * Address mask message data, RFC 950
165  */
166 struct icmp_msg_mask {
167 	uint32_t	icmp_id;		/* identifier */
168 	uint32_t	icmp_seq;		/* sequence number */
169 	uint32_t	icmp_mask;		/* address mask */
170 };
171 
172 /*
173  * Traceroute message data, RFC 1393, RFC 1812
174  */
175 struct icmp_msg_traceroute {
176 	uint16_t	icmp_id;		/* identifier */
177 	uint16_t	icmp_void;		/* unused */
178 	uint16_t	icmp_ohc;		/* outbound hop count */
179 	uint16_t	icmp_rhc;		/* return hop count */
180 	uint32_t	icmp_speed;		/* link speed, bytes/sec */
181 	uint32_t	icmp_mtu;		/* MTU in bytes */
182 };
183 
184 /*
185  * Domain name reply message data, RFC 1788
186  */
187 struct icmp_msg_dnsreply {
188 	uint16_t	icmp_id;		/* identifier */
189 	uint16_t	icmp_seq;		/* sequence number */
190 	uint32_t	icmp_ttl;		/* time-to-live */
191 	uint8_t		icmp_names __flexarr;	/* variable number of names */
192 };
193 
194 /*
195  * Generic identifier, sequence number data
196  */
197 struct icmp_msg_idseq {
198 	uint16_t	icmp_id;
199 	uint16_t	icmp_seq;
200 };
201 
202 /*
203  * ICMP message union
204  */
205 union icmp_msg {
206 	struct icmp_msg_echo	   echo;	/* ICMP_ECHO{REPLY} */
207 	struct icmp_msg_quote	   unreach;	/* ICMP_UNREACH */
208 	struct icmp_msg_needfrag   needfrag;	/* ICMP_UNREACH_NEEDFRAG */
209 	struct icmp_msg_quote	   srcquench;	/* ICMP_SRCQUENCH */
210 	struct icmp_msg_quote	   redirect;	/* ICMP_REDIRECT (set to 0) */
211 	uint32_t		   rtrsolicit;	/* ICMP_RTRSOLICIT */
212 	struct icmp_msg_rtradvert  rtradvert;	/* ICMP_RTRADVERT */
213 	struct icmp_msg_quote	   timexceed;	/* ICMP_TIMEXCEED */
214 	struct icmp_msg_quote	   paramprob;	/* ICMP_PARAMPROB */
215 	struct icmp_msg_tstamp	   tstamp;	/* ICMP_TSTAMP{REPLY} */
216 	struct icmp_msg_idseq	   info;	/* ICMP_INFO{REPLY} */
217 	struct icmp_msg_mask	   mask;	/* ICMP_MASK{REPLY} */
218 	struct icmp_msg_traceroute traceroute;	/* ICMP_TRACEROUTE */
219 	struct icmp_msg_idseq	   dns;		/* ICMP_DNS */
220 	struct icmp_msg_dnsreply   dnsreply;	/* ICMP_DNSREPLY */
221 };
222 
223 #ifndef __GNUC__
224 # pragma pack()
225 #endif
226 
227 #define icmp_pack_hdr(hdr, type, code) do {				\
228 	struct icmp_hdr *icmp_pack_p = (struct icmp_hdr *)(hdr);	\
229 	icmp_pack_p->icmp_type = type; icmp_pack_p->icmp_code = code;	\
230 } while (0)
231 
232 #define icmp_pack_hdr_echo(hdr, type, code, id, seq, data, len) do {	\
233 	struct icmp_msg_echo *echo_pack_p = (struct icmp_msg_echo *)	\
234 		((uint8_t *)(hdr) + ICMP_HDR_LEN);			\
235 	icmp_pack_hdr(hdr, type, code);					\
236 	echo_pack_p->icmp_id = htons(id);				\
237 	echo_pack_p->icmp_seq = htons(seq);				\
238 	memmove(echo_pack_p->icmp_data, data, len);			\
239 } while (0)
240 
241 #define icmp_pack_hdr_quote(hdr, type, code, word, pkt, len) do {	\
242 	struct icmp_msg_quote *quote_pack_p = (struct icmp_msg_quote *)	\
243 		((uint8_t *)(hdr) + ICMP_HDR_LEN);			\
244 	icmp_pack_hdr(hdr, type, code);					\
245 	quote_pack_p->icmp_void = htonl(word);				\
246 	memmove(quote_pack_p->icmp_ip, pkt, len);			\
247 } while (0)
248 
249 #define icmp_pack_hdr_mask(hdr, type, code, id, seq, mask) do {		\
250 	struct icmp_msg_mask *mask_pack_p = (struct icmp_msg_mask *)	\
251 		((uint8_t *)(hdr) + ICMP_HDR_LEN);			\
252 	icmp_pack_hdr(hdr, type, code);					\
253 	mask_pack_p->icmp_id = htons(id);				\
254 	mask_pack_p->icmp_seq = htons(seq);				\
255 	mask_pack_p->icmp_mask = htonl(mask);				\
256 } while (0)
257 
258 #define icmp_pack_hdr_needfrag(hdr, type, code, mtu, pkt, len) do {	\
259 	struct icmp_msg_needfrag *frag_pack_p =				\
260 	(struct icmp_msg_needfrag *)((uint8_t *)(hdr) + ICMP_HDR_LEN);	\
261 	icmp_pack_hdr(hdr, type, code);					\
262 	frag_pack_p->icmp_void = 0;					\
263 	frag_pack_p->icmp_mtu = htons(mtu);				\
264 	memmove(frag_pack_p->icmp_ip, pkt, len);			\
265 } while (0)
266 
267 #endif /* DNET_ICMP_H */
268