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.
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.
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]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/stream.h>
28 #define _SUN_TPI_VERSION 2
29 #include <sys/tihdr.h>
30 #include <sys/socket.h>
31 #include <sys/xti_xtiopt.h>
32 #include <sys/xti_inet.h>
34 #include <inet/common.h>
35 #include <netinet/ip6.h>
37 #include <inet/udp_impl.h>
39 * MK_XXX Following 2 includes temporary to import ip6_rthdr_t
40 * definition. May not be needed if we fix ip6_dg_snd_attrs_t
41 * to do all extension headers in identical manner.
46 #include <netinet/in.h>
47 #include <netinet/udp.h>
48 #include <inet/optcom.h>
51 * Table of all known options handled on a UDP protocol stack.
53 * Note: This table contains options processed by both UDP and IP levels
54 * and is the superset of options that can be performed on a UDP over IP
57 opdes_t udp_opt_arr
[] = {
59 { SO_DEBUG
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
60 { SO_DONTROUTE
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
61 { SO_USELOOPBACK
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
63 { SO_BROADCAST
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
64 { SO_REUSEADDR
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
65 { SO_TYPE
, SOL_SOCKET
, OA_R
, OA_R
, OP_NP
, 0, sizeof (int), 0 },
66 { SO_SNDBUF
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
67 { SO_RCVBUF
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
68 { SO_SNDTIMEO
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0,
69 sizeof (struct timeval
), 0 },
70 { SO_RCVTIMEO
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0,
71 sizeof (struct timeval
), 0 },
72 { SO_DGRAM_ERRIND
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int),
74 { SO_RECVUCRED
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
76 { SO_ALLZONES
, SOL_SOCKET
, OA_R
, OA_RW
, OP_CONFIG
, 0, sizeof (int),
78 { SO_VRRP
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_CONFIG
, 0, sizeof (int), 0 },
79 { SO_TIMESTAMP
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
82 * The maximum size reported here depends on the maximum value for
83 * ucredsize; unfortunately, we can't add ucredsize here so we need
84 * to estimate here. Before it was 512 or 384 + NGROUPS_UMAX * sizeof (gid_t);
85 * as we're changing NGROUPS_UMAX we now codify this here using NGROUPS_UMAX.
87 { SCM_UCRED
, SOL_SOCKET
, OA_W
, OA_W
, OP_NP
, OP_VARLEN
|OP_NODEFAULT
,
88 384 + NGROUPS_UMAX
* sizeof (gid_t
), 0 },
89 { SO_EXCLBIND
, SOL_SOCKET
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
90 { SO_DOMAIN
, SOL_SOCKET
, OA_R
, OA_R
, OP_NP
, 0, sizeof (int), 0 },
91 { SO_PROTOTYPE
, SOL_SOCKET
, OA_R
, OA_R
, OP_NP
, 0, sizeof (int), 0 },
93 { IP_OPTIONS
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
,
94 (OP_VARLEN
|OP_NODEFAULT
),
95 IP_MAX_OPT_LENGTH
+ IP_ADDR_LEN
, -1 /* not initialized */ },
96 { T_IP_OPTIONS
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
,
97 (OP_VARLEN
|OP_NODEFAULT
),
98 IP_MAX_OPT_LENGTH
+ IP_ADDR_LEN
, -1 /* not initialized */ },
100 { IP_TOS
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
101 { T_IP_TOS
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
102 { IP_TTL
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
103 { IP_RECVOPTS
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
104 { IP_RECVDSTADDR
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
106 { IP_RECVIF
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
107 { IP_RECVSLLA
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
108 { IP_RECVTTL
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int),
110 { IP_MULTICAST_IF
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0,
111 sizeof (struct in_addr
), 0 /* INADDR_ANY */ },
113 { IP_MULTICAST_LOOP
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, OP_DEF_FN
,
114 sizeof (uchar_t
), -1 /* not initialized */},
116 { IP_MULTICAST_TTL
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, OP_DEF_FN
,
117 sizeof (uchar_t
), -1 /* not initialized */ },
119 { IP_ADD_MEMBERSHIP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
, OP_NODEFAULT
,
120 sizeof (struct ip_mreq
), -1 /* not initialized */ },
122 { IP_DROP_MEMBERSHIP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
, OP_NODEFAULT
,
123 sizeof (struct ip_mreq
), -1 /* not initialized */ },
125 { IP_BLOCK_SOURCE
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
, OP_NODEFAULT
,
126 sizeof (struct ip_mreq_source
), -1 /* not initialized */ },
128 { IP_UNBLOCK_SOURCE
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
, OP_NODEFAULT
,
129 sizeof (struct ip_mreq_source
), -1 /* not initialized */ },
131 { IP_ADD_SOURCE_MEMBERSHIP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
132 OP_NODEFAULT
, sizeof (struct ip_mreq_source
), -1 },
134 { IP_DROP_SOURCE_MEMBERSHIP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
135 OP_NODEFAULT
, sizeof (struct ip_mreq_source
), -1 },
137 { IP_SEC_OPT
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, OP_NODEFAULT
,
138 sizeof (ipsec_req_t
), -1 /* not initialized */ },
140 { IP_BOUND_IF
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0,
141 sizeof (int), 0 /* no ifindex */ },
143 { IP_DHCPINIT_IF
, IPPROTO_IP
, OA_R
, OA_RW
, OP_CONFIG
, 0,
146 { IP_UNSPEC_SRC
, IPPROTO_IP
, OA_R
, OA_RW
, OP_RAW
, 0,
149 { IP_BROADCAST_TTL
, IPPROTO_IP
, OA_R
, OA_RW
, OP_RAW
, 0, sizeof (uchar_t
),
152 { IP_PKTINFO
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
,
153 (OP_NODEFAULT
|OP_VARLEN
),
154 sizeof (struct in_pktinfo
), -1 /* not initialized */ },
155 { IP_NEXTHOP
, IPPROTO_IP
, OA_R
, OA_RW
, OP_CONFIG
, 0,
156 sizeof (in_addr_t
), -1 /* not initialized */ },
158 { IP_DONTFRAG
, IPPROTO_IP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0 },
160 { MCAST_JOIN_GROUP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
161 OP_NODEFAULT
, sizeof (struct group_req
),
162 -1 /* not initialized */ },
163 { MCAST_LEAVE_GROUP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
164 OP_NODEFAULT
, sizeof (struct group_req
),
165 -1 /* not initialized */ },
166 { MCAST_BLOCK_SOURCE
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
167 OP_NODEFAULT
, sizeof (struct group_source_req
),
168 -1 /* not initialized */ },
169 { MCAST_UNBLOCK_SOURCE
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
170 OP_NODEFAULT
, sizeof (struct group_source_req
),
171 -1 /* not initialized */ },
172 { MCAST_JOIN_SOURCE_GROUP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
173 OP_NODEFAULT
, sizeof (struct group_source_req
),
174 -1 /* not initialized */ },
175 { MCAST_LEAVE_SOURCE_GROUP
, IPPROTO_IP
, OA_X
, OA_X
, OP_NP
,
176 OP_NODEFAULT
, sizeof (struct group_source_req
),
177 -1 /* not initialized */ },
179 { IPV6_MULTICAST_IF
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
182 { IPV6_MULTICAST_HOPS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
183 OP_DEF_FN
, sizeof (int), -1 /* not initialized */ },
185 { IPV6_MULTICAST_LOOP
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
186 OP_DEF_FN
, sizeof (int), -1 /* not initialized */},
188 { IPV6_JOIN_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
, OP_NODEFAULT
,
189 sizeof (struct ipv6_mreq
), -1 /* not initialized */ },
191 { IPV6_LEAVE_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
193 sizeof (struct ipv6_mreq
), -1 /* not initialized */ },
195 { IPV6_UNICAST_HOPS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, OP_DEF_FN
,
196 sizeof (int), -1 /* not initialized */ },
198 { IPV6_BOUND_IF
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
199 sizeof (int), 0 /* no ifindex */ },
201 { IPV6_UNSPEC_SRC
, IPPROTO_IPV6
, OA_R
, OA_RW
, OP_RAW
, 0,
204 { IPV6_PKTINFO
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
205 (OP_NODEFAULT
|OP_VARLEN
),
206 sizeof (struct in6_pktinfo
), -1 /* not initialized */ },
207 { IPV6_HOPLIMIT
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
209 sizeof (int), -1 /* not initialized */ },
210 { IPV6_NEXTHOP
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
211 (OP_NODEFAULT
|OP_VARLEN
),
212 sizeof (sin6_t
), -1 /* not initialized */ },
213 { IPV6_HOPOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
214 (OP_VARLEN
|OP_NODEFAULT
),
215 MAX_EHDR_LEN
, -1 /* not initialized */ },
216 { IPV6_DSTOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
217 (OP_VARLEN
|OP_NODEFAULT
),
218 MAX_EHDR_LEN
, -1 /* not initialized */ },
219 { IPV6_RTHDRDSTOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
220 (OP_VARLEN
|OP_NODEFAULT
),
221 MAX_EHDR_LEN
, -1 /* not initialized */ },
222 { IPV6_RTHDR
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
223 (OP_VARLEN
|OP_NODEFAULT
),
224 MAX_EHDR_LEN
, -1 /* not initialized */ },
225 { IPV6_TCLASS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
227 sizeof (int), -1 /* not initialized */ },
228 { IPV6_PATHMTU
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
230 sizeof (struct ip6_mtuinfo
), -1 },
231 { IPV6_DONTFRAG
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
233 { IPV6_USE_MIN_MTU
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
235 { IPV6_V6ONLY
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
238 { IPV6_RECVPKTINFO
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
240 { IPV6_RECVHOPLIMIT
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
242 { IPV6_RECVHOPOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
244 { _OLD_IPV6_RECVDSTOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
246 { IPV6_RECVDSTOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
248 { IPV6_RECVRTHDR
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
250 { IPV6_RECVRTHDRDSTOPTS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
252 { IPV6_RECVPATHMTU
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
,
253 0, sizeof (int), 0 },
254 { IPV6_RECVTCLASS
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
257 { IPV6_SEC_OPT
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, OP_NODEFAULT
,
258 sizeof (ipsec_req_t
), -1 /* not initialized */ },
259 { IPV6_SRC_PREFERENCES
, IPPROTO_IPV6
, OA_RW
, OA_RW
, OP_NP
, 0,
260 sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT
},
262 { MCAST_JOIN_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
263 OP_NODEFAULT
, sizeof (struct group_req
),
264 -1 /* not initialized */ },
265 { MCAST_LEAVE_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
266 OP_NODEFAULT
, sizeof (struct group_req
),
267 -1 /* not initialized */ },
268 { MCAST_BLOCK_SOURCE
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
269 OP_NODEFAULT
, sizeof (struct group_source_req
),
270 -1 /* not initialized */ },
271 { MCAST_UNBLOCK_SOURCE
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
272 OP_NODEFAULT
, sizeof (struct group_source_req
),
273 -1 /* not initialized */ },
274 { MCAST_JOIN_SOURCE_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
275 OP_NODEFAULT
, sizeof (struct group_source_req
),
276 -1 /* not initialized */ },
277 { MCAST_LEAVE_SOURCE_GROUP
, IPPROTO_IPV6
, OA_X
, OA_X
, OP_NP
,
278 OP_NODEFAULT
, sizeof (struct group_source_req
),
279 -1 /* not initialized */ },
281 { UDP_ANONPRIVBIND
, IPPROTO_UDP
, OA_R
, OA_RW
, OP_PRIVPORT
, 0,
283 { UDP_EXCLBIND
, IPPROTO_UDP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
285 { UDP_RCVHDR
, IPPROTO_UDP
, OA_RW
, OA_RW
, OP_NP
, 0, sizeof (int), 0
287 { UDP_NAT_T_ENDPOINT
, IPPROTO_UDP
, OA_RW
, OA_RW
, OP_PRIVPORT
, 0, sizeof (int),
292 * Table of all supported levels
293 * Note: Some levels (e.g. XTI_GENERIC) may be valid but may not have
294 * any supported options so we need this info separately.
296 * This is needed only for topmost tpi providers and is used only by
299 optlevel_t udp_valid_levels_arr
[] = {
307 #define UDP_VALID_LEVELS_CNT A_CNT(udp_valid_levels_arr)
308 #define UDP_OPT_ARR_CNT A_CNT(udp_opt_arr)
310 uint_t udp_max_optsize
; /* initialized when UDP driver is loaded */
313 * Initialize option database object for UDP
315 * This object represents database of options to search passed to
316 * {sock,tpi}optcom_req() interface routine to take care of option
317 * management and associated methods.
320 optdb_obj_t udp_opt_obj
= {
321 udp_opt_default
, /* UDP default value function pointer */
322 udp_tpi_opt_get
, /* UDP get function pointer */
323 udp_tpi_opt_set
, /* UDP set function pointer */
324 UDP_OPT_ARR_CNT
, /* UDP option database count of entries */
325 udp_opt_arr
, /* UDP option database */
326 UDP_VALID_LEVELS_CNT
, /* UDP valid level count of entries */
327 udp_valid_levels_arr
/* UDP valid level array */