1 /*
2  * serv.h
3  *
4  * MontaVista IPMI server include file
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2003,2004,2005,2012 MontaVista Software Inc.
11  *
12  * This software is available to you under a choice of one of two
13  * licenses.  You may choose to be licensed under the terms of the GNU
14  * Lesser General Public License (GPL) Version 2 or the modified BSD
15  * license below.  The following disclamer applies to both licenses:
16  *
17  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
18  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
22  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
23  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
25  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
26  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  * GNU Lesser General Public Licence
29  *
30  *  This program is free software; you can redistribute it and/or
31  *  modify it under the terms of the GNU Lesser General Public License
32  *  as published by the Free Software Foundation; either version 2 of
33  *  the License, or (at your option) any later version.
34  *
35  *  You should have received a copy of the GNU Lesser General Public
36  *  License along with this program; if not, write to the Free
37  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
38  *
39  * Modified BSD Licence
40  *
41  * Redistribution and use in source and binary forms, with or without
42  * modification, are permitted provided that the following conditions
43  * are met:
44  *
45  *   1. Redistributions of source code must retain the above copyright
46  *      notice, this list of conditions and the following disclaimer.
47  *   2. Redistributions in binary form must reproduce the above
48  *      copyright notice, this list of conditions and the following
49  *      disclaimer in the documentation and/or other materials provided
50  *      with the distribution.
51  *   3. The name of the author may not be used to endorse or promote
52  *      products derived from this software without specific prior
53  *      written permission.
54  */
55 
56 #ifndef __SERV_H_
57 #define __SERV_H_
58 
59 #include <stdint.h>
60 #include <stdio.h>
61 #include <sys/uio.h> /* for iovec */
62 #include <sys/types.h>
63 #include <sys/socket.h>
64 #include <netinet/in.h>
65 #include <arpa/nameser.h>
66 #include <resolv.h>
67 #include <netdb.h>
68 #include <OpenIPMI/msg.h>
69 #include <OpenIPMI/mcserv.h>
70 
71 #ifndef __GNUC__
72 #  ifndef __attribute__
73 #    define  __attribute__(x)  /*NOTHING*/
74 #  endif
75 #endif
76 
77 typedef void (*handle_oem_cb)(channel_t *chan, void *cb_data);
78 typedef struct oem_handler_s
79 {
80     unsigned int  manufacturer_id;
81     unsigned int  product_id;
82     handle_oem_cb handler;
83     void          *cb_data;
84 
85     struct oem_handler_s *next;
86 } oem_handler_t;
87 
88 /* Register a new OEM handler. */
89 void ipmi_register_oem(oem_handler_t *handler);
90 
91 typedef struct oem_handlers_s
92 {
93     void *oem_data;
94     void *user_data;
95 
96     /* IPMB address changed.  Can be called by OEM code if it detects
97        an IPMB address change.  It should be ignored if NULL. */
98     void (*ipmb_addr_change)(channel_t *chan, unsigned char addr);
99 
100     /* Do OEM message handling; this is called after the message is
101        authenticated.  Should return 0 if the standard handling should
102        continue, or non-zero if the message should not go through
103        normal handling.  This field may be NULL, and it will be
104        ignored. */
105     int (*oem_handle_msg)(channel_t *chan, msg_t *msg);
106 
107     /* Called before a response is sent.  Should return 0 if the
108        standard handling should continue, or non-zero if the OEM
109        handled the response itself. */
110     int (*oem_handle_rsp)(channel_t *chan, msg_t *msg, rsp_msg_t *rsp);
111 
112     /* Check the privilege of a command to see if it is permitted. */
113     int (*oem_check_permitted)(unsigned char priv,
114 			       unsigned char netfn,
115 			       unsigned char cmd);
116 } oem_handlers_t;
117 
118 #define IPMI_MAX_CHANNELS 16
119 #define NUM_PRIV_LEVEL 4
120 struct channel_s
121 {
122     lmc_data_t *mc;
123 
124     unsigned char medium_type;
125     unsigned char protocol_type;
126     unsigned char session_support;
127 
128     unsigned int PEF_alerting : 1;
129     unsigned int PEF_alerting_nonv : 1;
130     unsigned int per_msg_auth : 1;
131 
132     /* We don't support user-level authentication disable, and access
133        mode is always available and cannot be set. */
134 
135     unsigned int privilege_limit : 4;
136     unsigned int privilege_limit_nonv : 4;
137 
138 #define MAX_SESSIONS 63
139     unsigned int active_sessions : 6;
140 
141     struct {
142 	unsigned char allowed_auths;
143     } priv_info[NUM_PRIV_LEVEL];
144 
145     /* Information about the MC we are hooked to. */
146     unsigned int  manufacturer_id;
147     unsigned int  product_id;
148 
149     unsigned int channel_num;
150 
151     int has_recv_q;
152     msg_t *recv_q_head;
153     msg_t *recv_q_tail;
154 
155     /* Used by channel code. */
156     void (*log)(channel_t *chan, int logtype, msg_t *msg,
157 		const char *format, ...)
158 	__attribute__ ((__format__ (__printf__, 4, 5)));
159 
160     int (*smi_send)(channel_t *chan, msg_t *msg);
161     void *(*alloc)(channel_t *chan, int size);
162     void (*free)(channel_t *chan, void *data);
163 
164     /* Set by channel code */
165     void (*return_rsp)(channel_t *chan, msg_t *msg, rsp_msg_t *rsp);
166     /* Available for the specific channel code. */
167     void *chan_info;
168 
169     /* Set or clear the attn flag.  If irq is set, set/clear the irq. */
170     void (*set_atn)(channel_t *chan, int val, int irq);
171 
172     /* Something is about to be added to the receive queue.  If this returns
173        true, then this function consumed the message and it shouldn't
174        be queued. */
175     int (*recv_in_q)(channel_t *chan, msg_t *msg);
176 
177     void (*start_cmd)(channel_t *chan);
178     void (*stop_cmd)(channel_t *chan, int do_it_now);
179 
180     /* Perform some hardware operations. */
181 #define HW_OP_RESET		0
182 #define HW_OP_POWERON		1
183 #define HW_OP_POWEROFF		2
184 #define HW_OP_SEND_NMI		3
185 #define HW_OP_IRQ_ENABLE	4
186 #define HW_OP_IRQ_DISABLE	5
187 #define HW_OP_GRACEFUL_SHUTDOWN	6
188 #define HW_OP_CHECK_POWER	7
189     unsigned int hw_capabilities; /* Bitmask of above bits for capabilities. */
190 #define HW_OP_CAN_RESET(chan) ((chan)->hw_capabilities & (1 << HW_OP_RESET))
191 #define HW_OP_CAN_POWER(chan) ((chan)->hw_capabilities & (1 << HW_OP_POWERON))
192 #define HW_OP_CAN_NMI(chan) ((chan)->hw_capabilities & (1 << HW_OP_SEND_NMI))
193 #define HW_OP_CAN_IRQ(chan) ((chan)->hw_capabilities & (1 << HW_OP_IRQ_ENABLE))
194 #define HW_OP_CAN_GRACEFUL_SHUTDOWN(chan) ((chan)->hw_capabilities & \
195 					   (1 << HW_OP_GRACEFUL_SHUTDOWN))
196     int (*hw_op)(channel_t *chan, unsigned int op);
197 
198     /* Special command handlers. */
199     void (*set_lan_parms)(channel_t *chan, msg_t *msg, unsigned char *rdata,
200 			  unsigned int *rdata_len);
201     void (*get_lan_parms)(channel_t *chan, msg_t *msg, unsigned char *rdata,
202 			  unsigned int *rdata_len);
203     void (*set_chan_access)(channel_t *chan, msg_t *msg, unsigned char *rdata,
204 			    unsigned int *rdata_len);
205     int (*set_associated_mc)(channel_t *chan, uint32_t session_id,
206 			     unsigned int payload, lmc_data_t *mc,
207 			     uint16_t *port,
208 			     void (*close)(lmc_data_t *mc, uint32_t session_id,
209 					   void *cb_data),
210 			     void *cb_data);
211     lmc_data_t *(*get_associated_mc)(channel_t *chan, uint32_t session_id,
212 				     unsigned int payload);
213 
214     oem_handlers_t oem;
215 
216     /*
217      * Set by the low-level interface code if it needs to handle
218      * received messages specially.
219      */
220     int (*oem_intf_recv_handler)(channel_t *chan, msg_t *msg,
221 				 unsigned char *rdata, unsigned int *rdata_len);
222 
223     /* Set to 1 if ipmb channel 0 is listed in the config file, 0 otherwise */
224     int prim_ipmb_in_cfg_file;
225 };
226 
227 struct user_s
228 {
229     unsigned char valid;
230     unsigned char link_auth;
231     unsigned char cb_only;
232     unsigned char username[16];
233     unsigned char pw[20];
234     unsigned char privilege;
235     unsigned char max_sessions;
236     unsigned char curr_sessions;
237 
238     /* Set by the user code. */
239     int           idx; /* My idx in the table. */
240 };
241 
242 /*
243  * Restrictions: <=64 users (per spec, 6 bits)
244  */
245 #define MAX_USERS		63
246 #define USER_BITS_REQ		6 /* Bits required to hold a user. */
247 #define USER_MASK		0x3f
248 
249 #define MAX_EVENT_FILTERS 16
250 #define MAX_ALERT_POLICIES 16
251 #define MAX_ALERT_STRINGS 16
252 #define MAX_ALERT_STRING_LEN 64
253 
254 struct pef_data_s
255 {
256     unsigned int set_in_progress : 2;
257     void (*commit)(sys_data_t *sys); /* Called when the commit occurs. */
258 
259     unsigned char pef_control;
260     unsigned char pef_action_global_control;
261     unsigned char pef_startup_delay;
262     unsigned char pef_alert_startup_delay;
263     unsigned char num_event_filters;
264     unsigned char event_filter_table[MAX_EVENT_FILTERS][21];
265     unsigned char event_filter_data1[MAX_EVENT_FILTERS][2];
266     unsigned char num_alert_policies;
267     unsigned char alert_policy_table[MAX_ALERT_POLICIES][4];
268     unsigned char system_guid[17];
269     unsigned char num_alert_strings;
270     unsigned char alert_string_keys[MAX_ALERT_STRINGS][3];
271     unsigned char alert_strings[MAX_ALERT_STRINGS][MAX_ALERT_STRING_LEN];
272 
273     /* Tells what has changed, so the commit can do something about it. */
274     struct {
275 	unsigned int pef_control : 1;
276 	unsigned int pef_action_global_control : 1;
277 	unsigned int pef_startup_delay : 1;
278 	unsigned int pef_alert_startup_delay : 1;
279 	unsigned int system_guid : 1;
280 	unsigned char event_filter_table[MAX_EVENT_FILTERS];
281 	unsigned char event_filter_data1[MAX_EVENT_FILTERS];
282 	unsigned char alert_policy_table[MAX_ALERT_POLICIES];
283 	unsigned int alert_string_keys[MAX_ALERT_STRINGS];
284 	unsigned int alert_strings[MAX_ALERT_STRINGS];
285     } changed;
286 };
287 
288 typedef struct ipmi_timer_s ipmi_timer_t;
289 typedef struct ipmi_io_s ipmi_io_t;
290 
291 typedef struct sockaddr_ip_s {
292     union
293         {
294 	    struct sockaddr s_addr0;
295             struct sockaddr_in  s_addr4;
296 #ifdef PF_INET6
297             struct sockaddr_in6 s_addr6;
298 #endif
299         } s_ipsock;
300 /*    socklen_t addr_len;*/
301 } sockaddr_ip_t;
302 
303 typedef struct lan_addr_s {
304     sockaddr_ip_t addr;
305     socklen_t     addr_len;
306 } lan_addr_t;
307 
308 struct startcmd_s {
309     /* Command to start a VM */
310     char *startcmd;
311     unsigned int startnow; /* Start startcmd at simulator startup? */
312     unsigned int poweroff_wait_time;
313     unsigned int kill_wait_time;
314     int vmpid; /* Process id of the VM, 0 if not running. */
315     int wait_poweroff;
316 };
317 
318 /*
319  * Note that we keep odd addresses, too.  In some cases that's useful
320  * in virtual systems that don't have I2C restrictions.
321  */
322 #define IPMI_MAX_MCS 256
323 
324 /*
325  * Generic data about the system that is global for the whole system and
326  * required for all server types.
327  */
328 struct sys_data_s {
329     char *name;
330 
331     /* The MCs in the system */
332     lmc_data_t *ipmb_addrs[IPMI_MAX_MCS];
333 
334 #define DEBUG_RAW_MSG	(1 << 0)
335 #define DEBUG_MSG	(1 << 1)
336 #define DEBUG_SOL	(1 << 2)
337     unsigned int debug;
338 
339 #define NEW_SESSION			1
340 #define NEW_SESSION_FAILED		2
341 #define SESSION_CLOSED			3
342 #define SESSION_CHALLENGE		4
343 #define SESSION_CHALLENGE_FAILED	5
344 #define AUTH_FAILED			6
345 #define INVALID_MSG			7
346 #define OS_ERROR			8
347 #define LAN_ERR				9
348 #define INFO				10
349 #define DEBUG				11
350 #define SETUP_ERROR			12
351     void (*log)(sys_data_t *sys, int type, msg_t *msg, const char *format, ...)
352 	__attribute__ ((__format__ (__printf__, 4, 5)));
353 
354     /* Console port.  Length is zero if not set. */
355     sockaddr_ip_t console_addr;
356     socklen_t console_addr_len;
357     int console_fd;
358 
359     unsigned char bmc_ipmb;
360     int sol_present;
361 
362     void *info;
363 
364     /*
365      * When reading in config, this tracks which information we are
366      * working on.  This is initialized to the MC at 0x20, setting
367      * the working MC changes these to the new MC.
368      */
369     channel_t **chan_set;
370     startcmd_t *startcmd;
371     user_t *cusers;
372     pef_data_t *cpef;
373     ipmi_sol_t *sol;
374     lmc_data_t *mc;
375 
376     void *(*alloc)(sys_data_t *sys, int size);
377     void (*free)(sys_data_t *sys, void *data);
378 
379     int (*get_monotonic_time)(sys_data_t *sys, struct timeval *tv);
380     int (*get_real_time)(sys_data_t *sys, struct timeval *tv);
381 
382     int (*alloc_timer)(sys_data_t *sys, void (*cb)(void *cb_data),
383 		       void *cb_data, ipmi_timer_t **timer);
384     int (*start_timer)(ipmi_timer_t *timer, struct timeval *timeout);
385     int (*stop_timer)(ipmi_timer_t *timer);
386     void (*free_timer)(ipmi_timer_t *timer);
387 
388     int (*add_io_hnd)(sys_data_t *sys, int fd,
389 		      void (*read_hnd)(int fd, void *cb_data),
390 		      void *cb_data, ipmi_io_t **io);
391     void (*remove_io_hnd)(ipmi_io_t *io);
392     void (*io_set_hnds)(ipmi_io_t *io,
393 			void (*write_hnd)(int fd, void *cb_data),
394 			void (*except_hnd)(int fd, void *cb_data));
395     void (*io_set_enables)(ipmi_io_t *io, int read, int write, int except);
396 
397     int (*gen_rand)(sys_data_t *sys, void *data, int len);
398 
399     /* Called by interface code to report that the target did a reset. */
400     /* FIXME - move */
401     void (*target_reset)(sys_data_t *sys);
402 
403     /*
404      * These are a hack so the channel code in the MCs can pick up
405      * these functions.
406      */
407     void (*clog)(channel_t *chan, int logtype, msg_t *msg,
408 		 const char *format, ...);
409     int (*csmi_send)(channel_t *chan, msg_t *msg);
410     void *(*calloc)(channel_t *chan, int size);
411     void (*cfree)(channel_t *chan, void *data);
412     int (*lan_channel_init)(void *info, channel_t *chan);
413     int (*ser_channel_init)(void *info, channel_t *chan);
414     int (*ipmb_channel_init)(void *info, channel_t *chan);
415 };
416 
417 static inline void
zero_extend_ascii(uint8_t * c,unsigned int len)418 zero_extend_ascii(uint8_t *c, unsigned int len)
419 {
420     unsigned int i;
421 
422     i = 0;
423     while ((i < len) && (*c != 0)) {
424 	c++;
425 	i++;
426     }
427     while (i < len) {
428 	*c = 0;
429 	c++;
430 	i++;
431     }
432 }
433 
434 typedef struct ipmi_tick_handler_s {
435     void (*handler)(void *info, unsigned int seconds);
436     void *info;
437     struct ipmi_tick_handler_s *next;
438 } ipmi_tick_handler_t;
439 
440 void ipmi_register_tick_handler(ipmi_tick_handler_t *handler);
441 
442 typedef struct ipmi_child_quit_s {
443     void (*handler)(void *info, pid_t pid);
444     void *info;
445     struct ipmi_child_quit_s *next;
446 } ipmi_child_quit_t;
447 
448 void ipmi_register_child_quit_handler(ipmi_child_quit_t *handler);
449 
450 typedef struct ipmi_shutdown_s {
451     void (*handler)(void *info, int sig);
452     void *info;
453     struct ipmi_shutdown_s *next;
454 } ipmi_shutdown_t;
455 
456 void ipmi_register_shutdown_handler(ipmi_shutdown_t *handler);
457 
458 /* A helper function to allow OEM code to send messages. */
459 int ipmi_oem_send_msg(channel_t     *chan,
460 		      unsigned char netfn,
461 		      unsigned char cmd,
462 		      unsigned char *data,
463 		      unsigned int  len,
464 		      long          oem_data);
465 
466 void ipmi_handle_smi_rsp(channel_t *chan, msg_t *msg,
467 			 unsigned char *rsp, int rsp_len);
468 
469 int channel_smi_send(channel_t *chan, msg_t *msg);
470 
471 /*
472  * Start the "startcmd" specified in the configuration file.
473  */
474 void ipmi_do_start_cmd(startcmd_t *startcmd);
475 void ipmi_do_kill(startcmd_t *startcmd, int noblock);
476 
477 int chan_init(channel_t *chan);
478 void sysinfo_init(sys_data_t *sys);
479 
480 
481 #define MAX_CONFIG_LINE 1024
482 
483 const char *mystrtok(char *str, const char *delim, char **next);
484 
485 /*
486  * Note that "value" must be dynamically allocated.  "name" does not have
487  * to be.
488  */
489 int add_variable(const char *name, char *value);
490 const char *find_bvariable(const char *name);
491 
492 int get_delim_str(char **rtokptr, char **rval, const char **err);
493 
494 int get_bool(char **tokptr, unsigned int *rval, const char **err);
495 
496 int get_uint(char **tokptr, unsigned int *rval, const char **err);
497 
498 int get_int(char **tokptr, int *rval, const char **err);
499 
500 int get_priv(char **tokptr, unsigned int *rval, const char **err);
501 
502 int get_auths(char **tokptr, unsigned int *rval, const char **err);
503 
504 int read_bytes(char **tokptr, unsigned char *data, const char **err,
505 	       unsigned int len);
506 
507 int get_sock_addr(char **tokptr, sockaddr_ip_t *addr, socklen_t *len,
508 		  char *def_port, int socktype, const char **err);
509 
510 int read_config(sys_data_t    *sys,
511 		char          *config_file,
512 		int	      print_version);
513 int load_dynamic_libs(sys_data_t *sys, int print_version);
514 void post_init_dynamic_libs(sys_data_t *sys);
515 
516 void debug_log_raw_msg(sys_data_t *sys,
517 		       unsigned char *data, unsigned int len,
518 		       const char *format, ...);
519 
520 unsigned int ipmi_get_uint16(uint8_t *data);
521 void ipmi_set_uint16(uint8_t *data, int val);
522 unsigned int ipmi_get_uint32(uint8_t *data);
523 void ipmi_set_uint32(uint8_t *data, int val);
524 
525 uint8_t ipmb_checksum(uint8_t *data, int size, uint8_t start);
526 
527 /*
528  * Command handler interface.
529  */
530 typedef struct emu_data_s emu_data_t;
531 typedef struct emu_out_s
532 {
533     void (*eprintf)(struct emu_out_s *out, char *format, ...);
534     void *data;
535 } emu_out_t;
536 
537 #define MC	1
538 #define NOMC	0
539 typedef int (*ipmi_emu_cmd_handler)(emu_out_t  *out,
540 				    emu_data_t *emu,
541 				    lmc_data_t *mc,
542 				    char       **toks);
543 int ipmi_emu_add_cmd(const char *name, unsigned int flags,
544 		     ipmi_emu_cmd_handler handler);
545 
546 
547 #endif /* __SERV_H_ */
548