Print this page
3942 inject sanity into ipadm tcp buffer size properties
3943 _snd_lowat_fraction tcp tunable has no effect
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Peng Dai <peng.dai@delphix.com>


   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);


  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;


 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         }


 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         }


 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:


 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)




   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);


  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;


 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         }


 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         }


 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:


 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)