Print this page
usr/src/cmd/dlmgmtd/dlmgmt_door.c


   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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018, Joyent Inc.
  25  * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  26  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  27  * Copyright 2020 RackTop Systems Inc.

  28  */
  29 
  30 /*
  31  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  32  */
  33 
  34 /*
  35  * This module contains functions used to bring up and tear down the
  36  * Virtual Platform: [un]mounting file-systems, [un]plumbing network
  37  * interfaces, [un]configuring devices, establishing resource controls,
  38  * and creating/destroying the zone in the kernel.  These actions, on
  39  * the way up, ready the zone; on the way down, they halt the zone.
  40  * See the much longer block comment at the beginning of zoneadmd.c
  41  * for a bigger picture of how the whole program functions.
  42  *
  43  * This module also has primary responsibility for the layout of "scratch
  44  * zones."  These are mounted, but inactive, zones that are used during
  45  * operating system upgrade and potentially other administrative action.  The
  46  * scratch zone environment is similar to the miniroot environment.  The zone's
  47  * actual root is mounted read-write on /a, and the standard paths (/usr,


  69  */
  70 
  71 #include <sys/param.h>
  72 #include <sys/mount.h>
  73 #include <sys/mntent.h>
  74 #include <sys/socket.h>
  75 #include <sys/utsname.h>
  76 #include <sys/types.h>
  77 #include <sys/stat.h>
  78 #include <sys/sockio.h>
  79 #include <sys/stropts.h>
  80 #include <sys/conf.h>
  81 #include <sys/systeminfo.h>
  82 #include <sys/secflags.h>
  83 #include <sys/vnic.h>
  84 
  85 #include <libdlpi.h>
  86 #include <libdllink.h>
  87 #include <libdlvlan.h>
  88 #include <libdlvnic.h>

  89 
  90 #include <inet/tcp.h>
  91 #include <arpa/inet.h>
  92 #include <netinet/in.h>
  93 #include <net/route.h>
  94 
  95 #include <stdio.h>
  96 #include <errno.h>
  97 #include <fcntl.h>
  98 #include <unistd.h>
  99 #include <rctl.h>
 100 #include <stdlib.h>
 101 #include <string.h>
 102 #include <strings.h>
 103 #include <wait.h>
 104 #include <limits.h>
 105 #include <libgen.h>
 106 #include <libzfs.h>
 107 #include <libdevinfo.h>
 108 #include <zone.h>


3011                         zerror(zlogp, B_TRUE, "failed to add address");
3012                         free_ip_interface(zalist);
3013                         return (-1);
3014                 }
3015                 free_ip_interface(zalist);
3016         }
3017         (void) zonecfg_endnwifent(snap_hndl);
3018 
3019         if (prof != NULL && added) {
3020                 if (di_prof_commit(prof) != 0) {
3021                         zerror(zlogp, B_TRUE, "failed to commit profile");
3022                         return (-1);
3023                 }
3024         }
3025         if (prof != NULL)
3026                 di_prof_fini(prof);
3027 
3028         return (0);
3029 }
3030 








3031 static int























































