2 * Copyright (c) 2005-2009 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2008 HNR Consulting. All rights reserved.
4 * Copyright (c) 2013 Oracle and/or its affiliates. All rights reserved.
6 * This software is available to you under a choice of one of two
7 * licenses. You may choose to be licensed under the terms of the GNU
8 * General Public License (GPL) Version 2, available from the file
9 * COPYING in the main directory of this source tree, or the
10 * OpenIB.org BSD license below:
12 * Redistribution and use in source and binary forms, with or
13 * without modification, are permitted provided that the following
16 * - Redistributions of source code must retain the above
17 * copyright notice, this list of conditions and the following
20 * - Redistributions in binary form must reproduce the above
21 * copyright notice, this list of conditions and the following
22 * disclaimer in the documentation and/or other materials
23 * provided with the distribution.
25 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
38 * Provide a framework for the Console which decouples the connection
39 * or I/O from the functionality, or commands.
41 * Extensible - allows a variety of connection methods independent of
42 * the console commands.
47 #endif /* HAVE_CONFIG_H */
49 #define _WITH_GETLINE /* for getline */
50 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
52 #include <arpa/inet.h>
53 #include <netinet/in.h>
54 #include <sys/socket.h>
60 #include <opensm/osm_file_ids.h>
61 #define FILE_ID OSM_FILE_CONSOLE_IO_C
62 #include <opensm/osm_console_io.h>
65 static int is_local(char *str)
67 /* convenience - checks if just stdin/stdout */
69 return (strcmp(str, OSM_LOCAL_CONSOLE) == 0);
73 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
74 static int is_loopback(char *str)
76 /* convenience - checks if socket based connection */
78 return (strcmp(str, OSM_LOOPBACK_CONSOLE) == 0);
82 #define is_loopback is_local
85 #ifdef ENABLE_OSM_CONSOLE_SOCKET
86 static int is_remote(char *str)
88 /* convenience - checks if socket based connection */
90 return strcmp(str, OSM_REMOTE_CONSOLE) == 0 || is_loopback(str);
94 #define is_remote is_loopback
97 int is_console_enabled(osm_subn_opt_t * p_opt)
99 /* checks for a variety of types of consoles - default is off or 0 */
101 return is_local(p_opt->console) || is_loopback(p_opt->console)
102 || is_remote(p_opt->console);
107 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
108 int cio_close(osm_console_t * p_oct, osm_log_t * p_log)
111 if (p_oct && p_oct->in_fd > 0) {
112 OSM_LOG(p_log, OSM_LOG_VERBOSE,
113 "Console connection closed: %s (%s)\n",
114 p_oct->client_hn, p_oct->client_ip);
115 rtnval = fclose(p_oct->in);
124 int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log)
126 /* returns zero if opened fine, -1 otherwise */
131 if (p_oct->in_fd >= 0) {
132 FILE *file = fdopen(new_fd, "w+");
134 fprintf(file, "OpenSM Console connection already in use\n"
135 " kill other session (y/n)? ");
138 n = getline(&p_line, &len, file);
139 if (n > 0 && (p_line[0] == 'y' || p_line[0] == 'Y'))
140 cio_close(p_oct, p_log);
142 OSM_LOG(p_log, OSM_LOG_INFO,
143 "Console connection aborted: %s (%s) - "
145 p_oct->client_hn, p_oct->client_ip);
152 p_oct->in_fd = new_fd;
153 p_oct->out_fd = p_oct->in_fd;
154 p_oct->in = fdopen(p_oct->in_fd, "w+");
155 p_oct->out = p_oct->in;
156 osm_console_prompt(p_oct->out);
157 OSM_LOG(p_log, OSM_LOG_VERBOSE, "Console connection accepted: %s (%s)\n",
158 p_oct->client_hn, p_oct->client_ip);
160 return (p_oct->in == NULL) ? -1 : 0;
163 /**********************************************************************
164 * Do authentication & authorization check
165 **********************************************************************/
166 int is_authorized(osm_console_t * p_oct)
168 /* allowed to use the console? */
169 p_oct->authorized = !is_remote(p_oct->client_type) ||
170 hosts_ctl((char *)OSM_DAEMON_NAME, p_oct->client_hn, p_oct->client_ip,
171 (char *)STRING_UNKNOWN);
172 return p_oct->authorized;
176 void osm_console_prompt(FILE * out)
179 fprintf(out, "OpenSM %s", OSM_COMMAND_PROMPT);
184 int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log)
187 strncpy(p_oct->client_type, opt->console, sizeof(p_oct->client_type));
189 /* set up the file descriptors for the console */
190 if (strcmp(opt->console, OSM_LOCAL_CONSOLE) == 0) {
193 p_oct->in_fd = fileno(stdin);
194 p_oct->out_fd = fileno(stdout);
196 osm_console_prompt(p_oct->out);
197 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
198 } else if (strcmp(opt->console, OSM_LOOPBACK_CONSOLE) == 0
199 #ifdef ENABLE_OSM_CONSOLE_SOCKET
200 || strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0
203 struct sockaddr_in sin;
206 if ((p_oct->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
207 OSM_LOG(p_log, OSM_LOG_ERROR,
208 "ERR 4B01: Failed to open console socket: %s\n",
213 if (setsockopt(p_oct->socket, SOL_SOCKET, SO_REUSEADDR,
214 &optval, sizeof(optval))) {
215 OSM_LOG(p_log, OSM_LOG_ERROR,
216 "ERR 4B06: Failed to set socket option: %s\n",
221 sin.sin_family = AF_INET;
222 sin.sin_port = htons(opt->console_port);
223 #ifdef ENABLE_OSM_CONSOLE_SOCKET
224 if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0)
225 sin.sin_addr.s_addr = htonl(INADDR_ANY);
228 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
229 if (bind(p_oct->socket, (struct sockaddr *)&sin, sizeof(sin)) < 0) {
230 OSM_LOG(p_log, OSM_LOG_ERROR,
231 "ERR 4B02: Failed to bind console socket: %s\n",
235 if (listen(p_oct->socket, 1) < 0) {
236 OSM_LOG(p_log, OSM_LOG_ERROR,
237 "ERR 4B03: Failed to listen on console socket: %s\n",
242 signal(SIGPIPE, SIG_IGN); /* protect ourselves from closed pipes */
247 OSM_LOG(p_log, OSM_LOG_INFO,
248 "Console listening on port %d\n", opt->console_port);
255 /* clean up and release resources */
256 void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log)
258 #ifdef ENABLE_OSM_CONSOLE_LOOPBACK
259 cio_close(p_oct, p_log);
260 if (p_oct->socket > 0) {
261 OSM_LOG(p_log, OSM_LOG_INFO, "Closing console socket\n");
262 close(p_oct->socket);