2 * Copyright (c) 2005-2007 Voltaire, Inc. All rights reserved.
3 * Copyright (c) 2008 HNR Consulting. All rights reserved.
5 * This software is available to you under a choice of one of two
6 * licenses. You may choose to be licensed under the terms of the GNU
7 * General Public License (GPL) Version 2, available from the file
8 * COPYING in the main directory of this source tree, or the
9 * OpenIB.org BSD license below:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * - Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * - Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
37 * Provide a framework for the Console which decouples the connection
38 * or I/O from the functionality, or commands.
40 * Extensible - allows a variety of connection methods independent of
41 * the console commands.
46 #endif /* HAVE_CONFIG_H */
48 #define _GNU_SOURCE /* for getline */
49 #ifdef ENABLE_OSM_CONSOLE_SOCKET
51 #include <arpa/inet.h>
52 #include <netinet/in.h>
53 #include <sys/socket.h>
58 #include <opensm/osm_console_io.h>
60 static int is_local(char *str)
62 // convenience - checks if just stdin/stdout
64 return (strcmp(str, OSM_LOCAL_CONSOLE) == 0);
68 static int is_loopback(char *str)
70 // convenience - checks if socket based connection
72 return (strcmp(str, OSM_LOOPBACK_CONSOLE) == 0);
76 static int is_remote(char *str)
78 // convenience - checks if socket based connection
80 return (strcmp(str, OSM_REMOTE_CONSOLE) == 0)
85 int is_console_enabled(osm_subn_opt_t * p_opt)
87 // checks for a variety of types of consoles - default is off or 0
89 return (is_local(p_opt->console)
90 || is_loopback(p_opt->console)
91 || is_remote(p_opt->console));
96 #ifdef ENABLE_OSM_CONSOLE_SOCKET
97 static int cio_close(osm_console_t * p_oct)
100 if (p_oct && (p_oct->in_fd > 0)) {
101 rtnval = close(p_oct->in_fd);
111 /* close the connection */
112 static void osm_console_close(osm_console_t * p_oct, osm_log_t * p_log)
114 #ifdef ENABLE_OSM_CONSOLE_SOCKET
115 if ((p_oct->socket > 0) && (p_oct->in_fd != -1)) {
116 OSM_LOG(p_log, OSM_LOG_INFO,
117 "Console connection closed: %s (%s)\n",
118 p_oct->client_hn, p_oct->client_ip);
121 if (p_oct->socket > 0) {
122 close(p_oct->socket);
129 /**********************************************************************
130 * Do authentication & authorization check
131 **********************************************************************/
132 #ifdef ENABLE_OSM_CONSOLE_SOCKET
133 int is_authorized(osm_console_t * p_oct)
135 /* allowed to use the console? */
136 p_oct->authorized = !is_remote(p_oct->client_type) ||
137 hosts_ctl(OSM_DAEMON_NAME, p_oct->client_hn, p_oct->client_ip,
139 return p_oct->authorized;
143 void osm_console_prompt(FILE * out)
146 fprintf(out, "OpenSM %s", OSM_COMMAND_PROMPT);
151 int osm_console_init(osm_subn_opt_t * opt, osm_console_t * p_oct, osm_log_t * p_log)
154 strncpy(p_oct->client_type, opt->console, sizeof(p_oct->client_type));
156 /* set up the file descriptors for the console */
157 if (strcmp(opt->console, OSM_LOCAL_CONSOLE) == 0) {
160 p_oct->in_fd = fileno(stdin);
161 p_oct->out_fd = fileno(stdout);
163 osm_console_prompt(p_oct->out);
164 #ifdef ENABLE_OSM_CONSOLE_SOCKET
165 } else if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0
166 || strcmp(opt->console, OSM_LOOPBACK_CONSOLE) == 0) {
167 struct sockaddr_in sin;
170 if ((p_oct->socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
171 OSM_LOG(p_log, OSM_LOG_ERROR,
172 "ERR 4B01: Failed to open console socket: %s\n",
176 setsockopt(p_oct->socket, SOL_SOCKET, SO_REUSEADDR,
177 &optval, sizeof(optval));
178 sin.sin_family = AF_INET;
179 sin.sin_port = htons(opt->console_port);
180 if (strcmp(opt->console, OSM_REMOTE_CONSOLE) == 0)
181 sin.sin_addr.s_addr = htonl(INADDR_ANY);
183 sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
184 if (bind(p_oct->socket, &sin, sizeof(sin)) < 0) {
185 OSM_LOG(p_log, OSM_LOG_ERROR,
186 "ERR 4B02: Failed to bind console socket: %s\n",
190 if (listen(p_oct->socket, 1) < 0) {
191 OSM_LOG(p_log, OSM_LOG_ERROR,
192 "ERR 4B03: Failed to listen on socket: %s\n",
197 signal(SIGPIPE, SIG_IGN); /* protect ourselves from closed pipes */
202 OSM_LOG(p_log, OSM_LOG_INFO,
203 "Console listening on port %d\n", opt->console_port);
210 /* clean up and release resources */
211 void osm_console_exit(osm_console_t * p_oct, osm_log_t * p_log)
213 // clean up and release resources, currently just close the socket
214 osm_console_close(p_oct, p_log);
217 #ifdef ENABLE_OSM_CONSOLE_SOCKET
218 int cio_open(osm_console_t * p_oct, int new_fd, osm_log_t * p_log)
220 // returns zero if opened fine, -1 otherwise
225 if (p_oct->in_fd >= 0) {
226 FILE *file = fdopen(new_fd, "w+");
228 fprintf(file, "OpenSM Console connection already in use\n"
229 " kill other session (y/n)? ");
232 n = getline(&p_line, &len, file);
233 if (n > 0 && (p_line[0] == 'y' || p_line[0] == 'Y')) {
234 osm_console_close(p_oct, p_log);
236 OSM_LOG(p_log, OSM_LOG_INFO,
237 "Console connection aborted: %s (%s)\n",
238 p_oct->client_hn, p_oct->client_ip);
243 p_oct->in_fd = new_fd;
244 p_oct->out_fd = p_oct->in_fd;
245 p_oct->in = fdopen(p_oct->in_fd, "w+");
246 p_oct->out = p_oct->in;
247 osm_console_prompt(p_oct->out);
248 OSM_LOG(p_log, OSM_LOG_INFO,
249 "Console connection accepted: %s (%s)\n",
250 p_oct->client_hn, p_oct->client_ip);
252 return (p_oct->in == NULL) ? -1 : 0;