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