4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
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.
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]
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.
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.
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.
39 * The zone console architecture looks like this:
41 * Global Zone | Non-Global Zone
43 * .-----------. | zoneadmd -z | | .--------. .---------.
44 * | zlogin -C | | myzone | | | ttymon | | syslogd |
45 * `-----------' `--------------' | `--------' `---------'
48 * - - - - - - - - -|- - - -|- - - -|-|- - - - - - -|- - /dev/zconsole - - -
50 * [AF_UNIX Socket] | `--------. .-------------'
60 * +---master---+---slave---+
63 * | zonename="myzone" |
64 * +------------------------+
66 * There are basically two major tasks which the console subsystem in
67 * zoneadmd accomplishes:
69 * - Setup and teardown of zcons driver instances. One zcons instance
70 * is maintained per zone; we take advantage of the libdevice APIs
71 * to online new instances of zcons as needed. Care is taken to
72 * prune and manage these appropriately; see init_console_dev() and
73 * destroy_console_dev(). The end result is the creation of the
74 * zcons(7D) instance and an open file descriptor to the master side.
75 * zcons instances are associated with zones via their zonename device
76 * property. This the console instance to persist across reboots,
77 * and while the zone is halted.
79 * - Acting as a server for 'zlogin -C' instances. When zlogin -C is
80 * run, zlogin connects to zoneadmd via unix domain socket. zoneadmd
81 * functions as a two-way proxy for console I/O, relaying user input
82 * to the master side of the console, and relaying output from the
86 #include <sys/types.h>
87 #include <sys/socket.h>
89 #include <sys/termios.h>
90 #include <sys/zcons.h>
91 #include <sys/mkdev.h>
107 #include <libdevinfo.h>
108 #include <libdevice.h>
109 #include <libzonecfg.h>
112 #include <sys/modctl.h>
114 #include "zoneadmd.h"
116 #define ZCONSNEX_DEVTREEPATH "/pseudo/zconsnex@1"
117 #define ZCONSNEX_FILEPATH "/devices/pseudo/zconsnex@1"
119 #define CONSOLE_SOCKPATH ZONES_TMPDIR "/%s.console_sock"
121 static int serverfd
= -1; /* console server unix domain socket fd */
122 char boot_args
[BOOTARGS_MAX
];
123 char bad_boot_arg
[BOOTARGS_MAX
];
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.
131 static int eventstream
[2];
138 if (pipe(eventstream
) == -1)
144 eventstream_write(zone_evt_t evt
)
146 (void) write(eventstream
[0], &evt
, sizeof (evt
));
150 eventstream_read(void)
152 zone_evt_t evt
= Z_EVT_NULL
;
154 (void) read(eventstream
[1], &evt
, sizeof (evt
));
159 * count_console_devs() and its helper count_cb() do a walk of the
160 * subtree of the device tree where zone console nodes are represented.
161 * The goal is to count zone console instances already setup for a zone
162 * with the given name. More than 1 is anomolous, and our caller will
163 * have to deal with that if we find that's the case.
165 * Note: this algorithm is a linear search of nodes in the zconsnex subtree
166 * of the device tree, and could be a scalability problem, but I don't see
171 * cb_data is shared by count_cb and destroy_cb for simplicity.
180 count_cb(di_node_t node
, void *arg
)
182 struct cb_data
*cb
= (struct cb_data
*)arg
;
185 if (di_prop_lookup_strings(DDI_DEV_T_ANY
, node
, "zonename",
187 assert(prop_data
!= NULL
);
188 if (strcmp(prop_data
, zone_name
) == 0) {
190 return (DI_WALK_CONTINUE
);
193 return (DI_WALK_CONTINUE
);
197 count_console_devs(zlog_t
*zlogp
)
202 bzero(&cb
, sizeof (cb
));
205 if ((root
= di_init(ZCONSNEX_DEVTREEPATH
, DINFOCPYALL
)) ==
207 zerror(zlogp
, B_TRUE
, "%s failed", "di_init");
211 (void) di_walk_node(root
, DI_WALK_CLDFIRST
, (void *)&cb
, count_cb
);
217 * destroy_console_devs() and its helper destroy_cb() tears down any console
218 * instances associated with this zone. If things went very wrong, we
219 * might have more than one console instance hanging around. This routine
220 * hunts down and tries to remove all of them. Of course, if the console
221 * is open, the instance will not detach, which is a potential issue.
224 destroy_cb(di_node_t node
, void *arg
)
226 struct cb_data
*cb
= (struct cb_data
*)arg
;
229 char devpath
[MAXPATHLEN
];
232 if (di_prop_lookup_strings(DDI_DEV_T_ANY
, node
, "zonename",
234 return (DI_WALK_CONTINUE
);
236 assert(prop_data
!= NULL
);
237 if (strcmp(prop_data
, zone_name
) != 0) {
238 /* this is the console for a different zone */
239 return (DI_WALK_CONTINUE
);
243 tmp
= di_devfs_path(node
);
244 (void) snprintf(devpath
, sizeof (devpath
), "/devices/%s", tmp
);
245 di_devfs_path_free(tmp
);
247 if ((hdl
= devctl_device_acquire(devpath
, 0)) == NULL
) {
248 zerror(cb
->zlogp
, B_TRUE
, "WARNING: console %s found, "
249 "but it could not be controlled.", devpath
);
250 return (DI_WALK_CONTINUE
);
252 if (devctl_device_remove(hdl
) == 0) {
255 zerror(cb
->zlogp
, B_TRUE
, "WARNING: console %s found, "
256 "but it could not be removed.", devpath
);
259 return (DI_WALK_CONTINUE
);
263 destroy_console_devs(zlog_t
*zlogp
)
265 char conspath
[MAXPATHLEN
];
272 * Signal the master side to release its handle on the slave side by
273 * issuing a ZC_RELEASESLAVE ioctl.
275 (void) snprintf(conspath
, sizeof (conspath
), "/dev/zcons/%s/%s",
276 zone_name
, ZCONS_MASTER_NAME
);
277 if ((masterfd
= open(conspath
, O_RDWR
| O_NOCTTY
)) != -1) {
278 (void) snprintf(conspath
, sizeof (conspath
), "/dev/zcons/%s/%s",
279 zone_name
, ZCONS_SLAVE_NAME
);
280 if ((slavefd
= open(conspath
, O_RDWR
| O_NOCTTY
)) != -1) {
281 if (ioctl(masterfd
, ZC_RELEASESLAVE
,
282 (caddr_t
)(intptr_t)slavefd
) != 0)
283 zerror(zlogp
, B_TRUE
, "WARNING: error while "
284 "releasing slave handle of zone console for"
286 (void) close(slavefd
);
288 zerror(zlogp
, B_TRUE
, "WARNING: could not open slave "
289 "side of zone console for %s to release slave "
290 "handle", zone_name
);
292 (void) close(masterfd
);
294 zerror(zlogp
, B_TRUE
, "WARNING: could not open master side of "
295 "zone console for %s to release slave handle", zone_name
);
298 bzero(&cb
, sizeof (cb
));
301 if ((root
= di_init(ZCONSNEX_DEVTREEPATH
, DINFOCPYALL
)) ==
303 zerror(zlogp
, B_TRUE
, "%s failed", "di_init");
307 (void) di_walk_node(root
, DI_WALK_CLDFIRST
, (void *)&cb
, destroy_cb
);
309 zerror(zlogp
, B_FALSE
, "WARNING: multiple zone console "
310 "instances detected for zone '%s'; %d of %d "
311 "successfully removed.",
312 zone_name
, cb
.killed
, cb
.found
);
320 * init_console_dev() drives the device-tree configuration of the zone
321 * console device. The general strategy is to use the libdevice (devctl)
322 * interfaces to instantiate a new zone console node. We do a lot of
323 * sanity checking, and are careful to reuse a console if one exists.
325 * Once the device is in the device tree, we kick devfsadm via di_init_devs()
326 * to ensure that the appropriate symlinks (to the master and slave console
327 * devices) are placed in /dev in the global zone.
330 init_console_dev(zlog_t
*zlogp
)
332 char conspath
[MAXPATHLEN
];
333 devctl_hdl_t bus_hdl
= NULL
;
334 devctl_hdl_t dev_hdl
= NULL
;
335 devctl_ddef_t ddef_hdl
= NULL
;
336 di_devlink_handle_t dl
= NULL
;
344 * Don't re-setup console if it is working and ready already; just
345 * skip ahead to making devlinks, which we do for sanity's sake.
347 ndevs
= count_console_devs(zlogp
);
350 } else if (ndevs
> 1 || ndevs
== -1) {
352 * For now, this seems like a reasonable but harsh punishment.
353 * If needed, we could try to get clever and delete all but
354 * the console which is pointed at by the current symlink.
356 if (destroy_console_devs(zlogp
) == -1) {
362 * Time to make the consoles!
364 if ((bus_hdl
= devctl_bus_acquire(ZCONSNEX_FILEPATH
, 0)) == NULL
) {
365 zerror(zlogp
, B_TRUE
, "%s failed", "devctl_bus_acquire");
368 if ((ddef_hdl
= devctl_ddef_alloc("zcons", 0)) == NULL
) {
369 zerror(zlogp
, B_TRUE
, "failed to allocate ddef handle");
373 * Set three properties on this node; the first is the name of the
374 * zone; the second is a flag which lets pseudo know that it is
375 * OK to automatically allocate an instance # for this device;
376 * the third tells the device framework not to auto-detach this
377 * node-- we need the node to still be there when we ask devfsadmd
378 * to make links, and when we need to open it.
380 if (devctl_ddef_string(ddef_hdl
, "zonename", zone_name
) == -1) {
381 zerror(zlogp
, B_TRUE
, "failed to create zonename property");
384 if (devctl_ddef_int(ddef_hdl
, "auto-assign-instance", 1) == -1) {
385 zerror(zlogp
, B_TRUE
, "failed to create auto-assign-instance "
389 if (devctl_ddef_int(ddef_hdl
, "ddi-no-autodetach", 1) == -1) {
390 zerror(zlogp
, B_TRUE
, "failed to create ddi-no-auto-detach "
394 if (devctl_bus_dev_create(bus_hdl
, ddef_hdl
, 0, &dev_hdl
) == -1) {
395 zerror(zlogp
, B_TRUE
, "failed to create console node");
400 if ((dl
= di_devlink_init("zcons", DI_MAKE_LINK
)) != NULL
) {
401 (void) di_devlink_fini(&dl
);
403 zerror(zlogp
, B_TRUE
, "failed to create devlinks");
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.
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
);
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
);
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.
432 for (i
= 0; i
< 5; i
++) {
433 if (ioctl(masterfd
, ZC_HOLDSLAVE
, (caddr_t
)(intptr_t)slavefd
)
437 } else if (errno
!= ENXIO
) {
443 zerror(zlogp
, B_TRUE
, "ERROR: error while acquiring slave "
444 "handle of zone console for %s", zone_name
);
446 (void) close(slavefd
);
447 (void) close(masterfd
);
451 devctl_ddef_free(ddef_hdl
);
453 devctl_release(bus_hdl
);
455 devctl_release(dev_hdl
);
460 init_console_sock(zlog_t
*zlogp
)
463 struct sockaddr_un servaddr
;
465 bzero(&servaddr
, sizeof (servaddr
));
466 servaddr
.sun_family
= AF_UNIX
;
467 (void) snprintf(servaddr
.sun_path
, sizeof (servaddr
.sun_path
),
468 CONSOLE_SOCKPATH
, zone_name
);
470 if ((servfd
= socket(AF_UNIX
, SOCK_STREAM
, 0)) == -1) {
471 zerror(zlogp
, B_TRUE
, "console setup: could not create socket");
474 (void) unlink(servaddr
.sun_path
);
476 if (bind(servfd
, (struct sockaddr
*)&servaddr
,
477 sizeof (servaddr
)) == -1) {
478 zerror(zlogp
, B_TRUE
,
479 "console setup: could not bind to socket");
483 if (listen(servfd
, 4) == -1) {
484 zerror(zlogp
, B_TRUE
,
485 "console setup: could not listen on socket");
491 (void) unlink(servaddr
.sun_path
);
492 (void) close(servfd
);
497 destroy_console_sock(int servfd
)
499 char path
[MAXPATHLEN
];
501 (void) snprintf(path
, sizeof (path
), CONSOLE_SOCKPATH
, zone_name
);
503 (void) shutdown(servfd
, SHUT_RDWR
);
504 (void) close(servfd
);
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.
513 get_client_ident(int clifd
, pid_t
*pid
, char *locale
, size_t locale_len
,
516 char buf
[BUFSIZ
], *bufp
;
517 size_t buflen
= sizeof (buf
);
521 /* "eat up the ident string" case, for simplicity */
523 assert(locale
== NULL
&& locale_len
== 0);
524 while (read(clifd
, &c
, 1) == 1) {
530 bzero(buf
, sizeof (buf
));
531 while ((buflen
> 1) && (r
= read(clifd
, &c
, 1)) == 1) {
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
548 while ((r
= read(clifd
, &c
, sizeof (c
))) > 0)
554 * Parse buffer for message of the form:
555 * IDENT <pid> <locale> <disconnect flag>
558 if (strncmp(bufp
, "IDENT ", 6) != 0)
562 *pid
= strtoll(bufp
, &bufp
, 10);
566 while (*bufp
!= '\0' && isspace(*bufp
))
568 buflen
= strlen(bufp
) - 1;
569 *disconnect
= atoi(&bufp
[buflen
]);
570 bufp
[buflen
- 1] = '\0';
571 (void) strlcpy(locale
, bufp
, locale_len
);
577 accept_client(int servfd
, pid_t
*pid
, char *locale
, size_t locale_len
,
581 struct sockaddr_un cliaddr
;
584 clilen
= sizeof (cliaddr
);
585 connfd
= accept(servfd
, (struct sockaddr
*)&cliaddr
, &clilen
);
588 if (get_client_ident(connfd
, pid
, locale
, locale_len
,
590 (void) shutdown(connfd
, SHUT_RDWR
);
591 (void) close(connfd
);
594 (void) write(connfd
, "OK\n", 3);
599 reject_client(int servfd
, pid_t clientpid
)
602 struct sockaddr_un cliaddr
;
604 char nak
[MAXPATHLEN
];
606 clilen
= sizeof (cliaddr
);
607 connfd
= accept(servfd
, (struct sockaddr
*)&cliaddr
, &clilen
);
610 * After hear its ident string, tell client to get lost.
612 if (get_client_ident(connfd
, NULL
, NULL
, 0, NULL
) == 0) {
613 (void) snprintf(nak
, sizeof (nak
), "%lu\n",
615 (void) write(connfd
, nak
, strlen(nak
));
617 (void) shutdown(connfd
, SHUT_RDWR
);
618 (void) close(connfd
);
622 event_message(int clifd
, char *clilocale
, zone_evt_t evt
, int dflag
)
624 char *str
, *lstr
= NULL
;
632 case Z_EVT_ZONE_BOOTING
:
633 if (*boot_args
== '\0') {
634 str
= "NOTICE: Zone booting up";
638 (void) snprintf(lmsg
, sizeof (lmsg
), localize_msg(clilocale
,
639 "NOTICE: Zone booting up with arguments: %s"), boot_args
);
642 case Z_EVT_ZONE_READIED
:
643 str
= "NOTICE: Zone readied";
645 case Z_EVT_ZONE_HALTED
:
647 str
= "NOTICE: Zone halted. Disconnecting...";
649 str
= "NOTICE: Zone halted";
651 case Z_EVT_ZONE_REBOOTING
:
652 if (*boot_args
== '\0') {
653 str
= "NOTICE: Zone rebooting";
657 (void) snprintf(lmsg
, sizeof (lmsg
), localize_msg(clilocale
,
658 "NOTICE: Zone rebooting with arguments: %s"), boot_args
);
661 case Z_EVT_ZONE_UNINSTALLING
:
662 str
= "NOTICE: Zone is being uninstalled. Disconnecting...";
664 case Z_EVT_ZONE_BOOTFAILED
:
666 str
= "NOTICE: Zone boot failed. Disconnecting...";
668 str
= "NOTICE: Zone boot failed";
670 case Z_EVT_ZONE_BADARGS
:
672 (void) snprintf(lmsg
, sizeof (lmsg
),
673 localize_msg(clilocale
,
674 "WARNING: Ignoring invalid boot arguments: %s"),
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
));
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.
694 test_client(int clifd
)
696 if ((write(clifd
, "", 0) == -1) && errno
== EPIPE
)
702 * This routine drives the console I/O loop. It polls for input from the
703 * master side of the console (output to the console), and from the client
704 * (input from the console user). Additionally, it polls on the server fd,
705 * and disconnects any clients that might try to hook up with the zone while
706 * the console is in use.
708 * When the client first calls us up, it is expected to send a line giving
709 * its "identity"; this consists of the string 'IDENT <pid> <locale>'.
710 * This is so that we can report that the console is busy along with
711 * some diagnostics about who has it busy; the locale is used so that
712 * asynchronous messages about zone state (like the NOTICE: zone halted
713 * messages) can be output in the user's locale.
716 do_console_io(zlog_t
*zlogp
, int consfd
, int servfd
)
718 struct pollfd pollfds
[4];
723 char clilocale
[MAXPATHLEN
];
727 /* console side, watch for read events */
728 pollfds
[0].fd
= consfd
;
729 pollfds
[0].events
= POLLIN
| POLLRDNORM
| POLLRDBAND
|
730 POLLPRI
| POLLERR
| POLLHUP
| POLLNVAL
;
732 /* client side, watch for read events */
733 pollfds
[1].fd
= clifd
;
734 pollfds
[1].events
= pollfds
[0].events
;
736 /* the server socket; watch for events (new connections) */
737 pollfds
[2].fd
= servfd
;
738 pollfds
[2].events
= pollfds
[0].events
;
740 /* the eventstram; watch for events (e.g.: zone halted) */
741 pollfds
[3].fd
= eventstream
[1];
742 pollfds
[3].events
= pollfds
[0].events
;
745 pollfds
[0].revents
= pollfds
[1].revents
= 0;
746 pollfds
[2].revents
= pollfds
[3].revents
= 0;
749 sizeof (pollfds
) / sizeof (struct pollfd
), -1);
750 if (ret
== -1 && errno
!= EINTR
) {
751 zerror(zlogp
, B_TRUE
, "poll failed");
752 /* we are hosed, close connection */
756 /* event from console side */
757 if (pollfds
[0].revents
) {
758 if (pollfds
[0].revents
&
759 (POLLIN
| POLLRDNORM
| POLLRDBAND
| POLLPRI
)) {
761 cc
= read(consfd
, ibuf
, BUFSIZ
);
762 if (cc
<= 0 && (errno
!= EINTR
) &&
766 * Lose I/O if no one is listening
768 if (clifd
!= -1 && cc
> 0)
769 (void) write(clifd
, ibuf
, cc
);
771 pollerr
= pollfds
[0].revents
;
772 zerror(zlogp
, B_FALSE
,
773 "closing connection with (console) "
774 "pollerr %d\n", pollerr
);
779 /* event from client side */
780 if (pollfds
[1].revents
) {
781 if (pollfds
[1].revents
&
782 (POLLIN
| POLLRDNORM
| POLLRDBAND
| POLLPRI
)) {
784 cc
= read(clifd
, ibuf
, BUFSIZ
);
785 if (cc
<= 0 && (errno
!= EINTR
) &&
788 (void) write(consfd
, ibuf
, cc
);
790 pollerr
= pollfds
[1].revents
;
791 zerror(zlogp
, B_FALSE
,
792 "closing connection with (client) "
793 "pollerr %d\n", pollerr
);
798 /* event from server socket */
799 if (pollfds
[2].revents
&&
800 (pollfds
[2].revents
& (POLLIN
| POLLRDNORM
))) {
803 * Test the client to see if it is really
804 * still alive. If it has died but we
805 * haven't yet detected that, we might
806 * deny a legitimate connect attempt. If it
807 * is dead, we break out; once we tear down
808 * the old connection, the new connection
811 if (test_client(clifd
) == -1) {
814 /* we're already handling a client */
815 reject_client(servfd
, clipid
);
818 } else if ((clifd
= accept_client(servfd
, &clipid
,
819 clilocale
, sizeof (clilocale
),
820 &disconnect
)) != -1) {
821 pollfds
[1].fd
= clifd
;
829 * Watch for events on the eventstream. This is how we get
830 * notified of the zone halting, etc. It provides us a
831 * "wakeup" from poll when important things happen, which
834 if (pollfds
[3].revents
) {
835 int evt
= eventstream_read();
837 * After we drain out the event, if we aren't servicing
838 * a console client, we hop back out to our caller,
839 * which will check to see if it is time to shutdown
840 * the daemon, or if we should take another console
846 event_message(clifd
, clilocale
, evt
, disconnect
);
848 * Special handling for the message that the zone is
849 * uninstalling; we boot the client, then break out
850 * of this function. When we return to the
851 * serve_console loop, we will see that the zone is
852 * in a state < READY, and so zoneadmd will shutdown.
854 if (evt
== Z_EVT_ZONE_UNINSTALLING
) {
858 * Diconnect if -C and -d options were specified and
859 * zone was halted or failed to boot.
861 if ((evt
== Z_EVT_ZONE_HALTED
||
862 evt
== Z_EVT_ZONE_BOOTFAILED
) && disconnect
) {
870 (void) shutdown(clifd
, SHUT_RDWR
);
876 init_console(zlog_t
*zlogp
)
878 if (init_console_dev(zlogp
) == -1) {
879 zerror(zlogp
, B_FALSE
,
880 "console setup: device initialization failed");
884 if ((serverfd
= init_console_sock(zlogp
)) == -1) {
885 zerror(zlogp
, B_FALSE
,
886 "console setup: socket initialization failed");
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.
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
905 serve_console(zlog_t
*zlogp
)
909 char conspath
[MAXPATHLEN
];
911 (void) snprintf(conspath
, sizeof (conspath
),
912 "/dev/zcons/%s/%s", zone_name
, ZCONS_MASTER_NAME
);
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
);
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.
929 if (ioctl(masterfd
, I_SRDOPT
, RNORM
|RPROTDIS
) == -1) {
930 zerror(zlogp
, B_TRUE
, "failed to set options on "
932 (void) mutex_lock(&lock
);
936 do_console_io(zlogp
, masterfd
, serverfd
);
939 * We would prefer not to do this, but hostile zone processes
940 * can cause the stream to become tainted, and reads will
941 * fail. So, in case something has gone seriously ill,
942 * we dismantle the stream and reopen the console when we
945 (void) close(masterfd
);
947 (void) mutex_lock(&lock
);
949 * We need to set death_throes (see below) atomically with
950 * respect to noticing that (a) we have no console client and
951 * (b) the zone is not installed. Otherwise we could get a
952 * request to boot during this time. Once we set death_throes,
953 * any incoming door stuff will be turned away.
955 if (zone_get_state(zone_name
, &zstate
) == Z_OK
) {
956 if (zstate
< ZONE_STATE_READY
)
959 zerror(zlogp
, B_FALSE
,
960 "unable to determine state of zone");
964 * Even if zone_get_state() fails, stay conservative, and
967 (void) mutex_unlock(&lock
);
971 assert(MUTEX_HELD(&lock
));
972 in_death_throes
= B_TRUE
;
973 (void) mutex_unlock(&lock
);
975 destroy_console_sock(serverfd
);
976 (void) destroy_console_devs(zlogp
);