3032 remove_datalink_pool(zlog_t *zlogp, zoneid_t zoneid)
3033 {
3034         ushort_t flags;
3035         zone_iptype_t iptype;
3036         int i, dlnum = 0;
3037         datalink_id_t *dllink, *dllinks = NULL;
3038         dladm_status_t err;
3039 
3040         if (strlen(pool_name) == 0)
3041                 return (0);
3042 
3043         if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3044             sizeof (flags)) < 0) {
3045                 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3046                         zerror(zlogp, B_FALSE, "unable to determine ip-type");
3047                         return (-1);
3048                 }
3049         } else {
3050                 if (flags & ZF_NET_EXCL)
3051                         iptype = ZS_EXCLUSIVE;
3052                 else
3053                         iptype = ZS_SHARED;
3054         }
3055 
3056         if (iptype == ZS_EXCLUSIVE) {
3057                 /*
3058                  * Get the datalink count and for each datalink,
3059                  * attempt to clear the pool property and clear
3060                  * the pool_name.
3061                  */
3062                 if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
3063                         zerror(zlogp, B_TRUE, "unable to count network "
3064                             "interfaces");
3065                         return (-1);
3066                 }
3067 
3068                 if (dlnum == 0)
3069                         return (0);
3070 
3071                 if ((dllinks = malloc(dlnum * sizeof (datalink_id_t)))
3072                     == NULL) {
3073                         zerror(zlogp, B_TRUE, "memory allocation failed");
3074                         return (-1);
3075                 }
3076                 if (zone_list_datalink(zoneid, &dlnum, dllinks) != 0) {
3077                         zerror(zlogp, B_TRUE, "unable to list network "
3078                             "interfaces");
3079                         return (-1);
3080                 }
3081 
3082                 bzero(pool_name, sizeof (pool_name));
3083                 for (i = 0, dllink = dllinks; i < dlnum; i++, dllink++) {
3084                         err = dladm_set_linkprop(dld_handle, *dllink, "pool",
3085                             NULL, 0, DLADM_OPT_ACTIVE);
3086                         if (err != DLADM_STATUS_OK) {
3087                                 zerror(zlogp, B_TRUE,
3088                                     "WARNING: unable to clear pool");
3089                         }
3090                 }
3091                 free(dllinks);
3092         }
3093         return (0);
3094 }
3095 
3096 static int
3097 remove_datalink_protect(zlog_t *zlogp, zoneid_t zoneid)
3098 {
3099         ushort_t flags;
3100         zone_iptype_t iptype;
3101         int i, dlnum = 0;
3102         dladm_status_t dlstatus;
3103         datalink_id_t *dllink, *dllinks = NULL;
3104 
3105         if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3106             sizeof (flags)) < 0) {
3107                 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3108                         zerror(zlogp, B_FALSE, "unable to determine ip-type");
3109                         return (-1);
3110                 }
3111         } else {
3112                 if (flags & ZF_NET_EXCL)
3113                         iptype = ZS_EXCLUSIVE;
3114                 else
3115                         iptype = ZS_SHARED;
3116         }
3117 
3118         if (iptype != ZS_EXCLUSIVE)
3119                 return (0);
3120 
3121         /*
3122          * Get the datalink count and for each datalink,
3123          * attempt to clear the pool property and clear
3124          * the pool_name.
3125          */
3126         if (zone_list_datalink(zoneid, &dlnum, NULL) != 0) {
3127                 zerror(zlogp, B_TRUE, "unable to count network interfaces");
3128                 return (-1);
3129         }
3130 
3131         if (dlnum == 0)
3132                 return (0);
3133 
3134         if ((dllinks = malloc(dlnum * sizeof (datalink_id_t))) == NULL) {
3135                 zerror(zlogp, B_TRUE, "memory allocation failed");
3136                 return (-1);
3137         }
3138         if (zone_list_datalink(zoneid, &dlnum, dllinks) != 0) {
3139                 zerror(zlogp, B_TRUE, "unable to list network interfaces");
3140                 free(dllinks);
3141                 return (-1);
3142         }
3143 
3144         for (i = 0, dllink = dllinks; i < dlnum; i++, dllink++) {
3145                 char dlerr[DLADM_STRSIZE];
3146 
3147                 dlstatus = dladm_set_linkprop(dld_handle, *dllink,
3148                     "protection", NULL, 0, DLADM_OPT_ACTIVE);
3149                 if (dlstatus == DLADM_STATUS_NOTFOUND) {
3150                         /* datalink does not belong to the GZ */
3151                         continue;
3152                 }
3153                 if (dlstatus != DLADM_STATUS_OK)
3154                         zerror(zlogp, B_FALSE,
3155                             "clear 'protection' link property: %s",
3156                             dladm_status2str(dlstatus, dlerr));

3157 
3158                 dlstatus = dladm_set_linkprop(dld_handle, *dllink,
3159                     "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
3160                 if (dlstatus != DLADM_STATUS_OK)
3161                         zerror(zlogp, B_FALSE,
3162                             "clear 'allowed-ips' link property: %s",
3163                             dladm_status2str(dlstatus, dlerr));
3164         }

3165         free(dllinks);
3166         return (0);
3167 }
3168 
3169 static int









































































