Print this page
dccp: starting module template
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/inet/tunables.c
+++ new/usr/src/uts/common/inet/tunables.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) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 * Copyright (c) 1990 Mentat Inc.
24 24 */
25 25
26 26 #include <inet/tunables.h>
↓ open down ↓ |
26 lines elided |
↑ open up ↑ |
27 27 #include <sys/md5.h>
28 28 #include <inet/common.h>
29 29 #include <inet/ip.h>
30 30 #include <inet/ip6.h>
31 31 #include <netinet/icmp6.h>
32 32 #include <inet/ip_stack.h>
33 33 #include <inet/rawip_impl.h>
34 34 #include <inet/tcp_stack.h>
35 35 #include <inet/tcp_impl.h>
36 36 #include <inet/udp_impl.h>
37 +#include <inet/dccp_stack.h>
38 +#include <inet/dccp_impl.h>
37 39 #include <inet/sctp/sctp_stack.h>
38 40 #include <inet/sctp/sctp_impl.h>
39 41 #include <inet/tunables.h>
40 42
41 43 static int
42 44 prop_perm2const(mod_prop_info_t *pinfo)
43 45 {
44 46 if (pinfo->mpi_setf == NULL)
45 47 return (MOD_PROP_PERM_READ);
46 48 if (pinfo->mpi_getf == NULL)
47 49 return (MOD_PROP_PERM_WRITE);
48 50 return (MOD_PROP_PERM_RW);
49 51 }
50 52
51 53 /*
52 54 * Modifies the value of the property to default value or to the `pval'
53 55 * specified by the user.
54 56 */
55 57 /* ARGSUSED */
56 58 int
57 59 mod_set_boolean(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
58 60 const char *ifname, const void* pval, uint_t flags)
59 61 {
60 62 char *end;
61 63 unsigned long new_value;
62 64
63 65 if (flags & MOD_PROP_DEFAULT) {
64 66 pinfo->prop_cur_bval = pinfo->prop_def_bval;
65 67 return (0);
66 68 }
67 69
68 70 if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0')
69 71 return (EINVAL);
70 72 if (new_value != B_TRUE && new_value != B_FALSE)
71 73 return (EINVAL);
72 74 pinfo->prop_cur_bval = new_value;
73 75 return (0);
74 76 }
75 77
76 78 /*
77 79 * Retrieves property permission, default value, current value or possible
78 80 * values for those properties whose value type is boolean_t.
79 81 */
80 82 /* ARGSUSED */
81 83 int
82 84 mod_get_boolean(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
83 85 void *pval, uint_t psize, uint_t flags)
84 86 {
85 87 boolean_t get_def = (flags & MOD_PROP_DEFAULT);
86 88 boolean_t get_perm = (flags & MOD_PROP_PERM);
87 89 boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
88 90 size_t nbytes;
89 91
90 92 bzero(pval, psize);
91 93 if (get_perm)
92 94 nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
93 95 else if (get_range)
94 96 nbytes = snprintf(pval, psize, "%u,%u", B_FALSE, B_TRUE);
95 97 else if (get_def)
96 98 nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_bval);
97 99 else
98 100 nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_bval);
99 101 if (nbytes >= psize)
100 102 return (ENOBUFS);
101 103 return (0);
102 104 }
103 105
104 106 int
105 107 mod_uint32_value(const void *pval, mod_prop_info_t *pinfo, uint_t flags,
106 108 ulong_t *new_value)
107 109 {
108 110 char *end;
109 111
110 112 if (flags & MOD_PROP_DEFAULT) {
111 113 *new_value = pinfo->prop_def_uval;
112 114 return (0);
113 115 }
114 116
115 117 if (ddi_strtoul(pval, &end, 10, (ulong_t *)new_value) != 0 ||
116 118 *end != '\0')
117 119 return (EINVAL);
118 120 if (*new_value < pinfo->prop_min_uval ||
119 121 *new_value > pinfo->prop_max_uval) {
120 122 return (ERANGE);
121 123 }
122 124 return (0);
123 125 }
124 126
125 127 /*
126 128 * Modifies the value of the property to default value or to the `pval'
127 129 * specified by the user.
128 130 */
129 131 /* ARGSUSED */
130 132 int
131 133 mod_set_uint32(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
132 134 const char *ifname, const void *pval, uint_t flags)
133 135 {
134 136 unsigned long new_value;
135 137 int err;
136 138
137 139 if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
138 140 return (err);
139 141 pinfo->prop_cur_uval = (uint32_t)new_value;
140 142 return (0);
141 143 }
142 144
143 145 /*
144 146 * Rounds up the value to make it multiple of 8.
145 147 */
146 148 /* ARGSUSED */
147 149 int
148 150 mod_set_aligned(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
149 151 const char *ifname, const void* pval, uint_t flags)
150 152 {
151 153 int err;
152 154
153 155 if ((err = mod_set_uint32(cbarg, cr, pinfo, ifname, pval, flags)) != 0)
154 156 return (err);
155 157
156 158 /* if required, align the value to multiple of 8 */
157 159 if (pinfo->prop_cur_uval & 0x7) {
158 160 pinfo->prop_cur_uval &= ~0x7;
159 161 pinfo->prop_cur_uval += 0x8;
160 162 }
161 163
162 164 return (0);
163 165 }
164 166
165 167 /*
166 168 * Retrieves property permission, default value, current value or possible
167 169 * values for those properties whose value type is uint32_t.
168 170 */
169 171 /* ARGSUSED */
170 172 int
171 173 mod_get_uint32(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
172 174 void *pval, uint_t psize, uint_t flags)
173 175 {
174 176 boolean_t get_def = (flags & MOD_PROP_DEFAULT);
175 177 boolean_t get_perm = (flags & MOD_PROP_PERM);
176 178 boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
177 179 size_t nbytes;
178 180
179 181 bzero(pval, psize);
180 182 if (get_perm)
181 183 nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
182 184 else if (get_range)
183 185 nbytes = snprintf(pval, psize, "%u-%u",
184 186 pinfo->prop_min_uval, pinfo->prop_max_uval);
185 187 else if (get_def)
186 188 nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval);
187 189 else
188 190 nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_uval);
189 191 if (nbytes >= psize)
190 192 return (ENOBUFS);
191 193 return (0);
192 194 }
193 195
194 196 /*
195 197 * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for
196 198 * backward compatibility with /sbin/ndd.
197 199 */
↓ open down ↓ |
151 lines elided |
↑ open up ↑ |
198 200 /* ARGSUSED */
199 201 int
200 202 mod_get_allprop(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
201 203 void *val, uint_t psize, uint_t flags)
202 204 {
203 205 char *pval = val;
204 206 mod_prop_info_t *ptbl, *prop;
205 207 ip_stack_t *ipst;
206 208 tcp_stack_t *tcps;
207 209 sctp_stack_t *sctps;
210 + dccp_stack_t *dccps;
208 211 udp_stack_t *us;
209 212 icmp_stack_t *is;
210 213 uint_t size;
211 214 size_t nbytes = 0, tbytes = 0;
212 215
213 216 bzero(pval, psize);
214 217 size = psize;
215 218
216 219 switch (pinfo->mpi_proto) {
217 220 case MOD_PROTO_IP:
218 221 case MOD_PROTO_IPV4:
219 222 case MOD_PROTO_IPV6:
220 223 ipst = (ip_stack_t *)cbarg;
221 224 ptbl = ipst->ips_propinfo_tbl;
222 225 break;
223 226 case MOD_PROTO_RAWIP:
224 227 is = (icmp_stack_t *)cbarg;
225 228 ptbl = is->is_propinfo_tbl;
226 229 break;
227 230 case MOD_PROTO_TCP:
228 231 tcps = (tcp_stack_t *)cbarg;
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
229 232 ptbl = tcps->tcps_propinfo_tbl;
230 233 break;
231 234 case MOD_PROTO_UDP:
232 235 us = (udp_stack_t *)cbarg;
233 236 ptbl = us->us_propinfo_tbl;
234 237 break;
235 238 case MOD_PROTO_SCTP:
236 239 sctps = (sctp_stack_t *)cbarg;
237 240 ptbl = sctps->sctps_propinfo_tbl;
238 241 break;
242 + case MOD_PROTO_DCCP:
243 + dccps = (dccp_stack_t *)cbarg;
244 + ptbl = dccps->dccps_propinfo_tbl;
245 + break;
239 246 default:
240 247 return (EINVAL);
241 248 }
242 249
243 250 for (prop = ptbl; prop->mpi_name != NULL; prop++) {
244 251 if (prop->mpi_name[0] == '\0' ||
245 252 strcmp(prop->mpi_name, "?") == 0) {
246 253 continue;
247 254 }
248 255 nbytes = snprintf(pval, size, "%s %d %d", prop->mpi_name,
249 256 prop->mpi_proto, prop_perm2const(prop));
250 257 size -= nbytes + 1;
251 258 pval += nbytes + 1;
252 259 tbytes += nbytes + 1;
253 260 if (tbytes >= psize) {
254 261 /* Buffer overflow, stop copying information */
255 262 return (ENOBUFS);
256 263 }
257 264 }
258 265 return (0);
259 266 }
260 267
261 268 /*
262 269 * Hold a lock while changing *_epriv_ports to prevent multiple
263 270 * threads from changing it at the same time.
264 271 */
265 272 /* ARGSUSED */
266 273 int
267 274 mod_set_extra_privports(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
268 275 const char *ifname, const void* val, uint_t flags)
269 276 {
270 277 uint_t proto = pinfo->mpi_proto;
271 278 tcp_stack_t *tcps;
272 279 sctp_stack_t *sctps;
273 280 udp_stack_t *us;
274 281 unsigned long new_value;
275 282 char *end;
276 283 kmutex_t *lock;
277 284 uint_t i, nports;
278 285 in_port_t *ports;
279 286 boolean_t def = (flags & MOD_PROP_DEFAULT);
280 287 const char *pval = val;
281 288
282 289 if (!def) {
283 290 if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
284 291 *end != '\0') {
285 292 return (EINVAL);
286 293 }
287 294
288 295 if (new_value < pinfo->prop_min_uval ||
289 296 new_value > pinfo->prop_max_uval) {
290 297 return (ERANGE);
291 298 }
292 299 }
293 300
294 301 switch (proto) {
295 302 case MOD_PROTO_TCP:
296 303 tcps = (tcp_stack_t *)cbarg;
297 304 lock = &tcps->tcps_epriv_port_lock;
298 305 ports = tcps->tcps_g_epriv_ports;
299 306 nports = tcps->tcps_g_num_epriv_ports;
300 307 break;
301 308 case MOD_PROTO_UDP:
302 309 us = (udp_stack_t *)cbarg;
303 310 lock = &us->us_epriv_port_lock;
304 311 ports = us->us_epriv_ports;
305 312 nports = us->us_num_epriv_ports;
306 313 break;
307 314 case MOD_PROTO_SCTP:
308 315 sctps = (sctp_stack_t *)cbarg;
309 316 lock = &sctps->sctps_epriv_port_lock;
310 317 ports = sctps->sctps_g_epriv_ports;
311 318 nports = sctps->sctps_g_num_epriv_ports;
312 319 break;
313 320 default:
314 321 return (ENOTSUP);
315 322 }
316 323
317 324 mutex_enter(lock);
318 325
319 326 /* if MOD_PROP_DEFAULT is set then reset the ports list to default */
320 327 if (def) {
321 328 for (i = 0; i < nports; i++)
322 329 ports[i] = 0;
323 330 ports[0] = ULP_DEF_EPRIV_PORT1;
324 331 ports[1] = ULP_DEF_EPRIV_PORT2;
325 332 mutex_exit(lock);
326 333 return (0);
327 334 }
328 335
329 336 /* Check if the value is already in the list */
330 337 for (i = 0; i < nports; i++) {
331 338 if (new_value == ports[i])
332 339 break;
333 340 }
334 341
335 342 if (flags & MOD_PROP_REMOVE) {
336 343 if (i == nports) {
337 344 mutex_exit(lock);
338 345 return (ESRCH);
339 346 }
340 347 /* Clear the value */
341 348 ports[i] = 0;
342 349 } else if (flags & MOD_PROP_APPEND) {
343 350 if (i != nports) {
344 351 mutex_exit(lock);
345 352 return (EEXIST);
346 353 }
347 354
348 355 /* Find an empty slot */
349 356 for (i = 0; i < nports; i++) {
350 357 if (ports[i] == 0)
351 358 break;
352 359 }
353 360 if (i == nports) {
354 361 mutex_exit(lock);
355 362 return (EOVERFLOW);
356 363 }
357 364 /* Set the new value */
358 365 ports[i] = (in_port_t)new_value;
359 366 } else {
360 367 /*
361 368 * If the user used 'assignment' modifier.
362 369 * For eg:
363 370 * # ipadm set-prop -p extra_priv_ports=3001 tcp
364 371 *
365 372 * We clear all the ports and then just add 3001.
366 373 */
367 374 ASSERT(flags == MOD_PROP_ACTIVE);
368 375 for (i = 0; i < nports; i++)
369 376 ports[i] = 0;
370 377 ports[0] = (in_port_t)new_value;
371 378 }
372 379
373 380 mutex_exit(lock);
374 381 return (0);
375 382 }
376 383
377 384 /*
378 385 * Note: No locks are held when inspecting *_epriv_ports
379 386 * but instead the code relies on:
380 387 * - the fact that the address of the array and its size never changes
381 388 * - the atomic assignment of the elements of the array
382 389 */
383 390 /* ARGSUSED */
384 391 int
385 392 mod_get_extra_privports(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
386 393 void *val, uint_t psize, uint_t flags)
387 394 {
388 395 uint_t proto = pinfo->mpi_proto;
389 396 tcp_stack_t *tcps;
390 397 sctp_stack_t *sctps;
391 398 udp_stack_t *us;
392 399 uint_t i, nports, size;
393 400 in_port_t *ports;
394 401 char *pval = val;
395 402 size_t nbytes = 0, tbytes = 0;
396 403 boolean_t get_def = (flags & MOD_PROP_DEFAULT);
397 404 boolean_t get_perm = (flags & MOD_PROP_PERM);
398 405 boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
399 406
400 407 bzero(pval, psize);
401 408 size = psize;
402 409
403 410 if (get_def) {
404 411 tbytes = snprintf(pval, psize, "%u,%u", ULP_DEF_EPRIV_PORT1,
405 412 ULP_DEF_EPRIV_PORT2);
406 413 goto ret;
407 414 } else if (get_perm) {
408 415 tbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
409 416 goto ret;
410 417 }
411 418
412 419 switch (proto) {
413 420 case MOD_PROTO_TCP:
414 421 tcps = (tcp_stack_t *)cbarg;
415 422 ports = tcps->tcps_g_epriv_ports;
416 423 nports = tcps->tcps_g_num_epriv_ports;
417 424 break;
418 425 case MOD_PROTO_UDP:
419 426 us = (udp_stack_t *)cbarg;
420 427 ports = us->us_epriv_ports;
421 428 nports = us->us_num_epriv_ports;
422 429 break;
423 430 case MOD_PROTO_SCTP:
424 431 sctps = (sctp_stack_t *)cbarg;
425 432 ports = sctps->sctps_g_epriv_ports;
426 433 nports = sctps->sctps_g_num_epriv_ports;
427 434 break;
428 435 default:
429 436 return (ENOTSUP);
430 437 }
431 438
432 439 if (get_range) {
433 440 tbytes = snprintf(pval, psize, "%u-%u", pinfo->prop_min_uval,
434 441 pinfo->prop_max_uval);
435 442 goto ret;
436 443 }
437 444
438 445 for (i = 0; i < nports; i++) {
439 446 if (ports[i] != 0) {
440 447 if (psize == size)
441 448 nbytes = snprintf(pval, size, "%u", ports[i]);
442 449 else
443 450 nbytes = snprintf(pval, size, ",%u", ports[i]);
444 451 size -= nbytes;
445 452 pval += nbytes;
446 453 tbytes += nbytes;
447 454 if (tbytes >= psize)
448 455 return (ENOBUFS);
449 456 }
450 457 }
451 458 return (0);
452 459 ret:
453 460 if (tbytes >= psize)
454 461 return (ENOBUFS);
455 462 return (0);
456 463 }
↓ open down ↓ |
208 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX