1 /*****************************************************************************
2  *  Written by Chris Dunlap <cdunlap@llnl.gov>.
3  *  Copyright (C) 2007-2018 Lawrence Livermore National Security, LLC.
4  *  Copyright (C) 2001-2007 The Regents of the University of California.
5  *  UCRL-CODE-2002-009.
6  *
7  *  This file is part of ConMan: The Console Manager.
8  *  For details, see <https://dun.github.io/conman/>.
9  *
10  *  ConMan is free software: you can redistribute it and/or modify it under
11  *  the terms of the GNU General Public License as published by the Free
12  *  Software Foundation, either version 3 of the License, or (at your option)
13  *  any later version.
14  *
15  *  ConMan is distributed in the hope that it will be useful, but WITHOUT
16  *  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  *  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
18  *  for more details.
19  *
20  *  You should have received a copy of the GNU General Public License along
21  *  with ConMan.  If not, see <http://www.gnu.org/licenses/>.
22  *****************************************************************************/
23 
24 
25 #ifndef _SERVER_H
26 #define _SERVER_H
27 
28 #if HAVE_CONFIG_H
29 #  include <config.h>
30 #endif /* HAVE_CONFIG_H */
31 
32 #if HAVE_IPMICONSOLE_H
33 #  include <ipmiconsole.h>
34 #endif /* HAVE_IPMICONSOLE_H */
35 
36 #include <sys/types.h>                  /* include before in.h for bsd */
37 #include <netinet/in.h>                 /* for struct sockaddr_in            */
38 #include <pthread.h>                    /* for pthread_mutex_t               */
39 #include <stdio.h>                      /* for FILE                          */
40 #include <termios.h>                    /* for struct termios, speed_t       */
41 #include <time.h>                       /* for time_t                        */
42 #include <unistd.h>                     /* for pid_t                         */
43 #include "common.h"
44 #include "list.h"
45 #include "tpoll.h"
46 
47 
48 #define DEFAULT_LOGOPT_LOCK             1
49 #define DEFAULT_LOGOPT_SANITIZE         0
50 #define DEFAULT_LOGOPT_TIMESTAMP        0
51 
52 #define DEFAULT_SEROPT_BPS              B9600
53 #define DEFAULT_SEROPT_DATABITS         8
54 #define DEFAULT_SEROPT_PARITY           0
55 #define DEFAULT_SEROPT_STOPBITS         1
56 
57 #define MIN_CONNECT_SECS                60
58 
59 #if WITH_FREEIPMI
60 #define IPMI_ENGINE_CONSOLES_PER_THREAD 128
61 #define IPMI_MAX_USER_LEN               IPMI_MAX_USER_NAME_LENGTH
62 #define IPMI_MAX_PSWD_LEN               IPMI_2_0_MAX_PASSWORD_LENGTH
63 #define IPMI_MAX_KG_LEN                 IPMI_MAX_K_G_LENGTH
64 #define IPMI_CONNECT_TIMEOUT            300
65 #define IPMI_MAX_TIMEOUT                1800
66 #define IPMI_MIN_TIMEOUT                60
67 #endif /* WITH_FREEIPMI */
68 
69 #define PROCESS_MAX_TIMEOUT             1800
70 #define PROCESS_MIN_TIMEOUT             60
71 
72 #define RESET_CMD_TIMEOUT               60
73 
74 #define RESOLVE_RETRY_TIMEOUT           1800
75 
76 #define TELNET_MAX_TIMEOUT              1800
77 #define TELNET_MIN_TIMEOUT              15
78 
79 #define UNIXSOCK_MAX_TIMEOUT            60
80 #define UNIXSOCK_MIN_TIMEOUT            1
81 
82 
83 enum obj_type {                         /* type of auxiliary obj             */
84     CONMAN_OBJ_CLIENT   = 0x01,
85     CONMAN_OBJ_LOGFILE  = 0x02,
86     CONMAN_OBJ_PROCESS  = 0x04,
87     CONMAN_OBJ_SERIAL   = 0x08,
88     CONMAN_OBJ_TELNET   = 0x10,
89     CONMAN_OBJ_UNIXSOCK = 0x20,
90     CONMAN_OBJ_IPMI     = 0x40,
91     CONMAN_OBJ_TEST     = 0x80,
92     CONMAN_OBJ_LAST_ENTRY
93 };
94 
95 typedef struct client_obj {             /* CLIENT AUX OBJ DATA:              */
96     req_t           *req;               /*  client request info              */
97     time_t           timeLastRead;      /*  time last data was read from fd  */
98     unsigned         gotEscape:1;       /*  true if last char rcvd was esc   */
99     unsigned         gotSuspend:1;      /*  true if suspending client output */
100 } client_obj_t;
101 
102 typedef struct logfile_opt {            /* LOGFILE OBJ OPTIONS:              */
103     unsigned         enableLock:1;      /*  true if logfile being locked     */
104     unsigned         enableSanitize:1;  /*  true if logfile being sanitized  */
105     unsigned         enableTimestamp:1; /*  true if timestamping each line   */
106 } logopt_t;
107 
108 typedef enum logfile_line_state {       /* log CR/LF newline state (2 bits)  */
109     CONMAN_LOG_LINE_INIT,
110     CONMAN_LOG_LINE_DATA,
111     CONMAN_LOG_LINE_CR,
112     CONMAN_LOG_LINE_LF
113 } log_line_state_t;
114 
115 typedef struct logfile_obj {            /* LOGFILE AUX OBJ DATA:             */
116     struct base_obj *console;           /*  con obj ref for name expansion   */
117     char            *fmtName;           /*  name with conversion specifiers  */
118     logopt_t         opts;              /*  local options                    */
119     unsigned         gotProcessing:1;   /*  true if input processing req'd   */
120     unsigned         gotTruncate:1;     /*  true if ZeroLogs is enabled      */
121     unsigned         lineState:2;       /*  log_line_state_t CR/LF state     */
122 } logfile_obj_t;
123 
124 typedef enum process_connect_state {    /* process connection state (1 bit)  */
125     CONMAN_PROCESS_DOWN,
126     CONMAN_PROCESS_UP
127 } process_state_t;
128 
129 typedef struct process_obj {            /* PROCESS AUX OBJ DATA              */
130     char           **argv;              /*  NULL-term'd ary of ptrs to strs  */
131     char            *prog;              /*  reference to basename of argv[0] */
132     int              timer;             /*  timer id for repeated attempts   */
133     int              delay;             /*  secs 'til next reconnect attempt */
134     pid_t            pid;               /*  pid of forked process            */
135     time_t           tStart;            /*  time at which process was exec'd */
136     struct base_obj *logfile;           /*  log obj ref for console replay   */
137     unsigned         state:1;           /*  process_state_t conn state       */
138 } process_obj_t;
139 
140 typedef struct serial_opt {             /* SERIAL OBJ OPTIONS:               */
141     speed_t          bps;               /*  bps def for cfset*speed()        */
142     int              databits;          /*  databits (5-8)                   */
143     int              parity;            /*  parity (0=NONE,1=ODD,2=EVEN)     */
144     int              stopbits;          /*  stopbits (1-2)                   */
145 } seropt_t;
146 
147 typedef struct serial_obj {             /* SERIAL AUX OBJ DATA:              */
148     char            *dev;               /*  local serial device name         */
149     seropt_t         opts;              /*  serial options                   */
150     struct base_obj *logfile;           /*  log obj ref for console replay   */
151     struct termios   tty;               /*  saved cooked tty mode            */
152 } serial_obj_t;
153 
154 typedef enum telnet_connect_state {     /* state of n/w connection (2 bits)  */
155     CONMAN_TELNET_NONE,
156     CONMAN_TELNET_DOWN,
157     CONMAN_TELNET_PENDING,
158     CONMAN_TELNET_UP
159 } telnet_state_t;
160 
161 typedef struct telnet_obj {             /* TELNET AUX OBJ DATA:              */
162     char            *host;              /*  remote telnetd host name (or ip) */
163     int              port;              /*  remote telnetd port number       */
164     struct base_obj *logfile;           /*  log obj ref for console replay   */
165     int              timer;             /*  timer id for reconnects          */
166     int              delay;             /*  secs 'til next reconnect attempt */
167     int              iac;               /*  -1, or last char if in IAC seq   */
168     unsigned         state:2;           /*  telnet_state_t of n/w connection */
169     unsigned         enableKeepAlive:1; /*  true if using TCP keep-alive     */
170 } telnet_obj_t;
171 
172 typedef enum unixsock_connect_state {   /* socket connection state (1 bit)   */
173     CONMAN_UNIXSOCK_DOWN,
174     CONMAN_UNIXSOCK_UP
175 } unixsock_state_t;
176 
177 typedef struct unixsock_obj {           /* UNIXSOCK AUX OBJ DATA:            */
178     char            *dev;               /*  unix domain socket device name   */
179     struct base_obj *logfile;           /*  log obj ref for console replay   */
180     int              timer;             /*  timer id for reconnects          */
181     int              delay;             /*  secs 'til next reconnect attempt */
182     unsigned         state:1;           /*  unixsock_state_t conn state      */
183     unsigned         isViaInotify:1;    /*  true if triggered via inotify    */
184 } unixsock_obj_t;
185 
186 /*  Refer to struct ipmiconsole_ipmi_config in <ipmiconsole.h>.
187  */
188 #if WITH_FREEIPMI
189 typedef struct ipmi_opt {                               /* IPMI OBJ OPTIONS: */
190     char             username[ IPMI_MAX_USER_LEN + 1 ]; /*  BMC username     */
191     char             password[ IPMI_MAX_PSWD_LEN + 1 ]; /*  BMC password     */
192     unsigned char    kg[ IPMI_MAX_KG_LEN + 1 ];         /*  BMC K_g key      */
193     unsigned int     kgLen;                             /*  BMC K_g key len  */
194     int              privilegeLevel;                    /*  auth priv level  */
195     int              cipherSuite;                       /*  cipher suite id  */
196     unsigned int     workaroundFlags;                   /*  workaround flags */
197 } ipmiopt_t;
198 
199 typedef struct ipmiconsole_ctx ipmictx_t;
200 
201 typedef enum ipmi_connect_state {
202     CONMAN_IPMI_DOWN,
203     CONMAN_IPMI_PENDING,
204     CONMAN_IPMI_UP
205 } ipmi_state_t;
206 
207 typedef struct ipmi_obj {               /* IPMI AUX OBJ DATA:                */
208     char            *host;              /*  remote bmc host name (or ip)     */
209     ipmiopt_t        iconf;             /*  conf to connect to bmc           */
210     ipmictx_t       *ctx;               /*  ipmi session ctx ptr             */
211     struct base_obj *logfile;           /*  log obj ref for console replay   */
212     ipmi_state_t     state;             /*  connection state                 */
213     int              timer;             /*  timer id                         */
214     int              delay;             /*  secs 'til next reconnect attempt */
215     pthread_mutex_t  mutex;             /*  lock for ctx/state/timer/delay   */
216 } ipmi_obj_t;
217 #endif /* WITH_FREEIPMI */
218 
219 typedef struct test_opt {               /* TEST OBJ OPTIONS:                 */
220     int              numBytes;          /*  num bytes to output per burst    */
221     int              msecMax;           /*  max msecs between bursts, or -1  */
222     int              msecMin;           /*  min msecs between bursts, or -1  */
223     int              probability;       /*  %-probability of burst, [0-100]  */
224 } test_opt_t;
225 
226 typedef struct test_obj {               /* TEST AUX OBJ DATA:                */
227     test_opt_t       opts;              /*  test obj options                 */
228     struct base_obj *logfile;           /*  log obj ref for console replay   */
229     int              timer;             /*  timer id for next burst          */
230     int              numLeft;           /*  num bytes remaining in burst     */
231     char             lastChar;          /*  last char output by test console */
232 } test_obj_t;
233 
234 typedef union aux_obj {
235     client_obj_t     client;
236     logfile_obj_t    logfile;
237     process_obj_t    process;
238     serial_obj_t     serial;
239     telnet_obj_t     telnet;
240     unixsock_obj_t   unixsock;
241 #if WITH_FREEIPMI
242     ipmi_obj_t       ipmi;
243 #endif /* WITH_FREEIPMI */
244     test_obj_t       test;
245 } aux_obj_t;
246 
247 typedef struct base_obj {               /* BASE OBJ:                         */
248     char            *name;              /*  obj name                         */
249     int              fd;                /*  file descriptor                  */
250     unsigned char    buf[OBJ_BUF_SIZE]; /*  circular-buf to be written to fd */
251     unsigned char   *bufInPtr;          /*  ptr for data written in to buf   */
252     unsigned char   *bufOutPtr;         /*  ptr for data written out to fd   */
253     pthread_mutex_t  bufLock;           /*  lock protecting access to buf    */
254     List             readers;           /*  list of objs that read from me   */
255     List             writers;           /*  list of objs that write to me    */
256     char            *resetCmdRef;       /*  console reset cmd string ref     */
257     pid_t            resetCmdPid;       /*  console reset cmd active pid     */
258     int              resetCmdTimer;     /*  console reset cmd timer id       */
259     unsigned         type;              /*  enum obj_type of auxiliary obj   */
260     unsigned         gotBufWrap:1;      /*  true if circular-buf has wrapped */
261     unsigned         gotEOF:1;          /*  true if obj got EOF on last read */
262     aux_obj_t        aux;               /*  auxiliary obj data union         */
263 } obj_t;
264 
265 typedef struct server_conf {
266     char            *confFileName;      /* configuration file name           */
267     char            *coreDumpDir;       /* dir where core dumps are written  */
268     char            *cwd;               /* cwd when daemon was started       */
269     char            *execPath;          /* process exec path                 */
270     char            *logDirName;        /* dir prefix for relative logfiles  */
271     char            *logFileName;       /* file to which logmsgs are written */
272     char            *logFmtName;        /* name with conversion specifiers   */
273     FILE            *logFilePtr;        /* msg log file ptr, !closed at exit */
274     int              logFileLevel;      /* level at which to log msg to file */
275     int              numOpenFiles;      /* rlimit for number of open files   */
276     char            *pidFileName;       /* file to which pid is written      */
277     char            *resetCmd;          /* cmd to invoke for reset esc-seq   */
278     int              syslogFacility;    /* syslog facility or -1 if disabled */
279     int              throwSignal;       /* signal num to send running daemon */
280     int              tStampMinutes;     /* minutes 'tween logfile timestamps */
281     time_t           tStampNext;        /* time next stamp written to logs   */
282     int              fd;                /* configuration file descriptor     */
283     int              port;              /* port number on which to listen    */
284     int              ld;                /* listening socket descriptor       */
285     List             objs;              /* list of all server obj_t's        */
286     tpoll_t          tp;                /* tpoll obj for muxing i/o & timers */
287     char            *globalLogName;     /* global log name (must contain &)  */
288     logopt_t         globalLogOpts;     /* global opts for logfile objects   */
289     seropt_t         globalSerOpts;     /* global opts for serial objects    */
290 #if WITH_FREEIPMI
291     ipmiopt_t        globalIpmiOpts;    /* global opts for ipmi objects      */
292     int              numIpmiObjs;       /* number of ipmi consoles in config */
293 #endif /* WITH_FREEIPMI */
294     test_opt_t       globalTestOpts;    /* global opts for test objs         */
295     unsigned         enableCoreDump:1;  /* true if core dumps are enabled    */
296     unsigned         enableKeepAlive:1; /* true if using TCP keep-alive      */
297     unsigned         enableLoopBack:1;  /* true if only listening on loopback*/
298     unsigned         enableTCPWrap:1;   /* true if TCP-Wrappers is enabled   */
299     unsigned         enableVerbose:1;   /* true if verbose output requested  */
300     unsigned         enableZeroLogs:1;  /* true if console logs are zero'd   */
301     unsigned         enableForeground:1;/* true if daemon should not fork    */
302 } server_conf_t;
303 
304 typedef struct client_args {
305     int              sd;                /* socket descriptor of new client   */
306     server_conf_t   *conf;              /* server's configuration            */
307 } client_arg_t;
308 
309 
310 /*  Concering object READERS and WRITERS:
311  *
312  *  - an object's readers are those objects that read from it
313  *    (ie, those to which it writes data read from its file descriptor)
314  *  - an object's writers are those objects that write to it
315  *    (ie, those that write data into its circular write-buffer)
316  *
317  *  Data is read from an object's file descriptor and immediately written
318  *  into the circular write-buffer of each object listed in its readers list.
319  *  Data in an object's write-buffer is written out to its file descriptor.
320  *
321  *  CONSOLE objects: (aka PROCESS/SERIAL/TELNET objects)
322  *  - readers list can contain at most one logfile object
323  *    and any number of R/O or R/W client objects
324  *  - writers list can contain any number of R/W or W/O client objects
325  *
326  *  LOGFILE objects:
327  *  - readers list is empty
328  *  - writers list contains exactly one console object
329  *
330  *  R/O CLIENT objects:
331  *  - readers list is empty
332  *  - writers list contains exactly one console object
333  *
334  *  R/W CLIENT objects:
335  *  - readers list contains exactly one console object
336  *  - writers list contains exactly one console object
337  *
338  *  W/O CLIENT objects: (aka B/C CLIENT objects)
339  *  - readers list contains more than one console object
340  *  - writers list is empty
341  */
342 
343 
344 /*  Macros
345  */
346 #define CONMAN_OBJ_IS_CONSOLE \
347   ( CONMAN_OBJ_PROCESS  |     \
348     CONMAN_OBJ_SERIAL   |     \
349     CONMAN_OBJ_TELNET   |     \
350     CONMAN_OBJ_UNIXSOCK |     \
351     CONMAN_OBJ_IPMI     |     \
352     CONMAN_OBJ_TEST           \
353   )
354 #define is_client_obj(OBJ)   (OBJ->type == CONMAN_OBJ_CLIENT)
355 #define is_ipmi_obj(OBJ)     (OBJ->type == CONMAN_OBJ_IPMI)
356 #define is_logfile_obj(OBJ)  (OBJ->type == CONMAN_OBJ_LOGFILE)
357 #define is_process_obj(OBJ)  (OBJ->type == CONMAN_OBJ_PROCESS)
358 #define is_serial_obj(OBJ)   (OBJ->type == CONMAN_OBJ_SERIAL)
359 #define is_telnet_obj(OBJ)   (OBJ->type == CONMAN_OBJ_TELNET)
360 #define is_test_obj(OBJ)     (OBJ->type == CONMAN_OBJ_TEST)
361 #define is_unixsock_obj(OBJ) (OBJ->type == CONMAN_OBJ_UNIXSOCK)
362 #define is_console_obj(OBJ)  (OBJ->type &  CONMAN_OBJ_IS_CONSOLE)
363 
364 
365 /*  server-conf.c
366  */
367 server_conf_t * create_server_conf(void);
368 
369 void destroy_server_conf(server_conf_t *conf);
370 
371 void process_cmdline(server_conf_t *conf, int argc, char *argv[]);
372 
373 void process_config(server_conf_t *conf);
374 
375 
376 /*  server-esc.c
377  */
378 int process_client_escapes(obj_t *client, void *src, int len);
379 
380 
381 /* server-ipmi.c
382  */
383 #if WITH_FREEIPMI
384 
385 void ipmi_init(int num_consoles);
386 
387 void ipmi_fini(void);
388 
389 int is_ipmi_dev(const char *dev, char **host_ref);
390 
391 int init_ipmi_opts(ipmiopt_t *iopts);
392 
393 int parse_ipmi_opts(
394     ipmiopt_t *iopts, const char *str, char *errbuf, int errlen);
395 
396 obj_t * create_ipmi_obj(server_conf_t *conf, char *name,
397     ipmiopt_t *iconf, char *host, char *errbuf, int errlen);
398 
399 int open_ipmi_obj(obj_t *ipmi);
400 
401 int send_ipmi_break(obj_t *ipmi);
402 
403 #endif /* WITH_FREEIPMI */
404 
405 
406 /*  server-logfile.c
407  */
408 int parse_logfile_opts(logopt_t *opts, const char *str,
409     char *errbuf, int errlen);
410 
411 obj_t * create_logfile_obj(server_conf_t *conf, char *name,
412     obj_t *console, logopt_t *opts, char *errbuf, int errlen);
413 
414 int open_logfile_obj(obj_t *logfile);
415 
416 obj_t * get_console_logfile_obj(obj_t *console);
417 
418 int write_log_data(obj_t *log, const void *src, int len);
419 
420 
421 /*  server-obj.c
422  */
423 obj_t * create_obj(server_conf_t *conf, char *name,
424     int fd, enum obj_type type);
425 
426 obj_t * create_client_obj(server_conf_t *conf, req_t *req);
427 
428 void destroy_obj(obj_t *obj);
429 
430 void reopen_obj(obj_t *obj);
431 
432 int format_obj_string(char *buf, int buflen, obj_t *obj, const char *fmt);
433 
434 int compare_objs(obj_t *obj1, obj_t *obj2);
435 
436 int find_obj(obj_t *obj, obj_t *key);
437 
438 int write_notify_msg(obj_t *console, int priority, char *fmt, ...);
439 
440 void notify_console_objs(obj_t *console, char *msg);
441 
442 void link_objs(obj_t *src, obj_t *dst);
443 
444 void unlink_objs(obj_t *src, obj_t *dst);
445 
446 void unlink_obj(obj_t *obj);
447 
448 int shutdown_obj(obj_t *obj);
449 
450 int read_from_obj(obj_t *obj);
451 
452 int write_obj_data(obj_t *obj, const void *src, int len, int isInfo);
453 
454 int write_to_obj(obj_t *obj);
455 
456 
457 /*  server-process.c
458  */
459 int is_process_dev(const char *dev, const char *cwd,
460     const char *exec_path, char **path_ref);
461 
462 obj_t * create_process_obj(server_conf_t *conf, char *name, List args,
463     char *errbuf, int errlen);
464 
465 int open_process_obj(obj_t *process);
466 
467 
468 /*  server-serial.c
469  */
470 int is_serial_dev(const char *dev, const char *cwd, char **path_ref);
471 
472 int parse_serial_opts(
473     seropt_t *opts, const char *str, char *errbuf, int errlen);
474 
475 void set_serial_opts(struct termios *tty, obj_t *serial, seropt_t *opts);
476 
477 obj_t * create_serial_obj(server_conf_t *conf, char *name,
478     char *dev, seropt_t *opts, char *errbuf, int errlen);
479 
480 int open_serial_obj(obj_t *serial);
481 
482 
483 /*  server-sock.c
484  */
485 void process_client(client_arg_t *args);
486 
487 
488 /*  server-telnet.c
489  */
490 int is_telnet_dev(const char *dev, char **host_ref, int *port_ref);
491 
492 obj_t * create_telnet_obj(server_conf_t *conf, char *name,
493     char *host, int port, char *errbuf, int errlen);
494 
495 int open_telnet_obj(obj_t *telnet);
496 
497 int process_telnet_escapes(obj_t *telnet, void *src, int len);
498 
499 int send_telnet_cmd(obj_t *telnet, int cmd, int opt);
500 
501 
502 /*  server-test.c
503  */
504 int is_test_dev(const char *dev);
505 
506 int init_test_opts(test_opt_t *opts);
507 
508 int parse_test_opts(test_opt_t *opts, const char *str,
509     char *errbuf, int errlen);
510 
511 obj_t * create_test_obj(server_conf_t *conf, char *name,
512     test_opt_t *opts, char *errbuf, int errlen);
513 
514 int open_test_obj(obj_t *test);
515 
516 int read_test_obj(obj_t *test);
517 
518 
519 /*  server-unixsock.c
520  */
521 int is_unixsock_dev(const char *dev, const char *cwd, char **path_ref);
522 
523 obj_t * create_unixsock_obj(server_conf_t *conf, char *name, char *dev,
524     char *errbuf, int errlen);
525 
526 int open_unixsock_obj(obj_t *unixsock);
527 
528 
529 #endif /* !_SERVER_H */
530