3170 tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
3171     const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
3172 {
3173         int fd;
3174         struct strioctl ioc;
3175         tcp_ioc_abort_conn_t conn;
3176         int error;
3177 
3178         conn.ac_local = *local;
3179         conn.ac_remote = *remote;
3180         conn.ac_start = TCPS_SYN_SENT;
3181         conn.ac_end = TCPS_TIME_WAIT;
3182         conn.ac_zoneid = zoneid;
3183 
3184         ioc.ic_cmd = TCP_IOC_ABORT_CONN;
3185         ioc.ic_timout = -1; /* infinite timeout */
3186         ioc.ic_len = sizeof (conn);
3187         ioc.ic_dp = (char *)&conn;
3188 
3189         if ((fd = open("/dev/tcp", O_RDONLY)) < 0) {


5198 
5199                 if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
5200                         zerror(zlogp, B_TRUE, "cannot open mapfile");
5201                         return (-1);
5202                 }
5203                 retv = -1;
5204                 if (zonecfg_lock_scratch(fp) != 0)
5205                         zerror(zlogp, B_TRUE, "cannot lock mapfile");
5206                 else if (zonecfg_delete_scratch(fp, kernzone) != 0)
5207                         zerror(zlogp, B_TRUE, "cannot delete map entry");
5208                 else
5209                         retv = 0;
5210                 zonecfg_close_scratch(fp);
5211                 return (retv);
5212         } else {
5213                 return (0);
5214         }
5215 }
5216 
5217 /*
5218  * Delete all transient VNICs belonging to this zone. A transient VNIC
5219  * is one that is created and destroyed along with the lifetime of the
5220  * zone. Non-transient VNICs, ones that are assigned from the GZ to a
5221  * NGZ, are reassigned to the GZ in zone_shutdown() via the
5222  * zone-specific data (zsd) callbacks.
5223  */
5224 static int
5225 delete_transient_vnics(zlog_t *zlogp, zoneid_t zoneid)
5226 {
5227         dladm_status_t status;
5228         int num_links = 0;
5229         datalink_id_t *links, link;
5230         uint32_t link_flags;
5231         datalink_class_t link_class;
5232         char link_name[MAXLINKNAMELEN];
5233 
5234         if (zone_list_datalink(zoneid, &num_links, NULL) != 0) {
5235                 zerror(zlogp, B_TRUE, "unable to determine "
5236                     "number of network interfaces");
5237                 return (-1);
5238         }
5239 
5240         if (num_links == 0)
5241                 return (0);
5242 
5243         links = malloc(num_links * sizeof (datalink_id_t));
5244 
5245         if (links == NULL) {
5246                 zerror(zlogp, B_TRUE, "failed to delete "
5247                     "network interfaces because of alloc fail");
5248                 return (-1);
5249         }
5250 
5251         if (zone_list_datalink(zoneid, &num_links, links) != 0) {
5252                 zerror(zlogp, B_TRUE, "failed to delete "
5253                     "network interfaces because of failure "
5254                     "to list them");
5255                 return (-1);
5256         }
5257 
5258         for (int i = 0; i < num_links; i++) {
5259                 char dlerr[DLADM_STRSIZE];
5260                 link = links[i];



5261 
5262                 status = dladm_datalink_id2info(dld_handle, link, &link_flags,
5263                     &link_class, NULL, link_name, sizeof (link_name));
5264 
5265                 if (status != DLADM_STATUS_OK) {
5266                         zerror(zlogp, B_FALSE, "failed to "
5267                             "delete network interface (%u)"
5268                             "due to failure to get link info: %s",
5269                             link,
5270                             dladm_status2str(status, dlerr));
5271                         return (-1);
5272                 }
5273 
5274                 if (link_flags & DLADM_OPT_TRANSIENT) {
5275                         assert(link_class & DATALINK_CLASS_VNIC);




5276                         status = dladm_vnic_delete(dld_handle, link,
5277                             DLADM_OPT_ACTIVE);















5278 
5279                         if (status != DLADM_STATUS_OK) {
5280                                 zerror(zlogp, B_TRUE, "failed to delete link "
5281                                     "with id %d: %s", link,
5282                                     dladm_status2str(status, dlerr));
5283                                 return (-1);
5284                         }
5285                 }
5286         }
5287 

5288         return (0);
5289 }
5290 
5291 int
5292 vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting,
5293     boolean_t debug)
5294 {
5295         char *kzone;
5296         zoneid_t zoneid;
5297         int res;
5298         char pool_err[128];
5299         char cmdbuf[MAXPATHLEN];
5300         brand_handle_t bh = NULL;
5301         dladm_status_t status;
5302         char errmsg[DLADM_STRSIZE];
5303         ushort_t flags;
5304 
5305         kzone = zone_name;
5306         if (zonecfg_in_alt_root()) {
5307                 FILE *fp;


5311                         goto error;
5312                 }
5313                 if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(),
5314                     kernzone, sizeof (kernzone)) != 0) {
5315                         zerror(zlogp, B_FALSE, "unable to find scratch zone");
5316                         zonecfg_close_scratch(fp);
5317                         goto error;
5318                 }
5319                 zonecfg_close_scratch(fp);
5320                 kzone = kernzone;
5321         }
5322 
5323         if ((zoneid = getzoneidbyname(kzone)) == ZONE_ID_UNDEFINED) {
5324                 if (!bringup_failure_recovery)
5325                         zerror(zlogp, B_TRUE, "unable to get zoneid");
5326                 if (unmount_cmd)
5327                         (void) lu_root_teardown(zlogp);
5328                 goto error;
5329         }
5330 
5331         if (remove_datalink_pool(zlogp, zoneid) != 0)
5332                 zerror(zlogp, B_FALSE, "unable clear datalink pool property");


5333 
5334         if (remove_datalink_protect(zlogp, zoneid) != 0)
5335                 zerror(zlogp, B_FALSE,
5336                     "unable clear datalink protect property");

