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 */
48static int
49ip_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
98static int
99ip_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);
149ret:
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 */
160int
161ip_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 */
182int
183ip_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 */
212static int
213ip_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 */
269int
270ip_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 */
324void
325ip_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 */
356static int
357ip_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 */
377static int
378ip_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 */
450int
451ip_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 */
496mod_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
942int ip_propinfo_count = A_CNT(ip_propinfo_tbl);
943