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