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 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2015 by Delphix. All rights reserved.
26 */
27
28 /*
29 * zoneadm is a command interpreter for zone administration. It is all in
30 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
31 * main() calls parse_and_run() which calls cmd_match(), then invokes the
32 * appropriate command's handler function. The rest of the program is the
33 * handler functions and their helper functions.
34 *
35 * Some of the helper functions are used largely to simplify I18N: reducing
36 * the need for translation notes. This is particularly true of many of
37 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
38 * than zerror(gettext("foo failed")) with a translation note indicating
39 * that "foo" need not be translated.
40 */
41
42 #include <stdio.h>
43 #include <errno.h>
44 #include <unistd.h>
45 #include <signal.h>
84 #include <pwd.h>
85 #include <auth_list.h>
86 #include <auth_attr.h>
87 #include <secdb.h>
88
89 #include "zoneadm.h"
90
91 #define MAXARGS 8
92 #define SOURCE_ZONE (CMD_MAX + 1)
93
94 /* Reflects kernel zone entries */
95 typedef struct zone_entry {
96 zoneid_t zid;
97 char zname[ZONENAME_MAX];
98 char *zstate_str;
99 zone_state_t zstate_num;
100 char zbrand[MAXNAMELEN];
101 char zroot[MAXPATHLEN];
102 char zuuid[UUID_PRINTABLE_STRING_LENGTH];
103 zone_iptype_t ziptype;
104 } zone_entry_t;
105
106 #define CLUSTER_BRAND_NAME "cluster"
107
108 static zone_entry_t *zents;
109 static size_t nzents;
110
111 #define LOOPBACK_IF "lo0"
112 #define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
113
114 struct net_if {
115 char *name;
116 int af;
117 };
118
119 /* 0755 is the default directory mode. */
120 #define DEFAULT_DIR_MODE \
121 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
122
123 struct cmd {
426 char *ip_type_str;
427
428 /* Skip a zone that shutdown while we were collecting data. */
429 if (zent->zname[0] == '\0')
430 return;
431
432 if (zent->ziptype == ZS_EXCLUSIVE)
433 ip_type_str = "excl";
434 else
435 ip_type_str = "shared";
436
437 assert(!(verbose && parsable));
438 if (firsttime && verbose) {
439 firsttime = B_FALSE;
440 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
441 ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
442 "IP");
443 }
444 if (!verbose) {
445 char *cp, *clim;
446
447 if (!parsable) {
448 (void) printf("%s\n", zent->zname);
449 return;
450 }
451 if (zent->zid == ZONE_ID_UNDEFINED)
452 (void) printf("-");
453 else
454 (void) printf("%lu", zent->zid);
455 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
456 cp = zent->zroot;
457 while ((clim = strchr(cp, ':')) != NULL) {
458 (void) printf("%.*s\\:", clim - cp, cp);
459 cp = clim + 1;
460 }
461 (void) printf("%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
462 ip_type_str);
463 return;
464 }
465 if (zent->zstate_str != NULL) {
466 if (zent->zid == ZONE_ID_UNDEFINED)
467 (void) printf("%*s", ZONEID_WIDTH, "-");
468 else
469 (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
470 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
471 zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
472 }
473 }
474
475 static int
476 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
477 {
478 char root[MAXPATHLEN], *cp;
479 int err;
480 uuid_t uuid;
481 zone_dochandle_t handle;
482
537 */
538 if (getzoneid() != GLOBAL_ZONEID) {
539 assert(is_system_labeled() != 0);
540 (void) strlcpy(zent->zbrand, default_brand,
541 sizeof (zent->zbrand));
542 } else if (zone_get_brand(zent->zname, zent->zbrand,
543 sizeof (zent->zbrand)) != Z_OK) {
544 zperror2(zent->zname, gettext("could not get brand name"));
545 return (Z_ERR);
546 }
547
548 /*
549 * Get ip type of the zone.
550 * Note for global zone, ZS_SHARED is set always.
551 */
552 if (zid == GLOBAL_ZONEID) {
553 zent->ziptype = ZS_SHARED;
554 return (Z_OK);
555 }
556
557 /*
558 * There is a race condition where the zone could boot while
559 * we're walking the index file. In this case the zone state
560 * could be seen as running from the call above, but the zoneid
561 * would be undefined.
562 *
563 * There is also a race condition where the zone could shutdown after
564 * we got its running state above. This is also not an error and
565 * we fall back to getting the ziptype from the zone configuration.
566 */
567 if (zent->zstate_num == ZONE_STATE_RUNNING &&
568 zid != ZONE_ID_UNDEFINED) {
569 ushort_t flags;
570
571 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
572 sizeof (flags)) >= 0) {
573 if (flags & ZF_NET_EXCL)
574 zent->ziptype = ZS_EXCLUSIVE;
575 else
576 zent->ziptype = ZS_SHARED;
577 return (Z_OK);
578 }
579 }
580
581 if ((handle = zonecfg_init_handle()) == NULL) {
582 zperror2(zent->zname, gettext("could not init handle"));
583 return (Z_ERR);
584 }
585 if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
586 zperror2(zent->zname, gettext("could not get handle"));
587 zonecfg_fini_handle(handle);
588 return (Z_ERR);
589 }
590
591 if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
592 zperror2(zent->zname, gettext("could not get ip-type"));
593 zonecfg_fini_handle(handle);
594 return (Z_ERR);
595 }
596 zonecfg_fini_handle(handle);
597
598 return (Z_OK);
599 }
600
601 /*
602 * fetch_zents() calls zone_list(2) to find out how many zones are running
603 * (which is stored in the global nzents), then calls zone_list(2) again
604 * to fetch the list of running zones (stored in the global zents). This
605 * function may be called multiple times, so if zents is already set, we
606 * return immediately to save work.
607 *
608 * Note that the data about running zones can change while this function
609 * is running, so its possible that the list of zones will have empty slots
610 * at the end.
611 */
612
613 static int
614 fetch_zents(void)
615 {
616 zoneid_t *zids = NULL;
2775 return_code = Z_ERR;
2776 if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2777 return_code = Z_ERR;
2778 if (!in_alt_root && verify_datasets(handle) != Z_OK)
2779 return_code = Z_ERR;
2780
2781 /*
2782 * As the "mount" command is used for patching/upgrading of zones
2783 * or other maintenance processes, the zone's privilege set is not
2784 * checked in this case. Instead, the default, safe set of
2785 * privileges will be used when this zone is created in the
2786 * kernel.
2787 */
2788 if (!in_alt_root && cmd_num != CMD_MOUNT &&
2789 verify_limitpriv(handle) != Z_OK)
2790 return_code = Z_ERR;
2791
2792 return (return_code);
2793 }
2794
2795 static int
2796 verify_details(int cmd_num, char *argv[])
2797 {
2798 zone_dochandle_t handle;
2799 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2800 int return_code = Z_OK;
2801 int err;
2802
2803 if ((handle = zonecfg_init_handle()) == NULL) {
2804 zperror(cmd_to_str(cmd_num), B_TRUE);
2805 return (Z_ERR);
2806 }
2807 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2808 errno = err;
2809 zperror(cmd_to_str(cmd_num), B_TRUE);
2810 zonecfg_fini_handle(handle);
2811 return (Z_ERR);
2812 }
2813 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2814 Z_OK) {
2834 * TRANSLATION_NOTE
2835 * XML and zonepath are literals that should not be translated.
2836 */
2837 (void) fprintf(stderr, gettext("The XML repository has "
2838 "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2839 "These must match, so fix the incorrect entry.\n"),
2840 zonepath, checkpath);
2841 zonecfg_fini_handle(handle);
2842 return (Z_ERR);
2843 }
2844 if (cmd_num != CMD_ATTACH &&
2845 validate_zonepath(zonepath, cmd_num) != Z_OK) {
2846 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2847 "because of the above errors.\n"), zonepath);
2848 return_code = Z_ERR;
2849 }
2850
2851 if (verify_handle(cmd_num, handle, argv) != Z_OK)
2852 return_code = Z_ERR;
2853
2854 zonecfg_fini_handle(handle);
2855 if (return_code == Z_ERR)
2856 (void) fprintf(stderr,
2857 gettext("%s: zone %s failed to verify\n"),
2858 execname, target_zone);
2859 return (return_code);
2860 }
2861
2862 static int
2863 verify_func(int argc, char *argv[])
2864 {
2865 int arg;
2866
2867 optind = 0;
2868 if ((arg = getopt(argc, argv, "?")) != EOF) {
2869 switch (arg) {
2870 case '?':
2871 sub_usage(SHELP_VERIFY, CMD_VERIFY);
2872 return (optopt == '?' ? Z_OK : Z_USAGE);
2873 default:
|
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 /*
23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 * Copyright (c) 2015 by Delphix. All rights reserved.
26 * Copyright (c) 2011, Joyent Inc. All rights reserved.
27 */
28
29 /*
30 * zoneadm is a command interpreter for zone administration. It is all in
31 * C (i.e., no lex/yacc), and all the argument passing is argc/argv based.
32 * main() calls parse_and_run() which calls cmd_match(), then invokes the
33 * appropriate command's handler function. The rest of the program is the
34 * handler functions and their helper functions.
35 *
36 * Some of the helper functions are used largely to simplify I18N: reducing
37 * the need for translation notes. This is particularly true of many of
38 * the zerror() calls: doing e.g. zerror(gettext("%s failed"), "foo") rather
39 * than zerror(gettext("foo failed")) with a translation note indicating
40 * that "foo" need not be translated.
41 */
42
43 #include <stdio.h>
44 #include <errno.h>
45 #include <unistd.h>
46 #include <signal.h>
85 #include <pwd.h>
86 #include <auth_list.h>
87 #include <auth_attr.h>
88 #include <secdb.h>
89
90 #include "zoneadm.h"
91
92 #define MAXARGS 8
93 #define SOURCE_ZONE (CMD_MAX + 1)
94
95 /* Reflects kernel zone entries */
96 typedef struct zone_entry {
97 zoneid_t zid;
98 char zname[ZONENAME_MAX];
99 char *zstate_str;
100 zone_state_t zstate_num;
101 char zbrand[MAXNAMELEN];
102 char zroot[MAXPATHLEN];
103 char zuuid[UUID_PRINTABLE_STRING_LENGTH];
104 zone_iptype_t ziptype;
105 zoneid_t zdid;
106 } zone_entry_t;
107
108 #define CLUSTER_BRAND_NAME "cluster"
109
110 static zone_entry_t *zents;
111 static size_t nzents;
112
113 #define LOOPBACK_IF "lo0"
114 #define SOCKET_AF(af) (((af) == AF_UNSPEC) ? AF_INET : (af))
115
116 struct net_if {
117 char *name;
118 int af;
119 };
120
121 /* 0755 is the default directory mode. */
122 #define DEFAULT_DIR_MODE \
123 (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
124
125 struct cmd {
428 char *ip_type_str;
429
430 /* Skip a zone that shutdown while we were collecting data. */
431 if (zent->zname[0] == '\0')
432 return;
433
434 if (zent->ziptype == ZS_EXCLUSIVE)
435 ip_type_str = "excl";
436 else
437 ip_type_str = "shared";
438
439 assert(!(verbose && parsable));
440 if (firsttime && verbose) {
441 firsttime = B_FALSE;
442 (void) printf("%*s %-16s %-10s %-30s %-8s %-6s\n",
443 ZONEID_WIDTH, "ID", "NAME", "STATUS", "PATH", "BRAND",
444 "IP");
445 }
446 if (!verbose) {
447 char *cp, *clim;
448 char zdid[80];
449
450 if (!parsable) {
451 (void) printf("%s\n", zent->zname);
452 return;
453 }
454 if (zent->zid == ZONE_ID_UNDEFINED)
455 (void) printf("-");
456 else
457 (void) printf("%lu", zent->zid);
458 (void) printf(":%s:%s:", zent->zname, zent->zstate_str);
459 cp = zent->zroot;
460 while ((clim = strchr(cp, ':')) != NULL) {
461 (void) printf("%.*s\\:", clim - cp, cp);
462 cp = clim + 1;
463 }
464 if (zent->zdid == -1)
465 zdid[0] = '\0';
466 else
467 (void) snprintf(zdid, sizeof (zdid), "%d", zent->zdid);
468 (void) printf("%s:%s:%s:%s:%s\n", cp, zent->zuuid, zent->zbrand,
469 ip_type_str, zdid);
470 return;
471 }
472 if (zent->zstate_str != NULL) {
473 if (zent->zid == ZONE_ID_UNDEFINED)
474 (void) printf("%*s", ZONEID_WIDTH, "-");
475 else
476 (void) printf("%*lu", ZONEID_WIDTH, zent->zid);
477 (void) printf(" %-16s %-10s %-30s %-8s %-6s\n", zent->zname,
478 zent->zstate_str, zent->zroot, zent->zbrand, ip_type_str);
479 }
480 }
481
482 static int
483 lookup_zone_info(const char *zone_name, zoneid_t zid, zone_entry_t *zent)
484 {
485 char root[MAXPATHLEN], *cp;
486 int err;
487 uuid_t uuid;
488 zone_dochandle_t handle;
489
544 */
545 if (getzoneid() != GLOBAL_ZONEID) {
546 assert(is_system_labeled() != 0);
547 (void) strlcpy(zent->zbrand, default_brand,
548 sizeof (zent->zbrand));
549 } else if (zone_get_brand(zent->zname, zent->zbrand,
550 sizeof (zent->zbrand)) != Z_OK) {
551 zperror2(zent->zname, gettext("could not get brand name"));
552 return (Z_ERR);
553 }
554
555 /*
556 * Get ip type of the zone.
557 * Note for global zone, ZS_SHARED is set always.
558 */
559 if (zid == GLOBAL_ZONEID) {
560 zent->ziptype = ZS_SHARED;
561 return (Z_OK);
562 }
563
564 if ((handle = zonecfg_init_handle()) == NULL) {
565 zperror2(zent->zname, gettext("could not init handle"));
566 return (Z_ERR);
567 }
568 if ((err = zonecfg_get_handle(zent->zname, handle)) != Z_OK) {
569 zperror2(zent->zname, gettext("could not get handle"));
570 zonecfg_fini_handle(handle);
571 return (Z_ERR);
572 }
573
574 if ((err = zonecfg_get_iptype(handle, &zent->ziptype)) != Z_OK) {
575 zperror2(zent->zname, gettext("could not get ip-type"));
576 zonecfg_fini_handle(handle);
577 return (Z_ERR);
578 }
579
580 /*
581 * There is a race condition where the zone could boot while
582 * we're walking the index file. In this case the zone state
583 * could be seen as running from the call above, but the zoneid
584 * would be undefined.
585 *
586 * There is also a race condition where the zone could shutdown after
587 * we got its running state above. This is also not an error and
588 * we fall back to getting the ziptype from the zone configuration.
589 */
590 if (zent->zstate_num == ZONE_STATE_RUNNING &&
591 zid != ZONE_ID_UNDEFINED) {
592 ushort_t flags;
593
594 if (zone_getattr(zid, ZONE_ATTR_FLAGS, &flags,
595 sizeof (flags)) >= 0) {
596 if (flags & ZF_NET_EXCL)
597 zent->ziptype = ZS_EXCLUSIVE;
598 else
599 zent->ziptype = ZS_SHARED;
600 }
601 }
602
603 zent->zdid = zonecfg_get_did(handle);
604
605 zonecfg_fini_handle(handle);
606
607 return (Z_OK);
608 }
609
610 /*
611 * fetch_zents() calls zone_list(2) to find out how many zones are running
612 * (which is stored in the global nzents), then calls zone_list(2) again
613 * to fetch the list of running zones (stored in the global zents). This
614 * function may be called multiple times, so if zents is already set, we
615 * return immediately to save work.
616 *
617 * Note that the data about running zones can change while this function
618 * is running, so its possible that the list of zones will have empty slots
619 * at the end.
620 */
621
622 static int
623 fetch_zents(void)
624 {
625 zoneid_t *zids = NULL;
2784 return_code = Z_ERR;
2785 if (!in_alt_root && verify_brand(handle, cmd_num, argv) != Z_OK)
2786 return_code = Z_ERR;
2787 if (!in_alt_root && verify_datasets(handle) != Z_OK)
2788 return_code = Z_ERR;
2789
2790 /*
2791 * As the "mount" command is used for patching/upgrading of zones
2792 * or other maintenance processes, the zone's privilege set is not
2793 * checked in this case. Instead, the default, safe set of
2794 * privileges will be used when this zone is created in the
2795 * kernel.
2796 */
2797 if (!in_alt_root && cmd_num != CMD_MOUNT &&
2798 verify_limitpriv(handle) != Z_OK)
2799 return_code = Z_ERR;
2800
2801 return (return_code);
2802 }
2803
2804 /*
2805 * Called when readying or booting a zone. We double check that the zone's
2806 * debug ID is set and is unique. This covers the case of pre-existing zones
2807 * with no ID. Also, its possible that a zone was migrated to this host
2808 * and as a result it has a duplicate ID. In this case we preserve the ID
2809 * of the first zone we match on in the index file (since it was there before
2810 * the current zone) and we assign a new unique ID to the current zone.
2811 * Return true if we assigned a new ID, indicating that the zone configuration
2812 * needs to be saved.
2813 */
2814 static boolean_t
2815 verify_fix_did(zone_dochandle_t handle)
2816 {
2817 zoneid_t mydid;
2818 zone_entry_t zent;
2819 FILE *cookie;
2820 char *name;
2821 boolean_t fix = B_FALSE;
2822
2823 mydid = zonecfg_get_did(handle);
2824 if (mydid == -1) {
2825 zonecfg_set_did(handle);
2826 return (B_TRUE);
2827 }
2828
2829 /* Get the full list of zones from the configuration. */
2830 cookie = setzoneent();
2831 while ((name = getzoneent(cookie)) != NULL) {
2832 if (strcmp(target_zone, name) == 0) {
2833 free(name);
2834 break; /* Once we find our entry, stop. */
2835 }
2836
2837 if (strcmp(name, "global") == 0 ||
2838 lookup_zone_info(name, ZONE_ID_UNDEFINED, &zent) != Z_OK) {
2839 free(name);
2840 continue;
2841 }
2842
2843 free(name);
2844 if (zent.zdid == mydid) {
2845 fix = B_TRUE;
2846 break;
2847 }
2848 }
2849 endzoneent(cookie);
2850
2851 if (fix) {
2852 zonecfg_set_did(handle);
2853 return (B_TRUE);
2854 }
2855
2856 return (B_FALSE);
2857 }
2858
2859 static int
2860 verify_details(int cmd_num, char *argv[])
2861 {
2862 zone_dochandle_t handle;
2863 char zonepath[MAXPATHLEN], checkpath[MAXPATHLEN];
2864 int return_code = Z_OK;
2865 int err;
2866
2867 if ((handle = zonecfg_init_handle()) == NULL) {
2868 zperror(cmd_to_str(cmd_num), B_TRUE);
2869 return (Z_ERR);
2870 }
2871 if ((err = zonecfg_get_handle(target_zone, handle)) != Z_OK) {
2872 errno = err;
2873 zperror(cmd_to_str(cmd_num), B_TRUE);
2874 zonecfg_fini_handle(handle);
2875 return (Z_ERR);
2876 }
2877 if ((err = zonecfg_get_zonepath(handle, zonepath, sizeof (zonepath))) !=
2878 Z_OK) {
2898 * TRANSLATION_NOTE
2899 * XML and zonepath are literals that should not be translated.
2900 */
2901 (void) fprintf(stderr, gettext("The XML repository has "
2902 "zonepath '%s',\nbut the index file has zonepath '%s'.\n"
2903 "These must match, so fix the incorrect entry.\n"),
2904 zonepath, checkpath);
2905 zonecfg_fini_handle(handle);
2906 return (Z_ERR);
2907 }
2908 if (cmd_num != CMD_ATTACH &&
2909 validate_zonepath(zonepath, cmd_num) != Z_OK) {
2910 (void) fprintf(stderr, gettext("could not verify zonepath %s "
2911 "because of the above errors.\n"), zonepath);
2912 return_code = Z_ERR;
2913 }
2914
2915 if (verify_handle(cmd_num, handle, argv) != Z_OK)
2916 return_code = Z_ERR;
2917
2918 if (cmd_num == CMD_READY || cmd_num == CMD_BOOT)
2919 if (verify_fix_did(handle))
2920 if (zonecfg_save(handle) != Z_OK)
2921 (void) fprintf(stderr, gettext("Could not save "
2922 "debug ID.\n"));
2923
2924 zonecfg_fini_handle(handle);
2925 if (return_code == Z_ERR)
2926 (void) fprintf(stderr,
2927 gettext("%s: zone %s failed to verify\n"),
2928 execname, target_zone);
2929 return (return_code);
2930 }
2931
2932 static int
2933 verify_func(int argc, char *argv[])
2934 {
2935 int arg;
2936
2937 optind = 0;
2938 if ((arg = getopt(argc, argv, "?")) != EOF) {
2939 switch (arg) {
2940 case '?':
2941 sub_usage(SHELP_VERIFY, CMD_VERIFY);
2942 return (optopt == '?' ? Z_OK : Z_USAGE);
2943 default:
|