Print this page
7127 remove -Wno-missing-braces from Makefile.uts
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/tcp/tcp_opt_data.c
+++ new/usr/src/uts/common/inet/tcp/tcp_opt_data.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 #include <sys/types.h>
27 27 #include <sys/stream.h>
28 28 #define _SUN_TPI_VERSION 2
29 29 #include <sys/tihdr.h>
30 30 #include <sys/socket.h>
31 31 #include <sys/xti_xtiopt.h>
32 32 #include <sys/xti_inet.h>
33 33 #include <sys/policy.h>
34 34
35 35 #include <inet/common.h>
36 36 #include <netinet/ip6.h>
37 37 #include <inet/ip.h>
38 38
39 39 #include <netinet/in.h>
40 40 #include <netinet/tcp.h>
41 41 #include <inet/optcom.h>
42 42 #include <inet/proto_set.h>
43 43 #include <inet/tcp_impl.h>
44 44
45 45 static int tcp_opt_default(queue_t *, int, int, uchar_t *);
46 46
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
47 47 /*
48 48 * Table of all known options handled on a TCP protocol stack.
49 49 *
50 50 * Note: This table contains options processed by both TCP and IP levels
51 51 * and is the superset of options that can be performed on a TCP over IP
52 52 * stack.
53 53 */
54 54 opdes_t tcp_opt_arr[] = {
55 55
56 56 { SO_LINGER, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
57 - sizeof (struct linger), 0 },
57 + sizeof (struct linger), {0}},
58 58
59 -{ SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
60 -{ SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
61 -{ SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
62 -{ SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
59 +{ SO_DEBUG, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
60 +{ SO_KEEPALIVE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
61 +{ SO_DONTROUTE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
62 +{ SO_USELOOPBACK, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
63 63 },
64 -{ SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
65 -{ SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
66 -{ SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
67 -{ SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
68 -{ SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
69 -{ SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
64 +{ SO_BROADCAST, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
65 +{ SO_REUSEADDR, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
66 +{ SO_OOBINLINE, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
67 +{ SO_TYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
68 +{ SO_SNDBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
69 +{ SO_RCVBUF, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
70 70 { SO_SNDTIMEO, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
71 - sizeof (struct timeval), 0 },
71 + sizeof (struct timeval), {0}},
72 72 { SO_RCVTIMEO, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0,
73 - sizeof (struct timeval), 0 },
74 -{ SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
73 + sizeof (struct timeval), {0}},
74 +{ SO_DGRAM_ERRIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
75 75 },
76 -{ SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
76 +{ SO_SND_COPYAVOID, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
77 77 { SO_ANON_MLP, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
78 - 0 },
78 + {0}},
79 79 { SO_MAC_EXEMPT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
80 - 0 },
80 + {0}},
81 81 { SO_MAC_IMPLICIT, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
82 - 0 },
82 + {0}},
83 83 { SO_ALLZONES, SOL_SOCKET, OA_R, OA_RW, OP_CONFIG, 0, sizeof (int),
84 - 0 },
85 -{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
84 + {0}},
85 +{ SO_EXCLBIND, SOL_SOCKET, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
86 86
87 -{ SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
87 +{ SO_DOMAIN, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
88 88
89 -{ SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), 0 },
89 +{ SO_PROTOTYPE, SOL_SOCKET, OA_R, OA_R, OP_NP, 0, sizeof (int), {0}},
90 90
91 -{ TCP_NODELAY, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
91 +{ TCP_NODELAY, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
92 92 },
93 93 { TCP_MAXSEG, IPPROTO_TCP, OA_R, OA_R, OP_NP, 0, sizeof (uint_t),
94 - 536 },
94 + {536} },
95 95
96 96 { TCP_NOTIFY_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
97 - OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
97 + OP_DEF_FN, sizeof (int), {-1}/* not initialized */ },
98 98
99 99 { TCP_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
100 - OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
100 + OP_DEF_FN, sizeof (int), {-1}/* not initialized */ },
101 101
102 102 { TCP_CONN_NOTIFY_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
103 - OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
103 + OP_DEF_FN, sizeof (int), {-1}/* not initialized */ },
104 104
105 105 { TCP_CONN_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
106 - OP_DEF_FN, sizeof (int), -1 /* not initialized */ },
106 + OP_DEF_FN, sizeof (int), {-1}/* not initialized */ },
107 107
108 108 { TCP_RECVDSTADDR, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int),
109 - 0 },
109 + {0}},
110 110
111 111 { TCP_ANONPRIVBIND, IPPROTO_TCP, OA_R, OA_RW, OP_PRIVPORT, 0,
112 - sizeof (int), 0 },
112 + sizeof (int), {0}},
113 113
114 -{ TCP_EXCLBIND, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0
114 +{ TCP_EXCLBIND, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}
115 115 },
116 116
117 117 { TCP_INIT_CWND, IPPROTO_TCP, OA_RW, OA_RW, OP_CONFIG, 0,
118 - sizeof (int), 0 },
118 + sizeof (int), {0}},
119 119
120 120 { TCP_KEEPALIVE_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0,
121 - sizeof (int), 0 },
121 + sizeof (int), {0}},
122 122
123 -{ TCP_KEEPIDLE, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
123 +{ TCP_KEEPIDLE, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
124 124
125 -{ TCP_KEEPCNT, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
125 +{ TCP_KEEPCNT, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
126 126
127 -{ TCP_KEEPINTVL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
127 +{ TCP_KEEPINTVL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
128 128
129 129 { TCP_KEEPALIVE_ABORT_THRESHOLD, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0,
130 - sizeof (int), 0 },
130 + sizeof (int), {0}},
131 131
132 -{ TCP_CORK, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
132 +{ TCP_CORK, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
133 133
134 -{ TCP_RTO_INITIAL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
134 +{ TCP_RTO_INITIAL, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), {0}},
135 135
136 -{ TCP_RTO_MIN, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
136 +{ TCP_RTO_MIN, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), {0}},
137 137
138 -{ TCP_RTO_MAX, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
138 +{ TCP_RTO_MAX, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), {0}},
139 139
140 -{ TCP_LINGER2, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
140 +{ TCP_LINGER2, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
141 141
142 142 { IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
143 143 (OP_VARLEN|OP_NODEFAULT),
144 - IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
144 + IP_MAX_OPT_LENGTH + IP_ADDR_LEN, {-1}/* not initialized */ },
145 145 { T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
146 146 (OP_VARLEN|OP_NODEFAULT),
147 - IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
147 + IP_MAX_OPT_LENGTH + IP_ADDR_LEN, {-1}/* not initialized */ },
148 148
149 -{ IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
150 -{ T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
149 +{ IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
150 +{ T_IP_TOS, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
151 151 { IP_TTL, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
152 - sizeof (int), -1 /* not initialized */ },
152 + sizeof (int), {-1}/* not initialized */ },
153 153
154 154 { IP_SEC_OPT, IPPROTO_IP, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
155 - sizeof (ipsec_req_t), -1 /* not initialized */ },
155 + sizeof (ipsec_req_t), {-1}/* not initialized */ },
156 156
157 157 { IP_BOUND_IF, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0,
158 - sizeof (int), 0 /* no ifindex */ },
158 + sizeof (int), {0} /* no ifindex */ },
159 159
160 160 { IP_UNSPEC_SRC, IPPROTO_IP, OA_R, OA_RW, OP_RAW, 0,
161 - sizeof (int), 0 },
161 + sizeof (int), {0}},
162 162
163 163 { IPV6_UNICAST_HOPS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_DEF_FN,
164 - sizeof (int), -1 /* not initialized */ },
164 + sizeof (int), {-1}/* not initialized */ },
165 165
166 166 { IPV6_BOUND_IF, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
167 - sizeof (int), 0 /* no ifindex */ },
167 + sizeof (int), {0} /* no ifindex */ },
168 168
169 -{ IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
169 +{ IP_DONTFRAG, IPPROTO_IP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), {0}},
170 170
171 171 { IP_NEXTHOP, IPPROTO_IP, OA_R, OA_RW, OP_CONFIG, 0,
172 - sizeof (in_addr_t), -1 /* not initialized */ },
172 + sizeof (in_addr_t), {-1} /* not initialized */ },
173 173
174 174 { IPV6_UNSPEC_SRC, IPPROTO_IPV6, OA_R, OA_RW, OP_RAW, 0,
175 - sizeof (int), 0 },
175 + sizeof (int), {0}},
176 176
177 177 { IPV6_PKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
178 178 (OP_NODEFAULT|OP_VARLEN),
179 - sizeof (struct in6_pktinfo), -1 /* not initialized */ },
179 + sizeof (struct in6_pktinfo), {-1}/* not initialized */ },
180 180 { IPV6_NEXTHOP, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
181 181 OP_NODEFAULT,
182 - sizeof (sin6_t), -1 /* not initialized */ },
182 + sizeof (sin6_t), {-1}/* not initialized */ },
183 183 { IPV6_HOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
184 184 (OP_VARLEN|OP_NODEFAULT), 255*8,
185 - -1 /* not initialized */ },
185 + {-1} /* not initialized */ },
186 186 { IPV6_DSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
187 187 (OP_VARLEN|OP_NODEFAULT), 255*8,
188 - -1 /* not initialized */ },
188 + {-1} /* not initialized */ },
189 189 { IPV6_RTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
190 190 (OP_VARLEN|OP_NODEFAULT), 255*8,
191 - -1 /* not initialized */ },
191 + {-1} /* not initialized */ },
192 192 { IPV6_RTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
193 193 (OP_VARLEN|OP_NODEFAULT), 255*8,
194 - -1 /* not initialized */ },
194 + {-1} /* not initialized */ },
195 195 { IPV6_TCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
196 196 OP_NODEFAULT,
197 - sizeof (int), -1 /* not initialized */ },
197 + sizeof (int), {-1}/* not initialized */ },
198 198 { IPV6_PATHMTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP,
199 199 OP_NODEFAULT,
200 - sizeof (struct ip6_mtuinfo), -1 /* not initialized */ },
200 + sizeof (struct ip6_mtuinfo), {-1}/* not initialized */ },
201 201 { IPV6_DONTFRAG, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
202 - sizeof (int), 0 },
202 + sizeof (int), {0}},
203 203 { IPV6_USE_MIN_MTU, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
204 - sizeof (int), 0 },
204 + sizeof (int), {0}},
205 205 { IPV6_V6ONLY, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
206 - sizeof (int), 0 },
206 + sizeof (int), {0}},
207 207
208 208 /* Enable receipt of ancillary data */
209 209 { IPV6_RECVPKTINFO, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
210 - sizeof (int), 0 },
210 + sizeof (int), {0}},
211 211 { IPV6_RECVHOPLIMIT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
212 - sizeof (int), 0 },
212 + sizeof (int), {0}},
213 213 { IPV6_RECVHOPOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
214 - sizeof (int), 0 },
214 + sizeof (int), {0}},
215 215 { _OLD_IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
216 - sizeof (int), 0 },
216 + sizeof (int), {0}},
217 217 { IPV6_RECVDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
218 - sizeof (int), 0 },
218 + sizeof (int), {0}},
219 219 { IPV6_RECVRTHDR, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
220 - sizeof (int), 0 },
220 + sizeof (int), {0}},
221 221 { IPV6_RECVRTHDRDSTOPTS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
222 - sizeof (int), 0 },
222 + sizeof (int), {0}},
223 223 { IPV6_RECVTCLASS, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
224 - sizeof (int), 0 },
224 + sizeof (int), {0}},
225 225
226 226 { IPV6_SEC_OPT, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, OP_NODEFAULT,
227 - sizeof (ipsec_req_t), -1 /* not initialized */ },
227 + sizeof (ipsec_req_t), {-1}/* not initialized */ },
228 228 { IPV6_SRC_PREFERENCES, IPPROTO_IPV6, OA_RW, OA_RW, OP_NP, 0,
229 - sizeof (uint32_t), IPV6_PREFER_SRC_DEFAULT },
229 + sizeof (uint32_t), {IPV6_PREFER_SRC_DEFAULT} },
230 230 };
231 231
232 232 /*
233 233 * Table of all supported levels
234 234 * Note: Some levels (e.g. XTI_GENERIC) may be valid but may not have
235 235 * any supported options so we need this info separately.
236 236 *
237 237 * This is needed only for topmost tpi providers and is used only by
238 238 * XTI interfaces.
239 239 */
240 240 optlevel_t tcp_valid_levels_arr[] = {
241 241 XTI_GENERIC,
242 242 SOL_SOCKET,
243 243 IPPROTO_TCP,
244 244 IPPROTO_IP,
245 245 IPPROTO_IPV6
246 246 };
247 247
248 248
249 249 #define TCP_OPT_ARR_CNT A_CNT(tcp_opt_arr)
250 250 #define TCP_VALID_LEVELS_CNT A_CNT(tcp_valid_levels_arr)
251 251
252 252 uint_t tcp_max_optsize; /* initialized when TCP driver is loaded */
253 253
254 254 /*
255 255 * Initialize option database object for TCP
256 256 *
257 257 * This object represents database of options to search passed to
258 258 * {sock,tpi}optcom_req() interface routine to take care of option
259 259 * management and associated methods.
260 260 */
261 261
262 262 optdb_obj_t tcp_opt_obj = {
263 263 tcp_opt_default, /* TCP default value function pointer */
264 264 tcp_tpi_opt_get, /* TCP get function pointer */
265 265 tcp_tpi_opt_set, /* TCP set function pointer */
266 266 TCP_OPT_ARR_CNT, /* TCP option database count of entries */
267 267 tcp_opt_arr, /* TCP option database */
268 268 TCP_VALID_LEVELS_CNT, /* TCP valid level count of entries */
269 269 tcp_valid_levels_arr /* TCP valid level array */
270 270 };
271 271
272 272 static int tcp_max_init_cwnd = TCP_MAX_INIT_CWND;
273 273
274 274 /*
275 275 * Some TCP options can be "set" by requesting them in the option
276 276 * buffer. This is needed for XTI feature test though we do not
277 277 * allow it in general. We interpret that this mechanism is more
278 278 * applicable to OSI protocols and need not be allowed in general.
279 279 * This routine filters out options for which it is not allowed (most)
280 280 * and lets through those (few) for which it is. [ The XTI interface
281 281 * test suite specifics will imply that any XTI_GENERIC level XTI_* if
282 282 * ever implemented will have to be allowed here ].
283 283 */
284 284 static boolean_t
285 285 tcp_allow_connopt_set(int level, int name)
286 286 {
287 287
288 288 switch (level) {
289 289 case IPPROTO_TCP:
290 290 switch (name) {
291 291 case TCP_NODELAY:
292 292 return (B_TRUE);
293 293 default:
294 294 return (B_FALSE);
295 295 }
296 296 /*NOTREACHED*/
297 297 default:
298 298 return (B_FALSE);
299 299 }
300 300 /*NOTREACHED*/
301 301 }
302 302
303 303 /*
304 304 * This routine gets default values of certain options whose default
305 305 * values are maintained by protocol specific code
306 306 */
307 307 /* ARGSUSED */
308 308 static int
309 309 tcp_opt_default(queue_t *q, int level, int name, uchar_t *ptr)
310 310 {
311 311 int32_t *i1 = (int32_t *)ptr;
312 312 tcp_stack_t *tcps = Q_TO_TCP(q)->tcp_tcps;
313 313
314 314 switch (level) {
315 315 case IPPROTO_TCP:
316 316 switch (name) {
317 317 case TCP_NOTIFY_THRESHOLD:
318 318 *i1 = tcps->tcps_ip_notify_interval;
319 319 break;
320 320 case TCP_ABORT_THRESHOLD:
321 321 *i1 = tcps->tcps_ip_abort_interval;
322 322 break;
323 323 case TCP_CONN_NOTIFY_THRESHOLD:
324 324 *i1 = tcps->tcps_ip_notify_cinterval;
325 325 break;
326 326 case TCP_CONN_ABORT_THRESHOLD:
327 327 *i1 = tcps->tcps_ip_abort_cinterval;
328 328 break;
329 329 default:
330 330 return (-1);
331 331 }
332 332 break;
333 333 case IPPROTO_IP:
334 334 switch (name) {
335 335 case IP_TTL:
336 336 *i1 = tcps->tcps_ipv4_ttl;
337 337 break;
338 338 default:
339 339 return (-1);
340 340 }
341 341 break;
342 342 case IPPROTO_IPV6:
343 343 switch (name) {
344 344 case IPV6_UNICAST_HOPS:
345 345 *i1 = tcps->tcps_ipv6_hoplimit;
346 346 break;
347 347 default:
348 348 return (-1);
349 349 }
350 350 break;
351 351 default:
352 352 return (-1);
353 353 }
354 354 return (sizeof (int));
355 355 }
356 356
357 357 /*
358 358 * TCP routine to get the values of options.
359 359 */
360 360 int
361 361 tcp_opt_get(conn_t *connp, int level, int name, uchar_t *ptr)
362 362 {
363 363 int *i1 = (int *)ptr;
364 364 tcp_t *tcp = connp->conn_tcp;
365 365 conn_opt_arg_t coas;
366 366 int retval;
367 367
368 368 coas.coa_connp = connp;
369 369 coas.coa_ixa = connp->conn_ixa;
370 370 coas.coa_ipp = &connp->conn_xmit_ipp;
371 371 coas.coa_ancillary = B_FALSE;
372 372 coas.coa_changed = 0;
373 373
374 374 switch (level) {
375 375 case SOL_SOCKET:
376 376 switch (name) {
377 377 case SO_SND_COPYAVOID:
378 378 *i1 = tcp->tcp_snd_zcopy_on ?
379 379 SO_SND_COPYAVOID : 0;
380 380 return (sizeof (int));
381 381 case SO_ACCEPTCONN:
382 382 *i1 = (tcp->tcp_state == TCPS_LISTEN);
383 383 return (sizeof (int));
384 384 }
385 385 break;
386 386 case IPPROTO_TCP:
387 387 switch (name) {
388 388 case TCP_NODELAY:
389 389 *i1 = (tcp->tcp_naglim == 1) ? TCP_NODELAY : 0;
390 390 return (sizeof (int));
391 391 case TCP_MAXSEG:
392 392 *i1 = tcp->tcp_mss;
393 393 return (sizeof (int));
394 394 case TCP_NOTIFY_THRESHOLD:
395 395 *i1 = (int)tcp->tcp_first_timer_threshold;
396 396 return (sizeof (int));
397 397 case TCP_ABORT_THRESHOLD:
398 398 *i1 = tcp->tcp_second_timer_threshold;
399 399 return (sizeof (int));
400 400 case TCP_CONN_NOTIFY_THRESHOLD:
401 401 *i1 = tcp->tcp_first_ctimer_threshold;
402 402 return (sizeof (int));
403 403 case TCP_CONN_ABORT_THRESHOLD:
404 404 *i1 = tcp->tcp_second_ctimer_threshold;
405 405 return (sizeof (int));
406 406 case TCP_INIT_CWND:
407 407 *i1 = tcp->tcp_init_cwnd;
408 408 return (sizeof (int));
409 409 case TCP_KEEPALIVE_THRESHOLD:
410 410 *i1 = tcp->tcp_ka_interval;
411 411 return (sizeof (int));
412 412
413 413 /*
414 414 * TCP_KEEPIDLE expects value in seconds, but
415 415 * tcp_ka_interval is in milliseconds.
416 416 */
417 417 case TCP_KEEPIDLE:
418 418 *i1 = tcp->tcp_ka_interval / 1000;
419 419 return (sizeof (int));
420 420 case TCP_KEEPCNT:
421 421 *i1 = tcp->tcp_ka_cnt;
422 422 return (sizeof (int));
423 423
424 424 /*
425 425 * TCP_KEEPINTVL expects value in seconds, but
426 426 * tcp_ka_rinterval is in milliseconds.
427 427 */
428 428 case TCP_KEEPINTVL:
429 429 *i1 = tcp->tcp_ka_rinterval / 1000;
430 430 return (sizeof (int));
431 431 case TCP_KEEPALIVE_ABORT_THRESHOLD:
432 432 *i1 = tcp->tcp_ka_abort_thres;
433 433 return (sizeof (int));
434 434 case TCP_CORK:
435 435 *i1 = tcp->tcp_cork;
436 436 return (sizeof (int));
437 437 case TCP_RTO_INITIAL:
438 438 *i1 = tcp->tcp_rto_initial;
439 439 return (sizeof (uint32_t));
440 440 case TCP_RTO_MIN:
441 441 *i1 = tcp->tcp_rto_min;
442 442 return (sizeof (uint32_t));
443 443 case TCP_RTO_MAX:
444 444 *i1 = tcp->tcp_rto_max;
445 445 return (sizeof (uint32_t));
446 446 case TCP_LINGER2:
447 447 *i1 = tcp->tcp_fin_wait_2_flush_interval / SECONDS;
448 448 return (sizeof (int));
449 449 }
450 450 break;
451 451 case IPPROTO_IP:
452 452 if (connp->conn_family != AF_INET)
453 453 return (-1);
454 454 switch (name) {
455 455 case IP_OPTIONS:
456 456 case T_IP_OPTIONS:
457 457 /* Caller ensures enough space */
458 458 return (ip_opt_get_user(connp, ptr));
459 459 default:
460 460 break;
461 461 }
462 462 break;
463 463
464 464 case IPPROTO_IPV6:
465 465 /*
466 466 * IPPROTO_IPV6 options are only supported for sockets
467 467 * that are using IPv6 on the wire.
468 468 */
469 469 if (connp->conn_ipversion != IPV6_VERSION) {
470 470 return (-1);
471 471 }
472 472 switch (name) {
473 473 case IPV6_PATHMTU:
474 474 if (tcp->tcp_state < TCPS_ESTABLISHED)
475 475 return (-1);
476 476 break;
477 477 }
478 478 break;
479 479 }
480 480 mutex_enter(&connp->conn_lock);
481 481 retval = conn_opt_get(&coas, level, name, ptr);
482 482 mutex_exit(&connp->conn_lock);
483 483 return (retval);
484 484 }
485 485
486 486 /*
487 487 * We declare as 'int' rather than 'void' to satisfy pfi_t arg requirements.
488 488 * Parameters are assumed to be verified by the caller.
489 489 */
490 490 /* ARGSUSED */
491 491 int
492 492 tcp_opt_set(conn_t *connp, uint_t optset_context, int level, int name,
493 493 uint_t inlen, uchar_t *invalp, uint_t *outlenp, uchar_t *outvalp,
494 494 void *thisdg_attrs, cred_t *cr)
495 495 {
496 496 tcp_t *tcp = connp->conn_tcp;
497 497 int *i1 = (int *)invalp;
498 498 boolean_t onoff = (*i1 == 0) ? 0 : 1;
499 499 boolean_t checkonly;
500 500 int reterr;
501 501 tcp_stack_t *tcps = tcp->tcp_tcps;
502 502 conn_opt_arg_t coas;
503 503 uint32_t val = *((uint32_t *)invalp);
504 504
505 505 coas.coa_connp = connp;
506 506 coas.coa_ixa = connp->conn_ixa;
507 507 coas.coa_ipp = &connp->conn_xmit_ipp;
508 508 coas.coa_ancillary = B_FALSE;
509 509 coas.coa_changed = 0;
510 510
511 511 switch (optset_context) {
512 512 case SETFN_OPTCOM_CHECKONLY:
513 513 checkonly = B_TRUE;
514 514 /*
515 515 * Note: Implies T_CHECK semantics for T_OPTCOM_REQ
516 516 * inlen != 0 implies value supplied and
517 517 * we have to "pretend" to set it.
518 518 * inlen == 0 implies that there is no
519 519 * value part in T_CHECK request and just validation
520 520 * done elsewhere should be enough, we just return here.
521 521 */
522 522 if (inlen == 0) {
523 523 *outlenp = 0;
524 524 return (0);
525 525 }
526 526 break;
527 527 case SETFN_OPTCOM_NEGOTIATE:
528 528 checkonly = B_FALSE;
529 529 break;
530 530 case SETFN_UD_NEGOTIATE: /* error on conn-oriented transports ? */
531 531 case SETFN_CONN_NEGOTIATE:
532 532 checkonly = B_FALSE;
533 533 /*
534 534 * Negotiating local and "association-related" options
535 535 * from other (T_CONN_REQ, T_CONN_RES,T_UNITDATA_REQ)
536 536 * primitives is allowed by XTI, but we choose
537 537 * to not implement this style negotiation for Internet
538 538 * protocols (We interpret it is a must for OSI world but
539 539 * optional for Internet protocols) for all options.
540 540 * [ Will do only for the few options that enable test
541 541 * suites that our XTI implementation of this feature
542 542 * works for transports that do allow it ]
543 543 */
544 544 if (!tcp_allow_connopt_set(level, name)) {
545 545 *outlenp = 0;
546 546 return (EINVAL);
547 547 }
548 548 break;
549 549 default:
550 550 /*
551 551 * We should never get here
552 552 */
553 553 *outlenp = 0;
554 554 return (EINVAL);
555 555 }
556 556
557 557 ASSERT((optset_context != SETFN_OPTCOM_CHECKONLY) ||
558 558 (optset_context == SETFN_OPTCOM_CHECKONLY && inlen != 0));
559 559
560 560 /*
561 561 * For TCP, we should have no ancillary data sent down
562 562 * (sendmsg isn't supported for SOCK_STREAM), so thisdg_attrs
563 563 * has to be zero.
564 564 */
565 565 ASSERT(thisdg_attrs == NULL);
566 566
567 567 /*
568 568 * For fixed length options, no sanity check
569 569 * of passed in length is done. It is assumed *_optcom_req()
570 570 * routines do the right thing.
571 571 */
572 572 switch (level) {
573 573 case SOL_SOCKET:
574 574 switch (name) {
575 575 case SO_KEEPALIVE:
576 576 if (checkonly) {
577 577 /* check only case */
578 578 break;
579 579 }
580 580
581 581 if (!onoff) {
582 582 if (connp->conn_keepalive) {
583 583 if (tcp->tcp_ka_tid != 0) {
584 584 (void) TCP_TIMER_CANCEL(tcp,
585 585 tcp->tcp_ka_tid);
586 586 tcp->tcp_ka_tid = 0;
587 587 }
588 588 connp->conn_keepalive = 0;
589 589 }
590 590 break;
591 591 }
592 592 if (!connp->conn_keepalive) {
593 593 /* Crank up the keepalive timer */
594 594 tcp->tcp_ka_last_intrvl = 0;
595 595 tcp->tcp_ka_tid = TCP_TIMER(tcp,
596 596 tcp_keepalive_timer, tcp->tcp_ka_interval);
597 597 connp->conn_keepalive = 1;
598 598 }
599 599 break;
600 600 case SO_SNDBUF: {
601 601 if (*i1 > tcps->tcps_max_buf) {
602 602 *outlenp = 0;
603 603 return (ENOBUFS);
604 604 }
605 605 if (checkonly)
606 606 break;
607 607
608 608 connp->conn_sndbuf = *i1;
609 609 if (tcps->tcps_snd_lowat_fraction != 0) {
610 610 connp->conn_sndlowat = connp->conn_sndbuf /
611 611 tcps->tcps_snd_lowat_fraction;
612 612 }
613 613 (void) tcp_maxpsz_set(tcp, B_TRUE);
614 614 /*
615 615 * If we are flow-controlled, recheck the condition.
616 616 * There are apps that increase SO_SNDBUF size when
617 617 * flow-controlled (EWOULDBLOCK), and expect the flow
618 618 * control condition to be lifted right away.
619 619 */
620 620 mutex_enter(&tcp->tcp_non_sq_lock);
621 621 if (tcp->tcp_flow_stopped &&
622 622 TCP_UNSENT_BYTES(tcp) < connp->conn_sndbuf) {
623 623 tcp_clrqfull(tcp);
624 624 }
625 625 mutex_exit(&tcp->tcp_non_sq_lock);
626 626 *outlenp = inlen;
627 627 return (0);
628 628 }
629 629 case SO_RCVBUF:
630 630 if (*i1 > tcps->tcps_max_buf) {
631 631 *outlenp = 0;
632 632 return (ENOBUFS);
633 633 }
634 634 /* Silently ignore zero */
635 635 if (!checkonly && *i1 != 0) {
636 636 *i1 = MSS_ROUNDUP(*i1, tcp->tcp_mss);
637 637 (void) tcp_rwnd_set(tcp, *i1);
638 638 }
639 639 /*
640 640 * XXX should we return the rwnd here
641 641 * and tcp_opt_get ?
642 642 */
643 643 *outlenp = inlen;
644 644 return (0);
645 645 case SO_SND_COPYAVOID:
646 646 if (!checkonly) {
647 647 if (tcp->tcp_loopback ||
648 648 (onoff != 1) || !tcp_zcopy_check(tcp)) {
649 649 *outlenp = 0;
650 650 return (EOPNOTSUPP);
651 651 }
652 652 tcp->tcp_snd_zcopy_aware = 1;
653 653 }
654 654 *outlenp = inlen;
655 655 return (0);
656 656 }
657 657 break;
658 658 case IPPROTO_TCP:
659 659 switch (name) {
660 660 case TCP_NODELAY:
661 661 if (!checkonly)
662 662 tcp->tcp_naglim = *i1 ? 1 : tcp->tcp_mss;
663 663 break;
664 664 case TCP_NOTIFY_THRESHOLD:
665 665 if (!checkonly)
666 666 tcp->tcp_first_timer_threshold = *i1;
667 667 break;
668 668 case TCP_ABORT_THRESHOLD:
669 669 if (!checkonly)
670 670 tcp->tcp_second_timer_threshold = *i1;
671 671 break;
672 672 case TCP_CONN_NOTIFY_THRESHOLD:
673 673 if (!checkonly)
674 674 tcp->tcp_first_ctimer_threshold = *i1;
675 675 break;
676 676 case TCP_CONN_ABORT_THRESHOLD:
677 677 if (!checkonly)
678 678 tcp->tcp_second_ctimer_threshold = *i1;
679 679 break;
680 680 case TCP_RECVDSTADDR:
681 681 if (tcp->tcp_state > TCPS_LISTEN) {
682 682 *outlenp = 0;
683 683 return (EOPNOTSUPP);
684 684 }
685 685 /* Setting done in conn_opt_set */
686 686 break;
687 687 case TCP_INIT_CWND:
688 688 if (checkonly)
689 689 break;
690 690
691 691 /*
692 692 * Only allow socket with network configuration
693 693 * privilege to set the initial cwnd to be larger
694 694 * than allowed by RFC 3390.
695 695 */
696 696 if (val > MIN(4, MAX(2, 4380 / tcp->tcp_mss))) {
697 697 if ((reterr = secpolicy_ip_config(cr, B_TRUE))
698 698 != 0) {
699 699 *outlenp = 0;
700 700 return (reterr);
701 701 }
702 702 if (val > tcp_max_init_cwnd) {
703 703 *outlenp = 0;
704 704 return (EINVAL);
705 705 }
706 706 }
707 707
708 708 tcp->tcp_init_cwnd = val;
709 709
710 710 /*
711 711 * If the socket is connected, AND no outbound data
712 712 * has been sent, reset the actual cwnd values.
713 713 */
714 714 if (tcp->tcp_state == TCPS_ESTABLISHED &&
715 715 tcp->tcp_iss == tcp->tcp_snxt - 1) {
716 716 tcp->tcp_cwnd =
717 717 MIN(tcp->tcp_rwnd, val * tcp->tcp_mss);
718 718 }
719 719 break;
720 720
721 721 /*
722 722 * TCP_KEEPIDLE is in seconds but TCP_KEEPALIVE_THRESHOLD
723 723 * is in milliseconds. TCP_KEEPIDLE is introduced for
724 724 * compatibility with other Unix flavors.
725 725 * We can fall through TCP_KEEPALIVE_THRESHOLD logic after
726 726 * converting the input to milliseconds.
727 727 */
728 728 case TCP_KEEPIDLE:
729 729 *i1 *= 1000;
730 730 /* FALLTHRU */
731 731
732 732 case TCP_KEEPALIVE_THRESHOLD:
733 733 if (checkonly)
734 734 break;
735 735
736 736 if (*i1 < tcps->tcps_keepalive_interval_low ||
737 737 *i1 > tcps->tcps_keepalive_interval_high) {
738 738 *outlenp = 0;
739 739 return (EINVAL);
740 740 }
741 741 if (*i1 != tcp->tcp_ka_interval) {
742 742 tcp->tcp_ka_interval = *i1;
743 743 /*
744 744 * Check if we need to restart the
745 745 * keepalive timer.
746 746 */
747 747 if (tcp->tcp_ka_tid != 0) {
748 748 ASSERT(connp->conn_keepalive);
749 749 (void) TCP_TIMER_CANCEL(tcp,
750 750 tcp->tcp_ka_tid);
751 751 tcp->tcp_ka_last_intrvl = 0;
752 752 tcp->tcp_ka_tid = TCP_TIMER(tcp,
753 753 tcp_keepalive_timer,
754 754 tcp->tcp_ka_interval);
755 755 }
756 756 }
757 757 break;
758 758
759 759 /*
760 760 * tcp_ka_abort_thres = tcp_ka_rinterval * tcp_ka_cnt.
761 761 * So setting TCP_KEEPCNT or TCP_KEEPINTVL can affect all the
762 762 * three members - tcp_ka_abort_thres, tcp_ka_rinterval and
763 763 * tcp_ka_cnt.
764 764 */
765 765 case TCP_KEEPCNT:
766 766 if (checkonly)
767 767 break;
768 768
769 769 if (*i1 == 0) {
770 770 return (EINVAL);
771 771 } else if (tcp->tcp_ka_rinterval == 0) {
772 772 if ((tcp->tcp_ka_abort_thres / *i1) <
773 773 tcp->tcp_rto_min ||
774 774 (tcp->tcp_ka_abort_thres / *i1) >
775 775 tcp->tcp_rto_max)
776 776 return (EINVAL);
777 777
778 778 tcp->tcp_ka_rinterval =
779 779 tcp->tcp_ka_abort_thres / *i1;
780 780 } else {
781 781 if ((*i1 * tcp->tcp_ka_rinterval) <
782 782 tcps->tcps_keepalive_abort_interval_low ||
783 783 (*i1 * tcp->tcp_ka_rinterval) >
784 784 tcps->tcps_keepalive_abort_interval_high)
785 785 return (EINVAL);
786 786 tcp->tcp_ka_abort_thres =
787 787 (*i1 * tcp->tcp_ka_rinterval);
788 788 }
789 789 tcp->tcp_ka_cnt = *i1;
790 790 break;
791 791 case TCP_KEEPINTVL:
792 792 /*
793 793 * TCP_KEEPINTVL is specified in seconds, but
794 794 * tcp_ka_rinterval is in milliseconds.
795 795 */
796 796
797 797 if (checkonly)
798 798 break;
799 799
800 800 if ((*i1 * 1000) < tcp->tcp_rto_min ||
801 801 (*i1 * 1000) > tcp->tcp_rto_max)
802 802 return (EINVAL);
803 803
804 804 if (tcp->tcp_ka_cnt == 0) {
805 805 tcp->tcp_ka_cnt =
806 806 tcp->tcp_ka_abort_thres / (*i1 * 1000);
807 807 } else {
808 808 if ((*i1 * tcp->tcp_ka_cnt * 1000) <
809 809 tcps->tcps_keepalive_abort_interval_low ||
810 810 (*i1 * tcp->tcp_ka_cnt * 1000) >
811 811 tcps->tcps_keepalive_abort_interval_high)
812 812 return (EINVAL);
813 813 tcp->tcp_ka_abort_thres =
814 814 (*i1 * tcp->tcp_ka_cnt * 1000);
815 815 }
816 816 tcp->tcp_ka_rinterval = *i1 * 1000;
817 817 break;
818 818 case TCP_KEEPALIVE_ABORT_THRESHOLD:
819 819 if (!checkonly) {
820 820 if (*i1 <
821 821 tcps->tcps_keepalive_abort_interval_low ||
822 822 *i1 >
823 823 tcps->tcps_keepalive_abort_interval_high) {
824 824 *outlenp = 0;
825 825 return (EINVAL);
826 826 }
827 827 tcp->tcp_ka_abort_thres = *i1;
828 828 tcp->tcp_ka_cnt = 0;
829 829 tcp->tcp_ka_rinterval = 0;
830 830 }
831 831 break;
832 832 case TCP_CORK:
833 833 if (!checkonly) {
834 834 /*
835 835 * if tcp->tcp_cork was set and is now
836 836 * being unset, we have to make sure that
837 837 * the remaining data gets sent out. Also
838 838 * unset tcp->tcp_cork so that tcp_wput_data()
839 839 * can send data even if it is less than mss
840 840 */
841 841 if (tcp->tcp_cork && onoff == 0 &&
842 842 tcp->tcp_unsent > 0) {
843 843 tcp->tcp_cork = B_FALSE;
844 844 tcp_wput_data(tcp, NULL, B_FALSE);
845 845 }
846 846 tcp->tcp_cork = onoff;
847 847 }
848 848 break;
849 849 case TCP_RTO_INITIAL: {
850 850 clock_t rto;
851 851
852 852 if (checkonly || val == 0)
853 853 break;
854 854
855 855 /*
856 856 * Sanity checks
857 857 *
858 858 * The initial RTO should be bounded by the minimum
859 859 * and maximum RTO. And it should also be smaller
860 860 * than the connect attempt abort timeout. Otherwise,
861 861 * the connection won't be aborted in a period
862 862 * reasonably close to that timeout.
863 863 */
864 864 if (val < tcp->tcp_rto_min || val > tcp->tcp_rto_max ||
865 865 val > tcp->tcp_second_ctimer_threshold ||
866 866 val < tcps->tcps_rexmit_interval_initial_low ||
867 867 val > tcps->tcps_rexmit_interval_initial_high) {
868 868 *outlenp = 0;
869 869 return (EINVAL);
870 870 }
871 871 tcp->tcp_rto_initial = val;
872 872
873 873 /*
874 874 * If TCP has not sent anything, need to re-calculate
875 875 * tcp_rto. Otherwise, this option change does not
876 876 * really affect anything.
877 877 */
878 878 if (tcp->tcp_state >= TCPS_SYN_SENT)
879 879 break;
880 880
881 881 tcp->tcp_rtt_sa = tcp->tcp_rto_initial << 2;
882 882 tcp->tcp_rtt_sd = tcp->tcp_rto_initial >> 1;
883 883 rto = (tcp->tcp_rtt_sa >> 3) + tcp->tcp_rtt_sd +
884 884 tcps->tcps_rexmit_interval_extra +
885 885 (tcp->tcp_rtt_sa >> 5) +
886 886 tcps->tcps_conn_grace_period;
887 887 TCP_SET_RTO(tcp, rto);
888 888 break;
889 889 }
890 890 case TCP_RTO_MIN:
891 891 if (checkonly || val == 0)
892 892 break;
893 893
894 894 if (val < tcps->tcps_rexmit_interval_min_low ||
895 895 val > tcps->tcps_rexmit_interval_min_high ||
896 896 val > tcp->tcp_rto_max) {
897 897 *outlenp = 0;
898 898 return (EINVAL);
899 899 }
900 900 tcp->tcp_rto_min = val;
901 901 if (tcp->tcp_rto < val)
902 902 tcp->tcp_rto = val;
903 903 break;
904 904 case TCP_RTO_MAX:
905 905 if (checkonly || val == 0)
906 906 break;
907 907
908 908 /*
909 909 * Sanity checks
910 910 *
911 911 * The maximum RTO should not be larger than the
912 912 * connection abort timeout. Otherwise, the
913 913 * connection won't be aborted in a period reasonably
914 914 * close to that timeout.
915 915 */
916 916 if (val < tcps->tcps_rexmit_interval_max_low ||
917 917 val > tcps->tcps_rexmit_interval_max_high ||
918 918 val < tcp->tcp_rto_min ||
919 919 val > tcp->tcp_second_timer_threshold) {
920 920 *outlenp = 0;
921 921 return (EINVAL);
922 922 }
923 923 tcp->tcp_rto_max = val;
924 924 if (tcp->tcp_rto > val)
925 925 tcp->tcp_rto = val;
926 926 break;
927 927 case TCP_LINGER2:
928 928 if (checkonly || *i1 == 0)
929 929 break;
930 930
931 931 /*
932 932 * Note that the option value's unit is second. And
933 933 * the value should be bigger than the private
934 934 * parameter tcp_fin_wait_2_flush_interval's lower
935 935 * bound and smaller than the current value of that
936 936 * parameter. It should be smaller than the current
937 937 * value to avoid an app setting TCP_LINGER2 to a big
938 938 * value, causing resource to be held up too long in
939 939 * FIN-WAIT-2 state.
940 940 */
941 941 if (*i1 < 0 ||
942 942 tcps->tcps_fin_wait_2_flush_interval_low/SECONDS >
943 943 *i1 ||
944 944 tcps->tcps_fin_wait_2_flush_interval/SECONDS <
945 945 *i1) {
946 946 *outlenp = 0;
947 947 return (EINVAL);
948 948 }
949 949 tcp->tcp_fin_wait_2_flush_interval = *i1 * SECONDS;
950 950 break;
951 951 default:
952 952 break;
953 953 }
954 954 break;
955 955 case IPPROTO_IP:
956 956 if (connp->conn_family != AF_INET) {
957 957 *outlenp = 0;
958 958 return (EINVAL);
959 959 }
960 960 switch (name) {
961 961 case IP_SEC_OPT:
962 962 /*
963 963 * We should not allow policy setting after
964 964 * we start listening for connections.
965 965 */
966 966 if (tcp->tcp_state == TCPS_LISTEN) {
967 967 return (EINVAL);
968 968 }
969 969 break;
970 970 }
971 971 break;
972 972 case IPPROTO_IPV6:
973 973 /*
974 974 * IPPROTO_IPV6 options are only supported for sockets
975 975 * that are using IPv6 on the wire.
976 976 */
977 977 if (connp->conn_ipversion != IPV6_VERSION) {
978 978 *outlenp = 0;
979 979 return (EINVAL);
980 980 }
981 981
982 982 switch (name) {
983 983 case IPV6_RECVPKTINFO:
984 984 if (!checkonly) {
985 985 /* Force it to be sent up with the next msg */
986 986 tcp->tcp_recvifindex = 0;
987 987 }
988 988 break;
989 989 case IPV6_RECVTCLASS:
990 990 if (!checkonly) {
991 991 /* Force it to be sent up with the next msg */
992 992 tcp->tcp_recvtclass = 0xffffffffU;
993 993 }
994 994 break;
995 995 case IPV6_RECVHOPLIMIT:
996 996 if (!checkonly) {
997 997 /* Force it to be sent up with the next msg */
998 998 tcp->tcp_recvhops = 0xffffffffU;
999 999 }
1000 1000 break;
1001 1001 case IPV6_PKTINFO:
1002 1002 /* This is an extra check for TCP */
1003 1003 if (inlen == sizeof (struct in6_pktinfo)) {
1004 1004 struct in6_pktinfo *pkti;
1005 1005
1006 1006 pkti = (struct in6_pktinfo *)invalp;
1007 1007 /*
1008 1008 * RFC 3542 states that ipi6_addr must be
1009 1009 * the unspecified address when setting the
1010 1010 * IPV6_PKTINFO sticky socket option on a
1011 1011 * TCP socket.
1012 1012 */
1013 1013 if (!IN6_IS_ADDR_UNSPECIFIED(&pkti->ipi6_addr))
1014 1014 return (EINVAL);
1015 1015 }
1016 1016 break;
1017 1017 case IPV6_SEC_OPT:
1018 1018 /*
1019 1019 * We should not allow policy setting after
1020 1020 * we start listening for connections.
1021 1021 */
1022 1022 if (tcp->tcp_state == TCPS_LISTEN) {
1023 1023 return (EINVAL);
1024 1024 }
1025 1025 break;
1026 1026 }
1027 1027 break;
1028 1028 }
1029 1029 reterr = conn_opt_set(&coas, level, name, inlen, invalp,
1030 1030 checkonly, cr);
1031 1031 if (reterr != 0) {
1032 1032 *outlenp = 0;
1033 1033 return (reterr);
1034 1034 }
1035 1035
1036 1036 /*
1037 1037 * Common case of OK return with outval same as inval
1038 1038 */
1039 1039 if (invalp != outvalp) {
1040 1040 /* don't trust bcopy for identical src/dst */
1041 1041 (void) bcopy(invalp, outvalp, inlen);
1042 1042 }
1043 1043 *outlenp = inlen;
1044 1044
1045 1045 if (coas.coa_changed & COA_HEADER_CHANGED) {
1046 1046 /* If we are connected we rebuilt the headers */
1047 1047 if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
1048 1048 !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
1049 1049 reterr = tcp_build_hdrs(tcp);
1050 1050 if (reterr != 0)
1051 1051 return (reterr);
1052 1052 }
1053 1053 }
1054 1054 if (coas.coa_changed & COA_ROUTE_CHANGED) {
1055 1055 in6_addr_t nexthop;
1056 1056
1057 1057 /*
1058 1058 * If we are connected we re-cache the information.
1059 1059 * We ignore errors to preserve BSD behavior.
1060 1060 * Note that we don't redo IPsec policy lookup here
1061 1061 * since the final destination (or source) didn't change.
1062 1062 */
1063 1063 ip_attr_nexthop(&connp->conn_xmit_ipp, connp->conn_ixa,
1064 1064 &connp->conn_faddr_v6, &nexthop);
1065 1065
1066 1066 if (!IN6_IS_ADDR_UNSPECIFIED(&connp->conn_faddr_v6) &&
1067 1067 !IN6_IS_ADDR_V4MAPPED_ANY(&connp->conn_faddr_v6)) {
1068 1068 (void) ip_attr_connect(connp, connp->conn_ixa,
1069 1069 &connp->conn_laddr_v6, &connp->conn_faddr_v6,
1070 1070 &nexthop, connp->conn_fport, NULL, NULL,
1071 1071 IPDF_VERIFY_DST);
1072 1072 }
1073 1073 }
1074 1074 if ((coas.coa_changed & COA_SNDBUF_CHANGED) && !IPCL_IS_NONSTR(connp)) {
1075 1075 connp->conn_wq->q_hiwat = connp->conn_sndbuf;
1076 1076 }
1077 1077 if (coas.coa_changed & COA_WROFF_CHANGED) {
1078 1078 connp->conn_wroff = connp->conn_ht_iphc_allocated +
1079 1079 tcps->tcps_wroff_xtra;
1080 1080 (void) proto_set_tx_wroff(connp->conn_rq, connp,
1081 1081 connp->conn_wroff);
1082 1082 }
1083 1083 if (coas.coa_changed & COA_OOBINLINE_CHANGED) {
1084 1084 if (IPCL_IS_NONSTR(connp))
1085 1085 proto_set_rx_oob_opt(connp, onoff);
1086 1086 }
1087 1087 return (0);
1088 1088 }
↓ open down ↓ |
849 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX