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 | |
18 | struct icmp6_echo { /* Echo Messages */ |
19 | uint16_t id; |
20 | uint16_t seq_num; |
21 | }; |
22 | |
23 | union icmp6_error_body { |
24 | uint32_t unused; |
25 | uint32_t pointer; |
26 | uint32_t mtu; |
27 | }; |
28 | |
29 | /* |
30 | * NDP Messages |
31 | */ |
32 | struct ndp_rs { /* Router Solicitation Message */ |
33 | uint32_t reserved; |
34 | }; |
35 | |
36 | struct 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 | |
48 | G_STATIC_ASSERT(sizeof(struct ndp_ra) == 12); |
49 | |
50 | struct ndp_ns { /* Neighbor Solicitation Message */ |
51 | uint32_t reserved; |
52 | struct in6_addr target; /* Target Address */ |
53 | }; |
54 | |
55 | G_STATIC_ASSERT(sizeof(struct ndp_ns) == 20); |
56 | |
57 | struct 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 | |
69 | G_STATIC_ASSERT(sizeof(struct ndp_na) == 20); |
70 | |
71 | struct ndp_redirect { |
72 | uint32_t reserved; |
73 | struct in6_addr target; /* Target Address */ |
74 | struct in6_addr dest; /* Destination Address */ |
75 | }; |
76 | |
77 | G_STATIC_ASSERT(sizeof(struct ndp_redirect) == 36); |
78 | |
79 | /* |
80 | * Structure of an icmpv6 header. |
81 | */ |
82 | struct 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 | |
104 | G_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 | */ |
118 | struct 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 | |
212 | void icmp6_init(Slirp *slirp); |
213 | void icmp6_cleanup(Slirp *slirp); |
214 | void icmp6_input(struct mbuf *); |
215 | void icmp6_send_error(struct mbuf *m, uint8_t type, uint8_t code); |
216 | void ndp_send_ra(Slirp *slirp); |
217 | void ndp_send_ns(Slirp *slirp, struct in6_addr addr); |
218 | |
219 | #endif |
220 | |