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