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.
32 #include <sys/types.h>
37 #include <sys/socket.h>
44 #include <netinet/in.h>
54 /* vntsd_write_line() - write a line to TCP client */
56 vntsd_write_line(vntsd_client_t
*clientp
, char *line
)
60 rv
= vntsd_write_client(clientp
, line
, strlen(line
));
61 if (rv
== VNTSD_SUCCESS
) {
62 rv
= vntsd_write_client(clientp
, vntsd_eol
, VNTSD_EOL_LEN
);
68 /* vntsd_write_lines() write one or more lines to client. */
70 vntsd_write_lines(vntsd_client_t
*clientp
, char *lines
)
78 return (VNTSD_ERR_NO_MEM
);
83 while ((line
!= NULL
) && (*line
!= '\0')) {
85 endofline
= strchr(line
, '\n');
86 if (endofline
!= NULL
) {
90 (void) vntsd_write_line(clientp
, line
);
92 if (endofline
!= NULL
)
99 return (VNTSD_SUCCESS
);
102 /* vntsd_get_yes_no() - read in a "y" or "n" */
104 vntsd_get_yes_no(vntsd_client_t
*clientp
, char *msg
, int *yes_no
)
110 /* create [y/n] prompt */
111 (void) snprintf(yesno
, sizeof (yesno
), "[%c/%c] ",
112 *nl_langinfo(YESSTR
), *nl_langinfo(NOSTR
));
115 if ((rv
= vntsd_write_client(clientp
, msg
, strlen(msg
)))
120 if ((rv
= vntsd_write_client(clientp
, yesno
, strlen(yesno
))) !=
125 if ((rv
= vntsd_read_data(clientp
, &c
))
131 if ((rv
= vntsd_write_client(clientp
, &c
, 1)) !=
136 if ((rv
= vntsd_write_client(clientp
, vntsd_eol
,
137 VNTSD_EOL_LEN
)) != VNTSD_SUCCESS
) {
143 if (c
== *nl_langinfo(YESSTR
)) {
145 return (VNTSD_SUCCESS
);
148 if (c
== *nl_langinfo(NOSTR
)) {
150 return (VNTSD_SUCCESS
);
153 if ((rv
= vntsd_write_line(clientp
,
154 gettext("Invalid response. Try again.")))
164 /* vntsd_open_vcc() - open a vcc port */
166 vntsd_open_vcc(char *dev_name
, uint_t cons_no
)
171 sz
= strlen(VCC_DEVICE_PATH
) + strlen(dev_name
)+1;
173 path
= calloc(sz
, 1);
179 (void) snprintf(path
, sz
-1, VCC_DEVICE_PATH
, dev_name
);
182 drvfd
= open(path
, O_RDWR
);
184 if ((drvfd
< 0) && (errno
== EAGAIN
)) {
185 if (vntsd_vcc_ioctl(VCC_FORCE_CLOSE
, cons_no
, &cons_no
)
196 D1(stderr
, "t@%d open_vcc@%s exit\n", thr_self(), dev_name
);
205 /* vntsd_cons_by_consno() - match a console structure to cons no */
207 vntsd_cons_by_consno(vntsd_cons_t
*consp
, int *cons_id
)
209 if (consp
->status
& VNTSD_CONS_DELETED
) {
212 return (consp
->cons_no
== *cons_id
);
215 /* vntsd_write_client() write to telnet client */
217 vntsd_write_client(vntsd_client_t
*client
, char *buffer
, size_t sz
)
222 /* write to client */
223 rv
= vntsd_write_fd(client
->sockfd
, buffer
, sz
);
225 /* client has output, reset timer */
226 vntsd_reset_timer(client
->cons_tid
);
231 /* vntsd_write_fd() write to tcp socket file descriptor */
233 vntsd_write_fd(int fd
, void *buf
, size_t sz
)
238 n
= write(fd
, buf
, sz
);
240 if (errno
== EINTR
) {
241 return (VNTSD_STATUS_INTR
);
244 return (VNTSD_STATUS_CLIENT_QUIT
);
248 return (VNTSD_STATUS_CLIENT_QUIT
);
251 buf
= (caddr_t
)buf
+ n
;
254 return (VNTSD_SUCCESS
);
259 * vntsd_read_char() - read a char from TCP Clienti. Returns:
260 * VNTSD_SUCCESS, VNTSD_STATUS_CLIENT_QUIT or VNTSD_STATUS_INTR
263 vntsd_read_char(vntsd_client_t
*clientp
, char *c
)
269 tmo
.tid
= thr_self();
271 tmo
.clientp
= clientp
;
273 /* attach to timer */
274 if ((rv
= vntsd_attach_timer(&tmo
)) != VNTSD_SUCCESS
) {
278 n
= read(clientp
->sockfd
, c
, 1);
280 /* detach from timer */
281 if ((rv
= vntsd_detach_timer(&tmo
)) != VNTSD_SUCCESS
) {
286 return (VNTSD_SUCCESS
);
290 return (VNTSD_STATUS_CLIENT_QUIT
);
294 * read error or wake up by signal, either console is being removed or
297 if (errno
== EINTR
) {
298 return (VNTSD_STATUS_INTR
);
301 /* any other error, we close client */
302 return (VNTSD_STATUS_CLIENT_QUIT
);
306 * vntsd_read_data() - handle special commands
307 * such as telnet, daemon and ctrl cmds. Returns:
308 * from vntsd_read_char:
309 * VNTSD_STATUS_CLIENT_QUIT
311 * from vnts_process_daemon_cmd:
312 * VNTSD_STATUS_RESELECT_CONS
313 * VNTSD_STATUS_MOV_CONS_FORWARD
314 * VNTSD_STATUS_MOV_CONS_BACKWARD
315 * VNTSD_STATUS_ACQURE_WRITER
316 * VNTSD_STATUS_CONTINUE
317 * from vntsd_telnet_cmd
318 * VNTSD_STATUS_CONTINUE
321 vntsd_read_data(vntsd_client_t
*clientp
, char *c
)
326 if ((rv
= vntsd_read_char(clientp
, c
)) != VNTSD_SUCCESS
) {
331 rv
= vntsd_process_daemon_cmd(clientp
, *c
);
333 if (rv
== VNTSD_SUCCESS
) {
335 rv
= vntsd_telnet_cmd(clientp
, *c
);
338 if (rv
== VNTSD_STATUS_CONTINUE
) {
340 * either a daemon cmd or a telnet cmd
343 clientp
->prev_char
= 0;
353 /* vntsd_read_line() - read a line from TCP client */
355 vntsd_read_line(vntsd_client_t
*clientp
, char *buf
, int *in_sz
)
364 if ((rv
= vntsd_read_data(clientp
, &c
)) != VNTSD_SUCCESS
) {
370 if ((rv
= vntsd_write_client(clientp
, &c
, 1)) !=
376 if ((rv
= vntsd_write_client(clientp
, &c
, 1)) !=
386 if ((rv
= vntsd_write_client(clientp
, &c
, 1)) !=
397 return (VNTSD_SUCCESS
);
400 if (out_sz
== *in_sz
) {
401 return (VNTSD_SUCCESS
);
411 vntsd_free_client(vntsd_client_t
*clientp
)
414 if (clientp
->sockfd
!= -1) {
415 (void) close(clientp
->sockfd
);
418 (void) mutex_destroy(&clientp
->lock
);
424 /* check if a vcc console port still ok */
426 vntsd_vcc_cons_alive(vntsd_cons_t
*consp
)
428 vcc_console_t vcc_cons
;
432 assert(consp
->group
);
434 /* construct current configuration */
435 (void) strncpy(vcc_cons
.domain_name
, consp
->domain_name
, MAXPATHLEN
);
436 (void) strncpy(vcc_cons
.group_name
, consp
->group
->group_name
,
438 vcc_cons
.tcp_port
= consp
->group
->tcp_port
;
439 vcc_cons
.cons_no
= consp
->cons_no
;
441 /* call vcc to verify */
442 rv
= vntsd_vcc_ioctl(VCC_CONS_STATUS
, consp
->cons_no
, &vcc_cons
);
443 if (rv
!= VNTSD_SUCCESS
) {
447 if (vcc_cons
.cons_no
== -1) {
457 /* add to total if a console is alive */
459 total_cons(vntsd_cons_t
*consp
, int *num_cons
)
463 assert(consp
->group
);
464 rv
= vntsd_vcc_err(consp
);
465 if (rv
== VNTSD_STATUS_CONTINUE
) {
472 /* total alive consoles in a group */
474 vntsd_chk_group_total_cons(vntsd_group_t
*groupp
)
478 (void) vntsd_que_find(groupp
->conspq
, (compare_func_t
)total_cons
,
483 /* vntsd_log() log function for errors */
485 vntsd_log(vntsd_status_t status
, char *msg
)
487 char *status_msg
= NULL
;
493 status_msg
= "STATUS_OK";
496 case VNTSD_STATUS_CONTINUE
:
497 status_msg
= "CONTINUE";
500 case VNTSD_STATUS_EXIT_SIG
:
502 status_msg
= "KILL SIGNAL RECV";
505 case VNTSD_STATUS_SIG
:
506 status_msg
= "SIG RECV";
509 case VNTSD_STATUS_NO_HOST_NAME
:
510 status_msg
= "Warining NO HOST NAME";
513 case VNTSD_STATUS_CLIENT_QUIT
:
514 status_msg
= "CLIENT CLOSED GROUP CONNECTION";
517 case VNTSD_STATUS_RESELECT_CONS
:
518 status_msg
= "CLIENT RESELECTS CONSOLE";
521 case VNTSD_STATUS_VCC_IO_ERR
:
522 status_msg
= "CONSOLE WAS DELETED";
525 case VNTSD_STATUS_MOV_CONS_FORWARD
:
526 status_msg
= "MOVE CONSOLE FORWARD";
529 case VNTSD_STATUS_MOV_CONS_BACKWARD
:
530 status_msg
= "MOVE CONSOLE BACKWARD";
533 case VNTSD_STATUS_ACQUIRE_WRITER
:
534 status_msg
= "FORCE CONSOLE WRITE";
537 case VNTSD_STATUS_INTR
:
538 status_msg
= "RECV SIGNAL";
541 case VNTSD_STATUS_DISCONN_CONS
:
542 status_msg
= "DELETING CONSOLE";
545 case VNTSD_STATUS_NO_CONS
:
546 status_msg
= "All console(s) in the group have been deleted.";
549 case VNTSD_STATUS_AUTH_ENABLED
:
551 status_msg
= "VNTSD_STATUS_AUTH_ENABLED";
554 case VNTSD_ERR_NO_MEM
:
556 status_msg
= "NO MEMORY";
559 case VNTSD_ERR_NO_DRV
:
561 status_msg
= "NO VCC DRIVER";
564 case VNTSD_ERR_WRITE_CLIENT
:
565 status_msg
= "WRITE CLIENT ERR";
568 case VNTSD_ERR_EL_NOT_FOUND
:
570 status_msg
= "ELEMENT_NOT_FOUND";
573 case VNTSD_ERR_VCC_CTRL_DATA
:
575 status_msg
= "VCC CTRL DATA ERROR";
578 case VNTSD_ERR_VCC_POLL
:
580 status_msg
= "VCC POLL ERROR";
583 case VNTSD_ERR_VCC_IOCTL
:
585 status_msg
= "VCC IOCTL ERROR";
588 case VNTSD_ERR_VCC_GRP_NAME
:
590 status_msg
= "VCC GROUP NAME ERROR";
593 case VNTSD_ERR_CREATE_LISTEN_THR
:
595 status_msg
= "FAIL TO CREATE LISTEN THREAD";
598 case VNTSD_ERR_CREATE_WR_THR
:
600 status_msg
= "FAIL TO CREATE WRITE THREAD";
603 case VNTSD_ERR_ADD_CONS_FAILED
:
605 status_msg
= "FAIL TO ADD A CONSOLE";
608 case VNTSD_ERR_LISTEN_SOCKET
:
610 status_msg
= "LISTEN SOCKET ERROR";
613 case VNTSD_ERR_LISTEN_OPTS
:
615 status_msg
= "SET SOCKET OPTIONS ERROR";
618 case VNTSD_ERR_LISTEN_BIND
:
620 status_msg
= "BIND SOCKET ERROR";
623 case VNTSD_STATUS_ACCEPT_ERR
:
625 status_msg
= "LISTEN ACCEPT ERROR";
628 case VNTSD_ERR_CREATE_CONS_THR
:
630 status_msg
= "CREATE CONSOLE THREAD ERROR ";
635 status_msg
= "RECV UNKNOWN SIG";
638 case VNTSD_ERR_UNKNOWN_CMD
:
640 status_msg
= "RECV UNKNOWN COMMAND";
643 case VNTSD_ERR_CLIENT_TIMEOUT
:
644 status_msg
= "CLOSE CLIENT BECAUSE TIMEOUT";
647 status_msg
= "Unknown status recv";
653 syslog(LOG_ERR
, "%s: thread[%d] %s\n", status_msg
,
657 DERR(stderr
, "%s: thread[%d] %s\n", status_msg
, thr_self(), msg
);
658 syslog(LOG_ERR
, "%s: thread[%d] %s\n", status_msg
, thr_self(), msg
);