5337 
5338         /*
5339          * The datalinks assigned to the zone will be removed from the NGZ as
5340          * part of zone_shutdown() so that we need to remove protect/pool etc.
5341          * before zone_shutdown(). Even if the shutdown itself fails, the zone
5342          * will not be able to violate any constraints applied because the
5343          * datalinks are no longer available to the zone.
5344          */
5345         if (zone_shutdown(zoneid) != 0) {
5346                 zerror(zlogp, B_TRUE, "unable to shutdown zone");
5347                 goto error;
5348         }
5349 
5350         /* Get a handle to the brand info for this zone */
5351         if ((bh = brand_open(brand_name)) == NULL) {
5352                 zerror(zlogp, B_FALSE, "unable to determine zone brand");
5353                 return (-1);
5354         }
5355         /*
5356          * If there is a brand 'halt' callback, execute it now to give the


5382                                     "ip-type");
5383                                 goto error;
5384                         }
5385                 } else {
5386                         if (flags & ZF_NET_EXCL)
5387                                 iptype = ZS_EXCLUSIVE;
5388                         else
5389                                 iptype = ZS_SHARED;
5390                 }
5391 
5392                 switch (iptype) {
5393                 case ZS_SHARED:
5394                         if (unconfigure_shared_network_interfaces(zlogp,
5395                             zoneid) != 0) {
5396                                 zerror(zlogp, B_FALSE, "unable to unconfigure "
5397                                     "network interfaces in zone");
5398                                 goto error;
5399                         }
5400                         break;
5401                 case ZS_EXCLUSIVE:
5402                         if (delete_transient_vnics(zlogp, zoneid) != 0) {
5403                                 zerror(zlogp, B_FALSE, "unable to delete "
5404                                     "transient vnics in zone");
5405                                 goto error;
5406                         }






5407 
5408                         status = dladm_zone_halt(dld_handle, zoneid);
5409                         if (status != DLADM_STATUS_OK) {
5410                                 zerror(zlogp, B_FALSE, "unable to notify "
5411                                     "dlmgmtd of zone halt: %s",
5412                                     dladm_status2str(status, errmsg));
5413                                 goto error;
5414                         }
5415                         break;
5416                 }
5417         }
5418 
5419         if (!unmount_cmd && tcp_abort_connections(zlogp, zoneid) != 0) {
5420                 zerror(zlogp, B_TRUE, "unable to abort TCP connections");
5421                 goto error;
5422         }
5423 
5424         if (unmount_filesystems(zlogp, zoneid, unmount_cmd) != 0) {
5425                 zerror(zlogp, B_FALSE,
5426                     "unable to unmount file systems in zone");




   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 /*
  23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright 2018, Joyent Inc.
  25  * Copyright (c) 2015, 2016 by Delphix. All rights reserved.
  26  * Copyright 2019 OmniOS Community Edition (OmniOSce) Association.
  27  * Copyright 2020 RackTop Systems Inc.
  28  * Copyright 2023 Oxide Computer Company
  29  */
  30 
  31 /*
  32  * Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  33  */
  34 
  35 /*
  36  * This module contains functions used to bring up and tear down the
  37  * Virtual Platform: [un]mounting file-systems, [un]plumbing network
  38  * interfaces, [un]configuring devices, establishing resource controls,
  39  * and creating/destroying the zone in the kernel.  These actions, on
  40  * the way up, ready the zone; on the way down, they halt the zone.
  41  * See the much longer block comment at the beginning of zoneadmd.c
  42  * for a bigger picture of how the whole program functions.
  43  *
  44  * This module also has primary responsibility for the layout of "scratch
  45  * zones."  These are mounted, but inactive, zones that are used during
  46  * operating system upgrade and potentially other administrative action.  The
  47  * scratch zone environment is similar to the miniroot environment.  The zone's
  48  * actual root is mounted read-write on /a, and the standard paths (/usr,


  70  */
  71 
  72 #include <sys/param.h>
  73 #include <sys/mount.h>
  74 #include <sys/mntent.h>
  75 #include <sys/socket.h>
  76 #include <sys/utsname.h>
  77 #include <sys/types.h>
  78 #include <sys/stat.h>
  79 #include <sys/sockio.h>
  80 #include <sys/stropts.h>
  81 #include <sys/conf.h>
  82 #include <sys/systeminfo.h>
  83 #include <sys/secflags.h>
  84 #include <sys/vnic.h>
  85 
  86 #include <libdlpi.h>
  87 #include <libdllink.h>
  88 #include <libdlvlan.h>
  89 #include <libdlvnic.h>
  90 #include <libdlaggr.h>
  91 
  92 #include <inet/tcp.h>
  93 #include <arpa/inet.h>
  94 #include <netinet/in.h>
  95 #include <net/route.h>
  96 
  97 #include <stdio.h>
  98 #include <errno.h>
  99 #include <fcntl.h>
 100 #include <unistd.h>
 101 #include <rctl.h>
 102 #include <stdlib.h>
 103 #include <string.h>
 104 #include <strings.h>
 105 #include <wait.h>
 106 #include <limits.h>
 107 #include <libgen.h>
 108 #include <libzfs.h>
 109 #include <libdevinfo.h>
 110 #include <zone.h>


