1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 * Copyright 2016 Joyent, Inc.
25 */
26
27 #include <sys/types.h>
28 #include <sys/stream.h>
29 #define _SUN_TPI_VERSION 2
30 #include <sys/tihdr.h>
31 #include <sys/socket.h>
32 #include <sys/xti_xtiopt.h>
33 #include <sys/xti_inet.h>
34
35 #include <netinet/in.h>
36 #include <netinet/icmp6.h>
37 #include <inet/common.h>
38 #include <netinet/ip6.h>
39 #include <inet/ip.h>
40
41 #include <netinet/tcp.h>
42 #include <netinet/ip_mroute.h>
43 #include <inet/optcom.h>
44 #include <inet/rawip_impl.h>
45 #include <net/bpf.h>
46
47 /*
48 * Table of all known options handled on a ICMP protocol stack.
49 *
50 * Note: This table contains options processed by both ICMP and IP levels
51 * and is the superset of options that can be performed on a ICMP over IP
52 * stack.
53 */
54 opdes_t icmp_opt_arr[] = {
55
56 { SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
57 { SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
58 { SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
59 },
60 { SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
61 { SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
62
63 #ifdef SO_PROTOTYPE
64 /*
65 * icmp will only allow IPPROTO_ICMP for non-privileged streams
66 * that check is made on an adhoc basis.
67 */
68 { SO_PROTOTYPE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
69 #endif
70
71 { SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
72 { SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
73 { SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
74 { SO_SNDTIMEO, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
75 sizeof (struct timeval), 0 },
76 { SO_RCVTIMEO, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
77 sizeof (struct timeval), 0 },
78 { SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
79 0 },
80 { SO_TIMESTAMP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
81 },
82 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
83 0 },
84 { SO_MAC_IMPLICIT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
85 0 },
86
87 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
88 0 },
89 { SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
90
91 { SO_ATTACH_FILTER, SOL_SOCKET, OA_W, OA_W, OP_NP, 0,
92 sizeof (struct bpf_program), 0 },
93 { SO_DETACH_FILTER, SOL_SOCKET, OA_W, OA_W, OP_NP, 0, 0, 0 },
94
95 { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
96 (OP_VARLEN|OP_NODEFAULT),
97 IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
98 { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
99 (OP_VARLEN|OP_NODEFAULT),
100 IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
101
102 { IP_HDRINCL, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
103 sizeof (int), 0 },
104 { IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
105 { T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
106 { IP_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
107
108 { IP_MULTICAST_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
109 sizeof (struct in_addr), 0 /* INADDR_ANY */ },
110
111 { IP_MULTICAST_LOOP, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
112 sizeof (uchar_t), -1 /* not initialized */},
113
114 { IP_MULTICAST_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
115 sizeof (uchar_t), -1 /* not initialized */ },
116
117 { IP_ADD_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
118 sizeof (struct ip_mreq), -1 /* not initialized */ },
119
120 { IP_DROP_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
121 sizeof (struct ip_mreq), 0 },
122
123 { IP_BLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
124 sizeof (struct ip_mreq_source), -1 },
125
126 { IP_UNBLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP, OP_NODEFAULT,
127 sizeof (struct ip_mreq_source), -1 },
128
129 { IP_ADD_SOURCE_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP,
130 OP_NODEFAULT, sizeof (struct ip_mreq_source), -1 },
131
132 { IP_DROP_SOURCE_MEMBERSHIP, IPPROTO_IP, OA_X, OA_X, OP_NP,
133 OP_NODEFAULT, sizeof (struct ip_mreq_source), -1 },
134
135 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
136 sizeof (ipsec_req_t), -1 /* not initialized */ },
137
138 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
139 sizeof (int), 0 /* no ifindex */ },
140
141 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
142 sizeof (int), 0 },
143
144 { IP_BROADCAST_TTL, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0, sizeof (uchar_t),
145 0 /* disabled */ },
146
147 { IP_RECVIF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
148
149 { IP_PKTINFO, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
150 (OP_NODEFAULT|OP_VARLEN),
151 sizeof (struct in_pktinfo), -1 /* not initialized */ },
152
153 { IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
154
155 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
156 sizeof (in_addr_t), -1 /* not initialized */ },
157
158 { MRT_INIT, IPPROTO_IP, 0, OA_X, OP_CONFIG,
159 OP_NODEFAULT, sizeof (int),
160 -1 /* not initialized */ },
161
162 { MRT_DONE, IPPROTO_IP, 0, OA_X, OP_CONFIG,
163 OP_NODEFAULT, 0, -1 /* not initialized */ },
164
165 { MRT_ADD_VIF, IPPROTO_IP, 0, OA_X, OP_CONFIG, OP_NODEFAULT,
166 sizeof (struct vifctl), -1 /* not initialized */ },
167
168 { MRT_DEL_VIF, IPPROTO_IP, 0, OA_X, OP_CONFIG, OP_NODEFAULT,
169 sizeof (vifi_t), -1 /* not initialized */ },
170
171 { MRT_ADD_MFC, IPPROTO_IP, 0, OA_X, OP_CONFIG, OP_NODEFAULT,
172 sizeof (struct mfcctl), -1 /* not initialized */ },
173
174 { MRT_DEL_MFC, IPPROTO_IP, 0, OA_X, OP_CONFIG, OP_NODEFAULT,
175 sizeof (struct mfcctl), -1 /* not initialized */ },
176
177 { MRT_VERSION, IPPROTO_IP, OA_R, OA_R, OP_NP, OP_NODEFAULT,
178 sizeof (int), -1 /* not initialized */ },
179
180 { MRT_ASSERT, IPPROTO_IP, 0, OA_RW, OP_CONFIG,
181 OP_NODEFAULT,
182 sizeof (int), -1 /* not initialized */ },
183
184 { MCAST_JOIN_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
185 OP_NODEFAULT, sizeof (struct group_req),
186 -1 /* not initialized */ },
187 { MCAST_LEAVE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
188 OP_NODEFAULT, sizeof (struct group_req),
189 -1 /* not initialized */ },
190 { MCAST_BLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP,
191 OP_NODEFAULT, sizeof (struct group_source_req),
192 -1 /* not initialized */ },
193 { MCAST_UNBLOCK_SOURCE, IPPROTO_IP, OA_X, OA_X, OP_NP,
194 OP_NODEFAULT, sizeof (struct group_source_req),
195 -1 /* not initialized */ },
196 { MCAST_JOIN_SOURCE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
197 OP_NODEFAULT, sizeof (struct group_source_req),
198 -1 /* not initialized */ },
199 { MCAST_LEAVE_SOURCE_GROUP, IPPROTO_IP, OA_X, OA_X, OP_NP,
200 OP_NODEFAULT, sizeof (struct group_source_req),
201 -1 /* not initialized */ },
202
203 { IPV6_MULTICAST_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
204 sizeof (int), 0 },
205
206 { IPV6_MULTICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
207 OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
208
209 { IPV6_MULTICAST_LOOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
210 OP_DEF_FN, sizeof (int), -1 /* not initialized */},
211
212 { IPV6_JOIN_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP, OP_NODEFAULT,
213 sizeof (struct ipv6_mreq), -1 /* not initialized */ },
214
215 { IPV6_LEAVE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP, OP_NODEFAULT,
216 sizeof (struct ipv6_mreq), -1 /* not initialized */ },
217
218 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
219 sizeof (int), -1 /* not initialized */ },
220
221 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
222 sizeof (int), 0 /* no ifindex */ },
223
224 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
225 sizeof (int), 0 },
226
227 { IPV6_CHECKSUM, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
228 -1 },
229
230 { ICMP6_FILTER, IPPROTO_ICMPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN|OP_VARLEN,
231 sizeof (icmp6_filter_t), 0 },
232 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
233 (OP_NODEFAULT|OP_VARLEN),
234 sizeof (struct in6_pktinfo), -1 /* not initialized */ },
235 { IPV6_HOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
236 (OP_NODEFAULT|OP_VARLEN),
237 sizeof (int), -1 /* not initialized */ },
238 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
239 (OP_NODEFAULT|OP_VARLEN),
240 sizeof (sin6_t), -1 /* not initialized */ },
241 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
242 (OP_VARLEN|OP_NODEFAULT),
243 MAX_EHDR_LEN, -1 /* not initialized */ },
244 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
245 (OP_VARLEN|OP_NODEFAULT),
246 MAX_EHDR_LEN, -1 /* not initialized */ },
247 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
248 (OP_VARLEN|OP_NODEFAULT),
249 MAX_EHDR_LEN, -1 /* not initialized */ },
250 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
251 (OP_VARLEN|OP_NODEFAULT),
252 MAX_EHDR_LEN, -1 /* not initialized */ },
253 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
254 (OP_NODEFAULT|OP_VARLEN),
255 sizeof (int), -1 /* not initialized */ },
256 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
257 sizeof (struct ip6_mtuinfo), -1 },
258 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
259 sizeof (int), 0 },
260 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
261 sizeof (int), 0 },
262 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
263 sizeof (int), 0 },
264
265 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
266 sizeof (int), 0 },
267 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
268 sizeof (int), 0 },
269 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
270 sizeof (int), 0 },
271 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
272 sizeof (int), 0 },
273 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
274 sizeof (int), 0 },
275 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
276 sizeof (int), 0 },
277 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
278 sizeof (int), 0 },
279 { IPV6_RECVPATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
280 sizeof (int), 0 },
281 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
282 sizeof (int), 0 },
283
284 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
285 sizeof (ipsec_req_t), -1 /* not initialized */ },
286 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
287 sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
288
289 { MCAST_JOIN_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
290 OP_NODEFAULT, sizeof (struct group_req),
291 -1 /* not initialized */ },
292 { MCAST_LEAVE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
293 OP_NODEFAULT, sizeof (struct group_req),
294 -1 /* not initialized */ },
295 { MCAST_BLOCK_SOURCE, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
296 OP_NODEFAULT, sizeof (struct group_source_req),
297 -1 /* not initialized */ },
298 { MCAST_UNBLOCK_SOURCE, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
299 OP_NODEFAULT, sizeof (struct group_source_req),
300 -1 /* not initialized */ },
301 { MCAST_JOIN_SOURCE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
302 OP_NODEFAULT, sizeof (struct group_source_req),
303 -1 /* not initialized */ },
304 { MCAST_LEAVE_SOURCE_GROUP, IPPROTO_IPV6, OA_X, OA_X, OP_NP,
305 OP_NODEFAULT, sizeof (struct group_source_req),
306 -1 /* not initialized */ },
307 };
308
309 /*
310 * Table of all supported levels
311 * Note: Some levels (e.g. XTI_GENERIC) may be valid but may not have
312 * any supported options so we need this info separately.
313 *
314 * This is needed only for topmost tpi providers and is used only by
315 * XTI interfaces.
316 */
317 optlevel_t icmp_valid_levels_arr[] = {
318 XTI_GENERIC,
319 SOL_SOCKET,
320 IPPROTO_ICMP,
321 IPPROTO_IP,
322 IPPROTO_IPV6,
323 IPPROTO_ICMPV6
324 };
325
326 #define ICMP_VALID_LEVELS_CNT A_CNT(icmp_valid_levels_arr)
327 #define ICMP_OPT_ARR_CNT A_CNT(icmp_opt_arr)
328
329 uint_t icmp_max_optsize; /* initialized when ICMP driver is loaded */
330
331 /*
332 * Initialize option database object for ICMP
333 *
334 * This object represents database of options to search passed to
335 * {sock,tpi}optcom_req() interface routine to take care of option
336 * management and associated methods.
337 */
338
339 optdb_obj_t icmp_opt_obj = {
340 icmp_opt_default, /* ICMP default value function pointer */
341 icmp_tpi_opt_get, /* ICMP get function pointer */
342 icmp_tpi_opt_set, /* ICMP set function pointer */
343 ICMP_OPT_ARR_CNT, /* ICMP option database count of entries */
344 icmp_opt_arr, /* ICMP option database */
345 ICMP_VALID_LEVELS_CNT, /* ICMP valid level count of entries */
346 icmp_valid_levels_arr /* ICMP valid level array */
347 };