1 /*
2  * ipmi.c
3  *
4  * MontaVista IPMI generic code
5  *
6  * Author: MontaVista Software, Inc.
7  *         Corey Minyard <minyard@mvista.com>
8  *         source@mvista.com
9  *
10  * Copyright 2002,2003 MontaVista Software Inc.
11  *
12  *  This program is free software; you can redistribute it and/or
13  *  modify it under the terms of the GNU Lesser General Public License
14  *  as published by the Free Software Foundation; either version 2 of
15  *  the License, or (at your option) any later version.
16  *
17  *
18  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
19  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
23  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
24  *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25  *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
26  *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
27  *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *  You should have received a copy of the GNU Lesser General Public
30  *  License along with this program; if not, write to the Free
31  *  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
32  */
33 
34 #include <config.h>
35 
36 #include <string.h>
37 #include <stdio.h>
38 #include <stdlib.h>
39 #include <netdb.h>
40 
41 #include <OpenIPMI/os_handler.h>
42 #include <OpenIPMI/ipmi_conn.h>
43 #include <OpenIPMI/ipmi_err.h>
44 #include <OpenIPMI/ipmi_auth.h>
45 #include <OpenIPMI/ipmi_lan.h>
46 #include <OpenIPMI/ipmi_smi.h>
47 #include <OpenIPMI/ipmi_msgbits.h>
48 
49 #include <OpenIPMI/internal/ipmi_domain.h>
50 #include <OpenIPMI/internal/ipmi_mc.h>
51 #include <OpenIPMI/internal/ipmi_int.h>
52 #include <OpenIPMI/internal/ipmi_oem.h>
53 #include <OpenIPMI/internal/locked_list.h>
54 
55 #if defined(DEBUG_MSG) || defined(DEBUG_RAWMSG)
56 static void
dump_hex(const void * vdata,int len)57 dump_hex(const void *vdata, int len)
58 {
59     const unsigned char *data = vdata;
60     int i;
61     for (i=0; i<len; i++) {
62 	if ((i != 0) && ((i % 16) == 0)) {
63 	    ipmi_log(IPMI_LOG_DEBUG_CONT, "\n  ");
64 	}
65 	ipmi_log(IPMI_LOG_DEBUG_CONT, " %2.2x", data[i]);
66     }
67 }
68 #endif
69 static os_handler_t *ipmi_os_handler;
70 
71 unsigned int i__ipmi_log_mask = 0;
72 
73 os_handler_t *
ipmi_get_global_os_handler(void)74 ipmi_get_global_os_handler(void)
75 {
76     return ipmi_os_handler;
77 }
78 
79 int
ipmi_create_global_lock(ipmi_lock_t ** new_lock)80 ipmi_create_global_lock(ipmi_lock_t **new_lock)
81 {
82     return ipmi_create_lock_os_hnd(ipmi_os_handler, new_lock);
83 }
84 
85 int
ipmi_create_lock(ipmi_domain_t * domain,ipmi_lock_t ** new_lock)86 ipmi_create_lock(ipmi_domain_t *domain, ipmi_lock_t **new_lock)
87 {
88     return ipmi_create_lock_os_hnd(ipmi_domain_get_os_hnd(domain), new_lock);
89 }
90 
91 void
ipmi_log(enum ipmi_log_type_e log_type,const char * format,...)92 ipmi_log(enum ipmi_log_type_e log_type, const char *format, ...)
93 {
94     va_list ap;
95 
96     va_start(ap, format);
97     if (ipmi_os_handler && ipmi_os_handler->vlog)
98 	ipmi_os_handler->vlog(ipmi_os_handler, log_type, format, ap);
99     else {
100 	vfprintf(stderr, format, ap);
101 	switch (log_type) {
102 	case IPMI_LOG_DEBUG_START:
103 	case IPMI_LOG_DEBUG_CONT:
104 	    break;
105 	default:
106 	    fprintf(stderr, "\n");
107 	}
108     }
109     va_end(ap);
110 }
111 
112 static long seq = 0;
113 static os_hnd_lock_t *seq_lock;
114 long
ipmi_get_seq(void)115 ipmi_get_seq(void)
116 {
117     long rv;
118 
119     if (seq_lock)
120 	ipmi_os_handler->lock(ipmi_os_handler, seq_lock);
121     rv = seq;
122     seq++;
123     if (seq_lock)
124 	ipmi_os_handler->unlock(ipmi_os_handler, seq_lock);
125 
126     return rv;
127 }
128 
129 void
ipmi_event_state_init(ipmi_event_state_t * events)130 ipmi_event_state_init(ipmi_event_state_t *events)
131 {
132     events->status = 0;
133     events->__assertion_events = 0;
134     events->__deassertion_events = 0;
135 }
136 
137 void
ipmi_threshold_event_clear(ipmi_event_state_t * events,enum ipmi_thresh_e type,enum ipmi_event_value_dir_e value_dir,enum ipmi_event_dir_e dir)138 ipmi_threshold_event_clear(ipmi_event_state_t          *events,
139 			   enum ipmi_thresh_e          type,
140 			   enum ipmi_event_value_dir_e value_dir,
141 			   enum ipmi_event_dir_e       dir)
142 {
143     if (dir == IPMI_ASSERTION) {
144 	events->__assertion_events &= ~(1 << (type*2+value_dir));
145     } else {
146 	events->__deassertion_events &= ~(1 << (type*2+value_dir));
147     }
148 }
149 
150 void
ipmi_threshold_event_set(ipmi_event_state_t * events,enum ipmi_thresh_e type,enum ipmi_event_value_dir_e value_dir,enum ipmi_event_dir_e dir)151 ipmi_threshold_event_set(ipmi_event_state_t          *events,
152 			 enum ipmi_thresh_e          type,
153 			 enum ipmi_event_value_dir_e value_dir,
154 			 enum ipmi_event_dir_e       dir)
155 {
156     if (dir == IPMI_ASSERTION) {
157 	events->__assertion_events |= 1 << (type*2+value_dir);
158     } else {
159 	events->__deassertion_events |= 1 << (type*2+value_dir);
160     }
161 }
162 
163 int
ipmi_is_threshold_event_set(ipmi_event_state_t * events,enum ipmi_thresh_e type,enum ipmi_event_value_dir_e value_dir,enum ipmi_event_dir_e dir)164 ipmi_is_threshold_event_set(ipmi_event_state_t          *events,
165 			    enum ipmi_thresh_e          type,
166 			    enum ipmi_event_value_dir_e value_dir,
167 			    enum ipmi_event_dir_e       dir)
168 {
169     if (dir == IPMI_ASSERTION) {
170 	return (events->__assertion_events & (1 << (type*2+value_dir))) != 0;
171     } else {
172 	return (events->__deassertion_events & (1 << (type*2+value_dir))) != 0;
173     }
174 }
175 
176 void
ipmi_discrete_event_clear(ipmi_event_state_t * events,int event_offset,enum ipmi_event_dir_e dir)177 ipmi_discrete_event_clear(ipmi_event_state_t    *events,
178 			  int                   event_offset,
179 			  enum ipmi_event_dir_e dir)
180 {
181     if (dir == IPMI_ASSERTION) {
182 	events->__assertion_events &= ~(1 << event_offset);
183     } else {
184 	events->__deassertion_events &= ~(1 << event_offset);
185     }
186 }
187 
188 void
ipmi_discrete_event_set(ipmi_event_state_t * events,int event_offset,enum ipmi_event_dir_e dir)189 ipmi_discrete_event_set(ipmi_event_state_t    *events,
190 			int                   event_offset,
191 			enum ipmi_event_dir_e dir)
192 {
193     if (dir == IPMI_ASSERTION) {
194 	events->__assertion_events |= 1 << event_offset;
195     } else {
196 	events->__deassertion_events |= 1 << event_offset;
197     }
198 }
199 
200 int
ipmi_is_discrete_event_set(ipmi_event_state_t * events,int event_offset,enum ipmi_event_dir_e dir)201 ipmi_is_discrete_event_set(ipmi_event_state_t    *events,
202 			   int                   event_offset,
203 			   enum ipmi_event_dir_e dir)
204 {
205     if (dir == IPMI_ASSERTION) {
206 	return (events->__assertion_events & (1 << event_offset)) != 0;
207     } else {
208 	return (events->__deassertion_events & (1 << event_offset)) != 0;
209     }
210 }
211 
212 #define IPMI_SENSOR_EVENTS_ENABLED	0x80
213 #define IPMI_SENSOR_SCANNING_ENABLED	0x40
214 #define IPMI_SENSOR_BUSY		0x20
215 
ipmi_event_state_size(void)216 unsigned int ipmi_event_state_size(void)
217 {
218     return sizeof(ipmi_event_state_t);
219 }
220 
221 void
ipmi_copy_event_state(ipmi_event_state_t * dest,ipmi_event_state_t * src)222 ipmi_copy_event_state(ipmi_event_state_t *dest, ipmi_event_state_t *src)
223 {
224     *dest = *src;
225 }
226 
227 void
ipmi_event_state_set_events_enabled(ipmi_event_state_t * events,int val)228 ipmi_event_state_set_events_enabled(ipmi_event_state_t *events, int val)
229 {
230     if (val)
231 	events->status |= IPMI_SENSOR_EVENTS_ENABLED;
232     else
233 	events->status &= ~IPMI_SENSOR_EVENTS_ENABLED;
234 }
235 
236 int
ipmi_event_state_get_events_enabled(ipmi_event_state_t * events)237 ipmi_event_state_get_events_enabled(ipmi_event_state_t *events)
238 {
239     return (events->status >> 7) & 1;
240 }
241 
242 void
ipmi_event_state_set_scanning_enabled(ipmi_event_state_t * events,int val)243 ipmi_event_state_set_scanning_enabled(ipmi_event_state_t *events, int val)
244 {
245     if (val)
246 	events->status |= IPMI_SENSOR_SCANNING_ENABLED;
247     else
248 	events->status &= ~IPMI_SENSOR_SCANNING_ENABLED;
249 }
250 
251 int
ipmi_event_state_get_scanning_enabled(ipmi_event_state_t * events)252 ipmi_event_state_get_scanning_enabled(ipmi_event_state_t *events)
253 {
254     return (events->status >> 6) & 1;
255 }
256 
257 void
ipmi_event_state_set_busy(ipmi_event_state_t * events,int val)258 ipmi_event_state_set_busy(ipmi_event_state_t *events, int val)
259 {
260     if (val)
261 	events->status |= IPMI_SENSOR_BUSY;
262     else
263 	events->status &= ~IPMI_SENSOR_BUSY;
264 }
265 
266 int
ipmi_event_state_get_busy(ipmi_event_state_t * events)267 ipmi_event_state_get_busy(ipmi_event_state_t *events)
268 {
269     return (events->status >> 5) & 1;
270 }
271 
ipmi_thresholds_size(void)272 unsigned int ipmi_thresholds_size(void)
273 {
274     return sizeof(ipmi_thresholds_t);
275 }
276 
277 void
ipmi_copy_thresholds(ipmi_thresholds_t * dest,ipmi_thresholds_t * src)278 ipmi_copy_thresholds(ipmi_thresholds_t *dest, ipmi_thresholds_t *src)
279 {
280     *dest = *src;
281 }
282 
ipmi_thresholds_init(ipmi_thresholds_t * th)283 int ipmi_thresholds_init(ipmi_thresholds_t *th)
284 {
285     int i;
286     for (i=0; i<6; i++)
287 	th->vals[i].status = 0;
288     return 0;
289 }
290 
ipmi_threshold_set(ipmi_thresholds_t * th,ipmi_sensor_t * sensor,enum ipmi_thresh_e threshold,double value)291 int ipmi_threshold_set(ipmi_thresholds_t  *th,
292 		       ipmi_sensor_t      *sensor,
293 		       enum ipmi_thresh_e threshold,
294 		       double             value)
295 {
296     int rv = 0;
297 
298     if (threshold > IPMI_UPPER_NON_RECOVERABLE)
299 	return EINVAL;
300 
301     if (sensor) {
302 	int val;
303 	rv = ipmi_sensor_threshold_settable(sensor, threshold, &val);
304 	if (rv)
305 	    return rv;
306 	if (!val)
307 	    return ENOSYS;
308     }
309 
310     th->vals[threshold].status = 1;
311     th->vals[threshold].val = value;
312     return 0;
313 }
314 
ipmi_threshold_get(ipmi_thresholds_t * th,enum ipmi_thresh_e threshold,double * value)315 int ipmi_threshold_get(ipmi_thresholds_t  *th,
316 		       enum ipmi_thresh_e threshold,
317 		       double             *value)
318 {
319     if (threshold > IPMI_UPPER_NON_RECOVERABLE)
320 	return EINVAL;
321 
322     if (th->vals[threshold].status) {
323 	*value = th->vals[threshold].val;
324 	return 0;
325     } else {
326 	return ENOSYS;
327     }
328 }
329 
ipmi_states_size(void)330 unsigned int ipmi_states_size(void)
331 {
332     return sizeof(ipmi_states_t);
333 }
334 
335 void
ipmi_copy_states(ipmi_states_t * dest,ipmi_states_t * src)336 ipmi_copy_states(ipmi_states_t *dest, ipmi_states_t *src)
337 {
338     *dest = *src;
339 }
340 
341 void
ipmi_init_states(ipmi_states_t * states)342 ipmi_init_states(ipmi_states_t *states)
343 {
344     states->__event_messages_enabled = 0;
345     states->__sensor_scanning_enabled = 0;
346     states->__initial_update_in_progress = 0;
347     states->__states = 0;
348 }
349 
350 int
ipmi_is_event_messages_enabled(ipmi_states_t * states)351 ipmi_is_event_messages_enabled(ipmi_states_t *states)
352 {
353     return states->__event_messages_enabled;
354 }
355 
356 void
ipmi_set_event_messages_enabled(ipmi_states_t * states,int val)357 ipmi_set_event_messages_enabled(ipmi_states_t *states, int val)
358 {
359     states->__event_messages_enabled = val;
360 }
361 
362 int
ipmi_is_sensor_scanning_enabled(ipmi_states_t * states)363 ipmi_is_sensor_scanning_enabled(ipmi_states_t *states)
364 {
365     return states->__sensor_scanning_enabled;
366 }
367 
368 void
ipmi_set_sensor_scanning_enabled(ipmi_states_t * states,int val)369 ipmi_set_sensor_scanning_enabled(ipmi_states_t *states, int val)
370 {
371     states->__sensor_scanning_enabled = val;
372 }
373 
374 int
ipmi_is_initial_update_in_progress(ipmi_states_t * states)375 ipmi_is_initial_update_in_progress(ipmi_states_t *states)
376 {
377     return states->__initial_update_in_progress;
378 }
379 
380 void
ipmi_set_initial_update_in_progress(ipmi_states_t * states,int val)381 ipmi_set_initial_update_in_progress(ipmi_states_t *states, int val)
382 {
383     states->__initial_update_in_progress = val;
384 }
385 
386 int
ipmi_is_state_set(ipmi_states_t * states,int state_num)387 ipmi_is_state_set(ipmi_states_t *states,
388 		  int           state_num)
389 {
390     return (states->__states & (1 << state_num)) != 0;
391 }
392 
393 void
ipmi_set_state(ipmi_states_t * states,int state_num,int val)394 ipmi_set_state(ipmi_states_t *states,
395 	       int           state_num,
396 	       int           val)
397 {
398     if (val)
399 	states->__states |= 1 << state_num;
400     else
401 	states->__states &= ~(1 << state_num);
402 }
403 
404 int
ipmi_is_threshold_out_of_range(ipmi_states_t * states,enum ipmi_thresh_e thresh)405 ipmi_is_threshold_out_of_range(ipmi_states_t      *states,
406 			       enum ipmi_thresh_e thresh)
407 {
408     return (states->__states & (1 << thresh)) != 0;
409 }
410 
411 void
ipmi_set_threshold_out_of_range(ipmi_states_t * states,enum ipmi_thresh_e thresh,int val)412 ipmi_set_threshold_out_of_range(ipmi_states_t      *states,
413 				enum ipmi_thresh_e thresh,
414 				int                val)
415 {
416     if (val)
417 	states->__states |= 1 << thresh;
418     else
419 	states->__states &= ~(1 << thresh);
420 }
421 
422 void ipmi_oem_force_conn_init(void);
423 int ipmi_oem_motorola_mxp_init(void);
424 int ipmi_oem_intel_init(void);
425 int ipmi_oem_kontron_conn_init(void);
426 int ipmi_oem_atca_conn_init(void);
427 int ipmi_oem_atca_init(void);
428 int init_oem_test(void);
429 int i_ipmi_smi_init(os_handler_t *os_hnd);
430 int i_ipmi_lan_init(os_handler_t *os_hnd);
431 int ipmi_malloc_init(os_handler_t *os_hnd);
432 void ipmi_malloc_shutdown(void);
433 int i_ipmi_rakp_init(void);
434 int i_ipmi_aes_cbc_init(void);
435 int i_ipmi_hmac_init(void);
436 int i_ipmi_md5_init(void);
437 int i_ipmi_fru_init(void);
438 int i_ipmi_normal_fru_init(void);
439 int i_ipmi_fru_spd_decoder_init(void);
440 void i_ipmi_fru_shutdown(void);
441 void i_ipmi_normal_fru_shutdown(void);
442 void i_ipmi_fru_spd_decoder_shutdown(void);
443 int i_ipmi_sol_init(void);
444 
445 void i_ipmi_rakp_shutdown(void);
446 void i_ipmi_aes_cbc_shutdown(void);
447 void i_ipmi_hmac_shutdown(void);
448 void i_ipmi_md5_shutdown(void);
449 void ipmi_oem_atca_conn_shutdown(void);
450 void ipmi_oem_intel_shutdown(void);
451 void ipmi_oem_kontron_conn_shutdown(void);
452 void ipmi_oem_atca_shutdown(void);
453 int i_ipmi_smi_shutdown(void);
454 int i_ipmi_lan_shutdown(void);
455 void i_ipmi_sol_shutdown(void);
456 
457 
458 static locked_list_t *con_type_list;
459 static int ipmi_initialized;
460 
461 int
ipmi_init(os_handler_t * handler)462 ipmi_init(os_handler_t *handler)
463 {
464     int rv;
465 
466     if (ipmi_initialized)
467 	return 0;
468 
469     ipmi_os_handler = handler;
470 
471     /* Set up memory allocation first */
472     ipmi_malloc_init(handler);
473 
474     /* Set up logging in malloc code. */
475     ipmi_malloc_log = ipmi_log;
476 
477     con_type_list = locked_list_alloc(handler);
478 
479     rv = i_ipmi_conn_init(handler);
480     if (rv)
481 	return rv;
482 
483     ipmi_initialized = 1;
484 
485     if (handler->create_lock) {
486 	rv = handler->create_lock(handler, &seq_lock);
487 	if (rv)
488 	    goto out_err;
489     } else {
490 	seq_lock = NULL;
491     }
492 
493 #ifdef HAVE_OPENIPMI_SMI
494     rv = i_ipmi_smi_init(handler);
495     if (rv)
496 	goto out_err;
497 #endif
498 
499     rv = i_ipmi_lan_init(handler);
500     if (rv)
501 	goto out_err;
502 
503     i_ipmi_domain_init();
504     i_ipmi_mc_init();
505 
506     rv = i_ipmi_rakp_init();
507     if (rv)
508 	goto out_err;
509     rv = i_ipmi_aes_cbc_init();
510     if (rv)
511 	goto out_err;
512     rv = i_ipmi_hmac_init();
513     if (rv)
514 	goto out_err;
515     rv = i_ipmi_md5_init();
516     if (rv)
517 	goto out_err;
518 
519     rv = i_ipmi_fru_init();
520     if (rv)
521 	goto out_err;
522 
523     rv = i_ipmi_normal_fru_init();
524     if (rv)
525 	goto out_err;
526 
527     rv = i_ipmi_fru_spd_decoder_init();
528     if (rv)
529 	goto out_err;
530 
531     rv = i_ipmi_sol_init();
532     if (rv)
533 	goto out_err;
534 
535     /* Call the OEM handlers. */
536     ipmi_oem_force_conn_init();
537     ipmi_oem_motorola_mxp_init();
538     ipmi_oem_intel_init();
539     ipmi_oem_kontron_conn_init();
540     ipmi_oem_atca_conn_init();
541     ipmi_oem_atca_init();
542     init_oem_test();
543 
544     return 0;
545 
546  out_err:
547     ipmi_shutdown();
548     return rv;
549 }
550 
551 void
ipmi_shutdown(void)552 ipmi_shutdown(void)
553 {
554     if (! ipmi_initialized)
555 	return;
556 
557     i_ipmi_rakp_shutdown();
558     i_ipmi_aes_cbc_shutdown();
559     i_ipmi_hmac_shutdown();
560     i_ipmi_md5_shutdown();
561     i_ipmi_sol_shutdown();
562     i_ipmi_lan_shutdown();
563 #ifdef HAVE_OPENIPMI_SMI
564     i_ipmi_smi_shutdown();
565 #endif
566     ipmi_oem_atca_shutdown();
567     ipmi_oem_atca_conn_shutdown();
568     ipmi_oem_intel_shutdown();
569     ipmi_oem_kontron_conn_shutdown();
570     i_ipmi_mc_shutdown();
571     i_ipmi_domain_shutdown();
572     i_ipmi_fru_spd_decoder_shutdown();
573     i_ipmi_conn_shutdown();
574     i_ipmi_normal_fru_shutdown();
575     i_ipmi_fru_shutdown();
576     if (seq_lock)
577 	ipmi_os_handler->destroy_lock(ipmi_os_handler, seq_lock);
578     if (con_type_list)
579 	locked_list_destroy(con_type_list);
580     ipmi_debug_malloc_cleanup();
581     ipmi_malloc_shutdown();
582 
583     ipmi_os_handler = NULL;
584 
585     ipmi_initialized = 0;
586 }
587 
588 #define CHECK_ARG \
589     do { \
590         if (*curr_arg >= arg_count) { \
591 	    rv = EINVAL; \
592 	    goto out_err; \
593         } \
594     } while(0)
595 
596 int
ipmi_parse_args(int * curr_arg,int arg_count,char * const * args,ipmi_args_t ** iargs)597 ipmi_parse_args(int         *curr_arg,
598 		int         arg_count,
599 		char        * const *args,
600 		ipmi_args_t **iargs)
601 {
602     int rv;
603     CHECK_ARG;
604 
605     if (strcmp(args[*curr_arg], "smi") == 0) {
606 	/* Format is unchanged. */
607 	return ipmi_parse_args2(curr_arg, arg_count, args, iargs);
608     } else if (strcmp(args[*curr_arg], "lan") == 0) {
609 	/* Convert the format over to the new one and call the new
610 	   handler. */
611 	char *largs[16];
612 	int  c = 0;
613 	int  newcarg = 0;
614 	char *addr, *addr2 = NULL;
615 	char *port, *port2 = NULL;
616 	char *auth;
617 	char *priv;
618 	char *username;
619 	char *pw;
620 
621 	largs[c] = args[*curr_arg];
622 	(*curr_arg)++; CHECK_ARG;
623 	c++;
624 
625 	addr = args[*curr_arg];
626 	(*curr_arg)++; CHECK_ARG;
627 
628 	port = args[*curr_arg];
629 	(*curr_arg)++; CHECK_ARG;
630 
631 	if ((strcmp(args[*curr_arg], "none") != 0)
632 	    && (strcmp(args[*curr_arg], "md2") != 0)
633 	    && (strcmp(args[*curr_arg], "md5") != 0)
634 	    && (strcmp(args[*curr_arg], "straight") != 0)
635 	    && (strcmp(args[*curr_arg], "rmcp+") != 0))
636 	{
637 	    addr2 = args[*curr_arg];
638 	    (*curr_arg)++; CHECK_ARG;
639 
640 	    port2 = args[*curr_arg];
641 	    (*curr_arg)++; CHECK_ARG;
642 	}
643 
644 	auth = args[*curr_arg];
645 	(*curr_arg)++; CHECK_ARG;
646 
647 	priv = args[*curr_arg];
648 	(*curr_arg)++; CHECK_ARG;
649 
650 	username = args[*curr_arg];
651 	(*curr_arg)++; CHECK_ARG;
652 
653 	pw = args[*curr_arg];
654 	(*curr_arg)++;
655 
656 	largs[c] = "-U"; c++; largs[c] = username; c++;
657 	largs[c] = "-P"; c++; largs[c] = pw; c++;
658 	largs[c] = "-A"; c++; largs[c] = auth; c++;
659 	largs[c] = "-L"; c++; largs[c] = priv; c++;
660 	if (addr2) {
661 	    largs[c] = "-s"; c++;
662 	}
663 	largs[c] = "-p"; c++; largs[c] = port; c++;
664 	if (port2) {
665 	    largs[c] = "-p2"; c++; largs[c] = port2; c++;
666 	}
667 	largs[c] = addr; c++;
668 	if (addr2) {
669 	    largs[c] = addr2; c++;
670 	}
671 
672 	return ipmi_parse_args2(&newcarg, c, largs, iargs);
673     } else {
674 	rv = EINVAL;
675 	goto out_err;
676     }
677     return 0;
678 
679  out_err:
680     return rv;
681 }
682 
683 struct ipmi_args_s
684 {
685     ipmi_args_free_cb     free;
686     ipmi_args_connect_cb  connect;
687     ipmi_args_get_val_cb  get_val;
688     ipmi_args_set_val_cb  set_val;
689     ipmi_args_copy_cb     copy;
690     ipmi_args_validate_cb validate;
691     ipmi_args_free_val_cb free_val;
692     ipmi_args_get_type_cb get_type;
693 };
694 
695 struct ipmi_con_setup_s
696 {
697     ipmi_con_parse_args_cb parse;
698     ipmi_con_get_help_cb   help;
699     ipmi_con_alloc_args_cb alloc;
700 };
701 ipmi_con_setup_t *
i_ipmi_alloc_con_setup(ipmi_con_parse_args_cb parse,ipmi_con_get_help_cb help,ipmi_con_alloc_args_cb alloc)702 i_ipmi_alloc_con_setup(ipmi_con_parse_args_cb parse,
703 		       ipmi_con_get_help_cb   help,
704 		       ipmi_con_alloc_args_cb alloc)
705 {
706     ipmi_con_setup_t *rv;
707 
708     rv = ipmi_mem_alloc(sizeof(*rv));
709     if (!rv)
710 	return NULL;
711     memset(rv, 0, sizeof(*rv));
712     rv->parse = parse;
713     rv->help = help;
714     rv->alloc = alloc;
715     return rv;
716 }
717 
718 void
i_ipmi_free_con_setup(ipmi_con_setup_t * v)719 i_ipmi_free_con_setup(ipmi_con_setup_t *v)
720 {
721     ipmi_mem_free(v);
722 }
723 
724 typedef struct con_type_alloc_data_s
725 {
726     char        *con_type;
727     ipmi_args_t *args;
728     int         err;
729 } con_type_alloc_data_t;
730 
731 static int
con_type_alloc_handler(void * cb_data,void * item1,void * item2)732 con_type_alloc_handler(void *cb_data, void *item1, void *item2)
733 {
734     ipmi_con_setup_t      *setup = item2;
735     con_type_alloc_data_t *data = cb_data;
736 
737     if (strcmp(data->con_type, item1) == 0) {
738 	data->args = setup->alloc();
739 	if (!data->args)
740 	    data->err = ENOMEM;
741 	else
742 	    data->err = 0;
743 	return LOCKED_LIST_ITER_STOP;
744     }
745     return LOCKED_LIST_ITER_CONTINUE;
746 }
747 
748 int
ipmi_args_alloc(char * con_type,ipmi_args_t ** args)749 ipmi_args_alloc(char *con_type, ipmi_args_t **args)
750 {
751     con_type_alloc_data_t data;
752 
753     data.con_type = con_type;
754     data.err = EINVAL;
755     locked_list_iterate(con_type_list, con_type_alloc_handler, &data);
756     if (!data.err)
757 	*args = data.args;
758     return data.err;
759 }
760 
761 typedef struct con_type_help_data_s
762 {
763     ipmi_iter_help_cb help_cb;
764     void              *cb_data;
765 } con_type_help_data_t;
766 
767 static int
con_type_help_handler(void * cb_data,void * item1,void * item2)768 con_type_help_handler(void *cb_data, void *item1, void *item2)
769 {
770     ipmi_con_setup_t     *setup = item2;
771     con_type_help_data_t *data = cb_data;
772 
773     data->help_cb(item1, setup->help(), data->cb_data);
774     return LOCKED_LIST_ITER_CONTINUE;
775 }
776 
777 void
ipmi_parse_args_iter_help(ipmi_iter_help_cb help_cb,void * cb_data)778 ipmi_parse_args_iter_help(ipmi_iter_help_cb help_cb, void *cb_data)
779 {
780     con_type_help_data_t data;
781 
782     data.help_cb = help_cb;
783     data.cb_data = cb_data;
784     locked_list_iterate(con_type_list, con_type_help_handler, &data);
785 }
786 
787 typedef struct con_setup_data_s
788 {
789     const char  *name;
790     int         err;
791 
792     int         *curr_arg;
793     int         arg_count;
794     char        * const *args;
795     ipmi_args_t *iargs;
796 } con_setup_data_t;
797 
798 static int
con_type_check_parse(void * cb_data,void * item1,void * item2)799 con_type_check_parse(void *cb_data, void *item1, void *item2)
800 {
801     con_setup_data_t *data = cb_data;
802 
803     if (strcmp(item1, data->name) == 0) {
804 	ipmi_con_setup_t *setup = item2;
805 	data->err = setup->parse(data->curr_arg, data->arg_count, data->args,
806 				 &data->iargs);
807 	return LOCKED_LIST_ITER_STOP;
808     }
809     return LOCKED_LIST_ITER_CONTINUE;
810 }
811 
812 int
ipmi_parse_args2(int * curr_arg,int arg_count,char * const * args,ipmi_args_t ** iargs)813 ipmi_parse_args2(int         *curr_arg,
814 		 int         arg_count,
815 		 char        * const *args,
816 		 ipmi_args_t **iargs)
817 {
818     con_setup_data_t data;
819     int              rv;
820 
821     CHECK_ARG;
822     data.err = EINVAL;
823     data.name = args[*curr_arg];
824     (*curr_arg)++;
825     data.curr_arg = curr_arg;
826     data.arg_count = arg_count;
827     data.args = args;
828     locked_list_iterate(con_type_list, con_type_check_parse, &data);
829     if (data.err) {
830 	rv = data.err;
831 	goto out_err;
832     }
833 
834     *iargs = data.iargs;
835     return 0;
836 
837  out_err:
838     return rv;
839 }
840 
841 void
ipmi_free_args(ipmi_args_t * args)842 ipmi_free_args(ipmi_args_t *args)
843 {
844     if (args->free)
845 	args->free(args);
846     ipmi_mem_free(args);
847 }
848 
849 int
ipmi_args_setup_con(ipmi_args_t * args,os_handler_t * handlers,void * user_data,ipmi_con_t ** con)850 ipmi_args_setup_con(ipmi_args_t  *args,
851 		    os_handler_t *handlers,
852 		    void         *user_data,
853 		    ipmi_con_t   **con)
854 {
855     return args->connect(args, handlers, user_data, con);
856 }
857 
858 const char *
ipmi_args_get_type(ipmi_args_t * args)859 ipmi_args_get_type(ipmi_args_t *args)
860 {
861     return args->get_type(args);
862 }
863 
864 int
ipmi_args_get_val(ipmi_args_t * args,unsigned int argnum,const char ** name,const char ** type,const char ** help,char ** value,const char *** range)865 ipmi_args_get_val(ipmi_args_t  *args,
866 		  unsigned int argnum,
867 		  const char   **name,
868 		  const char   **type,
869 		  const char   **help,
870 		  char         **value,
871 		  const char   ***range)
872 {
873     return args->get_val(args, argnum, name, type, help, value, range);
874 }
875 
876 int
ipmi_args_set_val(ipmi_args_t * args,unsigned int argnum,const char * name,const char * value)877 ipmi_args_set_val(ipmi_args_t  *args,
878 		  unsigned int argnum,
879 		  const char   *name,
880 		  const char   *value)
881 {
882     return args->set_val(args, argnum, name, value);
883 }
884 
885 void
ipmi_args_free_str(ipmi_args_t * args,char * str)886 ipmi_args_free_str(ipmi_args_t *args, char *str)
887 {
888     args->free_val(args, str);
889 }
890 
891 ipmi_args_t *
ipmi_args_copy(ipmi_args_t * args)892 ipmi_args_copy(ipmi_args_t *args)
893 {
894     return args->copy(args);
895 }
896 
897 int
ipmi_args_validate(ipmi_args_t * args,int * argnum)898 ipmi_args_validate(ipmi_args_t *args, int *argnum)
899 {
900     return args->validate(args, argnum);
901 }
902 
903 ipmi_args_t *
i_ipmi_args_alloc(ipmi_args_free_cb free,ipmi_args_connect_cb connect,ipmi_args_get_val_cb get_val,ipmi_args_set_val_cb set_val,ipmi_args_copy_cb copy,ipmi_args_validate_cb validate,ipmi_args_free_val_cb free_val,ipmi_args_get_type_cb get_type,unsigned int extra_data_len)904 i_ipmi_args_alloc(ipmi_args_free_cb     free,
905 		 ipmi_args_connect_cb  connect,
906 		 ipmi_args_get_val_cb  get_val,
907 		 ipmi_args_set_val_cb  set_val,
908 		 ipmi_args_copy_cb     copy,
909 		 ipmi_args_validate_cb validate,
910 		 ipmi_args_free_val_cb free_val,
911 		 ipmi_args_get_type_cb get_type,
912 		 unsigned int          extra_data_len)
913 {
914     ipmi_args_t *val;
915 
916     val = ipmi_mem_alloc(sizeof(*val) + extra_data_len);
917     if (!val)
918 	return NULL;
919     memset(val, 0, sizeof(*val) + extra_data_len);
920     val->free = free;
921     val->connect = connect;
922     val->get_val = get_val;
923     val->set_val = set_val;
924     val->copy = copy;
925     val->validate = validate;
926     val->free_val = free_val;
927     val->get_type = get_type;
928     return val;
929 }
930 
931 void *
i_ipmi_args_get_extra_data(ipmi_args_t * args)932 i_ipmi_args_get_extra_data(ipmi_args_t *args)
933 {
934     return ((char *) args) + sizeof(*args);
935 }
936 
937 int
i_ipmi_register_con_type(const char * name,ipmi_con_setup_t * setup)938 i_ipmi_register_con_type(const char *name, ipmi_con_setup_t *setup)
939 {
940     if (locked_list_add(con_type_list, (void *) name, setup))
941 	return 0;
942     else
943 	return ENOMEM;
944 }
945 
946 typedef struct con_type_check_remover_s
947 {
948     const char *name;
949     int        err;
950 } con_type_check_remover_t;
951 
952 static int
con_type_check_remove(void * cb_data,void * item1,void * item2)953 con_type_check_remove(void *cb_data, void *item1, void *item2)
954 {
955     con_type_check_remover_t *data = cb_data;
956 
957     if (strcmp(item1, data->name) == 0) {
958 	locked_list_remove(con_type_list, item1, item2);
959 	data->err = 0;
960 	return LOCKED_LIST_ITER_STOP;
961     }
962     return LOCKED_LIST_ITER_CONTINUE;
963 }
964 
965 int
i_ipmi_unregister_con_type(const char * name,ipmi_con_setup_t * setup)966 i_ipmi_unregister_con_type(const char *name, ipmi_con_setup_t *setup)
967 {
968     con_type_check_remover_t data;
969 
970     data.err = EINVAL;
971     data.name = name;
972     locked_list_iterate(con_type_list, con_type_check_remove, &data);
973     return data.err;
974 }
975 
976 int
ipmi_parse_options(ipmi_open_option_t * option,char * arg)977 ipmi_parse_options(ipmi_open_option_t *option,
978 		   char               *arg)
979 {
980     if (strcmp(arg, "-noall") == 0) {
981 	option->option = IPMI_OPEN_OPTION_ALL;
982 	option->ival = 0;
983     } else if (strcmp(arg, "-all") == 0) {
984 	option->option = IPMI_OPEN_OPTION_ALL;
985 	option->ival = 1;
986     } else if (strcmp(arg, "-nosdrs") == 0) {
987 	option->option = IPMI_OPEN_OPTION_SDRS;
988 	option->ival = 0;
989     } else if (strcmp(arg, "-sdrs") == 0) {
990 	option->option = IPMI_OPEN_OPTION_SDRS;
991 	option->ival = 1;
992     } else if (strcmp(arg, "-nofrus") == 0) {
993 	option->option = IPMI_OPEN_OPTION_FRUS;
994 	option->ival = 0;
995     } else if (strcmp(arg, "-frus") == 0) {
996 	option->option = IPMI_OPEN_OPTION_FRUS;
997 	option->ival = 1;
998     } else if (strcmp(arg, "-nosel") == 0) {
999 	option->option = IPMI_OPEN_OPTION_SEL;
1000 	option->ival = 0;
1001     } else if (strcmp(arg, "-sel") == 0) {
1002 	option->option = IPMI_OPEN_OPTION_SEL;
1003 	option->ival = 1;
1004     } else if (strcmp(arg, "-noipmbscan") == 0) {
1005 	option->option = IPMI_OPEN_OPTION_IPMB_SCAN;
1006 	option->ival = 0;
1007     } else if (strcmp(arg, "-ipmbscan") == 0) {
1008 	option->option = IPMI_OPEN_OPTION_IPMB_SCAN;
1009 	option->ival = 1;
1010     } else if (strcmp(arg, "-nooeminit") == 0) {
1011 	option->option = IPMI_OPEN_OPTION_OEM_INIT;
1012 	option->ival = 0;
1013     } else if (strcmp(arg, "-oeminit") == 0) {
1014 	option->option = IPMI_OPEN_OPTION_OEM_INIT;
1015 	option->ival = 1;
1016     } else if (strcmp(arg, "-noseteventrcvr") == 0) {
1017 	option->option = IPMI_OPEN_OPTION_SET_EVENT_RCVR;
1018 	option->ival = 0;
1019     } else if (strcmp(arg, "-seteventrcvr") == 0) {
1020 	option->option = IPMI_OPEN_OPTION_SET_EVENT_RCVR;
1021 	option->ival = 1;
1022     } else if (strcmp(arg, "-noactivate") == 0) {
1023 	option->option = IPMI_OPEN_OPTION_ACTIVATE_IF_POSSIBLE;
1024 	option->ival = 0;
1025     } else if (strcmp(arg, "-activate") == 0) {
1026 	option->option = IPMI_OPEN_OPTION_ACTIVATE_IF_POSSIBLE;
1027 	option->ival = 1;
1028     } else if (strcmp(arg, "-nosetseltime") == 0) {
1029 	option->option = IPMI_OPEN_OPTION_SET_SEL_TIME;
1030 	option->ival = 0;
1031     } else if (strcmp(arg, "-setseltime") == 0) {
1032 	option->option = IPMI_OPEN_OPTION_SET_SEL_TIME;
1033 	option->ival = 1;
1034     } else if (strcmp(arg, "-nolocalonly") == 0) {
1035 	option->option = IPMI_OPEN_OPTION_LOCAL_ONLY;
1036 	option->ival = 0;
1037     } else if (strcmp(arg, "-localonly") == 0) {
1038 	option->option = IPMI_OPEN_OPTION_LOCAL_ONLY;
1039 	option->ival = 1;
1040     } else if (strcmp(arg, "-nocache") == 0) {
1041 	option->option = IPMI_OPEN_OPTION_USE_CACHE;
1042 	option->ival = 0;
1043     } else if (strcmp(arg, "-cache") == 0) {
1044 	option->option = IPMI_OPEN_OPTION_USE_CACHE;
1045 	option->ival = 1;
1046     } else
1047 	return EINVAL;
1048 
1049     return 0;
1050 }
1051 
1052 const char *
ipmi_parse_options_help(void)1053 ipmi_parse_options_help(void)
1054 {
1055     return
1056 	"-[no]all - all automatic handling\n"
1057 	"-[no]sdrs - sdr fetching\n"
1058 	"-[no]frus - FRU fetching\n"
1059 	"-[no]sel - SEL fetching\n"
1060 	"-[no]ipmbscan - IPMB bus scanning\n"
1061 	"-[no]oeminit - special OEM processing (like ATCA)\n"
1062 	"-[no]seteventrcvr - setting event receivers\n"
1063 	"-[no]setseltime - setting the SEL clock\n"
1064 	"-[no]activate - connection activation\n"
1065 	"-[no]localonly - Just talk to the local BMC, (ATCA-only, for blades)\n"
1066         "-[no]cache - use the local cache for SDRs.  On by default."
1067 	"-wait_til_up - wait until the domain is up before returning";
1068 }
1069 
1070 /* This is the number of seconds between 1/1/70 (IPMI event date) and
1071    1/1/98 (ipmi SNMP trap local timestamp). */
1072 #define IPMI_SNMP_DATE_OFFSET 883612800
1073 
1074 int
ipmi_handle_snmp_trap_data(const void * src_addr,unsigned int src_addr_len,int src_addr_type,long specific,const unsigned char * data,unsigned int data_len)1075 ipmi_handle_snmp_trap_data(const void          *src_addr,
1076 			   unsigned int        src_addr_len,
1077 			   int                 src_addr_type,
1078 			   long                specific,
1079 			   const unsigned char *data,
1080 			   unsigned int        data_len)
1081 {
1082     int           handled = 0;
1083     unsigned char pet_ack[12];
1084     ipmi_msg_t    *msg = NULL;
1085 
1086     if (DEBUG_RAWMSG) {
1087 	ipmi_log(IPMI_LOG_DEBUG_START, "Got SNMP trap from:\n  ");
1088 	dump_hex(src_addr, src_addr_len);
1089 	ipmi_log(IPMI_LOG_DEBUG_CONT, "\n data is:\n  ");
1090 	dump_hex(data, data_len);
1091 	ipmi_log(IPMI_LOG_DEBUG_END, " ");
1092     }
1093 
1094     if (data_len < 46)
1095 	return 0;
1096 
1097     /* I will take this opportunity to note that the SNMP trap format
1098        from IPMI is insufficient to actually perform the job.  It does
1099        not have:
1100        1 A guaranteed way to correlate the timestamp to the SEL.
1101        2 A guaranteed way to correlate the record id to the SEL.
1102        3 The channel or the LUN for the event generator.
1103 
1104        Because of these, there is no guaranteed way to correlate the
1105        data from the SNMP trap to an SEL event.  This can result in
1106        duplicate events, which is very bad.  So we currently do not
1107        deliver the events this way, we pass a NULL in the event
1108        message to tell the domain code to rescan the SEL for this MC.
1109        In addition, item 3 above means that you cannot determine which
1110        sensor issued the event, since the channel and the LUN are
1111        required to find the sensor.
1112     */
1113 
1114  /* Until we have some way to get full valid data from the trap, we
1115     just disable it. */
1116 #if 0
1117     ipmi_msg_t     tmsg;
1118     unsigned char  edata[17];
1119     unsigned long  timestamp;
1120     int16_t        utc_off;
1121     unsigned short record_id;
1122     timestamp = ntohl(*((uint32_t *) (data+18)));
1123     if (data[27] == 0xff)
1124 	/* Can't handle unspecific event generator */
1125 	return 0;
1126     if ((data[28] == 0xff) || (data[28] == 0x00))
1127 	/* Can't handle unspecific sensor */
1128 	return 0;
1129     if (timestamp == 0)
1130 	/* Can't handle unspecified timestamp. */
1131 	return 0;
1132     utc_off = ntohs(*((uint16_t *) (data+22)));
1133     if (utc_off == -1)
1134 	/* If unspecified (0xffff), we assume zero (UTC). */
1135 	utc_off = 0;
1136     timestamp -= utc_off; /* Remove timezone offset */
1137     timestamp += IPMI_SNMP_DATE_OFFSET; /* Convert to 1/1/70 offset */
1138 
1139     /* We assume the record id is in the sequence # field, since that
1140        makes the most sense. */
1141     record_id = ntohs(*((uint16_t *) (data+16)));
1142 
1143     tmsg.netfn = IPMI_APP_NETFN;
1144     tmsg.cmd = IPMI_READ_EVENT_MSG_BUFFER_CMD;
1145     tmsg.data = edata;
1146     tmsg.data_len = 17;
1147     msg = &tmsg;
1148     edata[0] = 0;
1149     edata[1] = record_id & 0xff;
1150     edata[2] = (record_id >> 8) & 0xff;
1151     edata[3] = 2; /* record type - system event */
1152     edata[4] = timestamp & 0xff;
1153     edata[5] = (timestamp >> 8) & 0xff;
1154     edata[6] = (timestamp >> 16) & 0xff;
1155     edata[7] = (timestamp >> 24) & 0xff;
1156     edata[8] = data[27]; /* Event generator */
1157     /* FIXME - is there a way to get the LUN? */
1158     edata[9] = 0; /* Assume channel 0, lun 0 */
1159     edata[10] = 0x04; /* IPMI 1.5 revision */
1160     edata[11] = (specific >> 16) & 0xff; /* Sensor type */
1161     edata[12] = data[28]; /* Sensor number */
1162     edata[13] = (specific >> 8) & 0xff; /* Event dir/type */
1163     memcpy(edata+14, data+31, 3); /* Event data 1-3 */
1164 #endif
1165 
1166     pet_ack[0] = data[17]; /* Record id */
1167     pet_ack[1] = data[16];
1168     pet_ack[2] = data[21]; /* Timestamp */
1169     pet_ack[3] = data[20];
1170     pet_ack[4] = data[19];
1171     pet_ack[5] = data[18];
1172     pet_ack[6] = data[25]; /* Event source type */
1173     pet_ack[7] = data[27]; /* Sensor device */
1174     pet_ack[8] = data[28]; /* Sensor number */
1175     memcpy(pet_ack+9, data+31, 3); /* Event data 1-3 */
1176 
1177     if (src_addr_type == IPMI_EXTERN_ADDR_IP)
1178 	handled = ipmi_lan_handle_external_event(src_addr, msg, pet_ack);
1179 
1180     return handled;
1181 }
1182 
1183 char *
ipmi_openipmi_version(void)1184 ipmi_openipmi_version(void)
1185 {
1186     return OPENIPMI_VERSION;
1187 }
1188 
1189 ipmi_msgi_t *
ipmi_alloc_msg_item(void)1190 ipmi_alloc_msg_item(void)
1191 {
1192     ipmi_msgi_t *rv;
1193 
1194     rv = ipmi_mem_alloc(sizeof(ipmi_msgi_t));
1195     if (!rv)
1196 	return NULL;
1197     memset(rv, 0, sizeof(*rv));
1198     rv->msg.data = rv->data;
1199     return rv;
1200 }
1201 
1202 void
ipmi_free_msg_item(ipmi_msgi_t * item)1203 ipmi_free_msg_item(ipmi_msgi_t *item)
1204 {
1205     if (item->msg.data && (item->msg.data != item->data))
1206 	ipmi_free_msg_item_data(item->msg.data);
1207     ipmi_mem_free(item);
1208 }
1209 
1210 void *
ipmi_alloc_msg_item_data(unsigned int size)1211 ipmi_alloc_msg_item_data(unsigned int size)
1212 {
1213     return ipmi_mem_alloc(size);
1214 }
1215 
1216 void
ipmi_free_msg_item_data(void * data)1217 ipmi_free_msg_item_data(void *data)
1218 {
1219     ipmi_mem_free(data);
1220 }
1221 
1222 void
ipmi_move_msg_item(ipmi_msgi_t * new_item,ipmi_msgi_t * old_item)1223 ipmi_move_msg_item(ipmi_msgi_t *new_item, ipmi_msgi_t *old_item)
1224 {
1225     if (new_item->msg.data && (new_item->msg.data != new_item->data))
1226 	ipmi_free_msg_item_data(new_item->msg.data);
1227     new_item->msg = old_item->msg;
1228 
1229     if (!old_item->msg.data) {
1230 	/* Nothing to do */
1231     } else if (old_item->msg.data != old_item->data) {
1232 	/* Copied the actual data pointer. */
1233 	old_item->msg.data = NULL;
1234     } else {
1235 	memcpy(new_item->data, old_item->data, old_item->msg.data_len);
1236 	new_item->msg.data = new_item->data;
1237     }
1238 }
1239 
1240 void
ipmi_handle_rsp_item_copyall(ipmi_con_t * ipmi,ipmi_msgi_t * rspi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg,ipmi_ll_rsp_handler_t rsp_handler)1241 ipmi_handle_rsp_item_copyall(ipmi_con_t            *ipmi,
1242 			     ipmi_msgi_t           *rspi,
1243 			     const ipmi_addr_t     *addr,
1244 			     unsigned int          addr_len,
1245 			     const ipmi_msg_t      *msg,
1246 			     ipmi_ll_rsp_handler_t rsp_handler)
1247 {
1248     int used = IPMI_MSG_ITEM_NOT_USED;
1249 
1250     memcpy(&rspi->addr, addr, addr_len);
1251     rspi->addr_len = addr_len;
1252     rspi->msg = *msg;
1253     memcpy(rspi->data, msg->data, msg->data_len);
1254     rspi->msg.data = rspi->data;
1255 
1256     /* call the user handler. */
1257     if (rsp_handler)
1258 	used = rsp_handler(ipmi, rspi);
1259 
1260     if (!used)
1261 	ipmi_free_msg_item(rspi);
1262 }
1263 
1264 void
ipmi_handle_rsp_item_copymsg(ipmi_con_t * ipmi,ipmi_msgi_t * rspi,const ipmi_msg_t * msg,ipmi_ll_rsp_handler_t rsp_handler)1265 ipmi_handle_rsp_item_copymsg(ipmi_con_t            *ipmi,
1266 			     ipmi_msgi_t           *rspi,
1267 			     const ipmi_msg_t      *msg,
1268 			     ipmi_ll_rsp_handler_t rsp_handler)
1269 {
1270     int used = IPMI_MSG_ITEM_NOT_USED;
1271 
1272     rspi->msg = *msg;
1273     memcpy(rspi->data, msg->data, msg->data_len);
1274     rspi->msg.data = rspi->data;
1275 
1276     /* call the user handler. */
1277     if (rsp_handler)
1278 	used = rsp_handler(ipmi, rspi);
1279 
1280     if (!used)
1281 	ipmi_free_msg_item(rspi);
1282 }
1283 
1284 void
ipmi_handle_rsp_item(ipmi_con_t * ipmi,ipmi_msgi_t * rspi,ipmi_ll_rsp_handler_t rsp_handler)1285 ipmi_handle_rsp_item(ipmi_con_t            *ipmi,
1286 		     ipmi_msgi_t           *rspi,
1287 		     ipmi_ll_rsp_handler_t rsp_handler)
1288 {
1289     int used = IPMI_MSG_ITEM_NOT_USED;
1290 
1291     /* call the user handler. */
1292     if (rsp_handler)
1293 	used = rsp_handler(ipmi, rspi);
1294 
1295     if (!used)
1296 	ipmi_free_msg_item(rspi);
1297 }
1298 
1299 os_handler_t *
ipmi_alloc_os_handler(void)1300 ipmi_alloc_os_handler(void)
1301 {
1302     os_handler_t *rv = ipmi_mem_alloc(sizeof(*rv));
1303     if (rv)
1304 	memset(rv, 0, sizeof(*rv));
1305     return rv;
1306 }
1307 
1308 void
ipmi_free_os_handler(os_handler_t * handler)1309 ipmi_free_os_handler(os_handler_t *handler)
1310 {
1311     ipmi_mem_free(handler);
1312 }
1313 
1314