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