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