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