1/* SPDX-License-Identifier: BSD-3-Clause */
2/*
3 * Copyright (c) 2013
4 * Guillaume Subiron, Yann Bordenave, Serigne Modou Wagne.
5 */
6
7#ifndef SLIRP_IP6_ICMP_H
8#define SLIRP_IP6_ICMP_H
9
10/*
11 * Interface Control Message Protocol version 6 Definitions.
12 * Per RFC 4443, March 2006.
13 *
14 * Network Discover Protocol Definitions.
15 * Per RFC 4861, September 2007.
16 */
17
18struct icmp6_echo { /* Echo Messages */
19 uint16_t id;
20 uint16_t seq_num;
21};
22
23union icmp6_error_body {
24 uint32_t unused;
25 uint32_t pointer;
26 uint32_t mtu;
27};
28
29/*
30 * NDP Messages
31 */
32struct ndp_rs { /* Router Solicitation Message */
33 uint32_t reserved;
34};
35
36struct ndp_ra { /* Router Advertisement Message */
37 uint8_t chl; /* Cur Hop Limit */
38#if G_BYTE_ORDER == G_BIG_ENDIAN
39 uint8_t M : 1, O : 1, reserved : 6;
40#else
41 uint8_t reserved : 6, O : 1, M : 1;
42#endif
43 uint16_t lifetime; /* Router Lifetime */
44 uint32_t reach_time; /* Reachable Time */
45 uint32_t retrans_time; /* Retrans Timer */
46};
47
48G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12);
49
50struct ndp_ns { /* Neighbor Solicitation Message */
51 uint32_t reserved;
52 struct in6_addr target; /* Target Address */
53};
54
55G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20);
56
57struct ndp_na { /* Neighbor Advertisement Message */
58#if G_BYTE_ORDER == G_BIG_ENDIAN
59 uint32_t R : 1, /* Router Flag */
60 S : 1, /* Solicited Flag */
61 O : 1, /* Override Flag */
62 reserved_hi : 5, reserved_lo : 24;
63#else
64 uint32_t reserved_hi : 5, O : 1, S : 1, R : 1, reserved_lo : 24;
65#endif
66 struct in6_addr target; /* Target Address */
67};
68
69G_STATIC_ASSERT(sizeof(struct ndp_na) == 20);
70
71struct ndp_redirect {
72 uint32_t reserved;
73 struct in6_addr target; /* Target Address */
74 struct in6_addr dest; /* Destination Address */
75};
76
77G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36);
78
79/*
80 * Structure of an icmpv6 header.
81 */
82struct icmp6 {
83 uint8_t icmp6_type; /* type of message, see below */
84 uint8_t icmp6_code; /* type sub code */
85 uint16_t icmp6_cksum; /* ones complement cksum of struct */
86 union {
87 union icmp6_error_body error_body;
88 struct icmp6_echo echo;
89 struct ndp_rs ndp_rs;
90 struct ndp_ra ndp_ra;
91 struct ndp_ns ndp_ns;
92 struct ndp_na ndp_na;
93 struct ndp_redirect ndp_redirect;
94 } icmp6_body;
95#define icmp6_err icmp6_body.error_body
96#define icmp6_echo icmp6_body.echo
97#define icmp6_nrs icmp6_body.ndp_rs
98#define icmp6_nra icmp6_body.ndp_ra
99#define icmp6_nns icmp6_body.ndp_ns
100#define icmp6_nna icmp6_body.ndp_na
101#define icmp6_redirect icmp6_body.ndp_redirect
102};
103
104G_STATIC_ASSERT(sizeof(struct icmp6) == 40);
105
106#define ICMP6_MINLEN 4
107#define ICMP6_ERROR_MINLEN 8
108#define ICMP6_ECHO_MINLEN 8
109#define ICMP6_NDP_RS_MINLEN 8
110#define ICMP6_NDP_RA_MINLEN 16
111#define ICMP6_NDP_NS_MINLEN 24
112#define ICMP6_NDP_NA_MINLEN 24
113#define ICMP6_NDP_REDIRECT_MINLEN 40
114
115/*
116 * NDP Options
117 */
118struct ndpopt {
119 uint8_t ndpopt_type; /* Option type */
120 uint8_t ndpopt_len; /* /!\ In units of 8 octets */
121 union {
122 unsigned char linklayer_addr[6]; /* Source/Target Link-layer */
123#define ndpopt_linklayer ndpopt_body.linklayer_addr
124 struct prefixinfo { /* Prefix Information */
125 uint8_t prefix_length;
126#if G_BYTE_ORDER == G_BIG_ENDIAN
127 uint8_t L : 1, A : 1, reserved1 : 6;
128#else
129 uint8_t reserved1 : 6, A : 1, L : 1;
130#endif
131 uint32_t valid_lt; /* Valid Lifetime */
132 uint32_t pref_lt; /* Preferred Lifetime */
133 uint32_t reserved2;
134 struct in6_addr prefix;
135 } SLIRP_PACKED prefixinfo;
136#define ndpopt_prefixinfo ndpopt_body.prefixinfo
137 struct rdnss {
138 uint16_t reserved;
139 uint32_t lifetime;
140 struct in6_addr addr;
141 } SLIRP_PACKED rdnss;
142#define ndpopt_rdnss ndpopt_body.rdnss
143 } ndpopt_body;
144} SLIRP_PACKED;
145
146/* NDP options type */
147#define NDPOPT_LINKLAYER_SOURCE 1 /* Source Link-Layer Address */
148#define NDPOPT_LINKLAYER_TARGET 2 /* Target Link-Layer Address */
149#define NDPOPT_PREFIX_INFO 3 /* Prefix Information */
150#define NDPOPT_RDNSS 25 /* Recursive DNS Server Address */
151
152/* NDP options size, in octets. */
153#define NDPOPT_LINKLAYER_LEN 8
154#define NDPOPT_PREFIXINFO_LEN 32
155#define NDPOPT_RDNSS_LEN 24
156
157/*
158 * Definition of type and code field values.
159 * Per https://www.iana.org/assignments/icmpv6-parameters/icmpv6-parameters.xml
160 * Last Updated 2012-11-12
161 */
162
163/* Errors */
164#define ICMP6_UNREACH 1 /* Destination Unreachable */
165#define ICMP6_UNREACH_NO_ROUTE 0 /* no route to dest */
166#define ICMP6_UNREACH_DEST_PROHIB 1 /* com with dest prohibited */
167#define ICMP6_UNREACH_SCOPE 2 /* beyond scope of src addr */
168#define ICMP6_UNREACH_ADDRESS 3 /* address unreachable */
169#define ICMP6_UNREACH_PORT 4 /* port unreachable */
170#define ICMP6_UNREACH_SRC_FAIL 5 /* src addr failed */
171#define ICMP6_UNREACH_REJECT_ROUTE 6 /* reject route to dest */
172#define ICMP6_UNREACH_SRC_HDR_ERROR 7 /* error in src routing header */
173#define ICMP6_TOOBIG 2 /* Packet Too Big */
174#define ICMP6_TIMXCEED 3 /* Time Exceeded */
175#define ICMP6_TIMXCEED_INTRANS 0 /* hop limit exceeded in transit */
176#define ICMP6_TIMXCEED_REASS 1 /* ttl=0 in reass */
177#define ICMP6_PARAMPROB 4 /* Parameter Problem */
178#define ICMP6_PARAMPROB_HDR_FIELD 0 /* err header field */
179#define ICMP6_PARAMPROB_NXTHDR_TYPE 1 /* unrecognized Next Header type */
180#define ICMP6_PARAMPROB_IPV6_OPT 2 /* unrecognized IPv6 option */
181
182/* Informational Messages */
183#define ICMP6_ECHO_REQUEST 128 /* Echo Request */
184#define ICMP6_ECHO_REPLY 129 /* Echo Reply */
185#define ICMP6_NDP_RS 133 /* Router Solicitation (NDP) */
186#define ICMP6_NDP_RA 134 /* Router Advertisement (NDP) */
187#define ICMP6_NDP_NS 135 /* Neighbor Solicitation (NDP) */
188#define ICMP6_NDP_NA 136 /* Neighbor Advertisement (NDP) */
189#define ICMP6_NDP_REDIRECT 137 /* Redirect Message (NDP) */
190
191/*
192 * Router Configuration Variables (rfc4861#section-6)
193 */
194#define NDP_IsRouter 1
195#define NDP_AdvSendAdvertisements 1
196#define NDP_MaxRtrAdvInterval 600000
197#define NDP_MinRtrAdvInterval \
198 ((NDP_MaxRtrAdvInterval >= 9) ? NDP_MaxRtrAdvInterval / 3 : \
199 NDP_MaxRtrAdvInterval)
200#define NDP_AdvManagedFlag 0
201#define NDP_AdvOtherConfigFlag 0
202#define NDP_AdvLinkMTU 0
203#define NDP_AdvReachableTime 0
204#define NDP_AdvRetransTime 0
205#define NDP_AdvCurHopLimit 64
206#define NDP_AdvDefaultLifetime ((3 * NDP_MaxRtrAdvInterval) / 1000)
207#define NDP_AdvValidLifetime 86400
208#define NDP_AdvOnLinkFlag 1
209#define NDP_AdvPrefLifetime 14400
210#define NDP_AdvAutonomousFlag 1
211
212void icmp6_init(Slirp *slirp);
213void icmp6_cleanup(Slirp *slirp);
214void icmp6_input(struct mbuf *);
215void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code);
216void ndp_send_ra(Slirp *slirp);
217void ndp_send_ns(Slirp *slirp, struct in6_addr addr);
218
219#endif
220