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