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