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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2012 Joyent, Inc. All rights reserved.
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
30 * Console support for zones requires a significant infrastructure. The
31 * core pieces are contained in this file, but other portions of note
32 * are in the zlogin(1M) command, the zcons(7D) driver, and in the
33 * devfsadm(1M) misc_link generator.
34 *
35 * Care is taken to make the console behave in an "intuitive" fashion for
36 * administrators. Essentially, we try as much as possible to mimic the
37 * experience of using a system via a tip line and system controller.
38 *
39 * The zone console architecture looks like this:
40 *
41 * Global Zone | Non-Global Zone
42 * .--------------. |
43 * .-----------. | zoneadmd -z | | .--------. .---------.
44 * | zlogin -C | | myzone | | | ttymon | | syslogd |
45 * `-----------' `--------------' | `--------' `---------'
101 #include <stropts.h>
102 #include <thread.h>
103 #include <ucred.h>
104 #include <unistd.h>
105 #include <zone.h>
106
107 #include <libdevinfo.h>
108 #include <libdevice.h>
109 #include <libzonecfg.h>
110
111 #include <syslog.h>
112 #include <sys/modctl.h>
113
114 #include "zoneadmd.h"
115
116 #define ZCONSNEX_DEVTREEPATH "/pseudo/zconsnex@1"
117 #define ZCONSNEX_FILEPATH "/devices/pseudo/zconsnex@1"
118
119 #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock"
120
121 static int serverfd = -1; /* console server unix domain socket fd */
122 char boot_args[BOOTARGS_MAX];
123 char bad_boot_arg[BOOTARGS_MAX];
124
125 /*
126 * The eventstream is a simple one-directional flow of messages from the
127 * door server to the console subsystem, implemented with a pipe.
128 * It is used to wake up the console poller when it needs to take action,
129 * message the user, die off, etc.
130 */
131 static int eventstream[2];
132
133
134
135 int
136 eventstream_init()
137 {
138 if (pipe(eventstream) == -1)
139 return (-1);
140 return (0);
141 }
142
143 void
144 eventstream_write(zone_evt_t evt)
145 {
146 (void) write(eventstream[0], &evt, sizeof (evt));
147 }
148
149 static zone_evt_t
150 eventstream_read(void)
151 {
152 zone_evt_t evt = Z_EVT_NULL;
153
154 (void) read(eventstream[1], &evt, sizeof (evt));
391 "property");
392 goto error;
393 }
394 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) {
395 zerror(zlogp, B_TRUE, "failed to create console node");
396 goto error;
397 }
398
399 devlinks:
400 if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) {
401 (void) di_devlink_fini(&dl);
402 } else {
403 zerror(zlogp, B_TRUE, "failed to create devlinks");
404 goto error;
405 }
406
407 /*
408 * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl,
409 * which will cause the master to retain a reference to the slave.
410 * This prevents ttymon from blowing through the slave's STREAMS anchor.
411 */
412 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
413 zone_name, ZCONS_MASTER_NAME);
414 if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
415 zerror(zlogp, B_TRUE, "ERROR: could not open master side of "
416 "zone console for %s to acquire slave handle", zone_name);
417 goto error;
418 }
419 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
420 zone_name, ZCONS_SLAVE_NAME);
421 if ((slavefd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
422 zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone"
423 " console for %s to acquire slave handle", zone_name);
424 (void) close(masterfd);
425 goto error;
426 }
427 /*
428 * This ioctl can occasionally return ENXIO if devfs doesn't have
429 * everything plumbed up yet due to heavy zone startup load. Wait for
430 * 1 sec. and retry a few times before we fail to boot the zone.
431 */
432 for (i = 0; i < 5; i++) {
433 if (ioctl(masterfd, ZC_HOLDSLAVE, (caddr_t)(intptr_t)slavefd)
434 == 0) {
435 rv = 0;
436 break;
437 } else if (errno != ENXIO) {
438 break;
439 }
440 (void) sleep(1);
441 }
442 if (rv != 0)
443 zerror(zlogp, B_TRUE, "ERROR: error while acquiring slave "
444 "handle of zone console for %s", zone_name);
445
446 (void) close(slavefd);
447 (void) close(masterfd);
448
449 error:
450 if (ddef_hdl)
451 devctl_ddef_free(ddef_hdl);
452 if (bus_hdl)
453 devctl_release(bus_hdl);
454 if (dev_hdl)
455 devctl_release(dev_hdl);
456 return (rv);
457 }
458
459 static int
460 init_console_sock(zlog_t *zlogp)
461 {
462 int servfd;
463 struct sockaddr_un servaddr;
464
465 bzero(&servaddr, sizeof (servaddr));
466 servaddr.sun_family = AF_UNIX;
500
501 (void) snprintf(path, sizeof (path), CONSOLE_SOCKPATH, zone_name);
502 (void) unlink(path);
503 (void) shutdown(servfd, SHUT_RDWR);
504 (void) close(servfd);
505 }
506
507 /*
508 * Read the "ident" string from the client's descriptor; this routine also
509 * tolerates being called with pid=NULL, for times when you want to "eat"
510 * the ident string from a client without saving it.
511 */
512 static int
513 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len,
514 int *disconnect)
515 {
516 char buf[BUFSIZ], *bufp;
517 size_t buflen = sizeof (buf);
518 char c = '\0';
519 int i = 0, r;
520
521 /* "eat up the ident string" case, for simplicity */
522 if (pid == NULL) {
523 assert(locale == NULL && locale_len == 0);
524 while (read(clifd, &c, 1) == 1) {
525 if (c == '\n')
526 return (0);
527 }
528 }
529
530 bzero(buf, sizeof (buf));
531 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) {
532 buflen--;
533 if (c == '\n')
534 break;
535
536 buf[i] = c;
537 i++;
538 }
539 if (r == -1)
540 return (-1);
541
542 /*
543 * We've filled the buffer, but still haven't seen \n. Keep eating
544 * until we find it; we don't expect this to happen, but this is
545 * defensive.
546 */
547 if (c != '\n') {
548 while ((r = read(clifd, &c, sizeof (c))) > 0)
549 if (c == '\n')
550 break;
551 }
552
553 /*
554 * Parse buffer for message of the form:
555 * IDENT <pid> <locale> <disconnect flag>
556 */
557 bufp = buf;
558 if (strncmp(bufp, "IDENT ", 6) != 0)
559 return (-1);
560 bufp += 6;
561 errno = 0;
562 *pid = strtoll(bufp, &bufp, 10);
563 if (errno != 0)
564 return (-1);
565
566 while (*bufp != '\0' && isspace(*bufp))
567 bufp++;
568 buflen = strlen(bufp) - 1;
569 *disconnect = atoi(&bufp[buflen]);
570 bufp[buflen - 1] = '\0';
571 (void) strlcpy(locale, bufp, locale_len);
572
573 return (0);
574 }
575
576 static int
577 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len,
578 int *disconnect)
579 {
580 int connfd;
581 struct sockaddr_un cliaddr;
582 socklen_t clilen;
583
584 clilen = sizeof (cliaddr);
650 break;
651 case Z_EVT_ZONE_REBOOTING:
652 if (*boot_args == '\0') {
653 str = "NOTICE: Zone rebooting";
654 break;
655 }
656 /*LINTED*/
657 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale,
658 "NOTICE: Zone rebooting with arguments: %s"), boot_args);
659 lstr = lmsg;
660 break;
661 case Z_EVT_ZONE_UNINSTALLING:
662 str = "NOTICE: Zone is being uninstalled. Disconnecting...";
663 break;
664 case Z_EVT_ZONE_BOOTFAILED:
665 if (dflag)
666 str = "NOTICE: Zone boot failed. Disconnecting...";
667 else
668 str = "NOTICE: Zone boot failed";
669 break;
670 case Z_EVT_ZONE_BADARGS:
671 /*LINTED*/
672 (void) snprintf(lmsg, sizeof (lmsg),
673 localize_msg(clilocale,
674 "WARNING: Ignoring invalid boot arguments: %s"),
675 bad_boot_arg);
676 lstr = lmsg;
677 break;
678 default:
679 return;
680 }
681
682 if (lstr == NULL)
683 lstr = localize_msg(clilocale, str);
684 (void) snprintf(outbuf, sizeof (outbuf), "\r\n[%s]\r\n", lstr);
685 (void) write(clifd, outbuf, strlen(outbuf));
686 }
687
688 /*
689 * Check to see if the client at the other end of the socket is still
690 * alive; we know it is not if it throws EPIPE at us when we try to write
691 * an otherwise harmless 0-length message to it.
692 */
693 static int
694 test_client(int clifd)
695 {
696 if ((write(clifd, "", 0) == -1) && errno == EPIPE)
697 return (-1);
861 if ((evt == Z_EVT_ZONE_HALTED ||
862 evt == Z_EVT_ZONE_BOOTFAILED) && disconnect) {
863 break;
864 }
865 }
866
867 }
868
869 if (clifd != -1) {
870 (void) shutdown(clifd, SHUT_RDWR);
871 (void) close(clifd);
872 }
873 }
874
875 int
876 init_console(zlog_t *zlogp)
877 {
878 if (init_console_dev(zlogp) == -1) {
879 zerror(zlogp, B_FALSE,
880 "console setup: device initialization failed");
881 return (-1);
882 }
883
884 if ((serverfd = init_console_sock(zlogp)) == -1) {
885 zerror(zlogp, B_FALSE,
886 "console setup: socket initialization failed");
887 return (-1);
888 }
889 return (0);
890 }
891
892 /*
893 * serve_console() is the master loop for driving console I/O. It is also the
894 * routine which is ultimately responsible for "pulling the plug" on zoneadmd
895 * when it realizes that the daemon should shut down.
896 *
897 * The rules for shutdown are: there must be no console client, and the zone
898 * state must be < ready. However, we need to give things a chance to actually
899 * get going when the daemon starts up-- otherwise the daemon would immediately
900 * exit on startup if the zone was in the installed state, so we first drop
901 * into the do_console_io() loop in order to give *something* a chance to
902 * happen.
903 */
904 void
905 serve_console(zlog_t *zlogp)
906 {
907 int masterfd;
908 zone_state_t zstate;
909 char conspath[MAXPATHLEN];
910
911 (void) snprintf(conspath, sizeof (conspath),
912 "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME);
913
914 for (;;) {
915 masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY);
916 if (masterfd == -1) {
917 zerror(zlogp, B_TRUE, "failed to open console master");
918 (void) mutex_lock(&lock);
919 goto death;
920 }
921
922 /*
923 * Setting RPROTDIS on the stream means that the control
924 * portion of messages received (which we don't care about)
925 * will be discarded by the stream head. If we allowed such
926 * messages, we wouldn't be able to use read(2), as it fails
927 * (EBADMSG) when a message with a control element is received.
928 */
929 if (ioctl(masterfd, I_SRDOPT, RNORM|RPROTDIS) == -1) {
930 zerror(zlogp, B_TRUE, "failed to set options on "
931 "console master");
932 (void) mutex_lock(&lock);
933 goto death;
934 }
935
936 do_console_io(zlogp, masterfd, serverfd);
|
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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 * Copyright 2015 Joyent, Inc.
26 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
30 * Console support for zones requires a significant infrastructure. The
31 * core pieces are contained in this file, but other portions of note
32 * are in the zlogin(1M) command, the zcons(7D) driver, and in the
33 * devfsadm(1M) misc_link generator.
34 *
35 * Care is taken to make the console behave in an "intuitive" fashion for
36 * administrators. Essentially, we try as much as possible to mimic the
37 * experience of using a system via a tip line and system controller.
38 *
39 * The zone console architecture looks like this:
40 *
41 * Global Zone | Non-Global Zone
42 * .--------------. |
43 * .-----------. | zoneadmd -z | | .--------. .---------.
44 * | zlogin -C | | myzone | | | ttymon | | syslogd |
45 * `-----------' `--------------' | `--------' `---------'
101 #include <stropts.h>
102 #include <thread.h>
103 #include <ucred.h>
104 #include <unistd.h>
105 #include <zone.h>
106
107 #include <libdevinfo.h>
108 #include <libdevice.h>
109 #include <libzonecfg.h>
110
111 #include <syslog.h>
112 #include <sys/modctl.h>
113
114 #include "zoneadmd.h"
115
116 #define ZCONSNEX_DEVTREEPATH "/pseudo/zconsnex@1"
117 #define ZCONSNEX_FILEPATH "/devices/pseudo/zconsnex@1"
118
119 #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock"
120
121 #define ZCONS_RETRY 10
122
123 static int serverfd = -1; /* console server unix domain socket fd */
124 char boot_args[BOOTARGS_MAX];
125
126 /*
127 * The eventstream is a simple one-directional flow of messages from the
128 * door server to the console subsystem, implemented with a pipe.
129 * It is used to wake up the console poller when it needs to take action,
130 * message the user, die off, etc.
131 */
132 static int eventstream[2];
133
134 /* flag used to cope with race creating master zcons devlink */
135 static boolean_t master_zcons_failed = B_FALSE;
136 /* flag to track if we've seen a state change when there is no master zcons */
137 static boolean_t state_changed = B_FALSE;
138
139 int
140 eventstream_init()
141 {
142 if (pipe(eventstream) == -1)
143 return (-1);
144 return (0);
145 }
146
147 void
148 eventstream_write(zone_evt_t evt)
149 {
150 (void) write(eventstream[0], &evt, sizeof (evt));
151 }
152
153 static zone_evt_t
154 eventstream_read(void)
155 {
156 zone_evt_t evt = Z_EVT_NULL;
157
158 (void) read(eventstream[1], &evt, sizeof (evt));
395 "property");
396 goto error;
397 }
398 if (devctl_bus_dev_create(bus_hdl, ddef_hdl, 0, &dev_hdl) == -1) {
399 zerror(zlogp, B_TRUE, "failed to create console node");
400 goto error;
401 }
402
403 devlinks:
404 if ((dl = di_devlink_init("zcons", DI_MAKE_LINK)) != NULL) {
405 (void) di_devlink_fini(&dl);
406 } else {
407 zerror(zlogp, B_TRUE, "failed to create devlinks");
408 goto error;
409 }
410
411 /*
412 * Open the master side of the console and issue the ZC_HOLDSLAVE ioctl,
413 * which will cause the master to retain a reference to the slave.
414 * This prevents ttymon from blowing through the slave's STREAMS anchor.
415 *
416 * In very rare cases the open returns ENOENT if devfs doesn't have
417 * everything setup yet due to heavy zone startup load. Wait for
418 * 1 sec. and retry a few times. Even if we can't setup the zone's
419 * console, we still go ahead and boot the zone.
420 */
421 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
422 zone_name, ZCONS_MASTER_NAME);
423 if ((masterfd = open(conspath, O_RDWR | O_NOCTTY)) == -1) {
424 zerror(zlogp, B_TRUE, "ERROR: could not open master side of "
425 "zone console for %s to acquire slave handle", zone_name);
426 master_zcons_failed = B_TRUE;
427 }
428 (void) snprintf(conspath, sizeof (conspath), "/dev/zcons/%s/%s",
429 zone_name, ZCONS_SLAVE_NAME);
430 for (i = 0; i < ZCONS_RETRY; i++) {
431 slavefd = open(conspath, O_RDWR | O_NOCTTY);
432 if (slavefd >= 0 || errno != ENOENT)
433 break;
434 (void) sleep(1);
435 }
436 if (slavefd == -1)
437 zerror(zlogp, B_TRUE, "ERROR: could not open slave side of zone"
438 " console for %s to acquire slave handle", zone_name);
439
440 /*
441 * This ioctl can occasionally return ENXIO if devfs doesn't have
442 * everything plumbed up yet due to heavy zone startup load. Wait for
443 * 1 sec. and retry a few times before we fail to boot the zone.
444 */
445 if (masterfd != -1 && slavefd != -1) {
446 for (i = 0; i < ZCONS_RETRY; i++) {
447 if (ioctl(masterfd, ZC_HOLDSLAVE,
448 (caddr_t)(intptr_t)slavefd) == 0) {
449 rv = 0;
450 break;
451 } else if (errno != ENXIO) {
452 break;
453 }
454 (void) sleep(1);
455 }
456 if (rv != 0)
457 zerror(zlogp, B_TRUE, "ERROR: error while acquiring "
458 "slave handle of zone console for %s", zone_name);
459 }
460
461 if (slavefd != -1)
462 (void) close(slavefd);
463 if (masterfd != -1)
464 (void) close(masterfd);
465
466 error:
467 if (ddef_hdl)
468 devctl_ddef_free(ddef_hdl);
469 if (bus_hdl)
470 devctl_release(bus_hdl);
471 if (dev_hdl)
472 devctl_release(dev_hdl);
473 return (rv);
474 }
475
476 static int
477 init_console_sock(zlog_t *zlogp)
478 {
479 int servfd;
480 struct sockaddr_un servaddr;
481
482 bzero(&servaddr, sizeof (servaddr));
483 servaddr.sun_family = AF_UNIX;
517
518 (void) snprintf(path, sizeof (path), CONSOLE_SOCKPATH, zone_name);
519 (void) unlink(path);
520 (void) shutdown(servfd, SHUT_RDWR);
521 (void) close(servfd);
522 }
523
524 /*
525 * Read the "ident" string from the client's descriptor; this routine also
526 * tolerates being called with pid=NULL, for times when you want to "eat"
527 * the ident string from a client without saving it.
528 */
529 static int
530 get_client_ident(int clifd, pid_t *pid, char *locale, size_t locale_len,
531 int *disconnect)
532 {
533 char buf[BUFSIZ], *bufp;
534 size_t buflen = sizeof (buf);
535 char c = '\0';
536 int i = 0, r;
537 ucred_t *cred = NULL;
538
539 /* "eat up the ident string" case, for simplicity */
540 if (pid == NULL) {
541 assert(locale == NULL && locale_len == 0);
542 while (read(clifd, &c, 1) == 1) {
543 if (c == '\n')
544 return (0);
545 }
546 }
547
548 bzero(buf, sizeof (buf));
549 while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) {
550 buflen--;
551 if (c == '\n')
552 break;
553
554 buf[i] = c;
555 i++;
556 }
557 if (r == -1)
558 return (-1);
559
560 /*
561 * We've filled the buffer, but still haven't seen \n. Keep eating
562 * until we find it; we don't expect this to happen, but this is
563 * defensive.
564 */
565 if (c != '\n') {
566 while ((r = read(clifd, &c, sizeof (c))) > 0)
567 if (c == '\n')
568 break;
569 }
570
571 if (getpeerucred(clifd, &cred) == 0) {
572 *pid = ucred_getpid((const ucred_t *)cred);
573 ucred_free(cred);
574 } else {
575 return (-1);
576 }
577
578 /*
579 * Parse buffer for message of the form:
580 * IDENT <locale> <disconnect flag>
581 */
582 bufp = buf;
583 if (strncmp(bufp, "IDENT ", 6) != 0)
584 return (-1);
585 bufp += 6;
586 errno = 0;
587
588 while (*bufp != '\0' && isspace(*bufp))
589 bufp++;
590 buflen = strlen(bufp) - 1;
591 *disconnect = atoi(&bufp[buflen]);
592 bufp[buflen - 1] = '\0';
593 (void) strlcpy(locale, bufp, locale_len);
594
595 return (0);
596 }
597
598 static int
599 accept_client(int servfd, pid_t *pid, char *locale, size_t locale_len,
600 int *disconnect)
601 {
602 int connfd;
603 struct sockaddr_un cliaddr;
604 socklen_t clilen;
605
606 clilen = sizeof (cliaddr);
672 break;
673 case Z_EVT_ZONE_REBOOTING:
674 if (*boot_args == '\0') {
675 str = "NOTICE: Zone rebooting";
676 break;
677 }
678 /*LINTED*/
679 (void) snprintf(lmsg, sizeof (lmsg), localize_msg(clilocale,
680 "NOTICE: Zone rebooting with arguments: %s"), boot_args);
681 lstr = lmsg;
682 break;
683 case Z_EVT_ZONE_UNINSTALLING:
684 str = "NOTICE: Zone is being uninstalled. Disconnecting...";
685 break;
686 case Z_EVT_ZONE_BOOTFAILED:
687 if (dflag)
688 str = "NOTICE: Zone boot failed. Disconnecting...";
689 else
690 str = "NOTICE: Zone boot failed";
691 break;
692 default:
693 return;
694 }
695
696 if (lstr == NULL)
697 lstr = localize_msg(clilocale, str);
698 (void) snprintf(outbuf, sizeof (outbuf), "\r\n[%s]\r\n", lstr);
699 (void) write(clifd, outbuf, strlen(outbuf));
700 }
701
702 /*
703 * Check to see if the client at the other end of the socket is still
704 * alive; we know it is not if it throws EPIPE at us when we try to write
705 * an otherwise harmless 0-length message to it.
706 */
707 static int
708 test_client(int clifd)
709 {
710 if ((write(clifd, "", 0) == -1) && errno == EPIPE)
711 return (-1);
875 if ((evt == Z_EVT_ZONE_HALTED ||
876 evt == Z_EVT_ZONE_BOOTFAILED) && disconnect) {
877 break;
878 }
879 }
880
881 }
882
883 if (clifd != -1) {
884 (void) shutdown(clifd, SHUT_RDWR);
885 (void) close(clifd);
886 }
887 }
888
889 int
890 init_console(zlog_t *zlogp)
891 {
892 if (init_console_dev(zlogp) == -1) {
893 zerror(zlogp, B_FALSE,
894 "console setup: device initialization failed");
895 }
896
897 if ((serverfd = init_console_sock(zlogp)) == -1) {
898 zerror(zlogp, B_FALSE,
899 "console setup: socket initialization failed");
900 return (-1);
901 }
902 return (0);
903 }
904
905 /*
906 * Maintain a simple flag that tracks if we have seen at least one state
907 * change. This is currently only used to handle the special case where we are
908 * running without a console device, which is what normally drives shutdown.
909 */
910 void
911 zcons_statechanged()
912 {
913 state_changed = B_TRUE;
914 }
915
916 /*
917 * serve_console() is the master loop for driving console I/O. It is also the
918 * routine which is ultimately responsible for "pulling the plug" on zoneadmd
919 * when it realizes that the daemon should shut down.
920 *
921 * The rules for shutdown are: there must be no console client, and the zone
922 * state must be < ready. However, we need to give things a chance to actually
923 * get going when the daemon starts up-- otherwise the daemon would immediately
924 * exit on startup if the zone was in the installed state, so we first drop
925 * into the do_console_io() loop in order to give *something* a chance to
926 * happen.
927 */
928 void
929 serve_console(zlog_t *zlogp)
930 {
931 int masterfd;
932 zone_state_t zstate;
933 char conspath[MAXPATHLEN];
934 static boolean_t cons_warned = B_FALSE;
935
936 (void) snprintf(conspath, sizeof (conspath),
937 "/dev/zcons/%s/%s", zone_name, ZCONS_MASTER_NAME);
938
939 for (;;) {
940 masterfd = open(conspath, O_RDWR|O_NONBLOCK|O_NOCTTY);
941 if (masterfd == -1) {
942 if (master_zcons_failed) {
943 /*
944 * If we don't have a console and the zone is
945 * not shutting down, there may have been a
946 * race/failure with devfs while creating the
947 * console. In this case we want to leave the
948 * zone up, even without a console, so
949 * periodically recheck.
950 */
951 int i;
952
953 /*
954 * In the normal flow of this loop, we use
955 * do_console_io to give things a chance to get
956 * going first. However, in this case we can't
957 * use that, so we have to wait for at least
958 * one state change before checking the state.
959 */
960 for (i = 0; i < 60; i++) {
961 if (state_changed)
962 break;
963 (void) sleep(1);
964 }
965
966 if (i < 60 && zone_get_state(zone_name,
967 &zstate) == Z_OK &&
968 (zstate == ZONE_STATE_READY ||
969 zstate == ZONE_STATE_RUNNING)) {
970 if (!cons_warned) {
971 zerror(zlogp, B_FALSE,
972 "WARNING: missing zone "
973 "console for %s",
974 zone_name);
975 cons_warned = B_TRUE;
976 }
977 (void) sleep(ZCONS_RETRY);
978 continue;
979 }
980 }
981
982 zerror(zlogp, B_TRUE, "failed to open console master");
983 (void) mutex_lock(&lock);
984 goto death;
985 }
986
987 /*
988 * Setting RPROTDIS on the stream means that the control
989 * portion of messages received (which we don't care about)
990 * will be discarded by the stream head. If we allowed such
991 * messages, we wouldn't be able to use read(2), as it fails
992 * (EBADMSG) when a message with a control element is received.
993 */
994 if (ioctl(masterfd, I_SRDOPT, RNORM|RPROTDIS) == -1) {
995 zerror(zlogp, B_TRUE, "failed to set options on "
996 "console master");
997 (void) mutex_lock(&lock);
998 goto death;
999 }
1000
1001 do_console_io(zlogp, masterfd, serverfd);
|