3013                         zerror(zlogp, B_TRUE, "failed to add address");
3014                         free_ip_interface(zalist);
3015                         return (-1);
3016                 }
3017                 free_ip_interface(zalist);
3018         }
3019         (void) zonecfg_endnwifent(snap_hndl);
3020 
3021         if (prof != NULL && added) {
3022                 if (di_prof_commit(prof) != 0) {
3023                         zerror(zlogp, B_TRUE, "failed to commit profile");
3024                         return (-1);
3025                 }
3026         }
3027         if (prof != NULL)
3028                 di_prof_fini(prof);
3029 
3030         return (0);
3031 }
3032 
3033 /*
3034  * Retrieve the list of datalink IDs assigned to a zone.
3035  *
3036  * On return, *count will be updated with the total number of links and, if it
3037  * is not NULL, **linksp will be updated to point to allocated memory
3038  * containing the link IDs. This should be passed to free() when the caller is
3039  * finished with it.
3040  */
3041 static int
3042 fetch_zone_datalinks(zlog_t *zlogp, zoneid_t zoneid, int *countp,
3043     datalink_id_t **linksp)
3044 {
3045         datalink_id_t *links = NULL;
3046         int links_size = 0;
3047         int num_links;
3048 
3049         if (linksp != NULL)
3050                 *linksp = NULL;
3051         *countp = 0;
3052 
3053         num_links = 0;
3054         if (zone_list_datalink(zoneid, &num_links, NULL) != 0) {
3055                 zerror(zlogp, B_TRUE,
3056                     "unable to determine number of network interfaces");
3057                 return (-1);
3058         }
3059 
3060         if (num_links == 0)
3061                 return (0);
3062 
3063         /* If linkp is NULL, the caller only wants the count. */
3064         if (linksp == NULL) {
3065                 *countp = num_links;
3066                 return (0);
3067         }
3068 
3069         do {
3070                 datalink_id_t *p;
3071 
3072                 links_size = num_links;
3073                 p = reallocarray(links, links_size, sizeof (datalink_id_t));
3074 
3075                 if (p == NULL) {
3076                         zerror(zlogp, B_TRUE,
3077                             "failed to allocate memory for zone links");
3078                         free(links);
3079                         return (-1);
3080                 }
3081                 links = p;
3082 
3083                 if (zone_list_datalink(zoneid, &num_links, links) != 0) {
3084                         zerror(zlogp, B_TRUE, "failed to list zone links");
3085                         free(links);
3086                         return (-1);
3087                 }
3088         } while (links_size < num_links);
3089 
3090         *countp = num_links;
3091         *linksp = links;
3092 
3093         return (0);
3094 }
3095 
3096 static int
3097 remove_datalink_pool(zlog_t *zlogp, zoneid_t zoneid)
3098 {
3099         ushort_t flags;
3100         zone_iptype_t iptype;
3101         int i;

3102         dladm_status_t err;
3103 
3104         if (strlen(pool_name) == 0)
3105                 return (0);
3106 
3107         if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3108             sizeof (flags)) < 0) {
3109                 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3110                         zerror(zlogp, B_FALSE, "unable to determine ip-type");
3111                         return (-1);
3112                 }
3113         } else {
3114                 if (flags & ZF_NET_EXCL)
3115                         iptype = ZS_EXCLUSIVE;
3116                 else
3117                         iptype = ZS_SHARED;
3118         }
3119 
3120         if (iptype == ZS_EXCLUSIVE) {
3121                 datalink_id_t *dllinks = NULL;
3122                 int dlnum = 0;








3123 
3124                 if (fetch_zone_datalinks(zlogp, zoneid, &dlnum, &dllinks) != 0)





3125                         return (-1);






3126 
3127                 bzero(pool_name, sizeof (pool_name));
3128                 for (i = 0; i < dlnum; i++) {
3129                         err = dladm_set_linkprop(dld_handle, dllinks[i], "pool",
3130                             NULL, 0, DLADM_OPT_ACTIVE);
3131                         if (err != DLADM_STATUS_OK) {
3132                                 zerror(zlogp, B_TRUE,
3133                                     "WARNING: unable to clear pool");
3134                         }
3135                 }
3136                 free(dllinks);
3137         }
3138         return (0);
3139 }
3140 
3141 static int
3142 remove_datalink_protect(zlog_t *zlogp, zoneid_t zoneid)
3143 {
3144         ushort_t flags;
3145         zone_iptype_t iptype;
3146         int i, dlnum = 0;
3147         dladm_status_t dlstatus;
3148         datalink_id_t *dllinks = NULL;
3149 
3150         if (zone_getattr(zoneid, ZONE_ATTR_FLAGS, &flags,
3151             sizeof (flags)) < 0) {
3152                 if (vplat_get_iptype(zlogp, &iptype) < 0) {
3153                         zerror(zlogp, B_FALSE, "unable to determine ip-type");
3154                         return (-1);
3155                 }
3156         } else {
3157                 if (flags & ZF_NET_EXCL)
3158                         iptype = ZS_EXCLUSIVE;
3159                 else
3160                         iptype = ZS_SHARED;
3161         }
3162 
3163         if (iptype != ZS_EXCLUSIVE)
3164                 return (0);
3165 
3166         /*
3167          * Get the datalink count and for each datalink, attempt to clear the
3168          * protection and allowed_ips properties.

3169          */




3170 
3171         if (fetch_zone_datalinks(zlogp, zoneid, &dlnum, &dllinks) != 0)




3172                 return (-1);






3173 
3174         for (i = 0; i < dlnum; i++) {
3175                 char dlerr[DLADM_STRSIZE];
3176 
3177                 dlstatus = dladm_set_linkprop(dld_handle, dllinks[i],
3178                     "protection", NULL, 0, DLADM_OPT_ACTIVE);
3179                 if (dlstatus == DLADM_STATUS_NOTFOUND) {
3180                         /* datalink does not belong to the GZ */
3181                         continue;
3182                 }
3183                 if (dlstatus != DLADM_STATUS_OK) {
3184                         zerror(zlogp, B_FALSE,
3185                             "clear link %d 'protection' link property: %s",
3186                             dllinks[i], dladm_status2str(dlstatus, dlerr));
3187                 }
3188 
3189                 dlstatus = dladm_set_linkprop(dld_handle, dllinks[i],
3190                     "allowed-ips", NULL, 0, DLADM_OPT_ACTIVE);
3191                 if (dlstatus != DLADM_STATUS_OK) {
3192                         zerror(zlogp, B_FALSE,
3193                             "clear link %d 'allowed-ips' link property: %s",
3194                             dllinks[i], dladm_status2str(dlstatus, dlerr));
3195                 }
3196         }
3197         free(dllinks);
3198         return (0);
3199 }
3200 
3201 static int
3202 unconfigure_exclusive_network_interfaces(zlog_t *zlogp, zoneid_t zoneid)
3203 {
3204         datalink_id_t *dllinks;
3205         int dlnum = 0;
3206         uint_t i;
3207 
3208         /*
3209          * The kernel shutdown callback for the dls module should have removed
3210          * all datalinks from this zone.  If any remain, then there's a
3211          * problem.
3212          */
3213 
3214         if (fetch_zone_datalinks(zlogp, zoneid, &dlnum, &dllinks) != 0)
3215                 return (-1);
3216 
3217         if (dlnum == 0)
3218                 return (0);
3219 
3220         /*
3221          * There are some datalinks left in the zone. The most likely cause of
3222          * this is that the datalink-management daemon (dlmgmtd) was not
3223          * running when the zone was shut down. That prevented the kernel from
3224          * doing the required upcall to move the links back to the GZ. To
3225          * attempt recovery, do that now.
3226          */
3227 
3228         for (i = 0; i < dlnum; i++) {
3229                 char dlerr[DLADM_STRSIZE];
3230                 dladm_status_t status;
3231                 uint32_t link_flags;
3232                 datalink_id_t link = dllinks[i];
3233                 char *prop_vals[] = { GLOBAL_ZONENAME };
3234 
3235                 status = dladm_datalink_id2info(dld_handle, link,
3236                     &link_flags, NULL, NULL, NULL, 0);
3237 
3238                 if (status != DLADM_STATUS_OK) {
3239                         zerror(zlogp, B_FALSE,
3240                             "failed to get link info for %u: %s",
3241                             link, dladm_status2str(status, dlerr));
3242                         continue;
3243                 }
3244 
3245                 if (link_flags & DLADM_OPT_TRANSIENT)
3246                         continue;
3247 
3248                 status = dladm_set_linkprop(dld_handle, link, "zone",
3249                     prop_vals, 1, DLADM_OPT_ACTIVE);
3250 
3251                 if (status != DLADM_STATUS_OK) {
3252                         zerror(zlogp, B_FALSE,
3253                             "failed to move link %u to GZ: %s",
3254                             link, dladm_status2str(status, dlerr));
3255                 }
3256         }
3257 
3258         free(dllinks);
3259 
3260         /* Check again and log a message if links remain */
3261 
3262         if (fetch_zone_datalinks(zlogp, zoneid, &dlnum, NULL) != 0)
3263                 return (-1);
3264 
3265         if (dlnum == 0)
3266                 return (0);
3267 
3268         zerror(zlogp, B_FALSE, "%d datalink(s) remain in zone after shutdown",
3269             dlnum);
3270 
3271         return (-1);
3272 }
3273 
3274 static int
3275 tcp_abort_conn(zlog_t *zlogp, zoneid_t zoneid,
3276     const struct sockaddr_storage *local, const struct sockaddr_storage *remote)
3277 {
3278         int fd;
3279         struct strioctl ioc;
3280         tcp_ioc_abort_conn_t conn;
3281         int error;
3282 
3283         conn.ac_local = *local;
3284         conn.ac_remote = *remote;
3285         conn.ac_start = TCPS_SYN_SENT;
3286         conn.ac_end = TCPS_TIME_WAIT;
3287         conn.ac_zoneid = zoneid;
3288 
3289         ioc.ic_cmd = TCP_IOC_ABORT_CONN;
3290         ioc.ic_timout = -1; /* infinite timeout */
3291         ioc.ic_len = sizeof (conn);
3292         ioc.ic_dp = (char *)&conn;
3293 
3294         if ((fd = open("/dev/tcp", O_RDONLY)) < 0) {


5303 
5304                 if ((fp = zonecfg_open_scratch("", B_FALSE)) == NULL) {
5305                         zerror(zlogp, B_TRUE, "cannot open mapfile");
5306                         return (-1);
5307                 }
5308                 retv = -1;
5309                 if (zonecfg_lock_scratch(fp) != 0)
5310                         zerror(zlogp, B_TRUE, "cannot lock mapfile");
5311                 else if (zonecfg_delete_scratch(fp, kernzone) != 0)
5312                         zerror(zlogp, B_TRUE, "cannot delete map entry");
5313                 else
5314                         retv = 0;
5315                 zonecfg_close_scratch(fp);
5316                 return (retv);
5317         } else {
5318                 return (0);
5319         }
5320 }
5321 
5322 /*
5323  * Delete all transient links belonging to this zone. A transient link
5324  * is one that is created and destroyed along with the lifetime of the
5325  * zone. Non-transient links, ones that are assigned from the GZ to a
5326  * NGZ, are reassigned to the GZ in zone_shutdown() via the
5327  * zone-specific data (zsd) callbacks.
5328  */
5329 static int
5330 delete_transient_links(zlog_t *zlogp, zoneid_t zoneid)
5331 {
5332         datalink_id_t *dllinks = NULL;
5333         int dlnum = 0;
5334         uint_t i;



5335 
5336         if (fetch_zone_datalinks(zlogp, zoneid, &dlnum, &dllinks) != 0)


5337                 return (-1);

5338 
5339         if (dlnum == 0)
5340                 return (0);
5341 
5342         for (i = 0; i < dlnum; i++) {
5343                 char link_name[MAXLINKNAMELEN];














5344                 char dlerr[DLADM_STRSIZE];
5345                 datalink_id_t link = dllinks[i];
5346                 datalink_class_t link_class;
5347                 dladm_status_t status;
5348                 uint32_t link_flags;
5349 
5350                 status = dladm_datalink_id2info(dld_handle, link, &link_flags,
5351                     &link_class, NULL, link_name, sizeof (link_name));
5352 
5353                 if (status != DLADM_STATUS_OK) {
5354                         zerror(zlogp, B_FALSE,
5355                             "failed to get link info for %u: %s",
5356                             link, dladm_status2str(status, dlerr));
5357                         continue;


5358                 }
5359 
5360                 if (!(link_flags & DLADM_OPT_TRANSIENT))
5361                         continue;
5362 
5363                 switch (link_class) {
5364                 case DATALINK_CLASS_VNIC:
5365                 case DATALINK_CLASS_ETHERSTUB:
5366                         status = dladm_vnic_delete(dld_handle, link,
5367                             DLADM_OPT_ACTIVE);
5368                         break;
5369                 case DATALINK_CLASS_VLAN:
5370                         status = dladm_vlan_delete(dld_handle, link,
5371                             DLADM_OPT_ACTIVE);
5372                         break;
5373                 case DATALINK_CLASS_AGGR:
5374                         status = dladm_aggr_delete(dld_handle, link,
5375                             DLADM_OPT_ACTIVE);
5376                         break;
5377                 default:
5378                         zerror(zlogp, B_FALSE,
5379                             "unhandled class for transient link %s (%u)",
5380                             link_name, link);
5381                         continue;
5382                 }
5383 
5384                 if (status != DLADM_STATUS_OK) {
5385                         zerror(zlogp, B_TRUE,
5386                             "failed to delete transient link %s (%u): %s",
5387                             link_name, link, dladm_status2str(status, dlerr));

5388                 }
5389         }

5390 
5391         free(dllinks);
5392         return (0);
5393 }
5394 
5395 int
5396 vplat_teardown(zlog_t *zlogp, boolean_t unmount_cmd, boolean_t rebooting,
5397     boolean_t debug)
5398 {
5399         char *kzone;
5400         zoneid_t zoneid;
5401         int res;
5402         char pool_err[128];
5403         char cmdbuf[MAXPATHLEN];
5404         brand_handle_t bh = NULL;
5405         dladm_status_t status;
5406         char errmsg[DLADM_STRSIZE];
5407         ushort_t flags;
5408 
5409         kzone = zone_name;
5410         if (zonecfg_in_alt_root()) {
5411                 FILE *fp;


5415                         goto error;
5416                 }
5417                 if (zonecfg_find_scratch(fp, zone_name, zonecfg_get_root(),
5418                     kernzone, sizeof (kernzone)) != 0) {
5419                         zerror(zlogp, B_FALSE, "unable to find scratch zone");
5420                         zonecfg_close_scratch(fp);
5421                         goto error;
5422                 }
5423                 zonecfg_close_scratch(fp);
5424                 kzone = kernzone;
5425         }
5426 
5427         if ((zoneid = getzoneidbyname(kzone)) == ZONE_ID_UNDEFINED) {
5428                 if (!bringup_failure_recovery)
5429                         zerror(zlogp, B_TRUE, "unable to get zoneid");
5430                 if (unmount_cmd)
5431                         (void) lu_root_teardown(zlogp);
5432                 goto error;
5433         }
5434 
5435         if (remove_datalink_pool(zlogp, zoneid) != 0) {
5436                 zerror(zlogp, B_FALSE,
5437                     "unable to clear datalink pool property");
5438         }
5439 
5440         if (remove_datalink_protect(zlogp, zoneid) != 0) {
5441                 zerror(zlogp, B_FALSE,
5442                     "unable to clear datalink protect property");
5443         }
5444 
5445         /*
5446          * The datalinks assigned to the zone will be removed from the NGZ as
5447          * part of zone_shutdown() so that we need to remove protect/pool etc.
5448          * before zone_shutdown(). Even if the shutdown itself fails, the zone
5449          * will not be able to violate any constraints applied because the
5450          * datalinks are no longer available to the zone.
5451          */
5452         if (zone_shutdown(zoneid) != 0) {
5453                 zerror(zlogp, B_TRUE, "unable to shutdown zone");
5454                 goto error;
5455         }
5456 
5457         /* Get a handle to the brand info for this zone */
5458         if ((bh = brand_open(brand_name)) == NULL) {
5459                 zerror(zlogp, B_FALSE, "unable to determine zone brand");
5460                 return (-1);
5461         }
5462         /*
5463          * If there is a brand 'halt' callback, execute it now to give the


5489                                     "ip-type");
5490                                 goto error;
5491                         }
5492                 } else {
5493                         if (flags & ZF_NET_EXCL)
5494                                 iptype = ZS_EXCLUSIVE;
5495                         else
5496                                 iptype = ZS_SHARED;
5497                 }
5498 
5499                 switch (iptype) {
5500                 case ZS_SHARED:
5501                         if (unconfigure_shared_network_interfaces(zlogp,
5502                             zoneid) != 0) {
5503                                 zerror(zlogp, B_FALSE, "unable to unconfigure "
5504                                     "network interfaces in zone");
5505                                 goto error;
5506                         }
5507                         break;
5508                 case ZS_EXCLUSIVE:
5509                         if (delete_transient_links(zlogp, zoneid) != 0) {
5510                                 zerror(zlogp, B_FALSE, "unable to delete "
5511                                     "transient links in zone");
5512                                 goto error;
5513                         }
5514                         if (unconfigure_exclusive_network_interfaces(zlogp,
5515                             zoneid) != 0) {
5516                                 zerror(zlogp, B_FALSE, "unable to unconfigure "
5517                                     "network interfaces in zone");
5518                                 goto error;
5519                         }
5520 
5521                         status = dladm_zone_halt(dld_handle, zoneid);
5522                         if (status != DLADM_STATUS_OK) {
5523                                 zerror(zlogp, B_FALSE, "unable to notify "
5524                                     "dlmgmtd of zone halt: %s",
5525                                     dladm_status2str(status, errmsg));
5526                                 goto error;
5527                         }
5528                         break;
5529                 }
5530         }
5531 
5532         if (!unmount_cmd && tcp_abort_connections(zlogp, zoneid) != 0) {
5533                 zerror(zlogp, B_TRUE, "unable to abort TCP connections");
5534                 goto error;
5535         }
5536 
5537         if (unmount_filesystems(zlogp, zoneid, unmount_cmd) != 0) {
5538                 zerror(zlogp, B_FALSE,
5539                     "unable to unmount file systems in zone");