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 2010 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
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 	char 		*end;
163 	unsigned long 	new_value;
164 
165 	if (cr != NULL && secpolicy_net_config(cr, B_FALSE) != 0)
166 		return (EPERM);
167 
168 	if (flags & MOD_PROP_DEFAULT) {
169 		ip_debug = pinfo->prop_def_uval;
170 		return (0);
171 	}
172 
173 	if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0')
174 		return (EINVAL);
175 	if (new_value < pinfo->prop_min_uval ||
176 	    new_value > pinfo->prop_max_uval) {
177 		return (ERANGE);
178 	}
179 	ip_debug = (uint32_t)new_value;
180 	return (0);
181 }
182 
183 /*
184  * ip_debug is a global property. For default, permission and value range
185  * we retrieve the value from `pinfo'. However for the current value we
186  * retrieve the value from the global variable `ip_debug'
187  */
188 /* ARGSUSED */
189 int
190 ip_get_debug(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
191     void *pval, uint_t psize, uint_t flags)
192 {
193 	boolean_t	get_def = (flags & MOD_PROP_DEFAULT);
194 	boolean_t	get_perm = (flags & MOD_PROP_PERM);
195 	boolean_t	get_range = (flags & MOD_PROP_POSSIBLE);
196 	size_t		nbytes;
197 
198 	bzero(pval, psize);
199 	if (get_perm)
200 		nbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
201 	else if (get_range)
202 		nbytes = snprintf(pval, psize, "%u-%u",
203 		    pinfo->prop_min_uval, pinfo->prop_max_uval);
204 	else if (get_def)
205 		nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval);
206 	else
207 		nbytes = snprintf(pval, psize, "%u", ip_debug);
208 	if (nbytes >= psize)
209 		return (ENOBUFS);
210 	return (0);
211 }
212 
213 /*
214  * Set the CGTP (multirouting) filtering status. If the status is changed
215  * from active to transparent or from transparent to active, forward the
216  * new status to the filtering module (if loaded).
217  */
218 /* ARGSUSED */
219 static int
220 ip_set_cgtp_filter(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
221     const char *ifname, const void* pval, uint_t flags)
222 {
223 	unsigned long	new_value;
224 	ip_stack_t	*ipst = (ip_stack_t *)cbarg;
225 	char		*end;
226 
227 	if (flags & MOD_PROP_DEFAULT) {
228 		new_value = pinfo->prop_def_bval;
229 	} else {
230 		if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
231 		    *end != '\0' || new_value > 1) {
232 			return (EINVAL);
233 		}
234 	}
235 	if (!pinfo->prop_cur_bval && new_value) {
236 		cmn_err(CE_NOTE, "IP: enabling CGTP filtering%s",
237 		    ipst->ips_ip_cgtp_filter_ops == NULL ?
238 		    " (module not loaded)" : "");
239 	}
240 	if (pinfo->prop_cur_bval && !new_value) {
241 		cmn_err(CE_NOTE, "IP: disabling CGTP filtering%s",
242 		    ipst->ips_ip_cgtp_filter_ops == NULL ?
243 		    " (module not loaded)" : "");
244 	}
245 	if (ipst->ips_ip_cgtp_filter_ops != NULL) {
246 		int	res;
247 		netstackid_t stackid = ipst->ips_netstack->netstack_stackid;
248 
249 		res = ipst->ips_ip_cgtp_filter_ops->cfo_change_state(stackid,
250 		    new_value);
251 		if (res)
252 			return (res);
253 	}
254 	pinfo->prop_cur_bval = (new_value == 1 ? B_TRUE : B_FALSE);
255 	ill_set_inputfn_all(ipst);
256 	return (0);
257 }
258 
259 /*
260  * Retrieve the default MTU or min-max MTU range for a given interface.
261  *
262  *  -- ill_max_frag value tells us the maximum MTU that can be handled by the
263  *     datalink. This value is advertised by the driver via DLPI messages
264  *     (DL_NOTE_SDU_SIZE/DL_INFO_ACK).
265  *
266  *  -- ill_current_frag for the most link-types will be same as ill_max_frag
267  *     to begin with. However it is dynamically computed for some link-types
268  *     like tunnels, based on the tunnel PMTU.
269  *
270  *  -- ill_mtu is the user set MTU using SIOCSLIFMTU and must lie between
271  *     (IPV6_MIN_MTU/IP_MIN_MTU) and ill_max_frag.
272  *
273  *  -- ill_user_mtu is set by in.ndpd using SIOCSLIFLNKINFO and must lie between
274  *     (IPV6_MIN_MTU/IP_MIN_MTU) and ill_max_frag.
275  */
276 int
277 ip_get_mtu(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
278     void *pval, uint_t psize, uint_t flags)
279 {
280 	ill_walk_context_t 	ctx;
281 	ill_t 			*ill;
282 	ip_stack_t 		*ipst =  (ip_stack_t *)cbarg;
283 	boolean_t		isv6;
284 	uint32_t		max_mtu, def_mtu;
285 	size_t			nbytes = 0;
286 
287 	if (!(flags & (MOD_PROP_DEFAULT|MOD_PROP_POSSIBLE)))
288 		return (ENOTSUP);
289 
290 	if (ifname == NULL || ifname[0] == '\0')
291 		return (ENOTSUP);
292 
293 	isv6 = (pinfo->mpi_proto == MOD_PROTO_IPV6 ? B_TRUE : B_FALSE);
294 	rw_enter(&ipst->ips_ill_g_lock, RW_READER);
295 	if (isv6)
296 		ill = ILL_START_WALK_V6(&ctx, ipst);
297 	else
298 		ill = ILL_START_WALK_V4(&ctx, ipst);
299 	for (; ill != NULL; ill = ill_next(&ctx, ill)) {
300 		if (strcmp(ifname, ill->ill_name) == 0)
301 			break;
302 	}
303 	if (ill == NULL) {
304 		rw_exit(&ipst->ips_ill_g_lock);
305 		return (ENXIO);
306 	}
307 	max_mtu = ill->ill_max_frag;
308 	def_mtu = ill->ill_current_frag;
309 	rw_exit(&ipst->ips_ill_g_lock);
310 
311 	if (flags & MOD_PROP_DEFAULT) {
312 		nbytes = snprintf(pval, psize, "%u", def_mtu);
313 	} else if (flags & MOD_PROP_POSSIBLE) {
314 		uint32_t	min_mtu;
315 
316 		min_mtu = isv6 ? IPV6_MIN_MTU : IP_MIN_MTU;
317 		nbytes = snprintf(pval, psize, "%u-%u", min_mtu, max_mtu);
318 	} else {
319 		return (ENOTSUP);
320 	}
321 
322 	if (nbytes >= psize)
323 		return (ENOBUFS);
324 	return (0);
325 }
326 
327 /*
328  * See the comments for ip[6]_strict_src_multihoming for an explanation
329  * of the semanitcs.
330  */
331 /* ARGSUSED */
332 static int
333 ip_set_src_multihoming(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
334     const char *ifname, const void* pval, uint_t flags)
335 {
336 	char 		*end;
337 	unsigned long 	new_value, old_value;
338 	boolean_t	isv6;
339 	ip_stack_t	*ipst = (ip_stack_t *)cbarg;
340 
341 	old_value = pinfo->prop_cur_uval;
342 
343 	if (flags & MOD_PROP_DEFAULT) {
344 		new_value = pinfo->prop_def_uval;
345 	} else {
346 		if (ddi_strtoul(pval, &end, 10, &new_value) != 0 ||
347 		    *end != '\0')
348 			return (EINVAL);
349 		if (new_value < pinfo->prop_min_uval ||
350 		    new_value > pinfo->prop_max_uval)
351 			return (ERANGE);
352 	}
353 	pinfo->prop_cur_uval = new_value;
354 	isv6 = (strcmp(pinfo->mpi_name, "ip6_strict_src_multihoming") == 0);
355 	if (new_value != old_value) {
356 		if (!isv6) {
357 			if (old_value == 0) {
358 				ire_walk_v4(ip_ire_rebind_walker, NULL,
359 				    ALL_ZONES, ipst);
360 			} else {
361 				ire_walk_v4(ip_ire_unbind_walker, NULL,
362 				    ALL_ZONES, ipst);
363 			}
364 			ipcl_walk(conn_ire_revalidate, (void *)B_FALSE, ipst);
365 		} else {
366 			if (old_value == 0) {
367 				ire_walk_v6(ip_ire_rebind_walker, NULL,
368 				    ALL_ZONES, ipst);
369 			} else {
370 				ire_walk_v6(ip_ire_unbind_walker, NULL,
371 				    ALL_ZONES, ipst);
372 			}
373 			ipcl_walk(conn_ire_revalidate, (void *)B_TRUE, ipst);
374 		}
375 	}
376 	return (0);
377 }
378 
379 /*
380  * All of these are alterable, within the min/max values given, at run time.
381  *
382  * Note: All those tunables which do not start with "ip_" are Committed and
383  * therefore are public. See PSARC 2009/306.
384  */
385 mod_prop_info_t ip_propinfo_tbl[] = {
386 	/* tunable - 0 */
387 	{ "ip_respond_to_address_mask_broadcast", MOD_PROTO_IP,
388 	    mod_set_boolean, mod_get_boolean,
389 	    {B_FALSE}, {B_FALSE} },
390 
391 	{ "ip_respond_to_echo_broadcast", MOD_PROTO_IP,
392 	    mod_set_boolean, mod_get_boolean,
393 	    {B_TRUE},  {B_TRUE} },
394 
395 	{ "ip_respond_to_echo_multicast", MOD_PROTO_IP,
396 	    mod_set_boolean, mod_get_boolean,
397 	    {B_TRUE}, {B_TRUE} },
398 
399 	{ "ip_respond_to_timestamp", MOD_PROTO_IP,
400 	    mod_set_boolean, mod_get_boolean,
401 	    {B_FALSE}, {B_FALSE} },
402 
403 	{ "ip_respond_to_timestamp_broadcast", MOD_PROTO_IP,
404 	    mod_set_boolean, mod_get_boolean,
405 	    {B_FALSE}, {B_FALSE} },
406 
407 	{ "ip_send_redirects", MOD_PROTO_IP,
408 	    mod_set_boolean, mod_get_boolean,
409 	    {B_TRUE}, {B_TRUE} },
410 
411 	{ "ip_forward_directed_broadcasts", MOD_PROTO_IP,
412 	    mod_set_boolean, mod_get_boolean,
413 	    {B_FALSE}, {B_FALSE} },
414 
415 	{ "ip_mrtdebug", MOD_PROTO_IP,
416 	    mod_set_uint32, mod_get_uint32,
417 	    {0, 10, 0}, {0} },
418 
419 	{ "ip_ire_reclaim_fraction", MOD_PROTO_IP,
420 	    mod_set_uint32, mod_get_uint32,
421 	    {1, 8, 3}, {3} },
422 
423 	{ "ip_nce_reclaim_fraction", MOD_PROTO_IP,
424 	    mod_set_uint32, mod_get_uint32,
425 	    {1, 8, 3}, {3} },
426 
427 	/* tunable - 10 */
428 	{ "ip_dce_reclaim_fraction", MOD_PROTO_IP,
429 	    mod_set_uint32, mod_get_uint32,
430 	    {1, 8, 3}, {3} },
431 
432 	{ "ttl", MOD_PROTO_IPV4,
433 	    mod_set_uint32, mod_get_uint32,
434 	    {1, 255, 255}, {255} },
435 
436 	{ "ip_forward_src_routed", MOD_PROTO_IP,
437 	    mod_set_boolean, mod_get_boolean,
438 	    {B_FALSE}, {B_FALSE} },
439 
440 	{ "ip_wroff_extra", MOD_PROTO_IP,
441 	    mod_set_uint32, mod_get_uint32,
442 	    {0, 256, 32}, {32} },
443 
444 	/* following tunable is in seconds - a deviant! */
445 	{ "ip_pathmtu_interval", MOD_PROTO_IP,
446 	    mod_set_uint32, mod_get_uint32,
447 	    {2, 999999999, 60*20}, {60*20} },
448 
449 	{ "ip_icmp_return_data_bytes", MOD_PROTO_IP,
450 	    mod_set_uint32, mod_get_uint32,
451 	    {8, 65536, 64}, {64} },
452 
453 	{ "ip_path_mtu_discovery", MOD_PROTO_IP,
454 	    mod_set_boolean, mod_get_boolean,
455 	    {B_TRUE}, {B_TRUE} },
456 
457 	{ "ip_pmtu_min", MOD_PROTO_IP,
458 	    mod_set_uint32, mod_get_uint32,
459 	    {68, 65535, 576}, {576} },
460 
461 	{ "ip_ignore_redirect", MOD_PROTO_IP,
462 	    mod_set_boolean, mod_get_boolean,
463 	    {B_FALSE}, {B_FALSE} },
464 
465 	{ "ip_arp_icmp_error", MOD_PROTO_IP,
466 	    mod_set_boolean, mod_get_boolean,
467 	    {B_FALSE}, {B_FALSE} },
468 
469 	/* tunable - 20 */
470 	{ "ip_broadcast_ttl", MOD_PROTO_IP,
471 	    mod_set_uint32, mod_get_uint32,
472 	    {1, 254, 1}, {1} },
473 
474 	{ "ip_icmp_err_interval", MOD_PROTO_IP,
475 	    mod_set_uint32, mod_get_uint32,
476 	    {0, 99999, 100}, {100} },
477 
478 	{ "ip_icmp_err_burst", MOD_PROTO_IP,
479 	    mod_set_uint32, mod_get_uint32,
480 	    {1, 99999, 10}, {10} },
481 
482 	{ "ip_reass_queue_bytes", MOD_PROTO_IP,
483 	    mod_set_uint32, mod_get_uint32,
484 	    {0, 999999999, 1000000}, {1000000} },
485 
486 	/*
487 	 * See comments for ip_strict_src_multihoming for an explanation
488 	 * of the semantics of ip_strict_dst_multihoming
489 	 */
490 	{ "ip_strict_dst_multihoming", MOD_PROTO_IP,
491 	    mod_set_uint32, mod_get_uint32,
492 	    {0, 1, 0}, {0} },
493 
494 	{ "ip_addrs_per_if", MOD_PROTO_IP,
495 	    mod_set_uint32, mod_get_uint32,
496 	    {1, MAX_ADDRS_PER_IF, 256}, {256} },
497 
498 	{ "ipsec_override_persocket_policy", MOD_PROTO_IP,
499 	    mod_set_boolean, mod_get_boolean,
500 	    {B_FALSE}, {B_FALSE} },
501 
502 	{ "icmp_accept_clear_messages", MOD_PROTO_IP,
503 	    mod_set_boolean, mod_get_boolean,
504 	    {B_TRUE}, {B_TRUE} },
505 
506 	{ "igmp_accept_clear_messages", MOD_PROTO_IP,
507 	    mod_set_boolean, mod_get_boolean,
508 	    {B_TRUE}, {B_TRUE} },
509 
510 	{ "ip_ndp_delay_first_probe_time", MOD_PROTO_IP,
511 	    mod_set_uint32, mod_get_uint32,
512 	    {2, 999999999, ND_DELAY_FIRST_PROBE_TIME},
513 	    {ND_DELAY_FIRST_PROBE_TIME} },
514 
515 	/* tunable - 30 */
516 	{ "ip_ndp_max_unicast_solicit", MOD_PROTO_IP,
517 	    mod_set_uint32, mod_get_uint32,
518 	    {1, 999999999, ND_MAX_UNICAST_SOLICIT}, {ND_MAX_UNICAST_SOLICIT} },
519 
520 	{ "hoplimit", MOD_PROTO_IPV6,
521 	    mod_set_uint32, mod_get_uint32,
522 	    {1, 255, IPV6_MAX_HOPS}, {IPV6_MAX_HOPS} },
523 
524 	{ "ip6_icmp_return_data_bytes", MOD_PROTO_IP,
525 	    mod_set_uint32, mod_get_uint32,
526 	    {8, IPV6_MIN_MTU, IPV6_MIN_MTU}, {IPV6_MIN_MTU} },
527 
528 	{ "ip6_forward_src_routed", MOD_PROTO_IP,
529 	    mod_set_boolean, mod_get_boolean,
530 	    {B_FALSE}, {B_FALSE} },
531 
532 	{ "ip6_respond_to_echo_multicast", MOD_PROTO_IP,
533 	    mod_set_boolean, mod_get_boolean,
534 	    {B_TRUE}, {B_TRUE} },
535 
536 	{ "ip6_send_redirects", MOD_PROTO_IP,
537 	    mod_set_boolean, mod_get_boolean,
538 	    {B_TRUE}, {B_TRUE} },
539 
540 	{ "ip6_ignore_redirect", MOD_PROTO_IP,
541 	    mod_set_boolean, mod_get_boolean,
542 	    {B_FALSE}, {B_FALSE} },
543 
544 	/*
545 	 * See comments for ip6_strict_src_multihoming for an explanation
546 	 * of the semantics of ip6_strict_dst_multihoming
547 	 */
548 	{ "ip6_strict_dst_multihoming", MOD_PROTO_IP,
549 	    mod_set_uint32, mod_get_uint32,
550 	    {0, 1, 0}, {0} },
551 
552 	{ "ip_src_check", MOD_PROTO_IP,
553 	    mod_set_uint32, mod_get_uint32,
554 	    {0, 2, 2}, {2} },
555 
556 	{ "ipsec_policy_log_interval", MOD_PROTO_IP,
557 	    mod_set_uint32, mod_get_uint32,
558 	    {0, 999999, 1000}, {1000} },
559 
560 	/* tunable - 40 */
561 	{ "pim_accept_clear_messages", MOD_PROTO_IP,
562 	    mod_set_boolean, mod_get_boolean,
563 	    {B_TRUE}, {B_TRUE} },
564 
565 	{ "ip_ndp_unsolicit_interval", MOD_PROTO_IP,
566 	    mod_set_uint32, mod_get_uint32,
567 	    {1000, 20000, 2000}, {2000} },
568 
569 	{ "ip_ndp_unsolicit_count", MOD_PROTO_IP,
570 	    mod_set_uint32, mod_get_uint32,
571 	    {1, 20, 3}, {3} },
572 
573 	{ "ip6_ignore_home_address_opt", MOD_PROTO_IP,
574 	    mod_set_boolean, mod_get_boolean,
575 	    {B_TRUE}, {B_TRUE} },
576 
577 	{ "ip_policy_mask", MOD_PROTO_IP,
578 	    mod_set_uint32, mod_get_uint32,
579 	    {0, 15, 0}, {0} },
580 
581 	{ "ip_ecmp_behavior", MOD_PROTO_IP,
582 	    mod_set_uint32, mod_get_uint32,
583 	    {0, 2, 2}, {2} },
584 
585 	{ "ip_multirt_ttl", MOD_PROTO_IP,
586 	    mod_set_uint32, mod_get_uint32,
587 	    {0, 255, 1}, {1} },
588 
589 	/* following tunable is in seconds - a deviant */
590 	{ "ip_ire_badcnt_lifetime", MOD_PROTO_IP,
591 	    mod_set_uint32, mod_get_uint32,
592 	    {0, 3600, 60}, {60} },
593 
594 	{ "ip_max_temp_idle", MOD_PROTO_IP,
595 	    mod_set_uint32, mod_get_uint32,
596 	    {0, 999999, 60*60*24}, {60*60*24} },
597 
598 	{ "ip_max_temp_defend", MOD_PROTO_IP,
599 	    mod_set_uint32, mod_get_uint32,
600 	    {0, 1000, 1}, {1} },
601 
602 	/* tunable - 50 */
603 	/*
604 	 * when a conflict of an active address is detected,
605 	 * defend up to ip_max_defend times, within any
606 	 * ip_defend_interval span.
607 	 */
608 	{ "ip_max_defend", MOD_PROTO_IP,
609 	    mod_set_uint32, mod_get_uint32,
610 	    {0, 1000, 3}, {3} },
611 
612 	{ "ip_defend_interval", MOD_PROTO_IP,
613 	    mod_set_uint32, mod_get_uint32,
614 	    {0, 999999, 30}, {30} },
615 
616 	{ "ip_dup_recovery", MOD_PROTO_IP,
617 	    mod_set_uint32, mod_get_uint32,
618 	    {0, 3600000, 300000}, {300000} },
619 
620 	{ "ip_restrict_interzone_loopback", MOD_PROTO_IP,
621 	    mod_set_boolean, mod_get_boolean,
622 	    {B_TRUE}, {B_TRUE} },
623 
624 	{ "ip_lso_outbound", MOD_PROTO_IP,
625 	    mod_set_boolean, mod_get_boolean,
626 	    {B_TRUE}, {B_TRUE} },
627 
628 	{ "igmp_max_version", MOD_PROTO_IP,
629 	    mod_set_uint32, mod_get_uint32,
630 	    {IGMP_V1_ROUTER, IGMP_V3_ROUTER, IGMP_V3_ROUTER},
631 	    {IGMP_V3_ROUTER} },
632 
633 	{ "mld_max_version", MOD_PROTO_IP,
634 	    mod_set_uint32, mod_get_uint32,
635 	    {MLD_V1_ROUTER, MLD_V2_ROUTER, MLD_V2_ROUTER}, {MLD_V2_ROUTER} },
636 
637 	{ "forwarding", MOD_PROTO_IPV4,
638 	    ip_set_forwarding, ip_get_forwarding,
639 	    {IP_FORWARD_NEVER}, {IP_FORWARD_NEVER} },
640 
641 	{ "forwarding", MOD_PROTO_IPV6,
642 	    ip_set_forwarding, ip_get_forwarding,
643 	    {IP_FORWARD_NEVER}, {IP_FORWARD_NEVER} },
644 
645 	{ "ip_reasm_timeout", MOD_PROTO_IP,
646 	    mod_set_uint32, mod_get_uint32,
647 	    {5, 255, IP_REASM_TIMEOUT},
648 	    {IP_REASM_TIMEOUT} },
649 
650 	/* tunable - 60 */
651 	{ "ip6_reasm_timeout", MOD_PROTO_IP,
652 	    mod_set_uint32, mod_get_uint32,
653 	    {5, 255, IPV6_REASM_TIMEOUT},
654 	    {IPV6_REASM_TIMEOUT} },
655 
656 	{ "ip_cgtp_filter", MOD_PROTO_IP,
657 	    ip_set_cgtp_filter, mod_get_boolean,
658 	    {B_FALSE}, {B_FALSE} },
659 
660 	/* delay before sending first probe: */
661 	{ "arp_probe_delay", MOD_PROTO_IP,
662 	    mod_set_uint32, mod_get_uint32,
663 	    {0, 20000, 1000}, {1000} },
664 
665 	{ "arp_fastprobe_delay", MOD_PROTO_IP,
666 	    mod_set_uint32, mod_get_uint32,
667 	    {0, 20000, 100}, {100} },
668 
669 	/* interval at which DAD probes are sent: */
670 	{ "arp_probe_interval", MOD_PROTO_IP,
671 	    mod_set_uint32, mod_get_uint32,
672 	    {10, 20000, 1500}, {1500} },
673 
674 	{ "arp_fastprobe_interval", MOD_PROTO_IP,
675 	    mod_set_uint32, mod_get_uint32,
676 	    {10, 20000, 150}, {150} },
677 
678 	{ "arp_probe_count", MOD_PROTO_IP,
679 	    mod_set_uint32, mod_get_uint32,
680 	    {0, 20, 3}, {3} },
681 
682 	{ "arp_fastprobe_count", MOD_PROTO_IP,
683 	    mod_set_uint32, mod_get_uint32,
684 	    {0, 20, 3}, {3} },
685 
686 	{ "ipv4_dad_announce_interval", MOD_PROTO_IP,
687 	    mod_set_uint32, mod_get_uint32,
688 	    {0, 3600000, 15000}, {15000} },
689 
690 	{ "ipv6_dad_announce_interval", MOD_PROTO_IP,
691 	    mod_set_uint32, mod_get_uint32,
692 	    {0, 3600000, 15000}, {15000} },
693 
694 	/* tunable - 70 */
695 	/*
696 	 * Rate limiting parameters for DAD defense used in
697 	 * ill_defend_rate_limit():
698 	 * defend_rate : pkts/hour permitted
699 	 * defend_interval : time that can elapse before we send out a
700 	 *			DAD defense.
701 	 * defend_period: denominator for defend_rate (in seconds).
702 	 */
703 	{ "arp_defend_interval", MOD_PROTO_IP,
704 	    mod_set_uint32, mod_get_uint32,
705 	    {0, 3600000, 300000}, {300000} },
706 
707 	{ "arp_defend_rate", MOD_PROTO_IP,
708 	    mod_set_uint32, mod_get_uint32,
709 	    {0, 20000, 100}, {100} },
710 
711 	{ "ndp_defend_interval", MOD_PROTO_IP,
712 	    mod_set_uint32, mod_get_uint32,
713 	    {0, 3600000, 300000}, {300000} },
714 
715 	{ "ndp_defend_rate", MOD_PROTO_IP,
716 	    mod_set_uint32, mod_get_uint32,
717 	    {0, 20000, 100}, {100} },
718 
719 	{ "arp_defend_period", MOD_PROTO_IP,
720 	    mod_set_uint32, mod_get_uint32,
721 	    {5, 86400, 3600}, {3600} },
722 
723 	{ "ndp_defend_period", MOD_PROTO_IP,
724 	    mod_set_uint32, mod_get_uint32,
725 	    {5, 86400, 3600}, {3600} },
726 
727 	{ "ipv4_icmp_return_pmtu", MOD_PROTO_IP,
728 	    mod_set_boolean, mod_get_boolean,
729 	    {B_TRUE}, {B_TRUE} },
730 
731 	{ "ipv6_icmp_return_pmtu", MOD_PROTO_IP,
732 	    mod_set_boolean, mod_get_boolean,
733 	    {B_TRUE}, {B_TRUE} },
734 
735 	/*
736 	 * publish count/interval values used to announce local addresses
737 	 * for IPv4, IPv6.
738 	 */
739 	{ "ip_arp_publish_count", MOD_PROTO_IP,
740 	    mod_set_uint32, mod_get_uint32,
741 	    {1, 20, 5}, {5} },
742 
743 	{ "ip_arp_publish_interval", MOD_PROTO_IP,
744 	    mod_set_uint32, mod_get_uint32,
745 	    {1000, 20000, 2000}, {2000} },
746 
747 	/* tunable - 80 */
748 	/*
749 	 * The ip*strict_src_multihoming and ip*strict_dst_multihoming provide
750 	 * a range of choices for setting strong/weak/preferred end-system
751 	 * behavior. The semantics for setting these are:
752 	 *
753 	 * ip*_strict_dst_multihoming = 0
754 	 *    weak end system model for managing ip destination addresses.
755 	 *    A packet with IP dst D1 that's received on interface I1 will be
756 	 *    accepted as long as D1 is one of the local addresses on
757 	 *    the machine, even if D1 is not configured on I1.
758 	 * ip*strict_dst_multihioming = 1
759 	 *    strong end system model for managing ip destination addresses.
760 	 *    A packet with IP dst D1 that's received on interface I1 will be
761 	 *    accepted if, and only if, D1 is configured on I1.
762 	 *
763 	 * ip*strict_src_multihoming = 0
764 	 *    Source agnostic route selection for outgoing packets: the
765 	 *    outgoing interface for a packet will be computed using
766 	 *    default algorithms for route selection, where the route
767 	 *    with the longest matching prefix is chosen for the output
768 	 *    unless other route selection constraints are explicitly
769 	 *    specified during routing table lookup.  This may result
770 	 *    in packet being sent out on interface I2 with source
771 	 *    address S1, even though S1 is not a configured address on I2.
772 	 * ip*strict_src_multihoming = 1
773 	 *    Preferred source aware route selection for outgoing packets: for
774 	 *    a packet with source S2, destination D2, the route selection
775 	 *    algorithm will first attempt to find a route for the destination
776 	 *    that goes out through an interface where S2 is
777 	 *    configured. If such a route cannot be found, then the
778 	 *    best-matching route for D2 will be selected.
779 	 * ip*strict_src_multihoming = 2
780 	 *    Source aware route selection for outgoing packets: a packet will
781 	 *    be sent out on an interface I2 only if the src address S2 of the
782 	 *    packet is a configured address on I2. In conjunction with
783 	 *    the setting 'ip_strict_dst_multihoming == 1', this will result in
784 	 *    the implementation of Strong ES as defined in Section 3.3.4.2 of
785 	 *    RFC 1122
786 	 */
787 	{ "ip_strict_src_multihoming", MOD_PROTO_IP,
788 	    ip_set_src_multihoming, mod_get_uint32,
789 	    {0, 2, 0}, {0} },
790 
791 	{ "ip6_strict_src_multihoming", MOD_PROTO_IP,
792 	    ip_set_src_multihoming, mod_get_uint32,
793 	    {0, 2, 0}, {0} },
794 
795 #ifdef DEBUG
796 	{ "ip6_drop_inbound_icmpv6", MOD_PROTO_IP,
797 	    mod_set_boolean, mod_get_boolean,
798 	    {B_FALSE}, {B_FALSE} },
799 #else
800 	{ "", 0, NULL, NULL, {0}, {0} },
801 #endif
802 	{ "mtu", MOD_PROTO_IPV4, NULL, ip_get_mtu, {0}, {0} },
803 
804 	{ "mtu", MOD_PROTO_IPV6, NULL, ip_get_mtu, {0}, {0} },
805 
806 	/*
807 	 * The following entry is a placeholder for `ip_debug' global
808 	 * variable. Within these callback functions, we will be
809 	 * setting/getting the global variable
810 	 */
811 	{ "ip_debug", MOD_PROTO_IP,
812 	    ip_set_debug, ip_get_debug,
813 	    {0, 20, 0}, {0} },
814 
815 	{ "?", MOD_PROTO_IP, NULL, mod_get_allprop, {0}, {0} },
816 
817 	{ NULL, 0, NULL, NULL, {0}, {0} }
818 };
819 
820 int ip_propinfo_count = A_CNT(ip_propinfo_tbl);
821