xref: /illumos-gate/usr/src/uts/common/inet/ip/ip_tunables.c (revision 51396a8ee7fb52fe0ab33bfe7b4f495ad431904a)
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 (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
23  * Copyright (c) 2013 by Delphix. All rights reserved.
24  * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25  */
26 /* Copyright (c) 1990 Mentat Inc. */
27 
28 #include <inet/ip.h>
29 #include <inet/ip6.h>
30 #include <inet/ip_if.h>
31 #include <inet/ip_ire.h>
32 #include <inet/ipclassifier.h>
33 #include <inet/ip_impl.h>
34 #include <inet/tunables.h>
35 #include <sys/sunddi.h>
36 #include <sys/policy.h>
37 
38 /* How long, in seconds, we allow frags to hang around. */
39 #define	IP_REASM_TIMEOUT	15
40 #define	IPV6_REASM_TIMEOUT	60
41 
42 /*
43  * Set ip{,6}_forwarding values. If the value is being set on an ill,
44  * find the ill and set the value on it. On the other hand if we are modifying
45  * global property, modify the global value and set the value on all the ills.
46  */
47 /* ARGSUSED */
48 static int
49 ip_set_forwarding(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
50     const char *ifname, const void* pval, uint_t flags)
51 {
52 	char			*end;
53 	unsigned long		new_value;
54 	boolean_t		per_ill, isv6;
55 	ill_walk_context_t	ctx;
56 	ill_t			*ill;
57 	ip_stack_t		*ipst = stack->netstack_ip;
58 
59 	if (flags & MOD_PROP_DEFAULT) {
60 		new_value = pinfo->prop_def_bval;
61 	} else {
62 		if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
63 		    *end != '\0')
64 			return (EINVAL);
65 		if (new_value != B_TRUE && new_value != B_FALSE)
66 			return (EINVAL);
67 	}
68 
69 	per_ill = (ifname != NULL && ifname[0] != '\0');
70 	/*
71 	 * if it's not per ill then set the global property and bring all the
72 	 * ills up to date with the new global value.
73 	 */
74 	if (!per_ill)
75 		pinfo->prop_cur_bval = (new_value == 1 ? B_TRUE : B_FALSE);
76 
77 	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6 ? B_TRUE : B_FALSE);
78 	rw_enter(&ipst->ips_ill_g_lock, RW_READER);
79 	if (isv6)
80 		ill = ILL_START_WALK_V6(&ctx, ipst);
81 	else
82 		ill = ILL_START_WALK_V4(&ctx, ipst);
83 
84 	for (; ill != NULL; ill = ill_next(&ctx, ill)) {
85 		/*
86 		 * if the property needs to be set on a particular
87 		 * interface, look for that interface.
88 		 */
89 		if (per_ill && strcmp(ifname, ill->ill_name) != 0)
90 			continue;
91 		(void) ill_forward_set(ill, new_value != 0);
92 	}
93 	rw_exit(&ipst->ips_ill_g_lock);
94 
95 	return (0);
96 }
97 
98 static int
99 ip_get_forwarding(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
100     void *pval, uint_t pr_size, uint_t flags)
101 {
102 	boolean_t		value;
103 	ill_walk_context_t	ctx;
104 	ill_t			*ill;
105 	ip_stack_t		*ipst = stack->netstack_ip;
106 	boolean_t		get_def = (flags & MOD_PROP_DEFAULT);
107 	boolean_t		get_perm = (flags & MOD_PROP_PERM);
108 	boolean_t		isv6;
109 	size_t			nbytes = 0;
110 
111 	if (get_perm) {
112 		nbytes = snprintf(pval, pr_size, "%d", MOD_PROP_PERM_RW);
113 		goto ret;
114 	} else if (get_def) {
115 		nbytes = snprintf(pval, pr_size, "%d", pinfo->prop_def_bval);
116 		goto ret;
117 	}
118 
119 	/*
120 	 * if per interface value is not asked for return the current
121 	 * global value
122 	 */
123 	if (ifname == NULL || ifname[0] == '\0') {
124 		nbytes = snprintf(pval, pr_size, "%d", pinfo->prop_cur_bval);
125 		goto ret;
126 	}
127 
128 	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6 ? B_TRUE : B_FALSE);
129 	rw_enter(&ipst->ips_ill_g_lock, RW_READER);
130 	if (isv6)
131 		ill = ILL_START_WALK_V6(&ctx, ipst);
132 	else
133 		ill = ILL_START_WALK_V4(&ctx, ipst);
134 	for (; ill != NULL; ill = ill_next(&ctx, ill)) {
135 		/*
136 		 * if the property needs to be obtained on a particular
137 		 * interface, look for that interface.
138 		 */
139 		if (strcmp(ifname, ill->ill_name) == 0)
140 			break;
141 	}
142 	if (ill == NULL) {
143 		rw_exit(&ipst->ips_ill_g_lock);
144 		return (ENXIO);
145 	}
146 	value = ((ill->ill_flags & ILLF_ROUTER) ? B_TRUE : B_FALSE);
147 	rw_exit(&ipst->ips_ill_g_lock);
148 	nbytes = snprintf(pval, pr_size, "%d", value);
149 ret:
150 	if (nbytes >= pr_size)
151 		return (ENOBUFS);
152 	return (0);
153 }
154 
155 /*
156  * `ip_debug' is a global variable. So, we will be modifying the global
157  * variable here.
158  */
159 /* ARGSUSED */
160 int
161 ip_set_debug(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
162     const char *ifname, const void* pval, uint_t flags)
163 {
164 	unsigned long	new_value;
165 	int		err;
166 
167 	if (cr != NULL && secpolicy_net_config(cr, B_FALSE) != 0)
168 		return (EPERM);
169 
170 	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
171 		return (err);
172 	ip_debug = (uint32_t)new_value;
173 	return (0);
174 }
175 
176 /*
177  * ip_debug is a global property. For default, permission and value range
178  * we retrieve the value from `pinfo'. However for the current value we
179  * retrieve the value from the global variable `ip_debug'
180  */
181 /* ARGSUSED */
182 int
183 ip_get_debug(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
184     void *pval, uint_t psize, uint_t flags)
185 {
186 	boolean_t	get_def = (flags & MOD_PROP_DEFAULT);
187 	boolean_t	get_perm = (flags & MOD_PROP_PERM);
188 	boolean_t	get_range = (flags & MOD_PROP_POSSIBLE);
189 	size_t		nbytes;
190 
191 	bzero(pval, psize);
192 	if (get_perm)
193 		nbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
194 	else if (get_range)
195 		nbytes = snprintf(pval, psize, "%u-%u",
196 		    pinfo->prop_min_uval, pinfo->prop_max_uval);
197 	else if (get_def)
198 		nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval);
199 	else
200 		nbytes = snprintf(pval, psize, "%u", ip_debug);
201 	if (nbytes >= psize)
202 		return (ENOBUFS);
203 	return (0);
204 }
205 
206 /*
207  * Set the CGTP (multirouting) filtering status. If the status is changed
208  * from active to transparent or from transparent to active, forward the
209  * new status to the filtering module (if loaded).
210  */
211 /* ARGSUSED */
212 static int
213 ip_set_cgtp_filter(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
214     const char *ifname, const void* pval, uint_t flags)
215 {
216 	unsigned long	new_value;
217 	ip_stack_t	*ipst = stack->netstack_ip;
218 	char		*end;
219 
220 	if (flags & MOD_PROP_DEFAULT) {
221 		new_value = pinfo->prop_def_bval;
222 	} else {
223 		if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
224 		    *end != '\0' || new_value > 1) {
225 			return (EINVAL);
226 		}
227 	}
228 	if (!pinfo->prop_cur_bval && new_value) {
229 		cmn_err(CE_NOTE, "IP: enabling CGTP filtering%s",
230 		    ipst->ips_ip_cgtp_filter_ops == NULL ?
231 		    " (module not loaded)" : "");
232 	}
233 	if (pinfo->prop_cur_bval && !new_value) {
234 		cmn_err(CE_NOTE, "IP: disabling CGTP filtering%s",
235 		    ipst->ips_ip_cgtp_filter_ops == NULL ?
236 		    " (module not loaded)" : "");
237 	}
238 	if (ipst->ips_ip_cgtp_filter_ops != NULL) {
239 		int	res;
240 		netstackid_t stackid = ipst->ips_netstack->netstack_stackid;
241 
242 		res = ipst->ips_ip_cgtp_filter_ops->cfo_change_state(stackid,
243 		    new_value);
244 		if (res)
245 			return (res);
246 	}
247 	pinfo->prop_cur_bval = (new_value == 1 ? B_TRUE : B_FALSE);
248 	ill_set_inputfn_all(ipst);
249 	return (0);
250 }
251 
252 /*
253  * Retrieve the default MTU or min-max MTU range for a given interface.
254  *
255  *  -- ill_max_frag value tells us the maximum MTU that can be handled by the
256  *     datalink. This value is advertised by the driver via DLPI messages
257  *     (DL_NOTE_SDU_SIZE/DL_INFO_ACK).
258  *
259  *  -- ill_current_frag for the most link-types will be same as ill_max_frag
260  *     to begin with. However it is dynamically computed for some link-types
261  *     like tunnels, based on the tunnel PMTU.
262  *
263  *  -- ill_mtu is the user set MTU using SIOCSLIFMTU and must lie between
264  *     (IPV6_MIN_MTU/IP_MIN_MTU) and ill_max_frag.
265  *
266  *  -- ill_user_mtu is set by in.ndpd using SIOCSLIFLNKINFO and must lie between
267  *     (IPV6_MIN_MTU/IP_MIN_MTU) and ill_max_frag.
268  */
269 int
270 ip_get_mtu(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
271     void *pval, uint_t psize, uint_t flags)
272 {
273 	ill_walk_context_t	ctx;
274 	ill_t			*ill;
275 	ip_stack_t		*ipst = stack->netstack_ip;
276 	boolean_t		isv6;
277 	uint32_t		max_mtu, def_mtu;
278 	size_t			nbytes = 0;
279 
280 	if (!(flags & (MOD_PROP_DEFAULT|MOD_PROP_POSSIBLE)))
281 		return (ENOTSUP);
282 
283 	if (ifname == NULL || ifname[0] == '\0')
284 		return (ENOTSUP);
285 
286 	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6 ? B_TRUE : B_FALSE);
287 	rw_enter(&ipst->ips_ill_g_lock, RW_READER);
288 	if (isv6)
289 		ill = ILL_START_WALK_V6(&ctx, ipst);
290 	else
291 		ill = ILL_START_WALK_V4(&ctx, ipst);
292 	for (; ill != NULL; ill = ill_next(&ctx, ill)) {
293 		if (strcmp(ifname, ill->ill_name) == 0)
294 			break;
295 	}
296 	if (ill == NULL) {
297 		rw_exit(&ipst->ips_ill_g_lock);
298 		return (ENXIO);
299 	}
300 	max_mtu = ill->ill_max_frag;
301 	def_mtu = ill->ill_current_frag;
302 	rw_exit(&ipst->ips_ill_g_lock);
303 
304 	if (flags & MOD_PROP_DEFAULT) {
305 		nbytes = snprintf(pval, psize, "%u", def_mtu);
306 	} else if (flags & MOD_PROP_POSSIBLE) {
307 		uint32_t	min_mtu;
308 
309 		min_mtu = isv6 ? IPV6_MIN_MTU : IP_MIN_MTU;
310 		nbytes = snprintf(pval, psize, "%u-%u", min_mtu, max_mtu);
311 	} else {
312 		return (ENOTSUP);
313 	}
314 
315 	if (nbytes >= psize)
316 		return (ENOBUFS);
317 	return (0);
318 }
319 
320 /*
321  * See the comments for ip[6]_strict_src_multihoming for an explanation
322  * of the semanitcs.
323  */
324 void
325 ip_set_src_multihoming_common(ulong_t new_value, ulong_t old_value,
326     boolean_t isv6, ip_stack_t *ipst)
327 {
328 	if (isv6)
329 		ipst->ips_ipv6_strict_src_multihoming = new_value;
330 	else
331 		ipst->ips_ip_strict_src_multihoming = new_value;
332 	if (new_value != old_value) {
333 		if (!isv6) {
334 			if (old_value == 0) {
335 				ire_walk_v4(ip_ire_rebind_walker, NULL,
336 				    ALL_ZONES, ipst);
337 			} else if (new_value == 0) {
338 				ire_walk_v4(ip_ire_unbind_walker, NULL,
339 				    ALL_ZONES, ipst);
340 			}
341 			ipcl_walk(conn_ire_revalidate, (void *)B_FALSE, ipst);
342 		} else {
343 			if (old_value == 0) {
344 				ire_walk_v6(ip_ire_rebind_walker, NULL,
345 				    ALL_ZONES, ipst);
346 			} else if (new_value == 0) {
347 				ire_walk_v6(ip_ire_unbind_walker, NULL,
348 				    ALL_ZONES, ipst);
349 			}
350 			ipcl_walk(conn_ire_revalidate, (void *)B_TRUE, ipst);
351 		}
352 	}
353 }
354 
355 /* ARGSUSED */
356 static int
357 ip_set_src_multihoming(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
358     const char *ifname, const void* pval, uint_t flags)
359 {
360 	unsigned long	new_value, old_value;
361 	boolean_t	isv6;
362 	ip_stack_t	*ipst = stack->netstack_ip;
363 	int		err;
364 
365 	old_value = pinfo->prop_cur_uval;
366 
367 	if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
368 		return (err);
369 	pinfo->prop_cur_uval = new_value;
370 	isv6 = (strcmp(pinfo->mpi_name, "ip6_strict_src_multihoming") == 0);
371 	ip_set_src_multihoming_common(new_value, old_value, isv6, ipst);
372 	return (0);
373 }
374 
375 
376 /* ARGSUSED */
377 static int
378 ip_set_hostmodel(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
379     const char *ifname, const void* pval, uint_t flags)
380 {
381 	ip_hostmodel_t	new_value, old_value;
382 	ip_stack_t	*ipst = stack->netstack_ip;
383 	uint32_t	old_src_multihoming;
384 	int		err;
385 	ulong_t		tmp;
386 	boolean_t	isv6;
387 
388 	old_value = pinfo->prop_cur_uval;
389 
390 	if ((err = mod_uint32_value(pval, pinfo, flags, &tmp)) != 0)
391 		return (err);
392 	new_value = tmp;
393 	pinfo->prop_cur_uval = new_value;
394 
395 	switch (old_value) {
396 	case IP_WEAK_ES:
397 		old_src_multihoming = 0;
398 		break;
399 	case IP_SRC_PRI_ES:
400 		old_src_multihoming = 1;
401 		break;
402 	case IP_STRONG_ES:
403 		old_src_multihoming = 2;
404 		break;
405 	default:
406 		ASSERT(0);
407 		old_src_multihoming = IP_MAXVAL_ES;
408 		break;
409 	}
410 	/*
411 	 * Changes to src_multihoming may require ire's to be rebound/unbound,
412 	 * and also require generation number resets. Changes to dst_multihoming
413 	 * require a simple reset of the value.
414 	 */
415 	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6);
416 	if (new_value != old_value) {
417 		switch (new_value) {
418 		case IP_WEAK_ES:
419 			ip_set_src_multihoming_common(0, old_src_multihoming,
420 			    isv6, ipst);
421 			if (isv6)
422 				ipst->ips_ipv6_strict_dst_multihoming = 0;
423 			else
424 				ipst->ips_ip_strict_dst_multihoming = 0;
425 			break;
426 		case IP_SRC_PRI_ES:
427 			ip_set_src_multihoming_common(1, old_src_multihoming,
428 			    isv6, ipst);
429 			if (isv6)
430 				ipst->ips_ipv6_strict_dst_multihoming = 0;
431 			else
432 				ipst->ips_ip_strict_dst_multihoming = 0;
433 			break;
434 		case IP_STRONG_ES:
435 			ip_set_src_multihoming_common(2, old_src_multihoming,
436 			    isv6, ipst);
437 			if (isv6)
438 				ipst->ips_ipv6_strict_dst_multihoming = 1;
439 			else
440 				ipst->ips_ip_strict_dst_multihoming = 1;
441 			break;
442 		default:
443 			return (EINVAL);
444 		}
445 	}
446 	return (0);
447 }
448 
449 /* ARGSUSED */
450 int
451 ip_get_hostmodel(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
452     void *pval, uint_t psize, uint_t flags)
453 {
454 	boolean_t	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6);
455 	ip_stack_t	*ipst = stack->netstack_ip;
456 	ip_hostmodel_t	hostmodel;
457 
458 	if (psize < sizeof (hostmodel))
459 		return (ENOBUFS);
460 	bzero(pval, psize);
461 	if (!isv6) {
462 		if (ipst->ips_ip_strict_src_multihoming == 0 &&
463 		    ipst->ips_ip_strict_dst_multihoming == 0)
464 			hostmodel = IP_WEAK_ES;
465 		else if (ipst->ips_ip_strict_src_multihoming == 1 &&
466 		    ipst->ips_ip_strict_dst_multihoming == 0)
467 			hostmodel = IP_SRC_PRI_ES;
468 		else if (ipst->ips_ip_strict_src_multihoming == 2 &&
469 		    ipst->ips_ip_strict_dst_multihoming == 1)
470 			hostmodel = IP_STRONG_ES;
471 		else
472 			hostmodel = IP_MAXVAL_ES;
473 	} else {
474 		if (ipst->ips_ipv6_strict_src_multihoming == 0 &&
475 		    ipst->ips_ipv6_strict_dst_multihoming == 0)
476 			hostmodel = IP_WEAK_ES;
477 		else if (ipst->ips_ipv6_strict_src_multihoming == 1 &&
478 		    ipst->ips_ipv6_strict_dst_multihoming == 0)
479 			hostmodel = IP_SRC_PRI_ES;
480 		else if (ipst->ips_ipv6_strict_src_multihoming == 2 &&
481 		    ipst->ips_ipv6_strict_dst_multihoming == 1)
482 			hostmodel = IP_STRONG_ES;
483 		else
484 			hostmodel = IP_MAXVAL_ES;
485 	}
486 	bcopy(&hostmodel, pval, sizeof (hostmodel));
487 	return (0);
488 }
489 
490 /*
491  * All of these are alterable, within the min/max values given, at run time.
492  *
493  * Note: All those tunables which do not start with "_" are Committed and
494  * therefore are public. See PSARC 2010/080.
495  */
496 mod_prop_info_t ip_propinfo_tbl[] = {
497 	/* tunable - 0 */
498 	{ "_respond_to_address_mask_broadcast", MOD_PROTO_IP,
499 	    mod_set_boolean, mod_get_boolean,
500 	    {B_FALSE}, {B_FALSE} },
501 
502 	{ "_respond_to_echo_broadcast", MOD_PROTO_IP,
503 	    mod_set_boolean, mod_get_boolean,
504 	    {B_TRUE},  {B_TRUE} },
505 
506 	{ "_respond_to_echo_multicast", MOD_PROTO_IPV4,
507 	    mod_set_boolean, mod_get_boolean,
508 	    {B_TRUE}, {B_TRUE} },
509 
510 	{ "_respond_to_timestamp", MOD_PROTO_IP,
511 	    mod_set_boolean, mod_get_boolean,
512 	    {B_FALSE}, {B_FALSE} },
513 
514 	{ "_respond_to_timestamp_broadcast", MOD_PROTO_IP,
515 	    mod_set_boolean, mod_get_boolean,
516 	    {B_FALSE}, {B_FALSE} },
517 
518 	{ "_send_redirects", MOD_PROTO_IPV4,
519 	    mod_set_boolean, mod_get_boolean,
520 	    {B_TRUE}, {B_TRUE} },
521 
522 	{ "_forward_directed_broadcasts", MOD_PROTO_IP,
523 	    mod_set_boolean, mod_get_boolean,
524 	    {B_FALSE}, {B_FALSE} },
525 
526 	{ "_mrtdebug", MOD_PROTO_IP,
527 	    mod_set_uint32, mod_get_uint32,
528 	    {0, 10, 0}, {0} },
529 
530 	{ "_ire_reclaim_fraction", MOD_PROTO_IP,
531 	    mod_set_uint32, mod_get_uint32,
532 	    {1, 8, 3}, {3} },
533 
534 	{ "_nce_reclaim_fraction", MOD_PROTO_IP,
535 	    mod_set_uint32, mod_get_uint32,
536 	    {1, 8, 3}, {3} },
537 
538 	/* tunable - 10 */
539 	{ "_dce_reclaim_fraction", MOD_PROTO_IP,
540 	    mod_set_uint32, mod_get_uint32,
541 	    {1, 8, 3}, {3} },
542 
543 	{ "ttl", MOD_PROTO_IPV4,
544 	    mod_set_uint32, mod_get_uint32,
545 	    {1, 255, 255}, {255} },
546 
547 	{ "_forward_src_routed", MOD_PROTO_IPV4,
548 	    mod_set_boolean, mod_get_boolean,
549 	    {B_FALSE}, {B_FALSE} },
550 
551 	{ "_wroff_extra", MOD_PROTO_IP,
552 	    mod_set_uint32, mod_get_uint32,
553 	    {0, 256, 32}, {32} },
554 
555 	/* following tunable is in seconds - a deviant! */
556 	{ "_pathmtu_interval", MOD_PROTO_IP,
557 	    mod_set_uint32, mod_get_uint32,
558 	    {2, 999999999, 60*20}, {60*20} },
559 
560 	{ "_icmp_return_data_bytes", MOD_PROTO_IPV4,
561 	    mod_set_uint32, mod_get_uint32,
562 	    {8, 65536, 64}, {64} },
563 
564 	{ "_path_mtu_discovery", MOD_PROTO_IP,
565 	    mod_set_boolean, mod_get_boolean,
566 	    {B_TRUE}, {B_TRUE} },
567 
568 	{ "_pmtu_min", MOD_PROTO_IP,
569 	    mod_set_uint32, mod_get_uint32,
570 	    {68, 65535, 576}, {576} },
571 
572 	{ "_ignore_redirect", MOD_PROTO_IPV4,
573 	    mod_set_boolean, mod_get_boolean,
574 	    {B_FALSE}, {B_FALSE} },
575 
576 	{ "_arp_icmp_error", MOD_PROTO_IP,
577 	    mod_set_boolean, mod_get_boolean,
578 	    {B_FALSE}, {B_FALSE} },
579 
580 	/* tunable - 20 */
581 	{ "_broadcast_ttl", MOD_PROTO_IP,
582 	    mod_set_uint32, mod_get_uint32,
583 	    {1, 254, 1}, {1} },
584 
585 	{ "_icmp_err_interval", MOD_PROTO_IP,
586 	    mod_set_uint32, mod_get_uint32,
587 	    {0, 99999, 100}, {100} },
588 
589 	{ "_icmp_err_burst", MOD_PROTO_IP,
590 	    mod_set_uint32, mod_get_uint32,
591 	    {1, 99999, 10}, {10} },
592 
593 	{ "_reass_queue_bytes", MOD_PROTO_IP,
594 	    mod_set_uint32, mod_get_uint32,
595 	    {0, 999999999, 1000000}, {1000000} },
596 
597 	/*
598 	 * See comments for ip_strict_src_multihoming for an explanation
599 	 * of the semantics of ip_strict_dst_multihoming
600 	 */
601 	{ "_strict_dst_multihoming", MOD_PROTO_IPV4,
602 	    mod_set_uint32, mod_get_uint32,
603 	    {0, 1, 0}, {0} },
604 
605 	{ "_addrs_per_if", MOD_PROTO_IP,
606 	    mod_set_uint32, mod_get_uint32,
607 	    {1, MAX_ADDRS_PER_IF, 256}, {256} },
608 
609 	{ "_ipsec_override_persocket_policy", MOD_PROTO_IP,
610 	    mod_set_boolean, mod_get_boolean,
611 	    {B_FALSE}, {B_FALSE} },
612 
613 	{ "_icmp_accept_clear_messages", MOD_PROTO_IP,
614 	    mod_set_boolean, mod_get_boolean,
615 	    {B_TRUE}, {B_TRUE} },
616 
617 	{ "_igmp_accept_clear_messages", MOD_PROTO_IP,
618 	    mod_set_boolean, mod_get_boolean,
619 	    {B_TRUE}, {B_TRUE} },
620 
621 	{ "_ndp_delay_first_probe_time", MOD_PROTO_IP,
622 	    mod_set_uint32, mod_get_uint32,
623 	    {2, 999999999, ND_DELAY_FIRST_PROBE_TIME},
624 	    {ND_DELAY_FIRST_PROBE_TIME} },
625 
626 	/* tunable - 30 */
627 	{ "_ndp_max_unicast_solicit", MOD_PROTO_IP,
628 	    mod_set_uint32, mod_get_uint32,
629 	    {1, 999999999, ND_MAX_UNICAST_SOLICIT}, {ND_MAX_UNICAST_SOLICIT} },
630 
631 	{ "hoplimit", MOD_PROTO_IPV6,
632 	    mod_set_uint32, mod_get_uint32,
633 	    {1, 255, IPV6_MAX_HOPS}, {IPV6_MAX_HOPS} },
634 
635 	{ "_icmp_return_data_bytes", MOD_PROTO_IPV6,
636 	    mod_set_uint32, mod_get_uint32,
637 	    {8, IPV6_MIN_MTU, IPV6_MIN_MTU}, {IPV6_MIN_MTU} },
638 
639 	{ "_forward_src_routed", MOD_PROTO_IPV6,
640 	    mod_set_boolean, mod_get_boolean,
641 	    {B_FALSE}, {B_FALSE} },
642 
643 	{ "_respond_to_echo_multicast", MOD_PROTO_IPV6,
644 	    mod_set_boolean, mod_get_boolean,
645 	    {B_TRUE}, {B_TRUE} },
646 
647 	{ "_send_redirects", MOD_PROTO_IPV6,
648 	    mod_set_boolean, mod_get_boolean,
649 	    {B_TRUE}, {B_TRUE} },
650 
651 	{ "_ignore_redirect", MOD_PROTO_IPV6,
652 	    mod_set_boolean, mod_get_boolean,
653 	    {B_FALSE}, {B_FALSE} },
654 
655 	/*
656 	 * See comments for ip6_strict_src_multihoming for an explanation
657 	 * of the semantics of ip6_strict_dst_multihoming
658 	 */
659 	{ "_strict_dst_multihoming", MOD_PROTO_IPV6,
660 	    mod_set_uint32, mod_get_uint32,
661 	    {0, 1, 0}, {0} },
662 
663 	{ "_src_check", MOD_PROTO_IP,
664 	    mod_set_uint32, mod_get_uint32,
665 	    {0, 2, 2}, {2} },
666 
667 	{ "_ipsec_policy_log_interval", MOD_PROTO_IP,
668 	    mod_set_uint32, mod_get_uint32,
669 	    {0, 999999, 0}, {0} },
670 
671 	/* tunable - 40 */
672 	{ "_pim_accept_clear_messages", MOD_PROTO_IP,
673 	    mod_set_boolean, mod_get_boolean,
674 	    {B_TRUE}, {B_TRUE} },
675 
676 	{ "_ndp_unsolicit_interval", MOD_PROTO_IP,
677 	    mod_set_uint32, mod_get_uint32,
678 	    {1000, 20000, 2000}, {2000} },
679 
680 	{ "_ndp_unsolicit_count", MOD_PROTO_IP,
681 	    mod_set_uint32, mod_get_uint32,
682 	    {1, 20, 3}, {3} },
683 
684 	{ "_ignore_home_address_opt", MOD_PROTO_IPV6,
685 	    mod_set_boolean, mod_get_boolean,
686 	    {B_TRUE}, {B_TRUE} },
687 
688 	{ "_policy_mask", MOD_PROTO_IP,
689 	    mod_set_uint32, mod_get_uint32,
690 	    {0, 15, 0}, {0} },
691 
692 	{ "_ecmp_behavior", MOD_PROTO_IP,
693 	    mod_set_uint32, mod_get_uint32,
694 	    {0, 2, 2}, {2} },
695 
696 	{ "_multirt_ttl", MOD_PROTO_IP,
697 	    mod_set_uint32, mod_get_uint32,
698 	    {0, 255, 1}, {1} },
699 
700 	/* following tunable is in seconds - a deviant */
701 	{ "_ire_badcnt_lifetime", MOD_PROTO_IP,
702 	    mod_set_uint32, mod_get_uint32,
703 	    {0, 3600, 60}, {60} },
704 
705 	{ "_max_temp_idle", MOD_PROTO_IP,
706 	    mod_set_uint32, mod_get_uint32,
707 	    {0, 999999, 60*60*24}, {60*60*24} },
708 
709 	{ "_max_temp_defend", MOD_PROTO_IP,
710 	    mod_set_uint32, mod_get_uint32,
711 	    {0, 1000, 1}, {1} },
712 
713 	/* tunable - 50 */
714 	/*
715 	 * when a conflict of an active address is detected,
716 	 * defend up to ip_max_defend times, within any
717 	 * ip_defend_interval span.
718 	 */
719 	{ "_max_defend", MOD_PROTO_IP,
720 	    mod_set_uint32, mod_get_uint32,
721 	    {0, 1000, 3}, {3} },
722 
723 	{ "_defend_interval", MOD_PROTO_IP,
724 	    mod_set_uint32, mod_get_uint32,
725 	    {0, 999999, 30}, {30} },
726 
727 	{ "_dup_recovery", MOD_PROTO_IP,
728 	    mod_set_uint32, mod_get_uint32,
729 	    {0, 3600000, 300000}, {300000} },
730 
731 	{ "_restrict_interzone_loopback", MOD_PROTO_IP,
732 	    mod_set_boolean, mod_get_boolean,
733 	    {B_TRUE}, {B_TRUE} },
734 
735 	{ "_lso_outbound", MOD_PROTO_IP,
736 	    mod_set_boolean, mod_get_boolean,
737 	    {B_TRUE}, {B_TRUE} },
738 
739 	{ "_igmp_max_version", MOD_PROTO_IP,
740 	    mod_set_uint32, mod_get_uint32,
741 	    {IGMP_V1_ROUTER, IGMP_V3_ROUTER, IGMP_V3_ROUTER},
742 	    {IGMP_V3_ROUTER} },
743 
744 	{ "_mld_max_version", MOD_PROTO_IP,
745 	    mod_set_uint32, mod_get_uint32,
746 	    {MLD_V1_ROUTER, MLD_V2_ROUTER, MLD_V2_ROUTER}, {MLD_V2_ROUTER} },
747 
748 	{ "forwarding", MOD_PROTO_IPV4,
749 	    ip_set_forwarding, ip_get_forwarding,
750 	    {IP_FORWARD_NEVER}, {IP_FORWARD_NEVER} },
751 
752 	{ "forwarding", MOD_PROTO_IPV6,
753 	    ip_set_forwarding, ip_get_forwarding,
754 	    {IP_FORWARD_NEVER}, {IP_FORWARD_NEVER} },
755 
756 	{ "_reasm_timeout", MOD_PROTO_IPV4,
757 	    mod_set_uint32, mod_get_uint32,
758 	    {5, 255, IP_REASM_TIMEOUT},
759 	    {IP_REASM_TIMEOUT} },
760 
761 	/* tunable - 60 */
762 	{ "_reasm_timeout", MOD_PROTO_IPV6,
763 	    mod_set_uint32, mod_get_uint32,
764 	    {5, 255, IPV6_REASM_TIMEOUT},
765 	    {IPV6_REASM_TIMEOUT} },
766 
767 	{ "_cgtp_filter", MOD_PROTO_IP,
768 	    ip_set_cgtp_filter, mod_get_boolean,
769 	    {B_FALSE}, {B_FALSE} },
770 
771 	/* delay before sending first probe: */
772 	{ "_arp_probe_delay", MOD_PROTO_IP,
773 	    mod_set_uint32, mod_get_uint32,
774 	    {0, 20000, 1000}, {1000} },
775 
776 	{ "_arp_fastprobe_delay", MOD_PROTO_IP,
777 	    mod_set_uint32, mod_get_uint32,
778 	    {0, 20000, 100}, {100} },
779 
780 	/* interval at which DAD probes are sent: */
781 	{ "_arp_probe_interval", MOD_PROTO_IP,
782 	    mod_set_uint32, mod_get_uint32,
783 	    {10, 20000, 1500}, {1500} },
784 
785 	{ "_arp_fastprobe_interval", MOD_PROTO_IP,
786 	    mod_set_uint32, mod_get_uint32,
787 	    {10, 20000, 150}, {150} },
788 
789 	{ "_arp_probe_count", MOD_PROTO_IP,
790 	    mod_set_uint32, mod_get_uint32,
791 	    {0, 20, 3}, {3} },
792 
793 	{ "_arp_fastprobe_count", MOD_PROTO_IP,
794 	    mod_set_uint32, mod_get_uint32,
795 	    {0, 20, 3}, {3} },
796 
797 	{ "_dad_announce_interval", MOD_PROTO_IPV4,
798 	    mod_set_uint32, mod_get_uint32,
799 	    {0, 3600000, 15000}, {15000} },
800 
801 	{ "_dad_announce_interval", MOD_PROTO_IPV6,
802 	    mod_set_uint32, mod_get_uint32,
803 	    {0, 3600000, 15000}, {15000} },
804 
805 	/* tunable - 70 */
806 	/*
807 	 * Rate limiting parameters for DAD defense used in
808 	 * ill_defend_rate_limit():
809 	 * defend_rate : pkts/hour permitted
810 	 * defend_interval : time that can elapse before we send out a
811 	 *			DAD defense.
812 	 * defend_period: denominator for defend_rate (in seconds).
813 	 */
814 	{ "_arp_defend_interval", MOD_PROTO_IP,
815 	    mod_set_uint32, mod_get_uint32,
816 	    {0, 3600000, 300000}, {300000} },
817 
818 	{ "_arp_defend_rate", MOD_PROTO_IP,
819 	    mod_set_uint32, mod_get_uint32,
820 	    {0, 20000, 100}, {100} },
821 
822 	{ "_ndp_defend_interval", MOD_PROTO_IP,
823 	    mod_set_uint32, mod_get_uint32,
824 	    {0, 3600000, 300000}, {300000} },
825 
826 	{ "_ndp_defend_rate", MOD_PROTO_IP,
827 	    mod_set_uint32, mod_get_uint32,
828 	    {0, 20000, 100}, {100} },
829 
830 	{ "_arp_defend_period", MOD_PROTO_IP,
831 	    mod_set_uint32, mod_get_uint32,
832 	    {5, 86400, 3600}, {3600} },
833 
834 	{ "_ndp_defend_period", MOD_PROTO_IP,
835 	    mod_set_uint32, mod_get_uint32,
836 	    {5, 86400, 3600}, {3600} },
837 
838 	{ "_icmp_return_pmtu", MOD_PROTO_IPV4,
839 	    mod_set_boolean, mod_get_boolean,
840 	    {B_TRUE}, {B_TRUE} },
841 
842 	{ "_icmp_return_pmtu", MOD_PROTO_IPV6,
843 	    mod_set_boolean, mod_get_boolean,
844 	    {B_TRUE}, {B_TRUE} },
845 
846 	/*
847 	 * publish count/interval values used to announce local addresses
848 	 * for IPv4, IPv6.
849 	 */
850 	{ "_arp_publish_count", MOD_PROTO_IP,
851 	    mod_set_uint32, mod_get_uint32,
852 	    {1, 20, 5}, {5} },
853 
854 	{ "_arp_publish_interval", MOD_PROTO_IP,
855 	    mod_set_uint32, mod_get_uint32,
856 	    {1000, 20000, 2000}, {2000} },
857 
858 	/* tunable - 80 */
859 	/*
860 	 * The ip*strict_src_multihoming and ip*strict_dst_multihoming provide
861 	 * a range of choices for setting strong/weak/preferred end-system
862 	 * behavior. The semantics for setting these are:
863 	 *
864 	 * ip*_strict_dst_multihoming = 0
865 	 *    weak end system model for managing ip destination addresses.
866 	 *    A packet with IP dst D1 that's received on interface I1 will be
867 	 *    accepted as long as D1 is one of the local addresses on
868 	 *    the machine, even if D1 is not configured on I1.
869 	 * ip*strict_dst_multihioming = 1
870 	 *    strong end system model for managing ip destination addresses.
871 	 *    A packet with IP dst D1 that's received on interface I1 will be
872 	 *    accepted if, and only if, D1 is configured on I1.
873 	 *
874 	 * ip*strict_src_multihoming = 0
875 	 *    Source agnostic route selection for outgoing packets: the
876 	 *    outgoing interface for a packet will be computed using
877 	 *    default algorithms for route selection, where the route
878 	 *    with the longest matching prefix is chosen for the output
879 	 *    unless other route selection constraints are explicitly
880 	 *    specified during routing table lookup.  This may result
881 	 *    in packet being sent out on interface I2 with source
882 	 *    address S1, even though S1 is not a configured address on I2.
883 	 * ip*strict_src_multihoming = 1
884 	 *    Preferred source aware route selection for outgoing packets: for
885 	 *    a packet with source S2, destination D2, the route selection
886 	 *    algorithm will first attempt to find a route for the destination
887 	 *    that goes out through an interface where S2 is
888 	 *    configured. If such a route cannot be found, then the
889 	 *    best-matching route for D2 will be selected.
890 	 * ip*strict_src_multihoming = 2
891 	 *    Source aware route selection for outgoing packets: a packet will
892 	 *    be sent out on an interface I2 only if the src address S2 of the
893 	 *    packet is a configured address on I2. In conjunction with
894 	 *    the setting 'ip_strict_dst_multihoming == 1', this will result in
895 	 *    the implementation of Strong ES as defined in Section 3.3.4.2 of
896 	 *    RFC 1122
897 	 */
898 	{ "_strict_src_multihoming", MOD_PROTO_IPV4,
899 	    ip_set_src_multihoming, mod_get_uint32,
900 	    {0, 2, 0}, {0} },
901 
902 	{ "_strict_src_multihoming", MOD_PROTO_IPV6,
903 	    ip_set_src_multihoming, mod_get_uint32,
904 	    {0, 2, 0}, {0} },
905 
906 #ifdef DEBUG
907 	{ "_drop_inbound_icmpv6", MOD_PROTO_IPV6,
908 	    mod_set_boolean, mod_get_boolean,
909 	    {B_FALSE}, {B_FALSE} },
910 #else
911 	{ "", 0, NULL, NULL, {0}, {0} },
912 #endif
913 
914 	{ "_dce_reclaim_threshold", MOD_PROTO_IP,
915 	    mod_set_uint32, mod_get_uint32,
916 	    {1, 100000, 32}, {32} },
917 
918 	{ "mtu", MOD_PROTO_IPV4, NULL, ip_get_mtu, {0}, {0} },
919 
920 	{ "mtu", MOD_PROTO_IPV6, NULL, ip_get_mtu, {0}, {0} },
921 
922 	/*
923 	 * The following entry is a placeholder for `ip_debug' global
924 	 * variable. Within these callback functions, we will be
925 	 * setting/getting the global variable
926 	 */
927 	{ "_debug", MOD_PROTO_IP,
928 	    ip_set_debug, ip_get_debug,
929 	    {0, 20, 0}, {0} },
930 
931 	{ "hostmodel", MOD_PROTO_IPV4, ip_set_hostmodel, ip_get_hostmodel,
932 	    {IP_WEAK_ES, IP_STRONG_ES, IP_WEAK_ES}, {IP_WEAK_ES} },
933 
934 	{ "hostmodel", MOD_PROTO_IPV6, ip_set_hostmodel, ip_get_hostmodel,
935 	    {IP_WEAK_ES, IP_STRONG_ES, IP_WEAK_ES}, {IP_WEAK_ES} },
936 
937 	{ "?", MOD_PROTO_IP, NULL, mod_get_allprop, {0}, {0} },
938 
939 	{ NULL, 0, NULL, NULL, {0}, {0} }
940 };
941 
942 int ip_propinfo_count = A_CNT(ip_propinfo_tbl);
943