1 /*
2 * ipmi_lan.c
3 *
4 * MontaVista IPMI code for handling IPMI LAN connections
5 *
6 * Author: MontaVista Software, Inc.
7 * Corey Minyard <minyard@mvista.com>
8 * source@mvista.com
9 *
10 * Copyright 2002,2003,2004 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 <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <sys/stat.h>
40 #include <sys/poll.h>
41 #include <sys/time.h>
42 #include <fcntl.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <unistd.h>
46 #include <string.h>
47 #include <netdb.h>
48 #include <arpa/inet.h>
49
50 #include <OpenIPMI/ipmi_conn.h>
51 #include <OpenIPMI/ipmi_msgbits.h>
52 #include <OpenIPMI/ipmi_auth.h>
53 #include <OpenIPMI/ipmi_err.h>
54 #include <OpenIPMI/ipmi_lan.h>
55
56 #include <OpenIPMI/internal/ipmi_event.h>
57 #include <OpenIPMI/internal/ipmi_int.h>
58 #include <OpenIPMI/internal/locked_list.h>
59
60 #if defined(DEBUG_MSG) || defined(DEBUG_RAWMSG)
61 static void
dump_hex(void * vdata,int len)62 dump_hex(void *vdata, int len)
63 {
64 unsigned char *data = vdata;
65 int i;
66 for (i=0; i<len; i++) {
67 if ((i != 0) && ((i % 16) == 0)) {
68 ipmi_log(IPMI_LOG_DEBUG_CONT, "\n ");
69 }
70 ipmi_log(IPMI_LOG_DEBUG_CONT, " %2.2x", data[i]);
71 }
72 }
73 #endif
74
75 #define LAN_AUDIT_TIMEOUT 10000000
76
77 /* Timeout to wait for IPMI responses, in microseconds. For commands
78 with side effects, we wait 5 seconds, not one. */
79 #define LAN_RSP_TIMEOUT 1000000
80 #define LAN_RSP_TIMEOUT_SIDEEFF 5000000
81
82 /* # of times to try a message before we fail it. */
83 #define LAN_RSP_RETRIES 6
84
85 /* Number of microseconds of consecutive failures allowed on an IP
86 before it is considered failed. */
87 #define IP_FAIL_TIME 7000000
88
89 /* Number of consecutive failures that must occur before an IP is
90 considered failed. */
91 #define IP_FAIL_COUNT 4
92
93 /* The default for the maximum number of messages that are allowed to be
94 outstanding. This is a pretty conservative number. */
95 #define DEFAULT_MAX_OUTSTANDING_MSG_COUNT 2
96 #define MAX_POSSIBLE_OUTSTANDING_MSG_COUNT 63
97
98 typedef struct lan_data_s lan_data_t;
99
100 typedef struct audit_timer_info_s
101 {
102 int cancelled;
103 ipmi_con_t *ipmi;
104 } audit_timer_info_t;
105
106 typedef struct lan_timer_info_s
107 {
108 int cancelled;
109 ipmi_con_t *ipmi;
110 os_hnd_timer_id_t *timer;
111 unsigned int seq;
112 } lan_timer_info_t;
113
114 typedef struct lan_wait_queue_s
115 {
116 lan_timer_info_t *info;
117 ipmi_addr_t addr;
118 unsigned int addr_len;
119 ipmi_msg_t msg;
120 unsigned char data[IPMI_MAX_MSG_LENGTH];
121 ipmi_ll_rsp_handler_t rsp_handler;
122 ipmi_msgi_t *rsp_item;
123 int side_effects;
124
125 struct lan_wait_queue_s *next;
126 } lan_wait_queue_t;
127
128 #define MAX_IP_ADDR 2
129
130 /* We must keep this number small, if it's too big and a failure
131 occurs, we will be outside the sequence number before we switch. */
132 #define SENDS_BETWEEN_IP_SWITCHES 3
133
134 /* Because sizeof(sockaddr_in6) > sizeof(sockaddr_in), this structure
135 * is used as a replacement of struct sockaddr. */
136 typedef struct sockaddr_ip_s {
137 union
138 {
139 struct sockaddr s_addr0;
140 struct sockaddr_in s_addr4;
141 #ifdef PF_INET6
142 struct sockaddr_in6 s_addr6;
143 #endif
144 } s_ipsock;
145 socklen_t ip_addr_len;
146 } sockaddr_ip_t;
147
148 struct ipmi_rmcpp_auth_s
149 {
150 lan_data_t *lan;
151 int addr_num;
152
153 uint8_t role;
154
155 /* Filled in by the auth algorithm. */
156 unsigned char my_rand[16];
157 unsigned int my_rand_len;
158 unsigned char mgsys_rand[16];
159 unsigned int mgsys_rand_len;
160 unsigned char mgsys_guid[16];
161 unsigned int mgsys_guid_len;
162 unsigned char sik[20];
163 unsigned int sik_len;
164 unsigned char k1[20];
165 unsigned int k1_len;
166 unsigned char k2[20];
167 unsigned int k2_len;
168 };
169
170 typedef struct lan_conn_parms_s
171 {
172 unsigned int num_ip_addr;
173 char *ip_addr_str[MAX_IP_ADDR];
174 char *ip_port_str[MAX_IP_ADDR];
175 sockaddr_ip_t ip_addr[MAX_IP_ADDR];
176 unsigned int authtype;
177 unsigned int privilege;
178 unsigned char username[IPMI_USERNAME_MAX];
179 unsigned int username_len;
180 unsigned char password[IPMI_PASSWORD_MAX];
181 unsigned int password_len;
182 unsigned int conf;
183 unsigned int integ;
184 unsigned int auth;
185 unsigned int name_lookup_only;
186 unsigned char bmc_key[IPMI_PASSWORD_MAX];
187 unsigned int bmc_key_len;
188 } lan_conn_parms_t;
189
190 typedef struct lan_link_s lan_link_t;
191 struct lan_link_s
192 {
193 lan_link_t *next, *prev;
194 lan_data_t *lan;
195 };
196
197 typedef struct lan_fd_s lan_fd_t;
198
199 typedef struct lan_stat_info_s
200 {
201 #define STAT_RECV_PACKETS 0
202 #define STAT_XMIT_PACKETS 1
203 #define STAT_REXMITS 2
204 #define STAT_TIMED_OUT 3
205 #define STAT_INVALID_RMCP 4
206 #define STAT_TOO_SHORT 5
207 #define STAT_INVALID_AUTH 6
208 #define STAT_BAD_SESSION_ID 7
209 #define STAT_AUTH_FAIL 8
210 #define STAT_DUPLICATES 9
211 #define STAT_SEQ_OUT_OF_RANGE 10
212 #define STAT_ASYNC_EVENTS 11
213 #define STAT_CONN_DOWN 12
214 #define STAT_CONN_UP 13
215 #define STAT_BAD_SIZE 14
216 #define STAT_DECRYPT_FAIL 15
217 #define STAT_INVALID_PAYLOAD 16
218 #define STAT_SEQ_ERR 17
219 #define STAT_RSP_NO_CMD 18
220 #define NUM_STATS 19
221 /* Statistics */
222 void *stats[NUM_STATS];
223 } lan_stat_info_t;
224
225 static const char *lan_stat_names[NUM_STATS] =
226 {
227 "lan_recv_packets",
228 "lan_xmit_packets",
229 "lan_rexmits",
230 "lan_timed_out",
231 "lan_invalid_rmcp",
232 "lan_too_short",
233 "lan_invalid_auth",
234 "lan_bad_session_id",
235 "lan_auth_fail",
236 "lan_duplicates",
237 "lan_seq_out_of_range",
238 "lan_async_events",
239 "lan_conn_down",
240 "lan_conn_up",
241 "lan_bad_size",
242 "lan_decrypt_fail",
243 "lan_invalid_payload",
244 "lan_seq_err",
245 "lan_rsp_no_cmd"
246 };
247
248
249 /* Per-IP specific information. */
250 typedef struct lan_ip_data_s
251 {
252 int working;
253 unsigned int consecutive_failures;
254 struct timeval failure_time;
255
256 /* For both RMCP and RMCP+. For RMCP+, the session id is the one
257 I receive and the sequence numbers are the authenticated
258 ones. */
259 unsigned char working_authtype;
260 uint32_t session_id;
261 uint32_t outbound_seq_num;
262 uint32_t inbound_seq_num;
263 uint32_t recv_msg_map;
264
265 /* RMCP+ specific info */
266 uint32_t unauth_out_seq_num;
267 uint32_t unauth_in_seq_num;
268 uint32_t unauth_recv_msg_map;
269 unsigned char working_integ;
270 unsigned char working_conf;
271 uint32_t mgsys_session_id;
272 ipmi_rmcpp_auth_t ainfo;
273
274 /* Used to hold the session id before the connection is up. */
275 uint32_t precon_session_id;
276 uint32_t precon_mgsys_session_id;
277
278 ipmi_rmcpp_confidentiality_t *conf_info;
279 void *conf_data;
280
281 ipmi_rmcpp_integrity_t *integ_info;
282 void *integ_data;
283
284 /* Use for linked-lists of IP addresses. */
285 lan_link_t ip_link;
286 } lan_ip_data_t;
287
288
289 #if IPMI_MAX_MSG_LENGTH > 80
290 # define LAN_MAX_RAW_MSG IPMI_MAX_MSG_LENGTH
291 #else
292 # define LAN_MAX_RAW_MSG 80 /* Enough to hold the rmcp+ session messages */
293 #endif
294 struct lan_data_s
295 {
296 unsigned int refcount;
297 unsigned int users;
298
299 ipmi_con_t *ipmi;
300 lan_fd_t *fd;
301 int fd_slot;
302
303 unsigned char slave_addr[MAX_IPMI_USED_CHANNELS];
304 int is_active;
305 int disabled;
306
307 /* Have we already been started? */
308 int started;
309
310 /* Are we currently in cleanup? Don't allow any outgoing messages. */
311 int in_cleanup;
312
313 /* Protects modifiecations to working, curr_ip_addr, RMCP
314 sequence numbers, the con_change_handler, and other
315 connection-related data. Note that if the seq_num_lock must
316 also be held, it must be locked before this lock. */
317 ipmi_lock_t *ip_lock;
318
319 /* If 0, we don't have a connection to the BMC right now. */
320 int connected;
321
322 /* If 0, we have not yet initialized */
323 int initialized;
324
325 /* If 0, the OEM handlers have not been called. */
326 int oem_conn_handlers_called;
327
328 /* Number of packets sent on the connection. Used to track when
329 to switch between IP addresses. */
330 unsigned int num_sends;
331
332 /* The IP address we are currently using. */
333 unsigned int curr_ip_addr;
334
335 /* Data about each IP address */
336 lan_ip_data_t ip[MAX_IP_ADDR];
337
338 /* We keep a session on each LAN connection. I don't think all
339 systems require that, but it's safer. */
340
341 /* From the get channel auth */
342 unsigned char oem_iana[3];
343 unsigned char oem_aux;
344
345 /* Parms we were configured with. */
346 lan_conn_parms_t cparm;
347
348 /* IPMI LAN 1.5 specific info. */
349 unsigned char chosen_authtype;
350 unsigned char challenge_string[16];
351 ipmi_authdata_t authdata;
352
353 /* RMCP+ specific info */
354 unsigned int use_two_keys : 1;
355
356 struct {
357 unsigned int inuse : 1;
358 ipmi_addr_t addr;
359 unsigned int addr_len;
360
361 ipmi_msg_t msg;
362 unsigned char data[LAN_MAX_RAW_MSG];
363 ipmi_ll_rsp_handler_t rsp_handler;
364 ipmi_msgi_t *rsp_item;
365 int use_orig_addr;
366 ipmi_addr_t orig_addr;
367 unsigned int orig_addr_len;
368 os_hnd_timer_id_t *timer;
369 lan_timer_info_t *timer_info;
370 int retries_left;
371 int side_effects;
372
373 /* If -1, just use the normal algorithm. If not -1, force to
374 this address. */
375 int addr_num;
376
377 /* The number of the last IP address sent on. */
378 int last_ip_num;
379 } seq_table[64];
380 ipmi_lock_t *seq_num_lock;
381
382 /* The current sequence number. Note that we reserve sequence
383 number 0 for our own neferous purposes. */
384 unsigned int last_seq;
385
386 /* The number of messages that are outstanding with the remote
387 MC. */
388 unsigned int outstanding_msg_count;
389
390 /* The maximum number of outstanding messages. This must NEVER be
391 larger than 63 (64 sequence numbers minus 1 for our reserved
392 sequence zero. */
393 unsigned int max_outstanding_msg_count;
394
395 /* Address family specified at startup. */
396 unsigned int addr_family;
397
398 /* List of messages waiting to be sent. */
399 lan_wait_queue_t *wait_q, *wait_q_tail;
400
401 locked_list_t *event_handlers;
402
403 os_hnd_timer_id_t *audit_timer;
404 audit_timer_info_t *audit_info;
405
406 /* Handles connection shutdown reporting. */
407 ipmi_ll_con_closed_cb close_done;
408 void *close_cb_data;
409
410 /* This lock is used to assure that the conn changes occur in
411 proper order. The user code is called with this lock held, but
412 it should be harmless to the user as this is the only use for
413 it. But the user cannot do a wait on I/O in the handler. */
414 ipmi_lock_t *con_change_lock;
415 locked_list_t *con_change_handlers;
416
417 locked_list_t *ipmb_change_handlers;
418
419 lan_link_t link;
420
421 locked_list_t *lan_stat_list;
422 };
423
424
425 /************************************************************************
426 *
427 * Authentication and encryption information and functions.
428 *
429 ***********************************************************************/
430 extern ipmi_payload_t i_ipmi_payload;
431
432 static int
open_format_msg(ipmi_con_t * ipmi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg,unsigned char * out_data,unsigned int * out_data_len,int * out_of_session,unsigned char seq)433 open_format_msg(ipmi_con_t *ipmi,
434 const ipmi_addr_t *addr,
435 unsigned int addr_len,
436 const ipmi_msg_t *msg,
437 unsigned char *out_data,
438 unsigned int *out_data_len,
439 int *out_of_session,
440 unsigned char seq)
441 {
442 unsigned char *tmsg = out_data;
443
444 if (msg->data_len > *out_data_len)
445 return E2BIG;
446
447 memcpy(tmsg, msg->data, msg->data_len);
448 tmsg[0] = seq; /* We use the message tag for the sequence # */
449 *out_of_session = 1;
450 *out_data_len = msg->data_len;
451 return 0;
452 }
453
454 static int
open_get_recv_seq(ipmi_con_t * ipmi,unsigned char * data,unsigned int data_len,unsigned char * seq)455 open_get_recv_seq(ipmi_con_t *ipmi,
456 unsigned char *data,
457 unsigned int data_len,
458 unsigned char *seq)
459 {
460 if (data_len < 1) { /* Minimum size of an IPMI msg. */
461 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
462 ipmi_log(IPMI_LOG_DEBUG,
463 "%sDropped message because too small(7)",
464 IPMI_CONN_NAME(ipmi));
465 return EINVAL;
466 }
467 *seq = data[0];
468 return 0;
469 }
470
471 static int
open_handle_recv(ipmi_con_t * ipmi,ipmi_msgi_t * rspi,ipmi_addr_t * orig_addr,unsigned int orig_addr_len,ipmi_msg_t * orig_msg,unsigned char * data,unsigned int data_len)472 open_handle_recv(ipmi_con_t *ipmi,
473 ipmi_msgi_t *rspi,
474 ipmi_addr_t *orig_addr,
475 unsigned int orig_addr_len,
476 ipmi_msg_t *orig_msg,
477 unsigned char *data,
478 unsigned int data_len)
479 {
480 ipmi_msg_t *msg = &(rspi->msg);
481 if (data_len > sizeof(rspi->data))
482 return E2BIG;
483 memcpy(rspi->data, data, data_len);
484 msg->data = rspi->data;
485 msg->data_len = data_len;
486 return 0;
487 }
488
489 static void
open_handle_recv_async(ipmi_con_t * ipmi,unsigned char * tmsg,unsigned int data_len)490 open_handle_recv_async(ipmi_con_t *ipmi,
491 unsigned char *tmsg,
492 unsigned int data_len)
493 {
494 }
495
496 static int
open_get_msg_tag(unsigned char * tmsg,unsigned int data_len,unsigned char * tag)497 open_get_msg_tag(unsigned char *tmsg,
498 unsigned int data_len,
499 unsigned char *tag)
500 {
501 if (data_len < 8)
502 return EINVAL;
503 *tag = ipmi_get_uint32(tmsg+4) - 1; /* session id */
504 return 0;
505 }
506
507 static ipmi_payload_t open_payload =
508 { open_format_msg, open_get_recv_seq, open_handle_recv,
509 open_handle_recv_async, open_get_msg_tag };
510
511 static ipmi_payload_t *payloads[64] =
512 {
513 &i_ipmi_payload,
514 [IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_REQUEST] = &open_payload,
515 [IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_RESPONSE] = &open_payload
516 };
517
518 typedef struct payload_entry_s payload_entry_t;
519 struct payload_entry_s
520 {
521 unsigned int payload_type;
522 unsigned char iana[3];
523 unsigned int payload_id;
524 ipmi_payload_t *payload;
525
526 payload_entry_t *next;
527 };
528
529 /* Note that we only add payloads to the head, so no lock is required
530 except for addition. */
531 static ipmi_lock_t *lan_payload_lock = NULL;
532 payload_entry_t *oem_payload_list = NULL;
533
534 int
ipmi_rmcpp_register_payload(unsigned int payload_type,ipmi_payload_t * payload)535 ipmi_rmcpp_register_payload(unsigned int payload_type,
536 ipmi_payload_t *payload)
537 {
538 if ((payload_type == IPMI_RMCPP_PAYLOAD_TYPE_IPMI)
539 || (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT)
540 || (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_REQUEST)
541 || (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_RESPONSE)
542 || (payload_type >= 64)
543 || ((payload_type >= 0x20) && (payload_type <= 0x27))) /* No OEM here*/
544 {
545 return EINVAL;
546 }
547 ipmi_lock(lan_payload_lock);
548 if (payloads[payload_type] && payload) {
549 ipmi_unlock(lan_payload_lock);
550 return EAGAIN;
551 }
552
553 payloads[payload_type] = payload;
554 ipmi_unlock(lan_payload_lock);
555 return 0;
556 }
557
558 int
ipmi_rmcpp_register_oem_payload(unsigned int payload_type,unsigned char iana[3],unsigned int payload_id,ipmi_payload_t * payload)559 ipmi_rmcpp_register_oem_payload(unsigned int payload_type,
560 unsigned char iana[3],
561 unsigned int payload_id,
562 ipmi_payload_t *payload)
563 {
564 payload_entry_t *e;
565 payload_entry_t *c;
566
567 e = ipmi_mem_alloc(sizeof(*e));
568 if (!e)
569 return ENOMEM;
570 e->payload_type = payload_type;
571 memcpy(e->iana, iana, 3);
572 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT)
573 e->payload_id = payload_id;
574 else
575 e->payload_id = 0;
576 e->payload = payload;
577
578 ipmi_lock(lan_payload_lock);
579 c = oem_payload_list;
580 while (c) {
581 if ((c->payload_type == payload_type)
582 && (memcmp(c->iana, iana, 3) == 0)
583 && (c->payload_id == payload_id))
584 {
585 ipmi_unlock(lan_payload_lock);
586 ipmi_mem_free(e);
587 return EAGAIN;
588 }
589 c = c->next;
590 }
591 e->next = oem_payload_list;
592 oem_payload_list = e;
593 ipmi_unlock(lan_payload_lock);
594 return 0;
595 }
596
597 static ipmi_lock_t *lan_auth_lock = NULL;
598
599 typedef struct auth_entry_s auth_entry_t;
600 struct auth_entry_s
601 {
602 unsigned int auth_num;
603 unsigned char iana[3];
604 ipmi_rmcpp_authentication_t *auth;
605 auth_entry_t *next;
606 };
607 static auth_entry_t *oem_auth_list = NULL;
608
609 static ipmi_rmcpp_authentication_t *auths[64];
610
611 int
ipmi_rmcpp_register_authentication(unsigned int auth_num,ipmi_rmcpp_authentication_t * auth)612 ipmi_rmcpp_register_authentication(unsigned int auth_num,
613 ipmi_rmcpp_authentication_t *auth)
614 {
615 if (auth_num >= 64)
616 return EINVAL;
617 if (auths[auth_num] && auth)
618 return EAGAIN;
619
620 auths[auth_num] = auth;
621 return 0;
622 }
623
624 int
ipmi_rmcpp_register_oem_authentication(unsigned int auth_num,unsigned char iana[3],ipmi_rmcpp_authentication_t * auth)625 ipmi_rmcpp_register_oem_authentication(unsigned int auth_num,
626 unsigned char iana[3],
627 ipmi_rmcpp_authentication_t *auth)
628 {
629 auth_entry_t *e;
630 auth_entry_t *c;
631
632 e = ipmi_mem_alloc(sizeof(*e));
633 if (!e)
634 return ENOMEM;
635 e->auth_num = auth_num;
636 memcpy(e->iana, iana, 3);
637 e->auth = auth;
638
639 ipmi_lock(lan_auth_lock);
640 c = oem_auth_list;
641 while (c) {
642 if ((c->auth_num == auth_num)
643 && (memcmp(c->iana, iana, 3) == 0))
644 {
645 ipmi_unlock(lan_auth_lock);
646 ipmi_mem_free(e);
647 return EAGAIN;
648 }
649 }
650 e->next = oem_auth_list;
651 oem_auth_list = e;
652 ipmi_unlock(lan_auth_lock);
653 return 0;
654 }
655
656 typedef struct conf_entry_s conf_entry_t;
657 struct conf_entry_s
658 {
659 unsigned int conf_num;
660 unsigned char iana[3];
661 ipmi_rmcpp_confidentiality_t *conf;
662 conf_entry_t *next;
663 };
664 static conf_entry_t *oem_conf_list = NULL;
665
666 static int
conf_none_init(ipmi_con_t * ipmi,ipmi_rmcpp_auth_t * ainfo,void ** conf_data)667 conf_none_init(ipmi_con_t *ipmi, ipmi_rmcpp_auth_t *ainfo, void **conf_data)
668 {
669 *conf_data = NULL;
670 return 0;
671 }
672
673 static void
conf_none_free(ipmi_con_t * ipmi,void * conf_data)674 conf_none_free(ipmi_con_t *ipmi, void *conf_data)
675 {
676 }
677
678 static int
conf_none_encrypt(ipmi_con_t * ipmi,void * conf_data,unsigned char ** payload,unsigned int * header_len,unsigned int * payload_len,unsigned int * max_payload_len)679 conf_none_encrypt(ipmi_con_t *ipmi,
680 void *conf_data,
681 unsigned char **payload,
682 unsigned int *header_len,
683 unsigned int *payload_len,
684 unsigned int *max_payload_len)
685 {
686 return 0;
687 }
688
689 static int
conf_none_decrypt(ipmi_con_t * ipmi,void * conf_data,unsigned char ** payload,unsigned int * payload_len)690 conf_none_decrypt(ipmi_con_t *ipmi,
691 void *conf_data,
692 unsigned char **payload,
693 unsigned int *payload_len)
694 {
695 return 0;
696 }
697 static ipmi_rmcpp_confidentiality_t conf_none =
698 { conf_none_init, conf_none_free, conf_none_encrypt, conf_none_decrypt};
699
700 static ipmi_rmcpp_confidentiality_t *confs[64] =
701 {
702 &conf_none
703 };
704
ipmi_rmcpp_register_confidentiality(unsigned int conf_num,ipmi_rmcpp_confidentiality_t * conf)705 int ipmi_rmcpp_register_confidentiality(unsigned int conf_num,
706 ipmi_rmcpp_confidentiality_t *conf)
707 {
708 if ((conf_num == 0) || (conf_num >= 64))
709 return EINVAL;
710 if (confs[conf_num] && conf)
711 return EAGAIN;
712
713 confs[conf_num] = conf;
714 return 0;
715 }
716
717 int
ipmi_rmcpp_register_oem_confidentiality(unsigned int conf_num,unsigned char iana[3],ipmi_rmcpp_confidentiality_t * conf)718 ipmi_rmcpp_register_oem_confidentiality(unsigned int conf_num,
719 unsigned char iana[3],
720 ipmi_rmcpp_confidentiality_t *conf)
721 {
722 conf_entry_t *e;
723 conf_entry_t *c;
724
725 e = ipmi_mem_alloc(sizeof(*e));
726 if (!e)
727 return ENOMEM;
728 e->conf_num = conf_num;
729 memcpy(e->iana, iana, 3);
730 e->conf = conf;
731
732 ipmi_lock(lan_auth_lock);
733 c = oem_conf_list;
734 while (c) {
735 if ((c->conf_num == conf_num)
736 && (memcmp(c->iana, iana, 3) == 0))
737 {
738 ipmi_unlock(lan_auth_lock);
739 ipmi_mem_free(e);
740 return EAGAIN;
741 }
742 }
743 e->next = oem_conf_list;
744 oem_conf_list = e;
745 ipmi_unlock(lan_auth_lock);
746 return 0;
747 }
748
749 typedef struct integ_entry_s integ_entry_t;
750 struct integ_entry_s
751 {
752 unsigned int integ_num;
753 unsigned char iana[3];
754 ipmi_rmcpp_integrity_t *integ;
755 integ_entry_t *next;
756 };
757 static integ_entry_t *oem_integ_list = NULL;
758
759 static int
integ_none_init(ipmi_con_t * ipmi,ipmi_rmcpp_auth_t * ainfo,void ** integ_data)760 integ_none_init(ipmi_con_t *ipmi,
761 ipmi_rmcpp_auth_t *ainfo,
762 void **integ_data)
763 {
764 *integ_data = NULL;
765 return 0;
766 }
767
768 static void
integ_none_free(ipmi_con_t * ipmi,void * integ_data)769 integ_none_free(ipmi_con_t *ipmi,
770 void *integ_data)
771 {
772 }
773
774 static int
integ_none_pad(ipmi_con_t * ipmi,void * integ_data,unsigned char * payload,unsigned int * payload_len,unsigned int max_payload_len)775 integ_none_pad(ipmi_con_t *ipmi,
776 void *integ_data,
777 unsigned char *payload,
778 unsigned int *payload_len,
779 unsigned int max_payload_len)
780 {
781 return 0;
782 }
783
784 static int
integ_none_add(ipmi_con_t * ipmi,void * integ_data,unsigned char * payload,unsigned int * payload_len,unsigned int max_payload_len)785 integ_none_add(ipmi_con_t *ipmi,
786 void *integ_data,
787 unsigned char *payload,
788 unsigned int *payload_len,
789 unsigned int max_payload_len)
790 {
791 return 0;
792 }
793
794 static int
integ_none_check(ipmi_con_t * ipmi,void * integ_data,unsigned char * payload,unsigned int payload_len,unsigned int total_len)795 integ_none_check(ipmi_con_t *ipmi,
796 void *integ_data,
797 unsigned char *payload,
798 unsigned int payload_len,
799 unsigned int total_len)
800 {
801 return 0;
802 }
803
804 static ipmi_rmcpp_integrity_t integ_none =
805 { integ_none_init, integ_none_free, integ_none_pad, integ_none_add,
806 integ_none_check };
807
808 static ipmi_rmcpp_integrity_t *integs[64] =
809 {
810 &integ_none
811 };
812
ipmi_rmcpp_register_integrity(unsigned int integ_num,ipmi_rmcpp_integrity_t * integ)813 int ipmi_rmcpp_register_integrity(unsigned int integ_num,
814 ipmi_rmcpp_integrity_t *integ)
815 {
816 if ((integ_num == 0) || (integ_num >= 64))
817 return EINVAL;
818 if (integs[integ_num] && integ)
819 return EAGAIN;
820
821 integs[integ_num] = integ;
822 return 0;
823 }
824
825 int
ipmi_rmcpp_register_oem_integrity(unsigned int integ_num,unsigned char iana[3],ipmi_rmcpp_integrity_t * integ)826 ipmi_rmcpp_register_oem_integrity(unsigned int integ_num,
827 unsigned char iana[3],
828 ipmi_rmcpp_integrity_t *integ)
829 {
830 integ_entry_t *e;
831 integ_entry_t *c;
832
833 e = ipmi_mem_alloc(sizeof(*e));
834 if (!e)
835 return ENOMEM;
836 e->integ_num = integ_num;
837 memcpy(e->iana, iana, 3);
838 e->integ = integ;
839
840 ipmi_lock(lan_auth_lock);
841 c = oem_integ_list;
842 while (c) {
843 if ((c->integ_num == integ_num)
844 && (memcmp(c->iana, iana, 3) == 0))
845 {
846 ipmi_unlock(lan_auth_lock);
847 ipmi_mem_free(e);
848 return EAGAIN;
849 }
850 }
851 e->next = oem_integ_list;
852 oem_integ_list = e;
853 ipmi_unlock(lan_auth_lock);
854 return 0;
855 }
856
857 uint32_t
ipmi_rmcpp_auth_get_my_session_id(ipmi_rmcpp_auth_t * ainfo)858 ipmi_rmcpp_auth_get_my_session_id(ipmi_rmcpp_auth_t *ainfo)
859 {
860 return ainfo->lan->ip[ainfo->addr_num].precon_session_id;
861 }
862
863 uint32_t
ipmi_rmcpp_auth_get_mgsys_session_id(ipmi_rmcpp_auth_t * ainfo)864 ipmi_rmcpp_auth_get_mgsys_session_id(ipmi_rmcpp_auth_t *ainfo)
865 {
866 return ainfo->lan->ip[ainfo->addr_num].precon_mgsys_session_id;
867 }
868
869 uint8_t
ipmi_rmcpp_auth_get_role(ipmi_rmcpp_auth_t * ainfo)870 ipmi_rmcpp_auth_get_role(ipmi_rmcpp_auth_t *ainfo)
871 {
872 return ainfo->role;
873 }
874
875 const unsigned char *
ipmi_rmcpp_auth_get_username(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)876 ipmi_rmcpp_auth_get_username(ipmi_rmcpp_auth_t *ainfo,
877 unsigned int *max_len)
878 {
879 *max_len = 16;
880 return ainfo->lan->cparm.username;
881 }
882
883 unsigned int
ipmi_rmcpp_auth_get_username_len(ipmi_rmcpp_auth_t * ainfo)884 ipmi_rmcpp_auth_get_username_len(ipmi_rmcpp_auth_t *ainfo)
885 {
886 return ainfo->lan->cparm.username_len;
887 }
888
889 const unsigned char *
ipmi_rmcpp_auth_get_password(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)890 ipmi_rmcpp_auth_get_password(ipmi_rmcpp_auth_t *ainfo,
891 unsigned int *max_len)
892 {
893 *max_len = 20;
894 return ainfo->lan->cparm.password;
895 }
896
897 unsigned int
ipmi_rmcpp_auth_get_password_len(ipmi_rmcpp_auth_t * ainfo)898 ipmi_rmcpp_auth_get_password_len(ipmi_rmcpp_auth_t *ainfo)
899 {
900 return ainfo->lan->cparm.password_len;
901 }
902
903 int
ipmi_rmcpp_auth_get_use_two_keys(ipmi_rmcpp_auth_t * ainfo)904 ipmi_rmcpp_auth_get_use_two_keys(ipmi_rmcpp_auth_t *ainfo)
905 {
906 return ainfo->lan->use_two_keys;
907 }
908
909 const unsigned char *
ipmi_rmcpp_auth_get_bmc_key(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)910 ipmi_rmcpp_auth_get_bmc_key(ipmi_rmcpp_auth_t *ainfo,
911 unsigned int *max_len)
912 {
913 *max_len = 20;
914 if (ainfo->lan->use_two_keys)
915 return ainfo->lan->cparm.bmc_key;
916 else
917 return ainfo->lan->cparm.password;
918 }
919
920 unsigned int
ipmi_rmcpp_auth_get_bmc_key_len(ipmi_rmcpp_auth_t * ainfo)921 ipmi_rmcpp_auth_get_bmc_key_len(ipmi_rmcpp_auth_t *ainfo)
922 {
923 if (ainfo->lan->use_two_keys)
924 return ainfo->lan->cparm.bmc_key_len;
925 else
926 return ainfo->lan->cparm.password_len;
927 }
928
929 /* From the get channel auth. */
930 const unsigned char *
ipmi_rmcpp_auth_get_oem_iana(ipmi_rmcpp_auth_t * ainfo,unsigned int * len)931 ipmi_rmcpp_auth_get_oem_iana(ipmi_rmcpp_auth_t *ainfo,
932 unsigned int *len)
933 {
934 *len = 3;
935 return ainfo->lan->oem_iana;
936 }
937
938 unsigned char
ipmi_rmcpp_auth_get_oem_aux(ipmi_rmcpp_auth_t * ainfo)939 ipmi_rmcpp_auth_get_oem_aux(ipmi_rmcpp_auth_t *ainfo)
940 {
941 return ainfo->lan->oem_aux;
942 }
943
944 /* Should be filled in by the auth algorithm. */
945 unsigned char *
ipmi_rmcpp_auth_get_my_rand(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)946 ipmi_rmcpp_auth_get_my_rand(ipmi_rmcpp_auth_t *ainfo,
947 unsigned int *max_len)
948 {
949 *max_len = 16;
950 return ainfo->my_rand;
951 }
952
953 unsigned int
ipmi_rmcpp_auth_get_my_rand_len(ipmi_rmcpp_auth_t * ainfo)954 ipmi_rmcpp_auth_get_my_rand_len(ipmi_rmcpp_auth_t *ainfo)
955 {
956 return ainfo->my_rand_len;
957 }
958
959 void
ipmi_rmcpp_auth_set_my_rand_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)960 ipmi_rmcpp_auth_set_my_rand_len(ipmi_rmcpp_auth_t *ainfo,
961 unsigned int length)
962 {
963 ainfo->my_rand_len = length;
964 }
965
966 unsigned char *
ipmi_rmcpp_auth_get_mgsys_rand(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)967 ipmi_rmcpp_auth_get_mgsys_rand(ipmi_rmcpp_auth_t *ainfo,
968 unsigned int *max_len)
969 {
970 *max_len = 16;
971 return ainfo->mgsys_rand;
972 }
973
974 unsigned int
ipmi_rmcpp_auth_get_mgsys_rand_len(ipmi_rmcpp_auth_t * ainfo)975 ipmi_rmcpp_auth_get_mgsys_rand_len(ipmi_rmcpp_auth_t *ainfo)
976 {
977 return ainfo->mgsys_rand_len;
978 }
979
980 void
ipmi_rmcpp_auth_set_mgsys_rand_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)981 ipmi_rmcpp_auth_set_mgsys_rand_len(ipmi_rmcpp_auth_t *ainfo,
982 unsigned int length)
983 {
984 ainfo->mgsys_rand_len = length;
985 }
986
987 unsigned char *
ipmi_rmcpp_auth_get_mgsys_guid(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)988 ipmi_rmcpp_auth_get_mgsys_guid(ipmi_rmcpp_auth_t *ainfo,
989 unsigned int *max_len)
990 {
991 *max_len = 16;
992 return ainfo->mgsys_guid;
993 }
994
995 unsigned int
ipmi_rmcpp_auth_get_mgsys_guid_len(ipmi_rmcpp_auth_t * ainfo)996 ipmi_rmcpp_auth_get_mgsys_guid_len(ipmi_rmcpp_auth_t *ainfo)
997 {
998 return ainfo->mgsys_guid_len;
999 }
1000
1001 void
ipmi_rmcpp_auth_set_mgsys_guid_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)1002 ipmi_rmcpp_auth_set_mgsys_guid_len(ipmi_rmcpp_auth_t *ainfo,
1003 unsigned int length)
1004 {
1005 ainfo->mgsys_guid_len = length;
1006 }
1007
1008 unsigned char *
ipmi_rmcpp_auth_get_sik(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)1009 ipmi_rmcpp_auth_get_sik(ipmi_rmcpp_auth_t *ainfo,
1010 unsigned int *max_len)
1011 {
1012 *max_len = 20;
1013 return ainfo->sik;
1014 }
1015
1016 unsigned int
ipmi_rmcpp_auth_get_sik_len(ipmi_rmcpp_auth_t * ainfo)1017 ipmi_rmcpp_auth_get_sik_len(ipmi_rmcpp_auth_t *ainfo)
1018 {
1019 return ainfo->sik_len;
1020 }
1021
1022 void
ipmi_rmcpp_auth_set_sik_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)1023 ipmi_rmcpp_auth_set_sik_len(ipmi_rmcpp_auth_t *ainfo,
1024 unsigned int length)
1025 {
1026 ainfo->sik_len = length;
1027 }
1028
1029 unsigned char *
ipmi_rmcpp_auth_get_k1(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)1030 ipmi_rmcpp_auth_get_k1(ipmi_rmcpp_auth_t *ainfo,
1031 unsigned int *max_len)
1032 {
1033 *max_len = 20;
1034 return ainfo->k1;
1035 }
1036
1037 unsigned int
ipmi_rmcpp_auth_get_k1_len(ipmi_rmcpp_auth_t * ainfo)1038 ipmi_rmcpp_auth_get_k1_len(ipmi_rmcpp_auth_t *ainfo)
1039 {
1040 return ainfo->k1_len;
1041 }
1042
1043 void
ipmi_rmcpp_auth_set_k1_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)1044 ipmi_rmcpp_auth_set_k1_len(ipmi_rmcpp_auth_t *ainfo,
1045 unsigned int length)
1046 {
1047 ainfo->k1_len = length;
1048 }
1049
1050 unsigned char *
ipmi_rmcpp_auth_get_k2(ipmi_rmcpp_auth_t * ainfo,unsigned int * max_len)1051 ipmi_rmcpp_auth_get_k2(ipmi_rmcpp_auth_t *ainfo,
1052 unsigned int *max_len)
1053 {
1054 *max_len = 20;
1055 return ainfo->k2;
1056 }
1057
1058 unsigned int
ipmi_rmcpp_auth_get_k2_len(ipmi_rmcpp_auth_t * ainfo)1059 ipmi_rmcpp_auth_get_k2_len(ipmi_rmcpp_auth_t *ainfo)
1060 {
1061 return ainfo->k2_len;
1062 }
1063
1064 void
ipmi_rmcpp_auth_set_k2_len(ipmi_rmcpp_auth_t * ainfo,unsigned int length)1065 ipmi_rmcpp_auth_set_k2_len(ipmi_rmcpp_auth_t *ainfo,
1066 unsigned int length)
1067 {
1068 ainfo->k2_len = length;
1069 }
1070
1071
1072 static void check_command_queue(ipmi_con_t *ipmi, lan_data_t *lan);
1073 static int send_auth_cap(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
1074 int force_ipmiv15);
1075
1076 static os_handler_t *lan_os_hnd;
1077
1078 #define MAX_CONS_PER_FD 32
1079 struct lan_fd_s
1080 {
1081 int fd;
1082 os_hnd_fd_id_t *fd_wait_id;
1083 unsigned int cons_in_use;
1084 lan_data_t *lan[MAX_CONS_PER_FD];
1085 lan_fd_t *next, *prev;
1086 ipmi_lock_t *con_lock;
1087
1088 /* Main list info. */
1089 ipmi_lock_t *lock;
1090 lan_fd_t **free_list;
1091 lan_fd_t *list;
1092 };
1093
1094 /* This is a list, but the only searching is to find an fd with a free
1095 slot (when creating a new lan). This is O(1) because the first
1096 entry is guaranteed to have a free slot if any have free slots.
1097 Note that once one of these is created, it is never destroyed
1098 (destruction is very difficult because of the race conditions). */
1099 static ipmi_lock_t *fd_list_lock = NULL;
1100 static lan_fd_t fd_list;
1101 static lan_fd_t *fd_free_list;
1102 #ifdef PF_INET6
1103 static ipmi_lock_t *fd6_list_lock = NULL;
1104 static lan_fd_t fd6_list;
1105 static lan_fd_t *fd6_free_list;
1106 #endif
1107
1108 static void data_handler(int fd,
1109 void *cb_data,
1110 os_hnd_fd_id_t *id);
1111
1112 static int
lan_addr_same(sockaddr_ip_t * a1,sockaddr_ip_t * a2)1113 lan_addr_same(sockaddr_ip_t *a1, sockaddr_ip_t *a2)
1114 {
1115 if (a1->ip_addr_len != a2->ip_addr_len)
1116 return 0;
1117
1118 if (a1->s_ipsock.s_addr0.sa_family != a2->s_ipsock.s_addr0.sa_family) {
1119 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
1120 ipmi_log(IPMI_LOG_DEBUG, "Address family mismatch: %d %d",
1121 a1->s_ipsock.s_addr0.sa_family,
1122 a2->s_ipsock.s_addr0.sa_family);
1123 return 0;
1124 }
1125
1126 switch (a1->s_ipsock.s_addr0.sa_family) {
1127 case PF_INET:
1128 {
1129 struct sockaddr_in *ip1 = &a1->s_ipsock.s_addr4;
1130 struct sockaddr_in *ip2 = &a2->s_ipsock.s_addr4;
1131
1132 if ((ip1->sin_port == ip2->sin_port)
1133 && (ip1->sin_addr.s_addr == ip2->sin_addr.s_addr))
1134 return 1;
1135 }
1136 break;
1137
1138 #ifdef PF_INET6
1139 case PF_INET6:
1140 {
1141 struct sockaddr_in6 *ip1 = &a1->s_ipsock.s_addr6;
1142 struct sockaddr_in6 *ip2 = &a2->s_ipsock.s_addr6;
1143 if ((ip1->sin6_port == ip2->sin6_port)
1144 && (memcmp(ip1->sin6_addr.s6_addr, ip2->sin6_addr.s6_addr,
1145 sizeof(struct in6_addr)) == 0))
1146 return 1;
1147 }
1148 break;
1149 #endif
1150 default:
1151 ipmi_log(IPMI_LOG_ERR_INFO,
1152 "ipmi_lan: Unknown protocol family: 0x%x",
1153 a1->s_ipsock.s_addr0.sa_family);
1154 break;
1155 }
1156
1157 return 0;
1158 }
1159
1160 static void
move_to_lan_list_end(lan_fd_t * item)1161 move_to_lan_list_end(lan_fd_t *item)
1162 {
1163 lan_fd_t *list = item->list;
1164
1165 item->next->prev = item->prev;
1166 item->prev->next = item->next;
1167 item->next = list;
1168 item->prev = list->prev;
1169 list->prev->next = item;
1170 list->prev = item;
1171 }
1172
1173 static void
move_to_lan_list_head(lan_fd_t * item)1174 move_to_lan_list_head(lan_fd_t *item)
1175 {
1176 lan_fd_t *list = item->list;
1177
1178 item->next->prev = item->prev;
1179 item->prev->next = item->next;
1180 item->next = list->next;
1181 item->prev = list;
1182 list->next->prev = item;
1183 list->next = item;
1184 }
1185
1186 static lan_fd_t *
find_free_lan_fd(int family,lan_data_t * lan,int * slot)1187 find_free_lan_fd(int family, lan_data_t *lan, int *slot)
1188 {
1189 ipmi_lock_t *lock;
1190 lan_fd_t *list, *item;
1191 lan_fd_t **free_list;
1192 int rv;
1193 int i;
1194
1195 if (family == PF_INET) {
1196 lock = fd_list_lock;
1197 list = &fd_list;
1198 free_list = &fd_free_list;
1199 }
1200 #ifdef PF_INET6
1201 else if (family == PF_INET6) {
1202 lock = fd6_list_lock;
1203 list = &fd6_list;
1204 free_list = &fd6_free_list;
1205 }
1206 #endif
1207 else {
1208 return NULL;
1209 }
1210
1211 ipmi_lock(lock);
1212 item = list->next;
1213 retry:
1214 if (item->cons_in_use < MAX_CONS_PER_FD) {
1215 int tslot = -1;
1216 /* Got an entry with a slot, just reuse it. */
1217 for (i=0; i<MAX_CONS_PER_FD; i++) {
1218 if (item->lan[i]) {
1219 /* Check for a matching IP address. Can't have two
1220 systems with the same address in the same fd entry. */
1221 unsigned int j, k;
1222 lan_data_t *l = item->lan[i];
1223
1224 for (j=0; j<l->cparm.num_ip_addr; j++) {
1225 for (k=0; k<lan->cparm.num_ip_addr; k++) {
1226 if (lan_addr_same(&l->cparm.ip_addr[j],
1227 &lan->cparm.ip_addr[k]))
1228 {
1229 /* Found the same address in the same
1230 lan_data file. Try another one. */
1231 item = item->next;
1232 goto retry;
1233 }
1234 }
1235 }
1236 } else if (tslot < 0)
1237 tslot = i;
1238 }
1239 if (tslot < 0) {
1240 lan_fd_t *next = item->next;
1241 /* Can't happen, but log and fix it up. */
1242 ipmi_log(IPMI_LOG_SEVERE, "ipmi_lan.c: Internal error, count"
1243 " in lan fd list item incorrect, but we can recover.");
1244 item->cons_in_use = MAX_CONS_PER_FD;
1245 move_to_lan_list_end(item);
1246 item = next;
1247 goto retry;
1248 }
1249 item->cons_in_use++;
1250 item->lan[tslot] = lan;
1251 *slot = tslot;
1252
1253 if (item->cons_in_use == MAX_CONS_PER_FD)
1254 /* Out of connections in this item, move it to the end of
1255 the list. */
1256 move_to_lan_list_end(item);
1257 } else {
1258 /* No free entries, create one */
1259 if (*free_list) {
1260 /* Pull them off the free list first. */
1261 item = *free_list;
1262 *free_list = item->next;
1263 } else {
1264 item = ipmi_mem_alloc(sizeof(*item));
1265 if (item) {
1266 memset(item, 0, sizeof(*item));
1267 rv = ipmi_create_global_lock(&item->con_lock);
1268 if (rv) {
1269 ipmi_mem_free(item);
1270 goto out_unlock;
1271 }
1272 item->lock = lock;
1273 item->free_list = free_list;
1274 item->list = list;
1275 }
1276 }
1277 if (!item)
1278 goto out_unlock;
1279
1280 item->next = item;
1281 item->prev = item;
1282
1283 item->fd = socket(family, SOCK_DGRAM, IPPROTO_UDP);
1284 if (item->fd == -1) {
1285 item->next = *free_list;
1286 *free_list = item;
1287 item = NULL;
1288 goto out_unlock;
1289 }
1290
1291 /* Bind is not necessary, we don't care what port we are. */
1292
1293 /* We want it to be non-blocking. */
1294 rv = fcntl(item->fd, F_SETFL, O_NONBLOCK);
1295 if (rv) {
1296 close(item->fd);
1297 item->next = *free_list;
1298 *free_list = item;
1299 item = NULL;
1300 goto out_unlock;
1301 }
1302
1303 rv = lan_os_hnd->add_fd_to_wait_for(lan_os_hnd,
1304 item->fd,
1305 data_handler,
1306 item,
1307 NULL,
1308 &(item->fd_wait_id));
1309 if (rv) {
1310 close(item->fd);
1311 item->next = *free_list;
1312 *free_list = item;
1313 item = NULL;
1314 goto out_unlock;
1315 }
1316
1317 item->cons_in_use++;
1318 item->lan[0] = lan;
1319 *slot = 0;
1320
1321 /* This will have free items, put it at the head of the list. */
1322 move_to_lan_list_head(item);
1323 }
1324 out_unlock:
1325 ipmi_unlock(lock);
1326 return item;
1327 }
1328
1329 static void
release_lan_fd(lan_fd_t * item,int slot)1330 release_lan_fd(lan_fd_t *item, int slot)
1331 {
1332 ipmi_lock(item->lock);
1333 item->lan[slot] = NULL;
1334 item->cons_in_use--;
1335 if (item->cons_in_use == 0) {
1336 lan_os_hnd->remove_fd_to_wait_for(lan_os_hnd, item->fd_wait_id);
1337 close(item->fd);
1338 item->next->prev = item->prev;
1339 item->prev->next = item->next;
1340 item->next = *(item->free_list);
1341 *(item->free_list) = item;
1342 } else {
1343 /* This has free connections, move it to the head of the
1344 list. */
1345 move_to_lan_list_head(item);
1346 }
1347 ipmi_unlock(item->lock);
1348 }
1349
1350 /*
1351 * We keep two hash tables, one by IP address and one by connection
1352 * address.
1353 */
1354 #define LAN_HASH_SIZE 256
1355 #define LAN_HASH_SHIFT 6
1356 static ipmi_lock_t *lan_list_lock = NULL;
1357 static lan_link_t lan_list[LAN_HASH_SIZE];
1358 static lan_link_t lan_ip_list[LAN_HASH_SIZE];
1359
1360 static unsigned int
hash_lan(const ipmi_con_t * ipmi)1361 hash_lan(const ipmi_con_t *ipmi)
1362 {
1363 unsigned int idx;
1364
1365 idx = (((unsigned long) ipmi)
1366 >> (sizeof(unsigned long) + LAN_HASH_SHIFT));
1367 idx %= LAN_HASH_SIZE;
1368 return idx;
1369 }
1370
1371 static unsigned int
hash_lan_addr(const struct sockaddr * addr)1372 hash_lan_addr(const struct sockaddr *addr)
1373 {
1374 unsigned int idx;
1375 switch (addr->sa_family)
1376 {
1377 case PF_INET:
1378 {
1379 struct sockaddr_in *iaddr = (struct sockaddr_in *) addr;
1380 idx = ntohl(iaddr->sin_addr.s_addr) % LAN_HASH_SIZE;
1381 break;
1382 }
1383 #ifdef PF_INET6
1384 case PF_INET6:
1385 {
1386 /* Use the lower 4 bytes of the IPV6 address. */
1387 struct sockaddr_in6 *iaddr = (struct sockaddr_in6 *) addr;
1388 idx = iaddr->sin6_addr.s6_addr[12];
1389 idx |= iaddr->sin6_addr.s6_addr[13] << 8;
1390 idx |= iaddr->sin6_addr.s6_addr[14] << 16;
1391 idx |= iaddr->sin6_addr.s6_addr[15] << 24;
1392 break;
1393 }
1394 #endif
1395 default:
1396 idx = 0;
1397 }
1398 idx %= LAN_HASH_SIZE;
1399 return idx;
1400 }
1401
1402 static void
lan_add_con(lan_data_t * lan)1403 lan_add_con(lan_data_t *lan)
1404 {
1405 unsigned int idx;
1406 lan_link_t *head;
1407 unsigned int i;
1408
1409 ipmi_lock(lan_list_lock);
1410 idx = hash_lan(lan->ipmi);
1411 head = &lan_list[idx];
1412 lan->link.lan = lan;
1413 lan->link.next = head;
1414 lan->link.prev = head->prev;
1415 head->prev->next = &lan->link;
1416 head->prev = &lan->link;
1417
1418 for (i=0; i<lan->cparm.num_ip_addr; i++) {
1419 struct sockaddr *addr = &lan->cparm.ip_addr[i].s_ipsock.s_addr0;
1420
1421 idx = hash_lan_addr(addr);
1422
1423 head = &lan_ip_list[idx];
1424 lan->ip[i].ip_link.lan = lan;
1425 lan->ip[i].ip_link.next = head;
1426 lan->ip[i].ip_link.prev = head->prev;
1427 head->prev->next = &lan->ip[i].ip_link;
1428 head->prev = &lan->ip[i].ip_link;
1429 }
1430 ipmi_unlock(lan_list_lock);
1431 }
1432
1433 /* Must be called with the lan list lock held. */
1434 static void
lan_remove_con_nolock(lan_data_t * lan)1435 lan_remove_con_nolock(lan_data_t *lan)
1436 {
1437 unsigned int i;
1438 if (!lan->link.lan)
1439 /* Hasn't been initialized. */
1440 return;
1441 lan->link.prev->next = lan->link.next;
1442 lan->link.next->prev = lan->link.prev;
1443 lan->link.lan = NULL;
1444 for (i=0; i<lan->cparm.num_ip_addr; i++) {
1445 lan->ip[i].ip_link.prev->next = lan->ip[i].ip_link.next;
1446 lan->ip[i].ip_link.next->prev = lan->ip[i].ip_link.prev;
1447 lan->ip[i].ip_link.lan = NULL;
1448 }
1449 }
1450
1451 static lan_data_t *
lan_find_con(ipmi_con_t * ipmi)1452 lan_find_con(ipmi_con_t *ipmi)
1453 {
1454 unsigned int idx;
1455 lan_link_t *l;
1456
1457 ipmi_lock(lan_list_lock);
1458 idx = hash_lan(ipmi);
1459 l = lan_list[idx].next;
1460 while (l->lan) {
1461 if (l->lan->ipmi == ipmi)
1462 break;
1463 l = l->next;
1464 }
1465 if (l->lan)
1466 l->lan->refcount++;
1467 ipmi_unlock(lan_list_lock);
1468
1469 return l->lan;
1470 }
1471
1472 static inline int
cmp_timeval(struct timeval * tv1,struct timeval * tv2)1473 cmp_timeval(struct timeval *tv1, struct timeval *tv2)
1474 {
1475 if (tv1->tv_sec < tv2->tv_sec)
1476 return -1;
1477
1478 if (tv1->tv_sec > tv2->tv_sec)
1479 return 1;
1480
1481 if (tv1->tv_usec < tv2->tv_usec)
1482 return -1;
1483
1484 if (tv1->tv_usec > tv2->tv_usec)
1485 return 1;
1486
1487 return 0;
1488 }
1489
1490 typedef struct lan_add_stat_info_s
1491 {
1492 int statnum;
1493 int count;
1494 } lan_add_stat_info_t;
1495
1496 int
add_stat_cb(void * cb_data,void * item1,void * item2)1497 add_stat_cb(void *cb_data, void *item1, void *item2)
1498 {
1499 ipmi_ll_stat_info_t *info = item2;
1500 lan_stat_info_t *stat = item1;
1501 lan_add_stat_info_t *sinfo = cb_data;
1502
1503 if (stat->stats[sinfo->statnum])
1504 ipmi_ll_con_stat_call_adder(info, stat->stats[sinfo->statnum],
1505 sinfo->count);
1506 return LOCKED_LIST_ITER_CONTINUE;
1507 }
1508
1509 static inline void
add_stat(ipmi_con_t * ipmi,int stat,int count)1510 add_stat(ipmi_con_t *ipmi, int stat, int count)
1511 {
1512 lan_data_t *lan = ipmi->con_data;
1513 lan_add_stat_info_t sinfo;
1514
1515 sinfo.statnum = stat;
1516 sinfo.count = count;
1517 locked_list_iterate(lan->lan_stat_list, add_stat_cb, &sinfo);
1518 }
1519
1520 /* Must be called with the ipmi read or write lock. */
lan_valid_ipmi(ipmi_con_t * ipmi)1521 static int lan_valid_ipmi(ipmi_con_t *ipmi)
1522 {
1523 return (lan_find_con(ipmi) != NULL);
1524 }
1525
1526 static void lan_cleanup(ipmi_con_t *ipmi);
1527
1528 static void
lan_put(ipmi_con_t * ipmi)1529 lan_put(ipmi_con_t *ipmi)
1530 {
1531 lan_data_t *lan = ipmi->con_data;
1532 int done;
1533
1534 ipmi_lock(lan_list_lock);
1535 lan->refcount--;
1536 done = lan->refcount == 0;
1537
1538 /* If done, remove it before we release the lock. */
1539 if (done)
1540 lan_remove_con_nolock(lan);
1541 ipmi_unlock(lan_list_lock);
1542
1543 if (done)
1544 lan_cleanup(ipmi);
1545 }
1546
1547 static int
auth_gen(lan_data_t * lan,unsigned char * out,uint8_t * ses_id,uint8_t * seq,unsigned char * data,unsigned int data_len,int addr_num)1548 auth_gen(lan_data_t *lan,
1549 unsigned char *out,
1550 uint8_t *ses_id,
1551 uint8_t *seq,
1552 unsigned char *data,
1553 unsigned int data_len,
1554 int addr_num)
1555 {
1556 int rv;
1557 ipmi_auth_sg_t l[] =
1558 { { ses_id, 4 },
1559 { data, data_len },
1560 { seq, 4 },
1561 { NULL, 0 }};
1562
1563 rv = ipmi_auths[lan->ip[addr_num].working_authtype]
1564 .authcode_gen(lan->authdata, l, out);
1565 return rv;
1566 }
1567
1568 static int
auth_check(lan_data_t * lan,uint8_t * ses_id,uint8_t * seq,unsigned char * data,unsigned int data_len,unsigned char * code,int addr_num)1569 auth_check(lan_data_t *lan,
1570 uint8_t *ses_id,
1571 uint8_t *seq,
1572 unsigned char *data,
1573 unsigned int data_len,
1574 unsigned char *code,
1575 int addr_num)
1576 {
1577 int rv;
1578 ipmi_auth_sg_t l[] =
1579 { { ses_id, 4 },
1580 { data, data_len },
1581 { seq, 4 },
1582 { NULL, 0 }};
1583
1584 rv = ipmi_auths[lan->ip[addr_num].working_authtype]
1585 .authcode_check(lan->authdata, l, code);
1586 return rv;
1587 }
1588
1589 #define IPMI_MAX_LAN_LEN (IPMI_MAX_MSG_LENGTH + 128)
1590 #define IPMI_LAN_MAX_HEADER 128
1591
1592 static int
rmcpp_format_msg(lan_data_t * lan,int addr_num,unsigned int payload_type,int in_session,unsigned char ** msgdata,unsigned int * data_len,unsigned int max_data_len,unsigned int header_len,unsigned char * oem_iana,unsigned int oem_payload_id,const ipmi_con_option_t * options)1593 rmcpp_format_msg(lan_data_t *lan, int addr_num,
1594 unsigned int payload_type, int in_session,
1595 unsigned char **msgdata, unsigned int *data_len,
1596 unsigned int max_data_len, unsigned int header_len,
1597 unsigned char *oem_iana, unsigned int oem_payload_id,
1598 const ipmi_con_option_t *options)
1599 {
1600 unsigned char *tmsg;
1601 int rv;
1602 unsigned int header_used;
1603 unsigned char *data;
1604 unsigned int payload_len;
1605 uint32_t *seqp;
1606 int do_auth = 1;
1607 int do_conf = 1;
1608
1609 if (options) {
1610 while (options->option != IPMI_CON_OPTION_LIST_END) {
1611 switch (options->option) {
1612 case IPMI_CON_MSG_OPTION_AUTH:
1613 do_auth = options->ival;
1614 break;
1615
1616 case IPMI_CON_MSG_OPTION_CONF:
1617 do_conf = options->ival;
1618 break;
1619
1620 default:
1621 /* Ignore unknown options. */
1622 break;
1623 }
1624 options++;
1625 }
1626 }
1627
1628 do_conf = (do_conf && in_session
1629 && (lan->ip[addr_num].working_conf
1630 != IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE));
1631 do_auth = (do_auth && in_session
1632 && (lan->ip[addr_num].working_integ
1633 != IPMI_LANP_INTEGRITY_ALGORITHM_NONE));
1634
1635 if (do_conf) {
1636 #if 0
1637 if (! lan->ip[addr_num].working)
1638 return EAGAIN;
1639 #endif
1640
1641 /* Note: This may encrypt the data, the old data will be lost. */
1642 rv = lan->ip[addr_num].conf_info->conf_encrypt
1643 (lan->ipmi,
1644 lan->ip[addr_num].conf_data,
1645 msgdata,
1646 &header_len, data_len,
1647 &max_data_len);
1648 if (rv)
1649 return rv;
1650 }
1651
1652 payload_len = *data_len;
1653
1654 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT)
1655 header_used = 22;
1656 else
1657 header_used = 16;
1658
1659 if (header_used > header_len)
1660 return E2BIG;
1661
1662 data = *msgdata - header_used;
1663 *data_len += header_used;
1664 max_data_len += header_used;
1665
1666 data[0] = 6; /* RMCP version 1.0. */
1667 data[1] = 0;
1668 data[2] = 0xff;
1669 data[3] = 0x07;
1670 data[4] = lan->ip[addr_num].working_authtype;
1671 data[5] = payload_type;
1672 tmsg = data+6;
1673 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT) {
1674 memcpy(tmsg, oem_iana, 3);
1675 tmsg += 3;
1676 *tmsg = 0;
1677 tmsg++;
1678 ipmi_set_uint16(tmsg, oem_payload_id);
1679 tmsg += 2;
1680 }
1681 if (in_session) {
1682 if (do_conf)
1683 data[5] |= 0x80;
1684 if (do_auth) {
1685 seqp = &(lan->ip[addr_num].outbound_seq_num);
1686 data[5] |= 0x40;
1687 } else {
1688 seqp = &(lan->ip[addr_num].unauth_out_seq_num);
1689 }
1690 ipmi_set_uint32(tmsg, lan->ip[addr_num].mgsys_session_id);
1691 tmsg += 4;
1692 ipmi_set_uint32(tmsg, *seqp);
1693 tmsg += 4;
1694 } else {
1695 ipmi_set_uint32(tmsg, 0); /* session id */
1696 tmsg += 4;
1697 ipmi_set_uint32(tmsg, 0); /* session sequence number */
1698 tmsg += 4;
1699 seqp = NULL;
1700 }
1701
1702 /* Payload length doesn't include the padding. */
1703 ipmi_set_uint16(tmsg, payload_len);
1704
1705 if (do_auth) {
1706 rv = lan->ip[addr_num].integ_info->integ_pad
1707 (lan->ipmi,
1708 lan->ip[addr_num].integ_data,
1709 data, data_len,
1710 max_data_len);
1711 if (rv)
1712 return rv;
1713
1714 rv = lan->ip[addr_num].integ_info->integ_add
1715 (lan->ipmi,
1716 lan->ip[addr_num].integ_data,
1717 data, data_len,
1718 max_data_len);
1719 if (rv)
1720 return rv;
1721 }
1722
1723 if (seqp) {
1724 (*seqp)++;
1725 if (*seqp == 0)
1726 *seqp = 1;
1727 }
1728
1729 *msgdata = data;
1730
1731 return 0;
1732 }
1733
1734 static int
lan15_format_msg(lan_data_t * lan,int addr_num,unsigned char ** msgdata,unsigned int * data_len)1735 lan15_format_msg(lan_data_t *lan, int addr_num,
1736 unsigned char **msgdata, unsigned int *data_len)
1737 {
1738 unsigned char *data;
1739 int rv;
1740
1741 if (lan->ip[addr_num].working_authtype == IPMI_AUTHTYPE_NONE)
1742 data = *msgdata - 14;
1743 else
1744 data = *msgdata - 30;
1745
1746 data[0] = 6; /* RMCP version 1.0. */
1747 data[1] = 0;
1748 data[2] = 0xff;
1749 data[3] = 0x07;
1750 data[4] = lan->ip[addr_num].working_authtype;
1751 ipmi_set_uint32(data+5, lan->ip[addr_num].outbound_seq_num);
1752 ipmi_set_uint32(data+9, lan->ip[addr_num].session_id);
1753
1754 /* FIXME - need locks for the sequence numbers. */
1755
1756 /* Increment the outbound number, but make sure it's not zero. If
1757 it's already zero, ignore it, we are in pre-setup. */
1758 if (lan->ip[addr_num].outbound_seq_num != 0) {
1759 (lan->ip[addr_num].outbound_seq_num)++;
1760 if (lan->ip[addr_num].outbound_seq_num == 0)
1761 (lan->ip[addr_num].outbound_seq_num)++;
1762 }
1763
1764 if (lan->ip[addr_num].working_authtype == IPMI_AUTHTYPE_NONE) {
1765 /* No authentication, so no authcode. */
1766 data[13] = *data_len;
1767 *data_len += 14;
1768 } else {
1769 data[29] = *data_len;
1770 rv = auth_gen(lan, data+13, data+9, data+5, *msgdata, *data_len,
1771 addr_num);
1772 if (rv)
1773 return rv;
1774 *data_len += 30;
1775 }
1776 *msgdata = data;
1777
1778 return 0;
1779 }
1780
1781 static int
lan_send_addr(lan_data_t * lan,const ipmi_addr_t * addr,int addr_len,const ipmi_msg_t * msg,uint8_t seq,int addr_num,const ipmi_con_option_t * options)1782 lan_send_addr(lan_data_t *lan,
1783 const ipmi_addr_t *addr,
1784 int addr_len,
1785 const ipmi_msg_t *msg,
1786 uint8_t seq,
1787 int addr_num,
1788 const ipmi_con_option_t *options)
1789 {
1790 unsigned char data[IPMI_MAX_LAN_LEN+IPMI_LAN_MAX_HEADER];
1791 unsigned char *tmsg;
1792 unsigned int pos;
1793 int rv;
1794 unsigned int payload_type;
1795 int out_of_session = 0;
1796 ipmi_payload_t *payload = NULL;
1797 unsigned char oem_iana[3] = {0, 0, 0};
1798 unsigned int oem_payload_id = 0;
1799
1800 if ((addr->addr_type >= IPMI_RMCPP_ADDR_START)
1801 && (addr->addr_type <= IPMI_RMCPP_ADDR_END))
1802 {
1803 /*
1804 * Let through the dodgy IPMI 1.5 Serial-over-LAN packets, but block
1805 * anything else that tries to send an RMCP+ packet to a non-RMCP+
1806 * host.
1807 */
1808 if ((addr->addr_type != IPMI_RMCPP_ADDR_SOL)
1809 && (lan->ip[addr_num].working_authtype != IPMI_AUTHTYPE_RMCP_PLUS))
1810 return EINVAL;
1811 payload_type = addr->addr_type - IPMI_RMCPP_ADDR_START;
1812 } else {
1813 switch (addr->addr_type) {
1814 case IPMI_SYSTEM_INTERFACE_ADDR_TYPE:
1815 case IPMI_IPMB_ADDR_TYPE:
1816 case IPMI_IPMB_BROADCAST_ADDR_TYPE:
1817 payload_type = IPMI_RMCPP_PAYLOAD_TYPE_IPMI;
1818 break;
1819 default:
1820 return EINVAL;
1821 }
1822 }
1823
1824 if ((payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT)
1825 || ((payload_type >= 0x20) && (payload_type <= 0x27)))
1826 {
1827 ipmi_rmcpp_addr_t *rmcpp_addr = (ipmi_rmcpp_addr_t *) addr;
1828 payload_entry_t *e;
1829
1830 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT) {
1831 memcpy(oem_iana, rmcpp_addr->oem_iana, 3);
1832 oem_payload_id = rmcpp_addr->oem_payload_id;
1833 } else {
1834 memcpy(oem_iana, lan->oem_iana, 3);
1835 oem_payload_id = 0;
1836 }
1837
1838 /* No lock required, only payload additions are allowed. */
1839 e = oem_payload_list;
1840 while (e) {
1841 if ((e->payload_type == payload_type)
1842 && (memcmp(e->iana, oem_iana, 3) == 0)
1843 && (e->payload_id == oem_payload_id))
1844 {
1845 payload = e->payload;
1846 break;
1847 }
1848 e = e->next;
1849 }
1850 } else {
1851 payload = payloads[payload_type];
1852 }
1853
1854 tmsg = data + IPMI_LAN_MAX_HEADER;
1855 if (!payload) {
1856 return ENOSYS;
1857 } else {
1858 pos = IPMI_MAX_LAN_LEN;
1859 rv = payload->format_for_xmit(lan->ipmi, addr, addr_len,
1860 msg, tmsg, &pos,
1861 &out_of_session, seq);
1862 if (rv)
1863 return rv;
1864 }
1865
1866 if (lan->ip[addr_num].working_authtype == IPMI_AUTHTYPE_RMCP_PLUS) {
1867 rv = rmcpp_format_msg(lan, addr_num,
1868 payload_type, !out_of_session,
1869 &tmsg, &pos,
1870 IPMI_MAX_LAN_LEN, IPMI_LAN_MAX_HEADER,
1871 oem_iana, oem_payload_id, options);
1872 } else {
1873 rv = lan15_format_msg(lan, addr_num, &tmsg, &pos);
1874 if (addr->addr_type == IPMI_RMCPP_ADDR_SOL)
1875 /*
1876 * We're sending SoL over IPMI 1.5, which requires that we set
1877 * a "reserved" bit. This is dodgy.
1878 */
1879 tmsg[4] |= 0x80;
1880 }
1881 if (rv)
1882 return rv;
1883
1884 if (DEBUG_RAWMSG) {
1885 char buf1[32], buf2[32];
1886 ipmi_log(IPMI_LOG_DEBUG_START, "%soutgoing seq %d\n addr =",
1887 IPMI_CONN_NAME(lan->ipmi), seq);
1888 dump_hex((unsigned char *) &(lan->cparm.ip_addr[addr_num]),
1889 sizeof(sockaddr_ip_t));
1890 ipmi_log(IPMI_LOG_DEBUG_CONT,
1891 "\n msg = netfn=%s cmd=%s data_len=%d.",
1892 ipmi_get_netfn_string(msg->netfn, buf1, 32),
1893 ipmi_get_command_string(msg->netfn, msg->cmd, buf2, 32),
1894 msg->data_len);
1895 if (pos) {
1896 ipmi_log(IPMI_LOG_DEBUG_CONT, "\n data =\n ");
1897 dump_hex(tmsg, pos);
1898 }
1899 ipmi_log(IPMI_LOG_DEBUG_END, " ");
1900 }
1901
1902 add_stat(lan->ipmi, STAT_XMIT_PACKETS, 1);
1903
1904 rv = sendto(lan->fd->fd, tmsg, pos, 0,
1905 (struct sockaddr *) &(lan->cparm.ip_addr[addr_num].s_ipsock),
1906 lan->cparm.ip_addr[addr_num].ip_addr_len);
1907 if (rv == -1)
1908 rv = errno;
1909 else
1910 rv = 0;
1911
1912 return rv;
1913 }
1914
1915 static int
lan_send(lan_data_t * lan,const ipmi_addr_t * addr,int addr_len,const ipmi_msg_t * msg,uint8_t seq,int * send_ip_num,const ipmi_con_option_t * options)1916 lan_send(lan_data_t *lan,
1917 const ipmi_addr_t *addr,
1918 int addr_len,
1919 const ipmi_msg_t *msg,
1920 uint8_t seq,
1921 int *send_ip_num,
1922 const ipmi_con_option_t *options)
1923 {
1924 int curr_ip_addr;
1925
1926 ipmi_lock(lan->ip_lock);
1927 if (msg->netfn & 1) {
1928 /* For unacknowledged packets, don't switch addresses. They
1929 don't contribute to detecting that the link is down. */
1930 curr_ip_addr = lan->curr_ip_addr;
1931 } else if (lan->connected) {
1932 lan->num_sends++;
1933
1934 /* We periodically switch between IP addresses, just to make sure
1935 they are all operational. */
1936 if ((lan->num_sends % SENDS_BETWEEN_IP_SWITCHES) == 0) {
1937 unsigned int addr_num = lan->curr_ip_addr + 1;
1938 if (addr_num >= lan->cparm.num_ip_addr)
1939 addr_num = 0;
1940 while (addr_num != lan->curr_ip_addr) {
1941 if (lan->ip[addr_num].working)
1942 break;
1943 addr_num++;
1944 if (addr_num >= lan->cparm.num_ip_addr)
1945 addr_num = 0;
1946 }
1947 lan->curr_ip_addr = addr_num;
1948 }
1949 } else {
1950 /* Just rotate between IP addresses if we are not yet connected */
1951 unsigned int addr_num = lan->curr_ip_addr + 1;
1952 if (addr_num >= lan->cparm.num_ip_addr)
1953 addr_num = 0;
1954 lan->curr_ip_addr = addr_num;
1955 }
1956 curr_ip_addr = lan->curr_ip_addr;
1957 ipmi_unlock(lan->ip_lock);
1958
1959 *send_ip_num = curr_ip_addr;
1960
1961 return lan_send_addr(lan, addr, addr_len, msg, seq, curr_ip_addr, options);
1962 }
1963
1964 typedef struct call_ipmb_change_handler_s
1965 {
1966 lan_data_t *lan;
1967 int err;
1968 const unsigned char *ipmb_addr;
1969 unsigned int num_ipmb_addr;
1970 int active;
1971 unsigned int hacks;
1972 } call_ipmb_change_handler_t;
1973
1974 static int
call_ipmb_change_handler(void * cb_data,void * item1,void * item2)1975 call_ipmb_change_handler(void *cb_data, void *item1, void *item2)
1976 {
1977 call_ipmb_change_handler_t *info = cb_data;
1978 ipmi_ll_ipmb_addr_cb handler = item1;
1979
1980 handler(info->lan->ipmi, info->err, info->ipmb_addr, info->num_ipmb_addr,
1981 info->active, info->hacks, item2);
1982 return LOCKED_LIST_ITER_CONTINUE;
1983 }
1984
1985 static void
call_ipmb_change_handlers(lan_data_t * lan,int err,const unsigned char ipmb_addr[],unsigned int num_ipmb_addr,int active,unsigned int hacks)1986 call_ipmb_change_handlers(lan_data_t *lan, int err,
1987 const unsigned char ipmb_addr[],
1988 unsigned int num_ipmb_addr,
1989 int active, unsigned int hacks)
1990 {
1991 call_ipmb_change_handler_t info;
1992
1993 info.lan = lan;
1994 info.err = err;
1995 info.ipmb_addr = ipmb_addr;
1996 info.num_ipmb_addr = num_ipmb_addr;
1997 info.active = active;
1998 info.hacks = hacks;
1999 locked_list_iterate(lan->ipmb_change_handlers, call_ipmb_change_handler,
2000 &info);
2001 }
2002
2003 static int
lan_add_ipmb_addr_handler(ipmi_con_t * ipmi,ipmi_ll_ipmb_addr_cb handler,void * cb_data)2004 lan_add_ipmb_addr_handler(ipmi_con_t *ipmi,
2005 ipmi_ll_ipmb_addr_cb handler,
2006 void *cb_data)
2007 {
2008 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2009
2010 if (locked_list_add(lan->ipmb_change_handlers, handler, cb_data))
2011 return 0;
2012 else
2013 return ENOMEM;
2014 }
2015
2016 static int
lan_remove_ipmb_addr_handler(ipmi_con_t * ipmi,ipmi_ll_ipmb_addr_cb handler,void * cb_data)2017 lan_remove_ipmb_addr_handler(ipmi_con_t *ipmi,
2018 ipmi_ll_ipmb_addr_cb handler,
2019 void *cb_data)
2020 {
2021 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2022
2023 if (locked_list_remove(lan->ipmb_change_handlers, handler, cb_data))
2024 return 0;
2025 else
2026 return EINVAL;
2027 }
2028
2029 static void
ipmb_handler(ipmi_con_t * ipmi,int err,const unsigned char ipmb_addr[],unsigned int num_ipmb_addr,int active,unsigned int hacks,void * cb_data)2030 ipmb_handler(ipmi_con_t *ipmi,
2031 int err,
2032 const unsigned char ipmb_addr[],
2033 unsigned int num_ipmb_addr,
2034 int active,
2035 unsigned int hacks,
2036 void *cb_data)
2037 {
2038 lan_data_t *lan;
2039 int changed = 0;
2040 int i;
2041
2042 if (err)
2043 return;
2044
2045 lan = (lan_data_t *) ipmi->con_data;
2046
2047 for (i=0; i<MAX_IPMI_USED_CHANNELS; i++) {
2048 if (! ipmb_addr[i])
2049 continue;
2050 if (ipmb_addr[i] != lan->slave_addr[i]) {
2051 lan->slave_addr[i] = ipmb_addr[i];
2052 ipmi->ipmb_addr[i] = ipmb_addr[i];
2053 changed = 1;
2054 }
2055 }
2056 if (changed || (lan->is_active != active)) {
2057 lan->is_active = active;
2058 ipmi->hacks = hacks;
2059 call_ipmb_change_handlers(lan, err, ipmb_addr, num_ipmb_addr,
2060 active, hacks);
2061 }
2062 }
2063
2064 static void
audit_timeout_handler(void * cb_data,os_hnd_timer_id_t * id)2065 audit_timeout_handler(void *cb_data,
2066 os_hnd_timer_id_t *id)
2067 {
2068 audit_timer_info_t *info = cb_data;
2069 ipmi_con_t *ipmi = info->ipmi;
2070 lan_data_t *lan;
2071 struct timeval timeout;
2072 ipmi_msg_t msg;
2073 unsigned int i;
2074 ipmi_system_interface_addr_t si;
2075 int start_up[MAX_IP_ADDR];
2076
2077
2078 /* If we were cancelled, just free the data and ignore the call. */
2079 if (info->cancelled)
2080 goto out_done;
2081
2082 if (!lan_valid_ipmi(ipmi))
2083 goto out_done;
2084
2085 lan = ipmi->con_data;
2086
2087 /* Send message to all addresses we think are down. If the
2088 connection is down, this will bring it up, otherwise it
2089 will keep it alive. */
2090 ipmi_lock(lan->ip_lock);
2091 for (i=0; i<lan->cparm.num_ip_addr; i++)
2092 start_up[i] = ! lan->ip[i].working;
2093 ipmi_unlock(lan->ip_lock);
2094
2095 for (i=0; i<lan->cparm.num_ip_addr; i++) {
2096 if (start_up[i])
2097 send_auth_cap(ipmi, lan, i, 0);
2098 }
2099
2100 msg.netfn = IPMI_APP_NETFN;
2101 msg.cmd = IPMI_GET_DEVICE_ID_CMD;
2102 msg.data = NULL;
2103 msg.data_len = 0;
2104
2105 /* Send a message to check the working of the interface. */
2106 if (ipmi->get_ipmb_addr) {
2107 /* If we have a way to query the IPMB address, do so
2108 periodically. */
2109 ipmi->get_ipmb_addr(ipmi, ipmb_handler, NULL);
2110 } else {
2111 si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2112 si.channel = 0xf;
2113 si.lun = 0;
2114 ipmi->send_command(ipmi, (ipmi_addr_t *) &si, sizeof(si),
2115 &msg, NULL, NULL);
2116 }
2117
2118 timeout.tv_sec = LAN_AUDIT_TIMEOUT / 1000000;
2119 timeout.tv_usec = LAN_AUDIT_TIMEOUT % 1000000;
2120 ipmi->os_hnd->start_timer(ipmi->os_hnd,
2121 id,
2122 &timeout,
2123 audit_timeout_handler,
2124 cb_data);
2125
2126 /* Make sure the timer info doesn't get freed. */
2127 info = NULL;
2128
2129 lan_put(ipmi);
2130
2131 out_done:
2132 if (info) {
2133 ipmi->os_hnd->free_timer(ipmi->os_hnd, id);
2134 ipmi_mem_free(info);
2135 }
2136 return;
2137 }
2138
2139 typedef struct call_con_change_handler_s
2140 {
2141 lan_data_t *lan;
2142 int err;
2143 unsigned int port;
2144 int any_port_up;
2145 } call_con_change_handler_t;
2146
2147 static int
call_con_change_handler(void * cb_data,void * item1,void * item2)2148 call_con_change_handler(void *cb_data, void *item1, void *item2)
2149 {
2150 call_con_change_handler_t *info = cb_data;
2151 ipmi_ll_con_changed_cb handler = item1;
2152
2153 handler(info->lan->ipmi, info->err, info->port, info->any_port_up, item2);
2154 return LOCKED_LIST_ITER_CONTINUE;
2155 }
2156
2157 static void
call_con_change_handlers(lan_data_t * lan,int err,unsigned int port,int any_port_up)2158 call_con_change_handlers(lan_data_t *lan, int err, unsigned int port,
2159 int any_port_up)
2160 {
2161 call_con_change_handler_t info;
2162
2163 info.lan = lan;
2164 info.err = err;
2165 info.port = port;
2166 info.any_port_up = any_port_up;
2167 locked_list_iterate(lan->con_change_handlers, call_con_change_handler,
2168 &info);
2169 }
2170
2171 void
i_ipmi_lan_con_change_lock(ipmi_con_t * ipmi)2172 i_ipmi_lan_con_change_lock(ipmi_con_t *ipmi)
2173 {
2174 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2175 ipmi_lock(lan->ip_lock);
2176 ipmi_lock(lan->con_change_lock);
2177 ipmi_unlock(lan->ip_lock);
2178 }
2179
2180 void
i_ipmi_lan_con_change_unlock(ipmi_con_t * ipmi)2181 i_ipmi_lan_con_change_unlock(ipmi_con_t *ipmi)
2182 {
2183 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2184 ipmi_unlock(lan->con_change_lock);
2185 }
2186
2187 void
i_ipmi_lan_call_con_change_handlers(ipmi_con_t * ipmi,int err,unsigned int port)2188 i_ipmi_lan_call_con_change_handlers(ipmi_con_t *ipmi,
2189 int err,
2190 unsigned int port)
2191 {
2192 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2193
2194 call_con_change_handlers(lan, err, port, lan->connected);
2195 }
2196
2197 static int
lan_add_con_change_handler(ipmi_con_t * ipmi,ipmi_ll_con_changed_cb handler,void * cb_data)2198 lan_add_con_change_handler(ipmi_con_t *ipmi,
2199 ipmi_ll_con_changed_cb handler,
2200 void *cb_data)
2201 {
2202 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2203
2204 if (locked_list_add(lan->con_change_handlers, handler, cb_data))
2205 return 0;
2206 else
2207 return ENOMEM;
2208 }
2209
2210 static int
lan_remove_con_change_handler(ipmi_con_t * ipmi,ipmi_ll_con_changed_cb handler,void * cb_data)2211 lan_remove_con_change_handler(ipmi_con_t *ipmi,
2212 ipmi_ll_con_changed_cb handler,
2213 void *cb_data)
2214 {
2215 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2216
2217 if (locked_list_remove(lan->con_change_handlers, handler, cb_data))
2218 return 0;
2219 else
2220 return EINVAL;
2221 }
2222
2223 static void
connection_up(lan_data_t * lan,int addr_num,int new_con)2224 connection_up(lan_data_t *lan, int addr_num, int new_con)
2225 {
2226 add_stat(lan->ipmi, STAT_CONN_UP, 1);
2227
2228 ipmi_lock(lan->ip_lock);
2229 if ((! lan->ip[addr_num].working) && new_con) {
2230 lan->ip[addr_num].working = 1;
2231
2232 ipmi_log(IPMI_LOG_INFO,
2233 "%sipmi_lan.c(connection_up): "
2234 "Connection %d to the BMC is up",
2235 IPMI_CONN_NAME(lan->ipmi), addr_num);
2236 }
2237
2238 if (new_con) {
2239 ipmi_log(IPMI_LOG_INFO,
2240 "%sipmi_lan.c(connection_up): "
2241 "Connection to the BMC restored",
2242 IPMI_CONN_NAME(lan->ipmi));
2243 lan->curr_ip_addr = addr_num;
2244 }
2245
2246 if (lan->connected) {
2247 ipmi_lock(lan->con_change_lock);
2248 ipmi_unlock(lan->ip_lock);
2249 call_con_change_handlers(lan, 0, addr_num, 1);
2250 ipmi_unlock(lan->con_change_lock);
2251 } else {
2252 ipmi_unlock(lan->ip_lock);
2253 }
2254 }
2255
2256 static void
reset_session_data(lan_data_t * lan,int addr_num)2257 reset_session_data(lan_data_t *lan, int addr_num)
2258 {
2259 lan_ip_data_t *ip = &lan->ip[addr_num];
2260
2261 ip->outbound_seq_num = 0;
2262 ip->inbound_seq_num = 0;
2263 ip->session_id = 0;
2264 ip->mgsys_session_id = 0;
2265 ip->precon_session_id = 0;
2266 ip->precon_mgsys_session_id = 0;
2267 ip->recv_msg_map = 0;
2268 ip->unauth_recv_msg_map = 0;
2269 ip->working_authtype = 0;
2270 ip->unauth_out_seq_num = 0;
2271 ip->unauth_in_seq_num = 0;
2272 if (ip->conf_data) {
2273 ip->conf_info->conf_free(lan->ipmi, ip->conf_data);
2274 ip->conf_data = NULL;
2275 }
2276 ip->conf_info = NULL;
2277 if (ip->integ_data) {
2278 ip->integ_info->integ_free(lan->ipmi, ip->integ_data);
2279 ip->integ_data = NULL;
2280 }
2281 ip->integ_info = NULL;
2282 ip->working_conf = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE;
2283 ip->working_integ = IPMI_LANP_INTEGRITY_ALGORITHM_NONE;
2284 }
2285
2286 static void
lost_connection(lan_data_t * lan,unsigned int addr_num)2287 lost_connection(lan_data_t *lan, unsigned int addr_num)
2288 {
2289 unsigned int i;
2290
2291 ipmi_lock(lan->ip_lock);
2292 if (! lan->ip[addr_num].working) {
2293 ipmi_unlock(lan->ip_lock);
2294 return;
2295 }
2296
2297 add_stat(lan->ipmi, STAT_CONN_DOWN, 1);
2298
2299 lan->ip[addr_num].working = 0;
2300
2301 reset_session_data(lan, addr_num);
2302
2303 ipmi_log(IPMI_LOG_WARNING,
2304 "%sipmi_lan.c(lost_connection): "
2305 "Connection %d to the BMC is down",
2306 IPMI_CONN_NAME(lan->ipmi), addr_num);
2307
2308 if (lan->curr_ip_addr == addr_num) {
2309 /* Scan to see if any address is operational. */
2310 for (i=0; i<lan->cparm.num_ip_addr; i++) {
2311 if (lan->ip[i].working) {
2312 lan->curr_ip_addr = i;
2313 break;
2314 }
2315 }
2316
2317 if (i >= lan->cparm.num_ip_addr) {
2318 /* There were no operational connections, report that. */
2319 ipmi_log(IPMI_LOG_SEVERE,
2320 "%sipmi_lan.c(lost_connection): "
2321 "All connections to the BMC are down",
2322 IPMI_CONN_NAME(lan->ipmi));
2323
2324 lan->connected = 0;
2325 }
2326 }
2327
2328 {
2329 int connected = lan->connected;
2330
2331 ipmi_lock(lan->con_change_lock);
2332 ipmi_unlock(lan->ip_lock);
2333 call_con_change_handlers(lan, ETIMEDOUT, addr_num, connected);
2334 ipmi_unlock(lan->con_change_lock);
2335 }
2336 }
2337
2338 static void
rsp_timeout_handler(void * cb_data,os_hnd_timer_id_t * id)2339 rsp_timeout_handler(void *cb_data,
2340 os_hnd_timer_id_t *id)
2341 {
2342 lan_timer_info_t *info = cb_data;
2343 ipmi_con_t *ipmi = info->ipmi;
2344 lan_data_t *lan;
2345 int seq;
2346 ipmi_ll_rsp_handler_t handler;
2347 ipmi_msgi_t *rspi;
2348 int ip_num = 0;
2349 int call_lost_con = 0;
2350
2351 if (!lan_valid_ipmi(ipmi))
2352 return;
2353
2354 lan = ipmi->con_data;
2355 seq = info->seq;
2356
2357 ipmi_lock(lan->seq_num_lock);
2358
2359 /* If we were cancelled, just free the data and ignore it. */
2360 if (info->cancelled) {
2361 ipmi_unlock(lan->seq_num_lock);
2362 goto out;
2363 }
2364
2365 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2366 ipmi_log(IPMI_LOG_DEBUG, "%sTimeout for seq #%d",
2367 IPMI_CONN_NAME(ipmi), seq);
2368
2369 if (! lan->seq_table[seq].inuse) {
2370 ipmi_unlock(lan->seq_num_lock);
2371 goto out;
2372 }
2373
2374 if (DEBUG_RAWMSG) {
2375 ip_num = lan->seq_table[seq].last_ip_num;
2376 ipmi_log(IPMI_LOG_DEBUG,
2377 "%sSeq #%d\n"
2378 " addr_type=%d, ip_num=%d, fails=%d\n"
2379 " fail_start_time=%ld.%6.6ld",
2380 IPMI_CONN_NAME(ipmi),
2381 seq, lan->seq_table[seq].addr.addr_type,
2382 lan->seq_table[seq].last_ip_num,
2383 lan->ip[ip_num].consecutive_failures,
2384 lan->ip[ip_num].failure_time.tv_sec,
2385 lan->ip[ip_num].failure_time.tv_usec);
2386 }
2387
2388 if (lan->seq_table[seq].addr.addr_type == IPMI_SYSTEM_INTERFACE_ADDR_TYPE)
2389 {
2390 /* We only count timeouts on messages to the system interface.
2391 Otherwise, if we sent a bunch of messages to the IPMB that
2392 timed out, we might trigger this code accidentally. */
2393 ip_num = lan->seq_table[seq].last_ip_num;
2394 ipmi_lock(lan->ip_lock);
2395 if (lan->ip[ip_num].working) {
2396 if (lan->ip[ip_num].consecutive_failures == 0) {
2397 /* Set the time when the connection will be considered
2398 failed. */
2399 ipmi->os_hnd->get_monotonic_time(ipmi->os_hnd,
2400 &(lan->ip[ip_num].failure_time));
2401 lan->ip[ip_num].failure_time.tv_sec += IP_FAIL_TIME / 1000000;
2402 lan->ip[ip_num].failure_time.tv_usec += IP_FAIL_TIME % 1000000;
2403 if (lan->ip[ip_num].failure_time.tv_usec > 1000000) {
2404 lan->ip[ip_num].failure_time.tv_sec += 1;
2405 lan->ip[ip_num].failure_time.tv_usec -= 1000000;
2406 }
2407 lan->ip[ip_num].consecutive_failures = 1;
2408 } else if (!lan->seq_table[seq].side_effects) {
2409 /* Don't use messages with side effects for failure
2410 detection. */
2411 lan->ip[ip_num].consecutive_failures++;
2412 if (lan->ip[ip_num].consecutive_failures >= IP_FAIL_COUNT) {
2413 /* Consider this for a failure, check after unlocking */
2414 call_lost_con = 1;
2415 }
2416 }
2417 }
2418 ipmi_unlock(lan->ip_lock);
2419
2420 if (call_lost_con) {
2421 struct timeval now;
2422 ipmi->os_hnd->get_monotonic_time(ipmi->os_hnd, &now);
2423 if (cmp_timeval(&now, &lan->ip[ip_num].failure_time) <= 0) {
2424 /* Not a failure yet. */
2425 call_lost_con = 0;
2426 }
2427 }
2428 }
2429
2430 rspi = lan->seq_table[seq].rsp_item;
2431
2432 if (lan->seq_table[seq].retries_left > 0)
2433 {
2434 struct timeval timeout;
2435 int rv;
2436
2437 lan->seq_table[seq].retries_left--;
2438
2439 add_stat(ipmi, STAT_REXMITS, 1);
2440
2441 /* Note that we will need a new session seq # here, we can't reuse
2442 the old one. If the message got lost on the way back, the other
2443 end would silently ignore resends of the seq #. */
2444 if (lan->seq_table[seq].addr_num >= 0)
2445 rv = lan_send_addr(lan,
2446 &(lan->seq_table[seq].addr),
2447 lan->seq_table[seq].addr_len,
2448 &(lan->seq_table[seq].msg),
2449 seq,
2450 lan->seq_table[seq].addr_num,
2451 NULL);
2452 else
2453 rv = lan_send(lan,
2454 &(lan->seq_table[seq].addr),
2455 lan->seq_table[seq].addr_len,
2456 &(lan->seq_table[seq].msg),
2457 seq,
2458 &(lan->seq_table[seq].last_ip_num),
2459 NULL);
2460
2461 if (rv) {
2462 /* If we get an error resending the message, report an unknown
2463 error. */
2464 rspi->data[0] = IPMI_UNKNOWN_ERR_CC;
2465 } else {
2466 if (!lan->seq_table[seq].side_effects) {
2467 timeout.tv_sec = LAN_RSP_TIMEOUT / 1000000;
2468 timeout.tv_usec = LAN_RSP_TIMEOUT % 1000000;
2469 } else {
2470 timeout.tv_sec = LAN_RSP_TIMEOUT_SIDEEFF / 1000000;
2471 timeout.tv_usec = LAN_RSP_TIMEOUT_SIDEEFF % 1000000;
2472 }
2473 ipmi->os_hnd->start_timer(ipmi->os_hnd,
2474 id,
2475 &timeout,
2476 rsp_timeout_handler,
2477 cb_data);
2478
2479 ipmi_unlock(lan->seq_num_lock);
2480 if (call_lost_con)
2481 lost_connection(lan, ip_num);
2482 lan_put(ipmi);
2483 return;
2484 }
2485 } else {
2486 add_stat(ipmi, STAT_TIMED_OUT, 1);
2487
2488 rspi->data[0] = IPMI_TIMEOUT_CC;
2489 }
2490
2491 rspi->msg.netfn = lan->seq_table[seq].msg.netfn | 1;
2492 rspi->msg.cmd = lan->seq_table[seq].msg.cmd;
2493 rspi->msg.data = rspi->data;
2494 rspi->msg.data_len = 1;
2495
2496 if (lan->seq_table[seq].use_orig_addr) {
2497 /* We did an address translation, so translate back. */
2498 memcpy(&rspi->addr, &lan->seq_table[seq].orig_addr,
2499 lan->seq_table[seq].orig_addr_len);
2500 rspi->addr_len = lan->seq_table[seq].orig_addr_len;
2501 } else {
2502 memcpy(&rspi->addr,
2503 &(lan->seq_table[seq].addr),
2504 lan->seq_table[seq].addr_len);
2505 rspi->addr_len = lan->seq_table[seq].addr_len;
2506 }
2507
2508 handler = lan->seq_table[seq].rsp_handler;
2509
2510 lan->seq_table[seq].inuse = 0;
2511
2512 check_command_queue(ipmi, lan);
2513 ipmi_unlock(lan->seq_num_lock);
2514
2515 ipmi->os_hnd->free_timer(ipmi->os_hnd, id);
2516
2517 /* Convert broadcasts back into normal sends. */
2518 if (rspi->addr.addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)
2519 rspi->addr.addr_type = IPMI_IPMB_ADDR_TYPE;
2520
2521 if (call_lost_con)
2522 lost_connection(lan, ip_num);
2523
2524 ipmi_handle_rsp_item(ipmi, rspi, handler);
2525
2526 out:
2527 lan_put(ipmi);
2528 ipmi_mem_free(info);
2529 }
2530
2531 typedef struct call_event_handler_s
2532 {
2533 lan_data_t *lan;
2534 const ipmi_addr_t *addr;
2535 unsigned int addr_len;
2536 ipmi_event_t *event;
2537 } call_event_handler_t;
2538
2539 static int
call_event_handler(void * cb_data,void * item1,void * item2)2540 call_event_handler(void *cb_data, void *item1, void *item2)
2541 {
2542 call_event_handler_t *info = cb_data;
2543 ipmi_ll_evt_handler_t handler = item1;
2544
2545 handler(info->lan->ipmi, info->addr, info->addr_len, info->event, item2);
2546 return LOCKED_LIST_ITER_CONTINUE;
2547 }
2548
2549 static int
lan_add_event_handler(ipmi_con_t * ipmi,ipmi_ll_evt_handler_t handler,void * cb_data)2550 lan_add_event_handler(ipmi_con_t *ipmi,
2551 ipmi_ll_evt_handler_t handler,
2552 void *cb_data)
2553 {
2554 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2555
2556 if (locked_list_add(lan->event_handlers, handler, cb_data))
2557 return 0;
2558 else
2559 return ENOMEM;
2560 }
2561
2562 static int
lan_remove_event_handler(ipmi_con_t * ipmi,ipmi_ll_evt_handler_t handler,void * cb_data)2563 lan_remove_event_handler(ipmi_con_t *ipmi,
2564 ipmi_ll_evt_handler_t handler,
2565 void *cb_data)
2566 {
2567 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2568
2569 if (locked_list_remove(lan->event_handlers, handler, cb_data))
2570 return 0;
2571 else
2572 return EINVAL;
2573 }
2574
2575 static ipmi_mcid_t invalid_mcid = IPMI_MCID_INVALID;
2576
2577 static void
handle_async_event(ipmi_con_t * ipmi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg)2578 handle_async_event(ipmi_con_t *ipmi,
2579 const ipmi_addr_t *addr,
2580 unsigned int addr_len,
2581 const ipmi_msg_t *msg)
2582 {
2583 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
2584 ipmi_event_t *event = NULL;
2585 ipmi_time_t timestamp;
2586 call_event_handler_t info;
2587
2588 add_stat(ipmi, STAT_ASYNC_EVENTS, 1);
2589
2590 if (msg) {
2591 unsigned int type = msg->data[2];
2592 unsigned int record_id = ipmi_get_uint16(msg->data);
2593
2594 if (type < 0xe0)
2595 timestamp = ipmi_seconds_to_time(ipmi_get_uint32(msg->data+3));
2596 else
2597 timestamp = -1;
2598 event = ipmi_event_alloc(invalid_mcid,
2599 record_id,
2600 type,
2601 timestamp,
2602 msg->data+3, 13);
2603 if (!event)
2604 /* We missed it here, but the SEL fetch should catch it later. */
2605 return;
2606 }
2607
2608 info.lan = lan;
2609 info.addr = addr;
2610 info.addr_len = addr_len;
2611 info.event = event;
2612 locked_list_iterate(lan->event_handlers, call_event_handler, &info);
2613
2614 if (event)
2615 ipmi_event_free(event);
2616 }
2617
2618 /* Must be called with the message sequence lock held. */
2619 static int
handle_msg_send(lan_timer_info_t * info,int addr_num,const ipmi_addr_t * iaddr,unsigned int addr_len,const ipmi_msg_t * msg,ipmi_ll_rsp_handler_t rsp_handler,ipmi_msgi_t * rspi,int side_effects)2620 handle_msg_send(lan_timer_info_t *info,
2621 int addr_num,
2622 const ipmi_addr_t *iaddr,
2623 unsigned int addr_len,
2624 const ipmi_msg_t *msg,
2625 ipmi_ll_rsp_handler_t rsp_handler,
2626 ipmi_msgi_t *rspi,
2627 int side_effects)
2628 {
2629 ipmi_con_t *ipmi = info->ipmi;
2630 lan_data_t *lan = ipmi->con_data;
2631 unsigned int seq;
2632 struct timeval timeout;
2633 int rv;
2634 char addr_data[sizeof(ipmi_addr_t)];
2635 char addr_data2[sizeof(ipmi_addr_t)];
2636 ipmi_addr_t *addr = (ipmi_addr_t *) addr_data;
2637 const ipmi_addr_t *orig_addr = NULL;
2638 unsigned int orig_addr_len = 0;
2639
2640 *addr = *iaddr;
2641
2642 seq = (lan->last_seq + 1) % 64;
2643 if (seq == 0)
2644 seq++;
2645 while (lan->seq_table[seq].inuse) {
2646 if (seq == lan->last_seq) {
2647 /* This cannot really happen if max_outstanding_msg_count <= 63. */
2648 ipmi_log(IPMI_LOG_FATAL,
2649 "%sipmi_lan.c(handle_msg_send): "
2650 "ipmi_lan: Attempted to start too many messages",
2651 IPMI_CONN_NAME(ipmi));
2652 abort();
2653 }
2654
2655 seq = (seq + 1) % 64;
2656 if (seq == 0)
2657 seq++;
2658 }
2659
2660 if (DEBUG_MSG) {
2661 char buf1[32], buf2[32];
2662 ipmi_log(IPMI_LOG_DEBUG_START, "%soutgoing msg to IPMI addr =",
2663 IPMI_CONN_NAME(ipmi));
2664 dump_hex((unsigned char *) addr, addr_len);
2665 ipmi_log(IPMI_LOG_DEBUG_CONT,
2666 "\n msg = netfn=%s cmd=%s data_len=%d",
2667 ipmi_get_netfn_string(msg->netfn, buf1, 32),
2668 ipmi_get_command_string(msg->netfn, msg->cmd, buf2, 32),
2669 msg->data_len);
2670 if (msg->data_len) {
2671 ipmi_log(IPMI_LOG_DEBUG_CONT, "\n data(len=%d.) =\n ",
2672 msg->data_len);
2673 dump_hex(msg->data, msg->data_len);
2674 }
2675 ipmi_log(IPMI_LOG_DEBUG_END, " ");
2676 }
2677
2678 if ((addr->addr_type == IPMI_IPMB_ADDR_TYPE)
2679 || (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE))
2680 {
2681 ipmi_ipmb_addr_t *ipmb = (ipmi_ipmb_addr_t *) addr;
2682
2683 if (ipmb->channel >= MAX_IPMI_USED_CHANNELS) {
2684 ipmi->os_hnd->free_timer(ipmi->os_hnd, info->timer);
2685 ipmi_mem_free(info);
2686 rv = EINVAL;
2687 goto out;
2688 }
2689
2690 if (ipmb->slave_addr == lan->slave_addr[ipmb->channel]) {
2691 ipmi_system_interface_addr_t *si = (void *) addr_data2;
2692 /* Most systems don't handle sending to your own slave
2693 address, so we have to translate here. */
2694
2695 si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
2696 si->channel = IPMI_BMC_CHANNEL;
2697 si->lun = ipmb->lun;
2698 orig_addr = addr;
2699 orig_addr_len = addr_len;
2700 addr = (ipmi_addr_t *) si;
2701 addr_len = sizeof(*si);
2702 }
2703 }
2704
2705 info->seq = seq;
2706 lan->seq_table[seq].inuse = 1;
2707 lan->seq_table[seq].side_effects = side_effects;
2708 lan->seq_table[seq].addr_num = addr_num;
2709 lan->seq_table[seq].rsp_handler = rsp_handler;
2710 lan->seq_table[seq].rsp_item = rspi;
2711 memcpy(&(lan->seq_table[seq].addr), addr, addr_len);
2712 lan->seq_table[seq].addr_len = addr_len;
2713 lan->seq_table[seq].msg = *msg;
2714 lan->seq_table[seq].msg.data = lan->seq_table[seq].data;
2715 memcpy(lan->seq_table[seq].data, msg->data, msg->data_len);
2716 lan->seq_table[seq].timer_info = info;
2717 if (addr->addr_type == IPMI_IPMB_BROADCAST_ADDR_TYPE)
2718 lan->seq_table[seq].retries_left = 0;
2719 else
2720 lan->seq_table[seq].retries_left = LAN_RSP_RETRIES;
2721 if (orig_addr) {
2722 lan->seq_table[seq].use_orig_addr = 1;
2723 memcpy(&(lan->seq_table[seq].orig_addr), orig_addr, orig_addr_len);
2724 lan->seq_table[seq].orig_addr_len = orig_addr_len;
2725
2726 /* In case it's a broadcast. */
2727 lan->seq_table[seq].orig_addr.addr_type = IPMI_IPMB_ADDR_TYPE;
2728 } else {
2729 lan->seq_table[seq].use_orig_addr = 0;
2730 }
2731
2732 if (!side_effects) {
2733 timeout.tv_sec = LAN_RSP_TIMEOUT / 1000000;
2734 timeout.tv_usec = LAN_RSP_TIMEOUT % 1000000;
2735 } else {
2736 timeout.tv_sec = LAN_RSP_TIMEOUT_SIDEEFF / 1000000;
2737 timeout.tv_usec = LAN_RSP_TIMEOUT_SIDEEFF % 1000000;
2738 }
2739 lan->seq_table[seq].timer = info->timer;
2740 rv = ipmi->os_hnd->start_timer(ipmi->os_hnd,
2741 lan->seq_table[seq].timer,
2742 &timeout,
2743 rsp_timeout_handler,
2744 info);
2745 if (rv) {
2746 lan->seq_table[seq].inuse = 0;
2747 ipmi->os_hnd->free_timer(ipmi->os_hnd,
2748 lan->seq_table[seq].timer);
2749 lan->seq_table[seq].timer = NULL;
2750 ipmi_mem_free(info);
2751 goto out;
2752 }
2753
2754 lan->last_seq = seq;
2755
2756 if (addr_num >= 0) {
2757 rv = lan_send_addr(lan, addr, addr_len, msg, seq, addr_num, NULL);
2758 lan->seq_table[seq].last_ip_num = addr_num;
2759 } else {
2760 rv = lan_send(lan, addr, addr_len, msg, seq,
2761 &(lan->seq_table[seq].last_ip_num),
2762 NULL);
2763 }
2764 if (rv) {
2765 int err;
2766
2767 lan->seq_table[seq].inuse = 0;
2768 err = ipmi->os_hnd->stop_timer(ipmi->os_hnd,
2769 lan->seq_table[seq].timer);
2770 /* Special handling, if we can't remove the timer, then it
2771 will time out on us, so we need to not free the command and
2772 instead let the timeout handle freeing it. */
2773 if (err) {
2774 info->cancelled = 1;
2775 } else {
2776 ipmi->os_hnd->free_timer(ipmi->os_hnd,
2777 lan->seq_table[seq].timer);
2778 lan->seq_table[seq].timer = NULL;
2779 ipmi_mem_free(info);
2780 }
2781 }
2782 out:
2783 return rv;
2784 }
2785
2786 static void
check_command_queue(ipmi_con_t * ipmi,lan_data_t * lan)2787 check_command_queue(ipmi_con_t *ipmi, lan_data_t *lan)
2788 {
2789 int rv;
2790 lan_wait_queue_t *q_item;
2791 int started = 0;
2792
2793 while (!started && (lan->wait_q != NULL)) {
2794 /* Commands are waiting to be started, remove the queue item
2795 and start it. */
2796 q_item = lan->wait_q;
2797 lan->wait_q = q_item->next;
2798 if (lan->wait_q == NULL)
2799 lan->wait_q_tail = NULL;
2800
2801 rv = handle_msg_send(q_item->info, -1, &q_item->addr, q_item->addr_len,
2802 &(q_item->msg), q_item->rsp_handler,
2803 q_item->rsp_item, q_item->side_effects);
2804 if (rv) {
2805 ipmi_unlock(lan->seq_num_lock);
2806
2807 /* Send an error response to the user. */
2808 ipmi_log(IPMI_LOG_ERR_INFO,
2809 "%sipmi_lan.c(check_command_queue): "
2810 "Command was not able to be sent due to error 0x%x",
2811 IPMI_CONN_NAME(ipmi), rv);
2812
2813 q_item->msg.netfn |= 1; /* Convert it to a response. */
2814 q_item->msg.data[0] = IPMI_UNKNOWN_ERR_CC;
2815 q_item->msg.data_len = 1;
2816 q_item->info = NULL;
2817 ipmi_handle_rsp_item_copyall(ipmi, q_item->rsp_item,
2818 &q_item->addr, q_item->addr_len,
2819 &q_item->msg, q_item->rsp_handler);
2820 ipmi_lock(lan->seq_num_lock);
2821 } else {
2822 /* We successfully sent a message, break out of the loop. */
2823 started = 1;
2824 }
2825 ipmi_mem_free(q_item);
2826 }
2827
2828 if (!started)
2829 lan->outstanding_msg_count--;
2830 }
2831
2832 /* Per the spec, RMCP and RMCP+ have different allowed sequence number
2833 ranges, so adjust for this. */
2834 static int
check_session_seq_num(lan_data_t * lan,uint32_t seq,uint32_t * in_seq,uint32_t * map,int gt_allowed,int lt_allowed)2835 check_session_seq_num(lan_data_t *lan, uint32_t seq,
2836 uint32_t *in_seq, uint32_t *map,
2837 int gt_allowed, int lt_allowed)
2838 {
2839 /* Check the sequence number. */
2840 if ((int) (seq - *in_seq) >= 0 && (int) (seq - *in_seq) <= gt_allowed) {
2841 /* It's after the current sequence number, but within gt_allowed.
2842 We move the sequence number forward. */
2843 *map <<= seq - *in_seq;
2844 *map |= 1;
2845 *in_seq = seq;
2846 } else if ((int) (*in_seq - seq) >= 0 && (int) (*in_seq - seq) <= lt_allowed) {
2847 /* It's before the current sequence number, but within lt_allowed. */
2848 uint32_t bit = 1 << (*in_seq - seq);
2849 if (*map & bit) {
2850 /* We've already received the message, so discard it. */
2851 add_stat(lan->ipmi, STAT_DUPLICATES, 1);
2852 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2853 ipmi_log(IPMI_LOG_DEBUG, "%sDropped message duplicate",
2854 IPMI_CONN_NAME(lan->ipmi));
2855 return EINVAL;
2856 }
2857
2858 *map |= bit;
2859 } else {
2860 /* It's outside the current sequence number range, discard
2861 the packet. */
2862 add_stat(lan->ipmi, STAT_SEQ_OUT_OF_RANGE, 1);
2863 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2864 ipmi_log(IPMI_LOG_DEBUG, "%sDropped message out of seq range",
2865 IPMI_CONN_NAME(lan->ipmi));
2866 return EINVAL;
2867 }
2868
2869 return 0;
2870 }
2871
2872 static int
check_15_session_seq_num(lan_data_t * lan,uint32_t seq,uint32_t * in_seq,uint32_t * map)2873 check_15_session_seq_num(lan_data_t *lan, uint32_t seq,
2874 uint32_t *in_seq, uint32_t *map)
2875 {
2876 return check_session_seq_num(lan, seq, in_seq, map, 8, 8);
2877 }
2878
2879 static int
check_20_session_seq_num(lan_data_t * lan,uint32_t seq,uint32_t * in_seq,uint32_t * map)2880 check_20_session_seq_num(lan_data_t *lan, uint32_t seq,
2881 uint32_t *in_seq, uint32_t *map)
2882 {
2883 return check_session_seq_num(lan, seq, in_seq, map, 15, 16);
2884 }
2885
2886 static void
handle_payload(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,int payload_type,unsigned char * tmsg,unsigned int payload_len)2887 handle_payload(ipmi_con_t *ipmi,
2888 lan_data_t *lan,
2889 int addr_num,
2890 int payload_type,
2891 unsigned char *tmsg,
2892 unsigned int payload_len)
2893 {
2894 ipmi_ll_rsp_handler_t handler;
2895 ipmi_msgi_t *rspi;
2896 unsigned char seq;
2897 int rv;
2898 int (*handle_send_rsp)(ipmi_con_t *con, ipmi_msg_t *msg);
2899
2900 handle_send_rsp = NULL;
2901
2902 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_RESPONSE) {
2903 if (payload_len < 1) {
2904 add_stat(ipmi, STAT_TOO_SHORT, 1);
2905 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2906 ipmi_log(IPMI_LOG_DEBUG, "%sPayload length to short",
2907 IPMI_CONN_NAME(ipmi));
2908 goto out;
2909 }
2910
2911 /* We use the message tag field to store the sequence #. */
2912 seq = tmsg[0] & 0x3f;
2913 } else if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT) {
2914 #if 0
2915 /* FIXME - add handling of OEM payloads. */
2916 handle_oem_payload(ipmi, lan, oem_iana, oem_payload_id,
2917 tmsg, payload_len);
2918 #else
2919 goto out;
2920 #endif
2921 } else if (! payloads[payload_type]) {
2922 add_stat(ipmi, STAT_INVALID_PAYLOAD, 1);
2923 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2924 ipmi_log(IPMI_LOG_DEBUG, "%sUnhandled payload: 0x%x",
2925 IPMI_CONN_NAME(ipmi), payload_type);
2926 goto out;
2927 } else {
2928 rv = payloads[payload_type]->get_recv_seq(ipmi, tmsg,
2929 payload_len, &seq);
2930 if (rv == ENOSYS) {
2931 payloads[payload_type]->handle_recv_async(ipmi, tmsg, payload_len);
2932 goto out;
2933 } else if (rv) {
2934 add_stat(ipmi, STAT_SEQ_ERR, 1);
2935 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2936 ipmi_log(IPMI_LOG_DEBUG, "%sError getting sequence: 0x%x",
2937 IPMI_CONN_NAME(ipmi), rv);
2938 goto out;
2939 }
2940 }
2941
2942 ipmi_lock(lan->seq_num_lock);
2943 if (! lan->seq_table[seq].inuse) {
2944 add_stat(ipmi, STAT_RSP_NO_CMD, 1);
2945 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
2946 ipmi_log(IPMI_LOG_DEBUG,
2947 "%sDropped message seq not in use: 0x%x",
2948 IPMI_CONN_NAME(ipmi), seq);
2949 goto out_unlock;
2950 }
2951
2952 rv = payloads[payload_type]->handle_recv_rsp
2953 (ipmi,
2954 lan->seq_table[seq].rsp_item,
2955 &lan->seq_table[seq].addr,
2956 lan->seq_table[seq].addr_len,
2957 &lan->seq_table[seq].msg,
2958 tmsg,
2959 payload_len);
2960 if (rv) {
2961 if (rv == -1)
2962 handle_send_rsp = ipmi->handle_send_rsp_err;
2963 else
2964 goto out_unlock;
2965 }
2966
2967 /* We got a response from the connection, so reset the failure
2968 count. */
2969 lan->ip[addr_num].consecutive_failures = 0;
2970
2971 /* The command matches up, cancel the timer and deliver it */
2972 rv = ipmi->os_hnd->stop_timer(ipmi->os_hnd,
2973 lan->seq_table[seq].timer);
2974 if (rv)
2975 /* Couldn't cancel the timer, make sure the timer
2976 doesn't do the callback. */
2977 lan->seq_table[seq].timer_info->cancelled = 1;
2978 else {
2979 /* Timer is cancelled, free its data. */
2980 ipmi->os_hnd->free_timer(ipmi->os_hnd,
2981 lan->seq_table[seq].timer);
2982 ipmi_mem_free(lan->seq_table[seq].timer_info);
2983 }
2984
2985 handler = lan->seq_table[seq].rsp_handler;
2986 rspi = lan->seq_table[seq].rsp_item;
2987 lan->seq_table[seq].inuse = 0;
2988
2989 if (lan->seq_table[seq].use_orig_addr) {
2990 /* We did an address translation, so translate back. */
2991 memcpy(&rspi->addr, &lan->seq_table[seq].orig_addr,
2992 lan->seq_table[seq].orig_addr_len);
2993 rspi->addr_len = lan->seq_table[seq].orig_addr_len;
2994 }
2995
2996 check_command_queue(ipmi, lan);
2997 ipmi_unlock(lan->seq_num_lock);
2998
2999 if (handle_send_rsp)
3000 handle_send_rsp(ipmi, &rspi->msg);
3001
3002 ipmi_handle_rsp_item(ipmi, rspi, handler);
3003
3004 out:
3005 return;
3006
3007 out_unlock:
3008 ipmi_unlock(lan->seq_num_lock);
3009 }
3010
3011 static void
handle_rmcpp_recv(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,unsigned char * data,unsigned int len)3012 handle_rmcpp_recv(ipmi_con_t *ipmi,
3013 lan_data_t *lan,
3014 int addr_num,
3015 unsigned char *data,
3016 unsigned int len)
3017 {
3018 unsigned char oem_iana[3] = { 0, 0, 0 };
3019 #if 0
3020 /* FIXME - add handling of OEM payloads. */
3021 unsigned int oem_payload_id = 0;
3022 #endif
3023 unsigned char *tmsg;
3024 int encrypted;
3025 int authenticated;
3026 unsigned int payload_type;
3027 uint32_t session_id;
3028 uint32_t session_seq;
3029 int rv;
3030 unsigned int payload_len;
3031 unsigned int header_len;
3032
3033 if (len < 16) { /* Minimum size of an RMCP+ msg. */
3034 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3035 ipmi_log(IPMI_LOG_DEBUG,
3036 "%sDropped message because too small(5)",
3037 IPMI_CONN_NAME(ipmi));
3038 goto out;
3039 }
3040
3041 encrypted = data[5] & 0x80;
3042 authenticated = data[5] & 0x40;
3043 payload_type = data[5] & 0x3f;
3044
3045 tmsg = data+6;
3046 if (payload_type == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT) {
3047 if (len < 22) { /* Minimum size of an RMCP+ type 2 msg. */
3048 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3049 ipmi_log(IPMI_LOG_DEBUG,
3050 "%sDropped message because too small(6)",
3051 IPMI_CONN_NAME(ipmi));
3052 goto out;
3053 }
3054 memcpy(oem_iana, tmsg, 3);
3055 tmsg += 4;
3056 #if 0
3057 /* FIXME - add handling of OEM payloads. */
3058 oem_payload_id = ipmi_get_uint16(tmsg);
3059 #endif
3060 tmsg += 2;
3061 }
3062
3063 session_id = ipmi_get_uint32(tmsg);
3064 tmsg += 4;
3065 if (session_id != lan->ip[addr_num].session_id) {
3066 add_stat(ipmi, STAT_BAD_SESSION_ID, 1);
3067 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3068 ipmi_log(IPMI_LOG_DEBUG,
3069 "%sDropped message not valid session id (2)",
3070 IPMI_CONN_NAME(ipmi));
3071 goto out;
3072 }
3073
3074 session_seq = ipmi_get_uint32(tmsg);
3075 tmsg += 4;
3076
3077 payload_len = ipmi_get_uint16(tmsg);
3078 tmsg += 2;
3079
3080 header_len = tmsg - data;
3081 if ((header_len + payload_len) > len) {
3082 add_stat(ipmi, STAT_BAD_SIZE, 1);
3083 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3084 ipmi_log(IPMI_LOG_DEBUG,
3085 "%sDropped message payload length doesn't match up",
3086 IPMI_CONN_NAME(ipmi));
3087 goto out;
3088 }
3089
3090 /* Authenticate the message before we do anything else. */
3091 if (authenticated) {
3092 unsigned int pad_len;
3093 unsigned int integ_len;
3094
3095 if (lan->ip[addr_num].working_integ
3096 == IPMI_LANP_INTEGRITY_ALGORITHM_NONE)
3097 {
3098 add_stat(ipmi, STAT_INVALID_AUTH, 1);
3099 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3100 ipmi_log(IPMI_LOG_DEBUG,
3101 "%sGot authenticated msg but authentication"
3102 " not available", IPMI_CONN_NAME(ipmi));
3103 goto out;
3104 }
3105
3106 /* Increase the length to include the padding; this eases the
3107 handling for the payload integrity check. */
3108 integ_len = header_len + payload_len;
3109 while ((integ_len < len) && (data[integ_len] == 0xff))
3110 integ_len++;
3111 if (integ_len < len)
3112 integ_len++;
3113
3114 rv = lan->ip[addr_num].integ_info->integ_check
3115 (ipmi,
3116 lan->ip[addr_num].integ_data,
3117 data,
3118 integ_len,
3119 len);
3120 if (rv) {
3121 add_stat(ipmi, STAT_AUTH_FAIL, 1);
3122 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3123 ipmi_log(IPMI_LOG_DEBUG, "%sIntegrity failed",
3124 IPMI_CONN_NAME(ipmi));
3125 goto out;
3126 }
3127
3128 /* Remove the integrity padding. */
3129 pad_len = data[integ_len-1] + 1;
3130 if ((integ_len - header_len - pad_len) != payload_len) {
3131 add_stat(ipmi, STAT_BAD_SIZE, 1);
3132 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3133 ipmi_log(IPMI_LOG_DEBUG, "%sPadding size not valid: %d",
3134 IPMI_CONN_NAME(ipmi), pad_len);
3135 goto out;
3136 }
3137 }
3138
3139 /* The packet is good, we can trust the data in it now. */
3140
3141 /* If it's from a down connection, report it as up. */
3142 ipmi_lock(lan->ip_lock);
3143 if (! lan->ip[addr_num].working) {
3144 ipmi_unlock(lan->ip_lock);
3145 connection_up(lan, addr_num, 0);
3146 ipmi_lock(lan->ip_lock);
3147 }
3148
3149 if (authenticated)
3150 rv = check_20_session_seq_num(lan, session_seq,
3151 &(lan->ip[addr_num].inbound_seq_num),
3152 &(lan->ip[addr_num].recv_msg_map));
3153 else if (session_id == 0)
3154 rv = 0; /* seq num not used for out-of-session messages. */
3155 else
3156 rv = check_20_session_seq_num(lan, session_seq,
3157 &(lan->ip[addr_num].unauth_in_seq_num),
3158 &(lan->ip[addr_num].unauth_recv_msg_map));
3159 ipmi_unlock(lan->ip_lock);
3160 if (rv) {
3161 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3162 ipmi_log(IPMI_LOG_DEBUG, "%sInvalid sequence number",
3163 IPMI_CONN_NAME(ipmi));
3164 add_stat(ipmi, STAT_SEQ_OUT_OF_RANGE, 1);
3165 goto out;
3166 }
3167
3168 /* Message is in sequence, so it's good to deliver after we
3169 decrypt it. */
3170
3171 if (encrypted) {
3172 if (lan->ip[addr_num].working_conf
3173 == IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE)
3174 {
3175 add_stat(ipmi, STAT_INVALID_AUTH, 1);
3176 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3177 ipmi_log(IPMI_LOG_DEBUG,
3178 "%sGot encrypted msg but encryption not available",
3179 IPMI_CONN_NAME(ipmi));
3180 goto out;
3181 }
3182
3183 rv = lan->ip[addr_num].conf_info->conf_decrypt
3184 (ipmi, lan->ip[addr_num].conf_data, &tmsg, &payload_len);
3185 if (rv) {
3186 add_stat(ipmi, STAT_DECRYPT_FAIL, 1);
3187 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3188 ipmi_log(IPMI_LOG_DEBUG, "%sDecryption failed",
3189 IPMI_CONN_NAME(ipmi));
3190 goto out;
3191 }
3192 }
3193
3194 handle_payload(ipmi, lan, addr_num, payload_type, tmsg, payload_len);
3195
3196 out:
3197 return;
3198 }
3199
3200 static void
handle_lan15_recv(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,unsigned char * data,unsigned int len)3201 handle_lan15_recv(ipmi_con_t *ipmi,
3202 lan_data_t *lan,
3203 int addr_num,
3204 unsigned char *data,
3205 unsigned int len)
3206 {
3207 uint32_t seq, sess_id;
3208 unsigned char *tmsg = NULL;
3209 unsigned int data_len;
3210 int rv;
3211
3212 if ((data[4] & 0x0f) == IPMI_AUTHTYPE_NONE) {
3213 if (len < 14) { /* Minimum size of an IPMI msg. */
3214 add_stat(ipmi, STAT_TOO_SHORT, 1);
3215 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3216 ipmi_log(IPMI_LOG_DEBUG,
3217 "%sDropped message because too small(1)",
3218 IPMI_CONN_NAME(ipmi));
3219 goto out;
3220 }
3221
3222 /* No authentication. */
3223 if (len < (unsigned int) (data[13] + 14)) {
3224 /* Not enough data was supplied, reject the message. */
3225 add_stat(ipmi, STAT_TOO_SHORT, 1);
3226 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3227 ipmi_log(IPMI_LOG_DEBUG,
3228 "%sDropped message because too small(2)",
3229 IPMI_CONN_NAME(ipmi));
3230 goto out;
3231 }
3232 data_len = data[13];
3233 } else {
3234 if (len < 30) { /* Minimum size of an authenticated IPMI msg. */
3235 add_stat(ipmi, STAT_TOO_SHORT, 1);
3236 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3237 ipmi_log(IPMI_LOG_DEBUG,
3238 "%sDropped message because too small(3)",
3239 IPMI_CONN_NAME(ipmi));
3240 goto out;
3241 }
3242 /* authcode in message, add 16 to the above checks. */
3243 if (len < (unsigned int) (data[29] + 30)) {
3244 add_stat(ipmi, STAT_TOO_SHORT, 1);
3245 /* Not enough data was supplied, reject the message. */
3246 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3247 ipmi_log(IPMI_LOG_DEBUG,
3248 "%sDropped message because too small(4)",
3249 IPMI_CONN_NAME(ipmi));
3250 goto out;
3251 }
3252 data_len = data[29];
3253 }
3254
3255 /* FIXME - need a lock on the session data. */
3256
3257 /* Drop if the authtypes are incompatible. */
3258 if (lan->ip[addr_num].working_authtype != (data[4] & 0x0f)) {
3259 add_stat(ipmi, STAT_INVALID_AUTH, 1);
3260 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3261 ipmi_log(IPMI_LOG_DEBUG, "%sDropped message not valid authtype,"
3262 " expected %d, got %d",
3263 IPMI_CONN_NAME(ipmi),
3264 lan->ip[addr_num].working_authtype,
3265 data[4] & 0x0f);
3266 goto out;
3267 }
3268
3269 /* Drop if sessions ID's don't match. */
3270 sess_id = ipmi_get_uint32(data+9);
3271 if (sess_id != lan->ip[addr_num].session_id) {
3272 add_stat(ipmi, STAT_BAD_SESSION_ID, 1);
3273 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3274 ipmi_log(IPMI_LOG_DEBUG,
3275 "%sDropped message not valid session id",
3276 IPMI_CONN_NAME(ipmi));
3277 goto out;
3278 }
3279
3280 seq = ipmi_get_uint32(data+5);
3281
3282 if ((data[4] & 0x0f) != 0) {
3283 /* Validate the message's authcode. Do this before checking
3284 the session seq num so we know the data is valid. */
3285 rv = auth_check(lan, data+9, data+5, data+30, data[29], data+13,
3286 addr_num);
3287 if (rv) {
3288 add_stat(ipmi, STAT_AUTH_FAIL, 1);
3289 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3290 ipmi_log(IPMI_LOG_DEBUG, "%sDropped message auth fail",
3291 IPMI_CONN_NAME(ipmi));
3292 goto out;
3293 }
3294 tmsg = data + 30;
3295 } else {
3296 tmsg = data + 14;
3297 }
3298
3299 /* If it's from a down connection, report it as up. */
3300 ipmi_lock(lan->ip_lock);
3301 if (! lan->ip[addr_num].working) {
3302 ipmi_unlock(lan->ip_lock);
3303 connection_up(lan, addr_num, 0);
3304 ipmi_lock(lan->ip_lock);
3305 }
3306
3307 rv = check_15_session_seq_num(lan, seq,
3308 &(lan->ip[addr_num].inbound_seq_num),
3309 &(lan->ip[addr_num].recv_msg_map));
3310 ipmi_unlock(lan->ip_lock);
3311 if (rv)
3312 goto out;
3313
3314 /*
3315 * Special case for Serial-over-LAN IPMI 1.5 packets, which use the
3316 * "reserved" nybble to identify the SoL payload.
3317 */
3318 if ((data[4] & 0xf0) == 0x80)
3319 handle_payload(ipmi, lan, addr_num,
3320 IPMI_RMCPP_PAYLOAD_TYPE_SOL, tmsg, data_len);
3321 else
3322 handle_payload(ipmi, lan, addr_num,
3323 IPMI_RMCPP_PAYLOAD_TYPE_IPMI, tmsg, data_len);
3324
3325 out:
3326 return;
3327 }
3328
3329 static int
addr_match_lan(lan_data_t * lan,uint32_t sid,sockaddr_ip_t * addr,int * raddr_num)3330 addr_match_lan(lan_data_t *lan, uint32_t sid, sockaddr_ip_t *addr,
3331 int *raddr_num)
3332 {
3333 unsigned int addr_num;
3334
3335 /* Make sure the source address matches one we expect from
3336 this system. */
3337 for (addr_num = 0; addr_num < lan->cparm.num_ip_addr; addr_num++) {
3338 if ((!sid || (lan->ip[addr_num].session_id == sid))
3339 && lan_addr_same(&(lan->cparm.ip_addr[addr_num]), addr))
3340 {
3341 *raddr_num = addr_num;
3342 return 1;
3343 }
3344 }
3345 return 0;
3346 }
3347
3348 static ipmi_con_t *
rmcpp_find_ipmi(lan_fd_t * item,unsigned char * data,unsigned int len,sockaddr_ip_t * addr,int * addr_num)3349 rmcpp_find_ipmi(lan_fd_t *item,
3350 unsigned char *data,
3351 unsigned int len,
3352 sockaddr_ip_t *addr,
3353 int *addr_num)
3354 {
3355 /* This is easy, the session id is our slot in the fd or is a
3356 message tag. */
3357 unsigned char payload;
3358 uint32_t tag;
3359 uint32_t sid;
3360 unsigned char ctag;
3361 unsigned int mlen;
3362 unsigned char *d;
3363 ipmi_con_t *ipmi = NULL;
3364 lan_data_t *lan;
3365
3366 /* We need to find the sessions id; it's position depends on
3367 the payload type. */
3368 if (len < 16) {
3369 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3370 ipmi_log(IPMI_LOG_DEBUG, "Message too short(2): %d", len);
3371 return NULL;
3372 }
3373 payload = data[5] & 0x3f;
3374 if (payload == IPMI_RMCPP_PAYLOAD_TYPE_OEM_EXPLICIT) {
3375 if (len < 22) {
3376 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3377 ipmi_log(IPMI_LOG_DEBUG, "Message too short(3): %d", len);
3378 return NULL;
3379 }
3380 d = data+12;
3381 } else {
3382 d = data+6;
3383 }
3384
3385 mlen = ipmi_get_uint16(d+8);
3386 if ((mlen + 10 + (d-data)) > len) {
3387 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3388 ipmi_log(IPMI_LOG_DEBUG,
3389 "Dropped message payload length doesn't match up");
3390 return NULL;
3391 }
3392
3393 sid = ipmi_get_uint32(d);
3394 if ((sid == 0) && payloads[payload]->get_msg_tag) {
3395 int rv = payloads[payload]->get_msg_tag(d+10, mlen, &ctag);
3396 if (rv) {
3397 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3398 ipmi_log(IPMI_LOG_DEBUG, "Error getting message tag: %d", rv);
3399 return NULL;
3400 }
3401 tag = ctag;
3402 } else
3403 tag = sid - 1;
3404
3405 if (tag >= MAX_CONS_PER_FD) {
3406 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3407 ipmi_log(IPMI_LOG_DEBUG, "tag is out of range: %d", tag);
3408 return NULL;
3409 }
3410
3411 ipmi_lock(item->con_lock);
3412 lan = item->lan[tag];
3413 if (lan && addr_match_lan(lan, sid, addr, addr_num))
3414 ipmi = lan->ipmi;
3415 else if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3416 ipmi_log(IPMI_LOG_DEBUG, "tag doesn't match: %d", tag);
3417 ipmi_unlock(item->con_lock);
3418
3419 return ipmi;
3420 }
3421
3422 static ipmi_con_t *
rmcp_find_ipmi(lan_fd_t * item,unsigned char * data,unsigned int len,sockaddr_ip_t * addr,int * addr_num)3423 rmcp_find_ipmi(lan_fd_t *item,
3424 unsigned char *data,
3425 unsigned int len,
3426 sockaddr_ip_t *addr,
3427 int *addr_num)
3428 {
3429 /* Old RMCP is harder, we have to hunt. */
3430 uint32_t sid;
3431 lan_data_t *lan;
3432 int i;
3433 ipmi_con_t *ipmi = NULL;
3434
3435 if (len < 13) {
3436 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3437 ipmi_log(IPMI_LOG_DEBUG, "Message too short(4): %d", len);
3438 return NULL;
3439 }
3440
3441 sid = ipmi_get_uint32(data+9);
3442 ipmi_lock(item->con_lock);
3443 for (i=0; i<MAX_CONS_PER_FD; i++) {
3444 lan = item->lan[i];
3445 if (lan && addr_match_lan(lan, sid, addr, addr_num)) {
3446 ipmi = lan->ipmi;
3447 break;
3448 }
3449 }
3450 ipmi_unlock(item->con_lock);
3451
3452 return ipmi;
3453 }
3454
3455 static void
data_handler(int fd,void * cb_data,os_hnd_fd_id_t * id)3456 data_handler(int fd,
3457 void *cb_data,
3458 os_hnd_fd_id_t *id)
3459 {
3460 lan_fd_t *item = cb_data;
3461 ipmi_con_t *ipmi;
3462 lan_data_t *lan;
3463 unsigned char data[IPMI_MAX_LAN_LEN];
3464 sockaddr_ip_t ipaddrd;
3465 socklen_t from_len;
3466 int len;
3467 int addr_num = 0; /* Keep gcc happy and initialize */
3468
3469 from_len = sizeof(ipaddrd.s_ipsock);
3470 len = recvfrom(fd, data, sizeof(data), 0, (struct sockaddr *)&ipaddrd,
3471 &from_len);
3472
3473 if (len < 0)
3474 /* Got an error, probably no data, just return. */
3475 return;
3476
3477 ipaddrd.ip_addr_len = from_len;
3478 if (DEBUG_RAWMSG) {
3479 ipmi_log(IPMI_LOG_DEBUG_START, "incoming\n addr = ");
3480 dump_hex((unsigned char *) &ipaddrd, from_len);
3481 if (len) {
3482 ipmi_log(IPMI_LOG_DEBUG_CONT, "\n data =\n ");
3483 dump_hex(data, len);
3484 }
3485 ipmi_log(IPMI_LOG_DEBUG_END, " ");
3486 }
3487
3488 if (len < 5) {
3489 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3490 ipmi_log(IPMI_LOG_DEBUG, "Message too short(1): %d", len);
3491 return;
3492 }
3493
3494 /* Validate the RMCP portion of the message. */
3495 if ((data[0] != 6)
3496 || (data[2] != 0xff)
3497 || (data[3] != 0x07))
3498 {
3499 if (DEBUG_RAWMSG || DEBUG_MSG_ERR)
3500 ipmi_log(IPMI_LOG_DEBUG, "Dropped message not valid IPMI/RMCP");
3501 return;
3502 }
3503
3504 if ((data[4] & 0x0f) == IPMI_AUTHTYPE_RMCP_PLUS) {
3505 ipmi = rmcpp_find_ipmi(item, data, len, &ipaddrd, &addr_num);
3506 } else {
3507 ipmi = rmcp_find_ipmi(item, data, len, &ipaddrd, &addr_num);
3508 }
3509
3510 if (!lan_valid_ipmi(ipmi))
3511 /* This can fail due to a race condition, just return and
3512 everything should be fine. */
3513 return;
3514
3515 lan = ipmi->con_data;
3516
3517 add_stat(ipmi, STAT_RECV_PACKETS, 1);
3518
3519 if ((data[4] & 0x0f) == IPMI_AUTHTYPE_RMCP_PLUS) {
3520 handle_rmcpp_recv(ipmi, lan, addr_num, data, len);
3521 } else {
3522 handle_lan15_recv(ipmi, lan, addr_num, data, len);
3523 }
3524
3525 lan_put(ipmi);
3526 return;
3527 }
3528
3529 /* Note that this puts the address number in data4 of the rspi. */
3530 int
ipmi_lan_send_command_forceip(ipmi_con_t * ipmi,int addr_num,ipmi_addr_t * addr,unsigned int addr_len,ipmi_msg_t * msg,ipmi_ll_rsp_handler_t rsp_handler,ipmi_msgi_t * rspi)3531 ipmi_lan_send_command_forceip(ipmi_con_t *ipmi,
3532 int addr_num,
3533 ipmi_addr_t *addr,
3534 unsigned int addr_len,
3535 ipmi_msg_t *msg,
3536 ipmi_ll_rsp_handler_t rsp_handler,
3537 ipmi_msgi_t *rspi)
3538 {
3539 lan_timer_info_t *info;
3540 lan_data_t *lan;
3541 int rv;
3542 /* We store the address number in data4. */
3543
3544 if (addr_num >= MAX_IP_ADDR)
3545 return EINVAL;
3546
3547 if (addr_len > sizeof(ipmi_addr_t))
3548 return EINVAL;
3549
3550 if (msg->data_len > IPMI_MAX_MSG_LENGTH)
3551 return EINVAL;
3552
3553 lan = (lan_data_t *) ipmi->con_data;
3554
3555 if (lan->in_cleanup)
3556 return ECANCELED;
3557
3558 /* Odd netfns are responses or unacknowledged data. Just send
3559 them. */
3560 if (msg->netfn & 1)
3561 return lan_send_addr(lan, addr, addr_len, msg, 0, addr_num, NULL);
3562
3563 info = ipmi_mem_alloc(sizeof(*info));
3564 if (!info)
3565 return ENOMEM;
3566 memset(info, 0, sizeof(*info));
3567
3568 /* Put it in the list first. */
3569 info->ipmi = ipmi;
3570 info->cancelled = 0;
3571
3572 rv = ipmi->os_hnd->alloc_timer(ipmi->os_hnd, &(info->timer));
3573 if (rv) {
3574 ipmi_mem_free(info);
3575 return rv;
3576 }
3577
3578 ipmi_lock(lan->seq_num_lock);
3579
3580 if (lan->outstanding_msg_count >= 60) {
3581 rv = EAGAIN;
3582 goto out_unlock;
3583 }
3584
3585 rspi->data4 = (void *) (long) addr_num;
3586 rv = handle_msg_send(info, addr_num, addr, addr_len, msg,
3587 rsp_handler, rspi, 0);
3588 /* handle_msg_send handles freeing the timer and info on an error */
3589 info = NULL;
3590 if (! rv)
3591 lan->outstanding_msg_count++;
3592 ipmi_unlock(lan->seq_num_lock);
3593 return rv;
3594
3595 out_unlock:
3596 ipmi_unlock(lan->seq_num_lock);
3597 if (rv) {
3598 if (info) {
3599 if (info->timer)
3600 ipmi->os_hnd->free_timer(ipmi->os_hnd, info->timer);
3601 ipmi_mem_free(info);
3602 }
3603 }
3604 return rv;
3605 }
3606
3607 static int
lan_send_command_option(ipmi_con_t * ipmi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg,const ipmi_con_option_t * options,ipmi_ll_rsp_handler_t rsp_handler,ipmi_msgi_t * trspi)3608 lan_send_command_option(ipmi_con_t *ipmi,
3609 const ipmi_addr_t *addr,
3610 unsigned int addr_len,
3611 const ipmi_msg_t *msg,
3612 const ipmi_con_option_t *options,
3613 ipmi_ll_rsp_handler_t rsp_handler,
3614 ipmi_msgi_t *trspi)
3615 {
3616 lan_timer_info_t *info;
3617 lan_data_t *lan;
3618 int rv;
3619 ipmi_msgi_t *rspi = trspi;
3620 int side_effects = 0;
3621 int i;
3622
3623
3624 if (addr_len > sizeof(ipmi_addr_t))
3625 return EINVAL;
3626
3627 if (msg->data_len > IPMI_MAX_MSG_LENGTH)
3628 return EINVAL;
3629
3630 lan = (lan_data_t *) ipmi->con_data;
3631
3632 /* Odd netfns are responses or unacknowledged data. Just send
3633 them. */
3634 if (msg->netfn & 1) {
3635 int dummy_send_ip;
3636 return lan_send(lan, addr, addr_len, msg, 0, &dummy_send_ip, options);
3637 }
3638
3639 if (options) {
3640 for (i=0; options[i].option != IPMI_CON_OPTION_LIST_END; i++) {
3641 if (options[i].option == IPMI_CON_MSG_OPTION_SIDE_EFFECTS)
3642 side_effects = options[i].ival;
3643 }
3644 }
3645
3646 if (!rspi) {
3647 rspi = ipmi_mem_alloc(sizeof(*rspi));
3648 if (!rspi)
3649 return ENOMEM;
3650 }
3651
3652 info = ipmi_mem_alloc(sizeof(*info));
3653 if (!info) {
3654 rv = ENOMEM;
3655 goto out_unlock2;
3656 }
3657 memset(info, 0, sizeof(*info));
3658
3659 /* Put it in the list first. */
3660 info->ipmi = ipmi;
3661 info->cancelled = 0;
3662
3663 rv = ipmi->os_hnd->alloc_timer(ipmi->os_hnd, &(info->timer));
3664 if (rv)
3665 goto out_unlock;
3666
3667 ipmi_lock(lan->seq_num_lock);
3668
3669 if (lan->outstanding_msg_count >= lan->max_outstanding_msg_count) {
3670 lan_wait_queue_t *q_item;
3671
3672 q_item = ipmi_mem_alloc(sizeof(*q_item));
3673 if (!q_item) {
3674 ipmi->os_hnd->free_timer(ipmi->os_hnd, info->timer);
3675 rv = ENOMEM;
3676 goto out_unlock;
3677 }
3678
3679 q_item->info = info;
3680 memcpy(&(q_item->addr), addr, addr_len);
3681 q_item->addr_len = addr_len;
3682 memcpy(&q_item->msg, msg, sizeof(q_item->msg));
3683 q_item->msg.data = q_item->data;
3684 memcpy(q_item->data, msg->data, msg->data_len);
3685 q_item->rsp_handler = rsp_handler;
3686 q_item->rsp_item = rspi;
3687 q_item->side_effects = side_effects;
3688
3689 /* Add it to the end of the queue. */
3690 q_item->next = NULL;
3691 if (lan->wait_q_tail == NULL) {
3692 lan->wait_q_tail = q_item;
3693 lan->wait_q = q_item;
3694 } else {
3695 lan->wait_q_tail->next = q_item;
3696 lan->wait_q_tail = q_item;
3697 }
3698 goto out_unlock;
3699 }
3700
3701 rv = handle_msg_send(info, -1, addr, addr_len, msg,
3702 rsp_handler, rspi, side_effects);
3703 /* handle_msg_send handles freeing the timer and info on an error */
3704 info = NULL;
3705 if (!rv)
3706 lan->outstanding_msg_count++;
3707 else if (!trspi && rspi)
3708 /* If we allocated an rspi, free it on error. */
3709 ipmi_mem_free(rspi);
3710 ipmi_unlock(lan->seq_num_lock);
3711 return rv;
3712
3713 out_unlock:
3714 ipmi_unlock(lan->seq_num_lock);
3715 if (rv) {
3716 if (info) {
3717 if (info->timer)
3718 ipmi->os_hnd->free_timer(ipmi->os_hnd, info->timer);
3719 ipmi_mem_free(info);
3720 }
3721 }
3722 out_unlock2:
3723 if (rv) {
3724 /* If we allocated an rspi, free it. */
3725 if (!trspi && rspi)
3726 ipmi_mem_free(rspi);
3727 }
3728 return rv;
3729 }
3730
3731 static int
lan_send_command(ipmi_con_t * ipmi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg,ipmi_ll_rsp_handler_t rsp_handler,ipmi_msgi_t * trspi)3732 lan_send_command(ipmi_con_t *ipmi,
3733 const ipmi_addr_t *addr,
3734 unsigned int addr_len,
3735 const ipmi_msg_t *msg,
3736 ipmi_ll_rsp_handler_t rsp_handler,
3737 ipmi_msgi_t *trspi)
3738 {
3739 return lan_send_command_option(ipmi, addr, addr_len, msg, NULL,
3740 rsp_handler, trspi);
3741 }
3742
3743 static int
lan_send_response(ipmi_con_t * ipmi,const ipmi_addr_t * addr,unsigned int addr_len,const ipmi_msg_t * msg,long sequence)3744 lan_send_response(ipmi_con_t *ipmi,
3745 const ipmi_addr_t *addr,
3746 unsigned int addr_len,
3747 const ipmi_msg_t *msg,
3748 long sequence)
3749 {
3750 return ENOSYS;
3751 }
3752
3753 static int
lan_register_for_command(ipmi_con_t * ipmi,unsigned char netfn,unsigned char cmd,ipmi_ll_cmd_handler_t handler,void * cmd_data,void * data2,void * data3)3754 lan_register_for_command(ipmi_con_t *ipmi,
3755 unsigned char netfn,
3756 unsigned char cmd,
3757 ipmi_ll_cmd_handler_t handler,
3758 void *cmd_data,
3759 void *data2,
3760 void *data3)
3761 {
3762 return ENOSYS;
3763 }
3764
3765 static int
lan_deregister_for_command(ipmi_con_t * ipmi,unsigned char netfn,unsigned char cmd)3766 lan_deregister_for_command(ipmi_con_t *ipmi,
3767 unsigned char netfn,
3768 unsigned char cmd)
3769 {
3770 return ENOSYS;
3771 }
3772
3773 static unsigned int
lan_get_num_ports(ipmi_con_t * ipmi)3774 lan_get_num_ports(ipmi_con_t *ipmi)
3775 {
3776 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
3777
3778 return lan->cparm.num_ip_addr;
3779 }
3780
3781 static int
lan_get_port_info(ipmi_con_t * ipmi,unsigned int port,char * info,int * info_len)3782 lan_get_port_info(ipmi_con_t *ipmi, unsigned int port,
3783 char *info, int *info_len)
3784 {
3785 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
3786 sockaddr_ip_t *a;
3787 int count = 0;
3788 int len = *info_len;
3789
3790 if (port > lan->cparm.num_ip_addr)
3791 return EINVAL;
3792
3793 a = &(lan->cparm.ip_addr[port]);
3794
3795 if (lan->ip[port].working_authtype == IPMI_AUTHTYPE_RMCP_PLUS)
3796 count = snprintf(info, len, "rmcp+: ");
3797 else
3798 count = snprintf(info, len, "rmcp: ");
3799
3800 switch (a->s_ipsock.s_addr0.sa_family) {
3801 case PF_INET:
3802 {
3803 struct sockaddr_in *ip = &a->s_ipsock.s_addr4;
3804 char buf[INET_ADDRSTRLEN];
3805
3806 inet_ntop(AF_INET, &ip->sin_addr, buf, sizeof(buf));
3807 count += snprintf(info+count, len-count, "inet:%s:%d",
3808 buf, ntohs(ip->sin_port));
3809 }
3810 break;
3811
3812 #ifdef PF_INET6
3813 case PF_INET6:
3814 {
3815 struct sockaddr_in6 *ip = &a->s_ipsock.s_addr6;
3816 char buf[INET6_ADDRSTRLEN];
3817
3818 inet_ntop(AF_INET6, &ip->sin6_addr, buf, sizeof(buf));
3819 count += snprintf(info+count, len-count, "inet6:%s:%d",
3820 buf, ntohs(ip->sin6_port));
3821 }
3822 break;
3823 #endif
3824 default:
3825 count += snprintf(info+count, len-count, "invalid");
3826 break;
3827 }
3828
3829 *info_len = count;
3830 return 0;
3831 }
3832
3833 static void *
auth_alloc(void * info,int size)3834 auth_alloc(void *info, int size)
3835 {
3836 return ipmi_mem_alloc(size);
3837 }
3838
3839 static void
auth_free(void * info,void * data)3840 auth_free(void *info, void *data)
3841 {
3842 ipmi_mem_free(data);
3843 }
3844
3845 /* Send the final close session to shut the connection down. */
3846 static void
send_close_session(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num)3847 send_close_session(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num)
3848 {
3849 ipmi_msg_t msg;
3850 unsigned char data[4];
3851 ipmi_system_interface_addr_t si;
3852
3853 si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
3854 si.channel = 0xf;
3855 si.lun = 0;
3856 msg.netfn = IPMI_APP_NETFN;
3857 msg.cmd = IPMI_CLOSE_SESSION_CMD;
3858 msg.data_len = 4;
3859 msg.data = data;
3860 if (lan->ip[addr_num].working_authtype == IPMI_AUTHTYPE_RMCP_PLUS)
3861 ipmi_set_uint32(data, lan->ip[addr_num].mgsys_session_id);
3862 else
3863 ipmi_set_uint32(data, lan->ip[addr_num].session_id);
3864 lan_send_addr(lan, (ipmi_addr_t *) &si, sizeof(si), &msg, 0, addr_num,
3865 NULL);
3866 }
3867
3868 typedef struct lan_unreg_stat_info_s
3869 {
3870 lan_data_t *lan;
3871 ipmi_ll_stat_info_t *cmpinfo;
3872 int found;
3873 } lan_unreg_stat_info_t;
3874
3875 static int
lan_unreg_stat_info(void * cb_data,void * item1,void * item2)3876 lan_unreg_stat_info(void *cb_data, void *item1, void *item2)
3877 {
3878 ipmi_ll_stat_info_t *info = item2;
3879 lan_stat_info_t *stat = item1;
3880 lan_unreg_stat_info_t *sinfo = cb_data;
3881 int i;
3882
3883 if (!sinfo->cmpinfo || (sinfo->cmpinfo == info)) {
3884 locked_list_remove(sinfo->lan->lan_stat_list, stat, info);
3885 for (i=0; i<NUM_STATS; i++)
3886 if (stat->stats[i]) {
3887 ipmi_ll_con_stat_call_unregister(info, stat->stats[i]);
3888 stat->stats[i] = NULL;
3889 }
3890 ipmi_mem_free(stat);
3891 sinfo->found = 1;
3892 }
3893 return LOCKED_LIST_ITER_CONTINUE;
3894 }
3895
3896 static void
cleanup_con(ipmi_con_t * ipmi)3897 cleanup_con(ipmi_con_t *ipmi)
3898 {
3899 lan_data_t *lan = NULL;
3900 unsigned int i;
3901
3902 if (ipmi) {
3903 lan = (lan_data_t *) ipmi->con_data;
3904 ipmi_con_attr_cleanup(ipmi);
3905 if (ipmi->name) {
3906 ipmi_mem_free(ipmi->name);
3907 ipmi->name = NULL;
3908 }
3909 ipmi_mem_free(ipmi);
3910 }
3911
3912 if (lan) {
3913 /* This is only called in the case of an error at startup, so
3914 there is no need to remove it from the LAN lists (hashes),
3915 because it won't be there yet. */
3916
3917 for (i=0; i<lan->cparm.num_ip_addr; i++) {
3918 if (lan->cparm.ip_addr_str[i])
3919 ipmi_mem_free(lan->cparm.ip_addr_str[i]);
3920 if (lan->cparm.ip_port_str[i])
3921 ipmi_mem_free(lan->cparm.ip_port_str[i]);
3922 }
3923
3924 if (lan->lan_stat_list) {
3925 lan_unreg_stat_info_t sinfo;
3926 sinfo.lan = lan;
3927 sinfo.cmpinfo = NULL;
3928 sinfo.found = 0;
3929 locked_list_iterate(lan->lan_stat_list, lan_unreg_stat_info,
3930 &sinfo);
3931 locked_list_destroy(lan->lan_stat_list);
3932 }
3933 if (lan->con_change_lock)
3934 ipmi_destroy_lock(lan->con_change_lock);
3935 if (lan->ip_lock)
3936 ipmi_destroy_lock(lan->ip_lock);
3937 if (lan->con_change_handlers)
3938 locked_list_destroy(lan->con_change_handlers);
3939 if (lan->event_handlers)
3940 locked_list_destroy(lan->event_handlers);
3941 if (lan->ipmb_change_handlers)
3942 locked_list_destroy(lan->ipmb_change_handlers);
3943 if (lan->seq_num_lock)
3944 ipmi_destroy_lock(lan->seq_num_lock);
3945 if (lan->fd)
3946 release_lan_fd(lan->fd, lan->fd_slot);
3947 if (lan->authdata)
3948 ipmi_auths[lan->chosen_authtype].authcode_cleanup(lan->authdata);
3949 for (i=0; i<MAX_IP_ADDR; i++) {
3950 if (lan->ip[i].conf_data)
3951 lan->ip[i].conf_info->conf_free(ipmi, lan->ip[i].conf_data);
3952 if (lan->ip[i].integ_data)
3953 lan->ip[i].integ_info->integ_free(ipmi, lan->ip[i].integ_data);
3954 }
3955 /* paranoia */
3956 memset(lan->cparm.password, 0, sizeof(lan->cparm.password));
3957 memset(lan->cparm.bmc_key, 0, sizeof(lan->cparm.bmc_key));
3958 ipmi_mem_free(lan);
3959 }
3960 }
3961
3962 static void
lan_cleanup(ipmi_con_t * ipmi)3963 lan_cleanup(ipmi_con_t *ipmi)
3964 {
3965 lan_data_t *lan = ipmi->con_data;
3966 int rv;
3967 unsigned int i;
3968
3969 /* After this point no other operations can occur on this ipmi
3970 interface, so it's safe. */
3971
3972 if (!lan->disabled) {
3973 for (i=0; i<lan->cparm.num_ip_addr; i++)
3974 send_close_session(ipmi, lan, i);
3975 }
3976
3977 lan->in_cleanup = 1;
3978
3979 ipmi_lock(lan->seq_num_lock);
3980 for (i=0; i<64; i++) {
3981 if (lan->seq_table[i].inuse) {
3982 ipmi_ll_rsp_handler_t handler;
3983 ipmi_msgi_t *rspi;
3984 lan_timer_info_t *info;
3985
3986 rv = ipmi->os_hnd->stop_timer(ipmi->os_hnd,
3987 lan->seq_table[i].timer);
3988
3989 rspi = lan->seq_table[i].rsp_item;
3990
3991 if (lan->seq_table[i].use_orig_addr) {
3992 /* We did an address translation, so translate back. */
3993 memcpy(&rspi->addr, &lan->seq_table[i].orig_addr,
3994 lan->seq_table[i].orig_addr_len);
3995 rspi->addr_len = lan->seq_table[i].orig_addr_len;
3996 } else {
3997 memcpy(&rspi->addr, &(lan->seq_table[i].addr),
3998 lan->seq_table[i].addr_len);
3999 rspi->addr_len = lan->seq_table[i].addr_len;
4000 }
4001 handler = lan->seq_table[i].rsp_handler;
4002 info = lan->seq_table[i].timer_info;
4003
4004 rspi->msg.netfn = lan->seq_table[i].msg.netfn | 1;
4005 rspi->msg.cmd = lan->seq_table[i].msg.cmd;
4006 rspi->msg.data = rspi->data;
4007 rspi->data[0] = IPMI_UNKNOWN_ERR_CC;
4008 rspi->msg.data_len = 1;
4009
4010 lan->seq_table[i].inuse = 0;
4011
4012 /* Wait until here to free the info, as we use it above.
4013 But we must be holding the lock while we do this. */
4014 if (rv)
4015 info->cancelled = 1;
4016 else {
4017 ipmi->os_hnd->free_timer(ipmi->os_hnd, info->timer);
4018 ipmi_mem_free(info);
4019 }
4020
4021 ipmi_unlock(lan->seq_num_lock);
4022
4023 /* The unlock is safe here because the connection is no
4024 longer valid and thus nothing else can really happen on
4025 this connection. Sends will fail and receives will not
4026 validate. */
4027
4028 ipmi_handle_rsp_item(NULL, rspi, handler);
4029
4030 ipmi_lock(lan->seq_num_lock);
4031 }
4032 }
4033 while (lan->wait_q != NULL) {
4034 lan_wait_queue_t *q_item;
4035
4036 q_item = lan->wait_q;
4037 lan->wait_q = q_item->next;
4038
4039 ipmi->os_hnd->free_timer(ipmi->os_hnd, q_item->info->timer);
4040
4041 if (!lan->disabled) {
4042 ipmi_unlock(lan->seq_num_lock);
4043
4044 q_item->msg.netfn |= 1; /* Convert it to a response. */
4045 q_item->msg.data[0] = IPMI_UNKNOWN_ERR_CC;
4046 q_item->msg.data_len = 1;
4047 ipmi_handle_rsp_item_copyall(ipmi, q_item->rsp_item,
4048 &q_item->addr, q_item->addr_len,
4049 &q_item->msg, q_item->rsp_handler);
4050
4051 ipmi_lock(lan->seq_num_lock);
4052 }
4053
4054 ipmi_mem_free(q_item->info);
4055 ipmi_mem_free(q_item);
4056 }
4057 if (lan->audit_info) {
4058 rv = ipmi->os_hnd->stop_timer(ipmi->os_hnd, lan->audit_timer);
4059 if (rv)
4060 lan->audit_info->cancelled = 1;
4061 else {
4062 ipmi->os_hnd->free_timer(ipmi->os_hnd, lan->audit_timer);
4063 ipmi_mem_free(lan->audit_info);
4064 }
4065 }
4066 ipmi_unlock(lan->seq_num_lock);
4067
4068 if (lan->close_done)
4069 lan->close_done(ipmi, lan->close_cb_data);
4070
4071 if (ipmi->oem_data_cleanup)
4072 ipmi->oem_data_cleanup(ipmi);
4073
4074 cleanup_con(ipmi);
4075 }
4076
4077 static int
lan_close_connection_done(ipmi_con_t * ipmi,ipmi_ll_con_closed_cb handler,void * cb_data)4078 lan_close_connection_done(ipmi_con_t *ipmi,
4079 ipmi_ll_con_closed_cb handler,
4080 void *cb_data)
4081 {
4082 lan_data_t *lan;
4083
4084 if (! lan_valid_ipmi(ipmi))
4085 return EINVAL;
4086
4087 lan = (lan_data_t *) ipmi->con_data;
4088
4089 ipmi_lock(lan_list_lock);
4090 if (lan->users > 1) {
4091 /* The connection has been reused, just report it going
4092 down. */
4093 lan->users--;
4094 ipmi_unlock(lan_list_lock);
4095 if (handler)
4096 handler(ipmi, cb_data);
4097 lan_put(ipmi);
4098 return 0;
4099 }
4100
4101 /* Once we begin the shutdown process, we don't want anyone else
4102 reusing the connection. */
4103 lan_remove_con_nolock(lan);
4104 ipmi_unlock(lan_list_lock);
4105
4106 lan->close_done = handler;
4107 lan->close_cb_data = cb_data;
4108
4109 /* Put it once for the lan_valid_ipmi() call, then once to
4110 actually destroy it. */
4111 lan_put(ipmi);
4112 lan_put(ipmi);
4113 return 0;
4114 }
4115
4116 static int
lan_close_connection(ipmi_con_t * ipmi)4117 lan_close_connection(ipmi_con_t *ipmi)
4118 {
4119 return lan_close_connection_done(ipmi, NULL, NULL);
4120 }
4121
4122 static void
handle_connected(ipmi_con_t * ipmi,int err,int addr_num)4123 handle_connected(ipmi_con_t *ipmi, int err, int addr_num)
4124 {
4125 lan_data_t *lan;
4126
4127 if (!ipmi)
4128 return;
4129
4130 lan = (lan_data_t *) ipmi->con_data;
4131
4132 /* This should be occurring single-threaded (the IP is down and is
4133 being brought back up or is initially coming up), so no need
4134 for a lock here. */
4135
4136 /* Make sure session data is reset on an error. */
4137 if (err)
4138 reset_session_data(lan, addr_num);
4139
4140 ipmi_lock(lan->ip_lock);
4141 ipmi_lock(lan->con_change_lock);
4142 ipmi_unlock(lan->ip_lock);
4143 call_con_change_handlers(lan, err, addr_num, lan->connected);
4144 ipmi_unlock(lan->con_change_lock);
4145 }
4146
4147 static void
finish_connection(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num)4148 finish_connection(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num)
4149 {
4150 lan->connected = 1;
4151 connection_up(lan, addr_num, 1);
4152 if (! lan->initialized) {
4153 lan->initialized = 1;
4154 handle_connected(ipmi, 0, addr_num);
4155 }
4156 }
4157
4158 static void
lan_set_ipmb_addr(ipmi_con_t * ipmi,const unsigned char ipmb_addr[],unsigned int num_ipmb_addr,int active,unsigned int hacks)4159 lan_set_ipmb_addr(ipmi_con_t *ipmi,
4160 const unsigned char ipmb_addr[],
4161 unsigned int num_ipmb_addr,
4162 int active,
4163 unsigned int hacks)
4164 {
4165 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
4166 int changed = 0;
4167 unsigned int i;
4168
4169 for (i=0; i<num_ipmb_addr && i<MAX_IPMI_USED_CHANNELS; i++) {
4170 if (! ipmb_addr[i])
4171 continue;
4172 if (lan->slave_addr[i] != ipmb_addr[i]) {
4173 lan->slave_addr[i] = ipmb_addr[i];
4174 ipmi->ipmb_addr[i] = ipmb_addr[i];
4175 changed = 1;
4176 }
4177 }
4178
4179 if (changed || (lan->is_active != active)) {
4180 lan->is_active = active;
4181 ipmi->hacks = hacks;
4182 call_ipmb_change_handlers(lan, 0, ipmb_addr, num_ipmb_addr,
4183 active, hacks);
4184 }
4185 }
4186
4187 static void
handle_ipmb_addr(ipmi_con_t * ipmi,int err,const unsigned char ipmb_addr[],unsigned int num_ipmb_addr,int active,unsigned int hacks,void * cb_data)4188 handle_ipmb_addr(ipmi_con_t *ipmi,
4189 int err,
4190 const unsigned char ipmb_addr[],
4191 unsigned int num_ipmb_addr,
4192 int active,
4193 unsigned int hacks,
4194 void *cb_data)
4195 {
4196 lan_data_t *lan;
4197 unsigned int addr_num = (unsigned long) cb_data;
4198 unsigned int i;
4199
4200 if (err) {
4201 handle_connected(ipmi, err, addr_num);
4202 return;
4203 }
4204
4205 if (!ipmi) {
4206 handle_connected(ipmi, ECANCELED, addr_num);
4207 return;
4208 }
4209
4210 lan = (lan_data_t *) ipmi->con_data;
4211
4212 for (i=0; i<num_ipmb_addr && i<MAX_IPMI_USED_CHANNELS; i++) {
4213 if (! ipmb_addr[i])
4214 continue;
4215 lan->slave_addr[i] = ipmb_addr[i];
4216 ipmi->ipmb_addr[i] = ipmb_addr[i];
4217 }
4218
4219 lan->is_active = active;
4220 ipmi->hacks = hacks;
4221 finish_connection(ipmi, lan, addr_num);
4222 call_ipmb_change_handlers(lan, err, ipmb_addr, num_ipmb_addr,
4223 active, hacks);
4224 }
4225
4226 static int
handle_dev_id(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4227 handle_dev_id(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4228 {
4229 ipmi_msg_t *msg = &rspi->msg;
4230 lan_data_t *lan = NULL;
4231 int err;
4232 unsigned int manufacturer_id;
4233 unsigned int product_id;
4234 int addr_num = (long) rspi->data4;
4235
4236 if (!ipmi) {
4237 err = ECANCELED;
4238 goto out_err;
4239 }
4240
4241 lan = (lan_data_t *) ipmi->con_data;
4242
4243 if (msg->data[0] != 0) {
4244 err = IPMI_IPMI_ERR_VAL(msg->data[0]);
4245 goto out_err;
4246 }
4247
4248 if (msg->data_len < 12) {
4249 err = EINVAL;
4250 goto out_err;
4251 }
4252
4253 manufacturer_id = (msg->data[7]
4254 | (msg->data[8] << 8)
4255 | (msg->data[9] << 16));
4256 product_id = msg->data[10] | (msg->data[11] << 8);
4257
4258 if (!lan->oem_conn_handlers_called) {
4259 lan->oem_conn_handlers_called = 1;
4260 err = ipmi_check_oem_conn_handlers(ipmi, manufacturer_id, product_id);
4261 if (err)
4262 goto out_err;
4263
4264 if (ipmi->get_ipmb_addr) {
4265 /* We have a way to fetch the IPMB address, do so. */
4266 err = ipmi->get_ipmb_addr(ipmi, handle_ipmb_addr,
4267 (void *) (long) addr_num);
4268 if (err)
4269 goto out_err;
4270 } else
4271 finish_connection(ipmi, lan, addr_num);
4272 } else {
4273 finish_connection(ipmi, lan, addr_num);
4274 }
4275 return IPMI_MSG_ITEM_NOT_USED;
4276
4277 out_err:
4278 handle_connected(ipmi, err, addr_num);
4279 return IPMI_MSG_ITEM_NOT_USED;
4280 }
4281
4282 static int
send_get_dev_id(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,ipmi_msgi_t * rspi)4283 send_get_dev_id(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
4284 ipmi_msgi_t *rspi)
4285 {
4286 ipmi_msg_t msg;
4287 int rv;
4288 ipmi_system_interface_addr_t addr;
4289
4290 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
4291 addr.channel = 0xf;
4292 addr.lun = 0;
4293
4294 msg.cmd = IPMI_GET_DEVICE_ID_CMD;
4295 msg.netfn = IPMI_APP_NETFN;
4296 msg.data = NULL;
4297 msg.data_len = 0;
4298
4299 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
4300 (ipmi_addr_t *) &addr, sizeof(addr),
4301 &msg, handle_dev_id, rspi);
4302 return rv;
4303 }
4304
4305 static void
lan_oem_done(ipmi_con_t * ipmi,void * cb_data)4306 lan_oem_done(ipmi_con_t *ipmi, void *cb_data)
4307 {
4308 lan_data_t *lan;
4309 int rv;
4310 ipmi_msgi_t *rspi = cb_data;
4311 int addr_num = (long) rspi->data4;
4312
4313 if (! ipmi) {
4314 ipmi_mem_free(rspi);
4315 return;
4316 }
4317
4318 lan = (lan_data_t *) ipmi->con_data;
4319 rv = send_get_dev_id(ipmi, lan, addr_num, rspi);
4320 if (rv) {
4321 handle_connected(ipmi, rv, addr_num);
4322 ipmi_mem_free(rspi);
4323 }
4324 }
4325
4326 static int
session_privilege_set(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4327 session_privilege_set(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4328 {
4329 ipmi_msg_t *msg = &rspi->msg;
4330 lan_data_t *lan;
4331 int rv;
4332 int addr_num = (long) rspi->data4;
4333
4334 if (!ipmi) {
4335 handle_connected(ipmi, ECANCELED, addr_num);
4336 goto out;
4337 }
4338
4339 lan = (lan_data_t *) ipmi->con_data;
4340
4341 if (msg->data[0] != 0) {
4342 handle_connected(ipmi, IPMI_IPMI_ERR_VAL(msg->data[0]), addr_num);
4343 goto out;
4344 }
4345
4346 if (msg->data_len < 2) {
4347 handle_connected(ipmi, EINVAL, addr_num);
4348 goto out;
4349 }
4350
4351 if (lan->cparm.privilege != (unsigned int) (msg->data[1] & 0xf)) {
4352 /* Requested privilege level did not match. */
4353 handle_connected(ipmi, EINVAL, addr_num);
4354 goto out;
4355 }
4356
4357 rv = ipmi_conn_check_oem_handlers(ipmi, lan_oem_done, rspi);
4358 if (rv) {
4359 handle_connected(ipmi, rv, addr_num);
4360 goto out;
4361 }
4362
4363 return IPMI_MSG_ITEM_USED;
4364
4365 out:
4366 return IPMI_MSG_ITEM_NOT_USED;
4367 }
4368
4369 static int
send_set_session_privilege(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,ipmi_msgi_t * rspi)4370 send_set_session_privilege(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
4371 ipmi_msgi_t *rspi)
4372 {
4373 unsigned char data[1];
4374 ipmi_msg_t msg;
4375 int rv;
4376 ipmi_system_interface_addr_t addr;
4377
4378 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
4379 addr.channel = 0xf;
4380 addr.lun = 0;
4381
4382 data[0] = lan->cparm.privilege;
4383
4384 msg.cmd = IPMI_SET_SESSION_PRIVILEGE_CMD;
4385 msg.netfn = IPMI_APP_NETFN;
4386 msg.data = data;
4387 msg.data_len = 1;
4388
4389 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
4390 (ipmi_addr_t *) &addr, sizeof(addr),
4391 &msg, session_privilege_set, rspi);
4392 return rv;
4393 }
4394
4395 static int
check_rakp_rsp(ipmi_con_t * ipmi,ipmi_msg_t * msg,char * caller,unsigned int min_length,int addr_num)4396 check_rakp_rsp(ipmi_con_t *ipmi,
4397 ipmi_msg_t *msg,
4398 char *caller,
4399 unsigned int min_length,
4400 int addr_num)
4401 {
4402 if (!ipmi) {
4403 handle_connected(ipmi, ECANCELED, addr_num);
4404 return ECANCELED;
4405 }
4406
4407 if (msg->data_len < 2) {
4408 ipmi_log(IPMI_LOG_ERR_INFO,
4409 "%sipmi_lan.c(%s): Message data too short: %d",
4410 IPMI_CONN_NAME(ipmi), caller, msg->data_len);
4411 handle_connected(ipmi, EINVAL, addr_num);
4412 return EINVAL;
4413 }
4414
4415 if (msg->data[1]) {
4416 /* Got an RMCP+ error. */
4417 handle_connected(ipmi, IPMI_RMCPP_ERR_VAL(msg->data[1]), addr_num);
4418 return EINVAL;
4419 }
4420
4421 if (msg->data_len < min_length) {
4422 ipmi_log(IPMI_LOG_ERR_INFO,
4423 "%sipmi_lan.c(%s): Message data too short: %d",
4424 IPMI_CONN_NAME(ipmi), caller, msg->data_len);
4425 handle_connected(ipmi, EINVAL, addr_num);
4426 return EINVAL;
4427 }
4428
4429 return 0;
4430 }
4431
4432 typedef struct auth_info_s
4433 {
4434 ipmi_msgi_t *rspi;
4435 lan_data_t *lan;
4436 } auth_info_t;
4437
4438 static void
rmcpp_auth_finished(ipmi_con_t * ipmi,int err,int addr_num,void * cb_data)4439 rmcpp_auth_finished(ipmi_con_t *ipmi,
4440 int err,
4441 int addr_num,
4442 void *cb_data)
4443 {
4444 auth_info_t *info = cb_data;
4445 lan_data_t *lan = info->lan;
4446 int rv = EINVAL;
4447
4448 if (!ipmi) {
4449 handle_connected(lan->ipmi, ECANCELED, addr_num);
4450 goto out;
4451 }
4452
4453 if (err) {
4454 handle_connected(lan->ipmi, err, addr_num);
4455 goto out;
4456 }
4457
4458 lan->ip[addr_num].session_id = lan->ip[addr_num].precon_session_id;
4459 lan->ip[addr_num].mgsys_session_id
4460 = lan->ip[addr_num].precon_mgsys_session_id;
4461 lan->ip[addr_num].inbound_seq_num = 1;
4462 lan->ip[addr_num].outbound_seq_num = 1;
4463 lan->ip[addr_num].unauth_in_seq_num = 1;
4464 lan->ip[addr_num].unauth_out_seq_num = 1;
4465
4466 /* We're up!. Start the session stuff. */
4467 rv = send_set_session_privilege(ipmi, lan, addr_num, info->rspi);
4468 if (rv) {
4469 handle_connected(ipmi, rv, addr_num);
4470 goto out;
4471 }
4472
4473 out:
4474 if (rv)
4475 ipmi_free_msg_item(info->rspi);
4476 ipmi_mem_free(info);
4477 return;
4478 }
4479
4480 static int
rmcpp_set_info(ipmi_con_t * ipmi,int addr_num,ipmi_rmcpp_auth_t * ainfo,void * cb_data)4481 rmcpp_set_info(ipmi_con_t *ipmi,
4482 int addr_num,
4483 ipmi_rmcpp_auth_t *ainfo,
4484 void *cb_data)
4485 {
4486 auth_info_t *info = cb_data;
4487 lan_data_t *lan = info->lan;
4488 int rv;
4489
4490 rv = lan->ip[addr_num].conf_info->conf_init
4491 (ipmi, ainfo, &(lan->ip[addr_num].conf_data));
4492 if (rv)
4493 goto out;
4494
4495 rv = lan->ip[addr_num].integ_info->integ_init
4496 (ipmi, ainfo, &(lan->ip[addr_num].integ_data));
4497 if (rv)
4498 goto out;
4499
4500 out:
4501 return rv;
4502 }
4503
4504 static int
got_rmcpp_open_session_rsp(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4505 got_rmcpp_open_session_rsp(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4506 {
4507 ipmi_msg_t *msg = &rspi->msg;
4508 lan_data_t *lan;
4509 int addr_num = (long) rspi->data4;
4510 uint32_t session_id;
4511 uint32_t mgsys_session_id;
4512 unsigned int privilege;
4513 unsigned int auth, integ, conf;
4514 ipmi_rmcpp_authentication_t *authp = NULL;
4515 ipmi_rmcpp_confidentiality_t *confp = NULL;
4516 ipmi_rmcpp_integrity_t *integp = NULL;
4517 auth_info_t *info;
4518 int rv;
4519
4520 if (check_rakp_rsp(ipmi, msg, "got_rmcpp_open_session_rsp", 36, addr_num))
4521 goto out;
4522
4523 lan = (lan_data_t *) ipmi->con_data;
4524
4525 privilege = msg->data[2] & 0xf;
4526 if (privilege < lan->cparm.privilege) {
4527 ipmi_log(IPMI_LOG_WARNING,
4528 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4529 "Expected privilege %d, got %d",
4530 IPMI_CONN_NAME(ipmi), lan->cparm.privilege, privilege);
4531 }
4532
4533 session_id = ipmi_get_uint32(msg->data+4);
4534 if (session_id != lan->ip[addr_num].precon_session_id) {
4535 ipmi_log(IPMI_LOG_ERR_INFO,
4536 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4537 " Got wrong session id: 0x%x",
4538 IPMI_CONN_NAME(ipmi), session_id);
4539 handle_connected(ipmi, EINVAL, addr_num);
4540 goto out;
4541 }
4542
4543 mgsys_session_id = ipmi_get_uint32(msg->data+8);
4544 if (mgsys_session_id == 0) {
4545 ipmi_log(IPMI_LOG_ERR_INFO,
4546 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4547 "Got NULL mgd system session id", IPMI_CONN_NAME(ipmi));
4548 handle_connected(ipmi, EINVAL, addr_num);
4549 goto out;
4550 }
4551 lan->ip[addr_num].precon_mgsys_session_id = mgsys_session_id;
4552
4553 if ((msg->data[12] != 0) || (msg->data[15] != 8)) {
4554 ipmi_log(IPMI_LOG_ERR_INFO,
4555 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4556 "Got NULL or invalid authentication payload",
4557 IPMI_CONN_NAME(ipmi));
4558 handle_connected(ipmi, EINVAL, addr_num);
4559 goto out;
4560 }
4561 auth = msg->data[16] & 0x3f;
4562
4563 if ((msg->data[20] != 1) || (msg->data[23] != 8)) {
4564 ipmi_log(IPMI_LOG_ERR_INFO,
4565 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4566 "Got NULL or invalid integrity payload",
4567 IPMI_CONN_NAME(ipmi));
4568 handle_connected(ipmi, EINVAL, addr_num);
4569 goto out;
4570 }
4571 integ = msg->data[24] & 0x3f;
4572
4573 if ((msg->data[28] != 2) || (msg->data[31] != 8)) {
4574 ipmi_log(IPMI_LOG_ERR_INFO,
4575 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4576 "Got NULL or invalid confidentiality payload",
4577 IPMI_CONN_NAME(ipmi));
4578 handle_connected(ipmi, EINVAL, addr_num);
4579 goto out;
4580 }
4581 conf = msg->data[32] & 0x3f;
4582
4583 if (auth >= 0x30) {
4584 auth_entry_t *e = oem_auth_list;
4585 while (e) {
4586 if ((e->auth_num == auth)
4587 && (memcmp(e->iana, lan->oem_iana, 3) == 0))
4588 {
4589 authp = e->auth;
4590 break;
4591 }
4592 e = e->next;
4593 }
4594 } else
4595 authp = auths[auth];
4596
4597 if (!authp) {
4598 ipmi_log(IPMI_LOG_ERR_INFO,
4599 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4600 "BMC returned an auth algorithm that wasn't supported: %d",
4601 IPMI_CONN_NAME(ipmi), auth);
4602 handle_connected(ipmi, EINVAL, addr_num);
4603 goto out;
4604 }
4605
4606 if (conf >= 0x30) {
4607 conf_entry_t *e = oem_conf_list;
4608 while (e) {
4609 if ((e->conf_num == conf)
4610 && (memcmp(e->iana, lan->oem_iana, 3) == 0))
4611 {
4612 confp = e->conf;
4613 break;
4614 }
4615 e = e->next;
4616 }
4617 } else
4618 confp = confs[conf];
4619
4620 if (!confp) {
4621 ipmi_log(IPMI_LOG_ERR_INFO,
4622 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4623 "BMC returned a conf algorithm that wasn't supported: %d",
4624 IPMI_CONN_NAME(ipmi), conf);
4625 handle_connected(ipmi, EINVAL, addr_num);
4626 goto out;
4627 }
4628
4629 if (integ >= 0x30) {
4630 integ_entry_t *e = oem_integ_list;
4631 while (e) {
4632 if ((e->integ_num == integ)
4633 && (memcmp(e->iana, lan->oem_iana, 3) == 0))
4634 {
4635 integp = e->integ;
4636 break;
4637 }
4638 e = e->next;
4639 }
4640 } else
4641 integp = integs[integ];
4642
4643 if (!integp) {
4644 ipmi_log(IPMI_LOG_ERR_INFO,
4645 "%sipmi_lan.c(got_rmcpp_open_session_rsp): "
4646 "BMC returned an integ algorithm that wasn't supported: %d",
4647 IPMI_CONN_NAME(ipmi), integ);
4648 handle_connected(ipmi, EINVAL, addr_num);
4649 goto out;
4650 }
4651
4652 info = ipmi_mem_alloc(sizeof(*info));
4653 if (!info) {
4654 handle_connected(ipmi, ENOMEM, addr_num);
4655 goto out;
4656 }
4657
4658 lan->ip[addr_num].working_conf = conf;
4659 lan->ip[addr_num].working_integ = integ;
4660 lan->ip[addr_num].conf_info = confp;
4661 lan->ip[addr_num].integ_info = integp;
4662
4663 lan->ip[addr_num].ainfo.lan = lan;
4664 lan->ip[addr_num].ainfo.role = ((lan->cparm.name_lookup_only << 4)
4665 | lan->cparm.privilege);
4666
4667 info->lan = lan;
4668 info->rspi = rspi;
4669
4670 rv = authp->start_auth(ipmi, addr_num, lan->fd_slot,
4671 &(lan->ip[addr_num].ainfo),
4672 rmcpp_set_info, rmcpp_auth_finished,
4673 info);
4674 if (rv) {
4675 ipmi_mem_free(info);
4676 handle_connected(ipmi, rv, addr_num);
4677 goto out;
4678 }
4679
4680 return IPMI_MSG_ITEM_USED;
4681
4682 out:
4683 return IPMI_MSG_ITEM_NOT_USED;
4684 }
4685
4686 static int
send_rmcpp_open_session(ipmi_con_t * ipmi,lan_data_t * lan,ipmi_msgi_t * rspi,int addr_num)4687 send_rmcpp_open_session(ipmi_con_t *ipmi, lan_data_t *lan, ipmi_msgi_t *rspi,
4688 int addr_num)
4689 {
4690 int rv;
4691 unsigned char data[32];
4692 ipmi_msg_t msg;
4693 ipmi_rmcpp_addr_t addr;
4694
4695 memset(data, 0, sizeof(data));
4696 data[0] = 0; /* Set to seq# by the formatting code. */
4697 data[1] = lan->cparm.privilege;
4698 ipmi_set_uint32(data+4, lan->ip[addr_num].precon_session_id);
4699 data[8] = 0; /* auth algorithm */
4700 if ((int) lan->cparm.auth == IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK)
4701 data[11] = 0; /* Let the BMC pick */
4702 else {
4703 data[11] = 8;
4704 data[12] = lan->cparm.auth;
4705 }
4706 data[16] = 1; /* integrity algorithm */
4707 if ((int) lan->cparm.integ == IPMI_LANP_INTEGRITY_ALGORITHM_BMCPICK)
4708 data[19] = 0; /* Let the BMC pick */
4709 else {
4710 data[19] = 8;
4711 data[20] = lan->cparm.integ;
4712 }
4713 data[24] = 2; /* confidentiality algorithm */
4714 if ((int) lan->cparm.conf == IPMI_LANP_CONFIDENTIALITY_ALGORITHM_BMCPICK)
4715 data[27] = 0; /* Let the BMC pick */
4716 else {
4717 data[27] = 8;
4718 data[28] = lan->cparm.conf;
4719 }
4720
4721 msg.netfn = IPMI_RMCPP_DUMMY_NETFN;
4722 msg.cmd = IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_REQUEST;
4723 msg.data = data;
4724 msg.data_len = 32;
4725 addr.addr_type = (IPMI_RMCPP_ADDR_START
4726 + IPMI_RMCPP_PAYLOAD_TYPE_OPEN_SESSION_REQUEST);
4727
4728 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
4729 (ipmi_addr_t *) &addr, sizeof(addr),
4730 &msg, got_rmcpp_open_session_rsp, rspi);
4731 return rv;
4732 }
4733
4734 static int
start_rmcpp(ipmi_con_t * ipmi,lan_data_t * lan,ipmi_msgi_t * rspi,int addr_num)4735 start_rmcpp(ipmi_con_t *ipmi, lan_data_t *lan, ipmi_msgi_t *rspi, int addr_num)
4736 {
4737 int rv;
4738
4739 /* We don't really need to get the cipher suites, the user
4740 requests them (or defaults them to the mandatory ones). */
4741
4742 lan->ip[addr_num].working_authtype = IPMI_AUTHTYPE_RMCP_PLUS;
4743 lan->ip[addr_num].outbound_seq_num = 0;
4744 lan->ip[addr_num].unauth_out_seq_num = 0;
4745 lan->ip[addr_num].inbound_seq_num = 0;
4746 lan->ip[addr_num].unauth_in_seq_num = 0;
4747 /* Use our fd_slot in the fd for the session id, so we can look it
4748 up quickly. */
4749 lan->ip[addr_num].precon_session_id = lan->fd_slot + 1;
4750 lan->ip[addr_num].working_conf = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE;
4751 lan->ip[addr_num].working_integ = IPMI_LANP_INTEGRITY_ALGORITHM_NONE;
4752
4753 rv = send_rmcpp_open_session(ipmi, lan, rspi, addr_num);
4754 if (rv) {
4755 handle_connected(ipmi, rv, addr_num);
4756 goto out;
4757 }
4758
4759 return IPMI_MSG_ITEM_USED;
4760
4761 out:
4762 return IPMI_MSG_ITEM_NOT_USED;
4763 }
4764
4765 static int
session_activated(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4766 session_activated(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4767 {
4768 ipmi_msg_t *msg = &rspi->msg;
4769 lan_data_t *lan;
4770 int rv;
4771 int addr_num = (long) rspi->data4;
4772
4773
4774 if (!ipmi) {
4775 handle_connected(ipmi, ECANCELED, addr_num);
4776 goto out;
4777 }
4778
4779 lan = (lan_data_t *) ipmi->con_data;
4780
4781 if (msg->data[0] != 0) {
4782 handle_connected(ipmi, IPMI_IPMI_ERR_VAL(msg->data[0]), addr_num);
4783 goto out;
4784 }
4785
4786 if (msg->data_len < 11) {
4787 handle_connected(ipmi, EINVAL, addr_num);
4788 goto out;
4789 }
4790
4791 lan->ip[addr_num].working_authtype = msg->data[1] & 0xf;
4792 if ((lan->ip[addr_num].working_authtype != 0)
4793 && (lan->ip[addr_num].working_authtype != lan->chosen_authtype))
4794 {
4795 /* Eh? It didn't return a valid authtype. */
4796 handle_connected(ipmi, EINVAL, addr_num);
4797 goto out;
4798 }
4799
4800 lan->ip[addr_num].session_id = ipmi_get_uint32(msg->data+2);
4801 lan->ip[addr_num].outbound_seq_num = ipmi_get_uint32(msg->data+6);
4802
4803 rv = send_set_session_privilege(ipmi, lan, addr_num, rspi);
4804 if (rv) {
4805 handle_connected(ipmi, rv, addr_num);
4806 goto out;
4807 }
4808
4809 return IPMI_MSG_ITEM_USED;
4810
4811 out:
4812 return IPMI_MSG_ITEM_NOT_USED;
4813 }
4814
4815 static int
send_activate_session(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,ipmi_msgi_t * rspi)4816 send_activate_session(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
4817 ipmi_msgi_t *rspi)
4818 {
4819 unsigned char data[IPMI_MAX_MSG_LENGTH];
4820 ipmi_msg_t msg;
4821 int rv;
4822 ipmi_system_interface_addr_t addr;
4823
4824 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
4825 addr.channel = 0xf;
4826 addr.lun = 0;
4827
4828 data[0] = lan->chosen_authtype;
4829 data[1] = lan->cparm.privilege;
4830 memcpy(data+2, lan->challenge_string, 16);
4831 ipmi_set_uint32(data+18, lan->ip[addr_num].inbound_seq_num);
4832
4833 msg.cmd = IPMI_ACTIVATE_SESSION_CMD;
4834 msg.netfn = IPMI_APP_NETFN;
4835 msg.data = data;
4836 msg.data_len = 22;
4837
4838 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
4839 (ipmi_addr_t *) &addr, sizeof(addr),
4840 &msg, session_activated, rspi);
4841 return rv;
4842 }
4843
4844 static int
challenge_done(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4845 challenge_done(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4846 {
4847 ipmi_msg_t *msg = &rspi->msg;
4848 lan_data_t *lan;
4849 int rv;
4850 int addr_num = (long) rspi->data4;
4851
4852
4853 if (!ipmi) {
4854 handle_connected(ipmi, ECANCELED, addr_num);
4855 goto out;
4856 }
4857
4858 lan = (lan_data_t *) ipmi->con_data;
4859
4860 if (msg->data[0] != 0) {
4861 handle_connected(ipmi, IPMI_IPMI_ERR_VAL(msg->data[0]), addr_num);
4862 goto out;
4863 }
4864
4865 if (msg->data_len < 21) {
4866 handle_connected(ipmi, EINVAL, addr_num);
4867 goto out;
4868 }
4869
4870 /* Get the temporary session id. */
4871 lan->ip[addr_num].session_id = ipmi_get_uint32(msg->data+1);
4872
4873 lan->ip[addr_num].outbound_seq_num = 0;
4874 lan->ip[addr_num].working_authtype = lan->chosen_authtype;
4875 memcpy(lan->challenge_string, msg->data+5, 16);
4876
4877 /* Get a random number of the other end to start sending me sequence
4878 numbers at, but don't let it be zero. */
4879 while (lan->ip[addr_num].inbound_seq_num == 0) {
4880 rv = ipmi->os_hnd->get_random(ipmi->os_hnd,
4881 &(lan->ip[addr_num].inbound_seq_num), 4);
4882 if (rv) {
4883 handle_connected(ipmi, rv, addr_num);
4884 goto out;
4885 }
4886 }
4887
4888 rv = send_activate_session(ipmi, lan, addr_num, rspi);
4889 if (rv) {
4890 handle_connected(ipmi, rv, addr_num);
4891 goto out;
4892 }
4893
4894 return IPMI_MSG_ITEM_USED;
4895
4896 out:
4897 return IPMI_MSG_ITEM_NOT_USED;
4898 }
4899
4900 static int
send_challenge(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,ipmi_msgi_t * rspi)4901 send_challenge(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
4902 ipmi_msgi_t *rspi)
4903 {
4904 unsigned char data[IPMI_MAX_MSG_LENGTH];
4905 ipmi_msg_t msg;
4906 ipmi_system_interface_addr_t addr;
4907 int rv;
4908
4909 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
4910 addr.channel = 0xf;
4911 addr.lun = 0;
4912
4913 data[0] = lan->chosen_authtype;
4914 msg.cmd = IPMI_GET_SESSION_CHALLENGE_CMD;
4915 msg.netfn = IPMI_APP_NETFN;
4916 msg.data = data;
4917 msg.data_len = 1;
4918 memcpy(data+1, lan->cparm.username, IPMI_USERNAME_MAX);
4919 msg.data_len += IPMI_USERNAME_MAX;
4920
4921 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
4922 (ipmi_addr_t *) &addr, sizeof(addr),
4923 &msg, challenge_done, rspi);
4924 return rv;
4925 }
4926
4927 static int
auth_cap_done(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)4928 auth_cap_done(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
4929 {
4930 ipmi_msg_t *msg = &rspi->msg;
4931 lan_data_t *lan;
4932 int rv;
4933 int addr_num = (long) rspi->data4;
4934 int supports_ipmi2;
4935 int extended_capabilities_reported;
4936
4937 if (!ipmi) {
4938 handle_connected(ipmi, ECANCELED, addr_num);
4939 goto out;
4940 }
4941
4942 lan = (lan_data_t *) ipmi->con_data;
4943
4944 if (msg->data[0] != 0) {
4945 handle_connected(ipmi, IPMI_IPMI_ERR_VAL(msg->data[0]), addr_num);
4946 goto out;
4947 }
4948
4949 if (msg->data_len < 9) {
4950 handle_connected(ipmi, EINVAL, addr_num);
4951 goto out;
4952 }
4953
4954 extended_capabilities_reported = (msg->data[2] & 0x80);
4955 supports_ipmi2 = (msg->data[4] & 0x02);
4956 if (extended_capabilities_reported && supports_ipmi2) {
4957 /* We have RMCP+ support! Use it. */
4958 lan->use_two_keys = (msg->data[3] >> 5) & 1;
4959 memcpy(lan->oem_iana, msg->data+5, 3);
4960 lan->oem_aux = msg->data[8];
4961 return start_rmcpp(ipmi, lan, rspi, addr_num);
4962 }
4963 else if (supports_ipmi2)
4964 {
4965 /*
4966 * The BMC has said that it supports RMCP+/IPMI 2.0 in the
4967 * extended response fields, but has not indicated that we
4968 * should USE the extended response fields! The SuperMicro
4969 * AOC-IPMI20-E currently does this (April 2005), and will do
4970 * so until they provide BMC firmware that supports RMCP+.
4971 */
4972 ipmi_log(IPMI_LOG_WARNING,
4973 "%sipmi_lan.c(auth_cap_done): "
4974 "BMC confused about RMCP+ support. Disabling RMCP+.",
4975 IPMI_CONN_NAME(lan->ipmi));
4976 }
4977 if (lan->cparm.authtype == IPMI_AUTHTYPE_RMCP_PLUS) {
4978 /* The user specified RMCP+, but the system doesn't have it. */
4979 ipmi_log(IPMI_LOG_ERR_INFO,
4980 "%sipmi_lan.c(auth_cap_done): "
4981 "User requested RMCP+, but not supported",
4982 IPMI_CONN_NAME(lan->ipmi));
4983 handle_connected(ipmi, ENOENT, addr_num);
4984 goto out;
4985 }
4986
4987 memcpy(lan->oem_iana, msg->data+5, 3);
4988 lan->oem_aux = msg->data[8];
4989
4990 if (lan->authdata) {
4991 ipmi_auths[lan->chosen_authtype].authcode_cleanup(lan->authdata);
4992 lan->authdata = NULL;
4993 }
4994
4995 if ((int) lan->cparm.authtype == IPMI_AUTHTYPE_DEFAULT) {
4996 /* Pick the most secure authentication type. */
4997 if (msg->data[2] & (1 << IPMI_AUTHTYPE_MD5)) {
4998 lan->chosen_authtype = IPMI_AUTHTYPE_MD5;
4999 } else if (msg->data[2] & (1 << IPMI_AUTHTYPE_MD2)) {
5000 lan->chosen_authtype = IPMI_AUTHTYPE_MD2;
5001 } else if (msg->data[2] & (1 << IPMI_AUTHTYPE_STRAIGHT)) {
5002 lan->chosen_authtype = IPMI_AUTHTYPE_STRAIGHT;
5003 } else if (msg->data[2] & (1 << IPMI_AUTHTYPE_NONE)) {
5004 lan->chosen_authtype = IPMI_AUTHTYPE_NONE;
5005 } else {
5006 ipmi_log(IPMI_LOG_ERR_INFO,
5007 "%sipmi_lan.c(auth_cap_done): "
5008 "No valid authentication supported",
5009 IPMI_CONN_NAME(lan->ipmi));
5010 handle_connected(ipmi, EINVAL, addr_num);
5011 goto out;
5012 }
5013 } else {
5014 if (!(msg->data[2] & (1 << lan->cparm.authtype))) {
5015 ipmi_log(IPMI_LOG_ERR_INFO,
5016 "%sipmi_lan.c(auth_cap_done): "
5017 "Requested authentication not supported",
5018 IPMI_CONN_NAME(lan->ipmi));
5019 handle_connected(ipmi, EINVAL, addr_num);
5020 goto out;
5021 }
5022 lan->chosen_authtype = lan->cparm.authtype;
5023 }
5024
5025 rv = ipmi_auths[lan->chosen_authtype].authcode_init(lan->cparm.password,
5026 &(lan->authdata),
5027 NULL, auth_alloc,
5028 auth_free);
5029 if (rv) {
5030 ipmi_log(IPMI_LOG_ERR_INFO,
5031 "%sipmi_lan.c(auth_cap_done): "
5032 "Unable to initialize authentication data: 0x%x",
5033 IPMI_CONN_NAME(lan->ipmi), rv);
5034 handle_connected(ipmi, rv, addr_num);
5035 goto out;
5036 }
5037
5038 rv = send_challenge(ipmi, lan, addr_num, rspi);
5039 if (rv) {
5040 ipmi_log(IPMI_LOG_ERR_INFO,
5041 "%sipmi_lan.c(auth_cap_done): "
5042 "Unable to send challenge command: 0x%x",
5043 IPMI_CONN_NAME(lan->ipmi), rv);
5044 handle_connected(ipmi, rv, addr_num);
5045 goto out;
5046 }
5047
5048 return IPMI_MSG_ITEM_USED;
5049
5050 out:
5051 return IPMI_MSG_ITEM_NOT_USED;
5052 }
5053
5054 static int
auth_cap_done_p(ipmi_con_t * ipmi,ipmi_msgi_t * rspi)5055 auth_cap_done_p(ipmi_con_t *ipmi, ipmi_msgi_t *rspi)
5056 {
5057 ipmi_msg_t *msg = &rspi->msg;
5058 lan_data_t *lan;
5059 int addr_num = (long) rspi->data4;
5060 int rv;
5061
5062 if (!ipmi) {
5063 handle_connected(ipmi, ECANCELED, addr_num);
5064 goto out;
5065 }
5066
5067 lan = (lan_data_t *) ipmi->con_data;
5068
5069 if ((msg->data[0] != 0) || (msg->data_len < 9)) {
5070 /* Got an error, try it without the RMCP+ bit set. Some
5071 systems incorrectly return errors when reserved data is
5072 set. */
5073
5074 if (lan->cparm.authtype == IPMI_AUTHTYPE_RMCP_PLUS) {
5075 /* The user specified RMCP+, but the system doesn't have it. */
5076 ipmi_log(IPMI_LOG_ERR_INFO,
5077 "%sipmi_lan.c(auth_cap_done_p): "
5078 "Use requested RMCP+, but not supported",
5079 IPMI_CONN_NAME(lan->ipmi));
5080 handle_connected(ipmi, ENOENT, addr_num);
5081 goto out;
5082 }
5083
5084 rv = send_auth_cap(ipmi, lan, addr_num, 1);
5085 if (rv) {
5086 handle_connected(ipmi, rv, addr_num);
5087 }
5088 goto out;
5089 }
5090
5091
5092 return auth_cap_done(ipmi, rspi);
5093
5094 out:
5095 return IPMI_MSG_ITEM_NOT_USED;
5096 }
5097
5098 static int
send_auth_cap(ipmi_con_t * ipmi,lan_data_t * lan,int addr_num,int force_ipmiv15)5099 send_auth_cap(ipmi_con_t *ipmi, lan_data_t *lan, int addr_num,
5100 int force_ipmiv15)
5101 {
5102 unsigned char data[2];
5103 ipmi_msg_t msg;
5104 ipmi_system_interface_addr_t addr;
5105 int rv;
5106 ipmi_msgi_t *rspi;
5107 ipmi_ll_rsp_handler_t rsp_handler;
5108
5109 /* FIXME - a system may only support RMCP+ and not RMCP. We need
5110 a way to detect and handle that. */
5111
5112 rspi = ipmi_mem_alloc(sizeof(*rspi));
5113 if (!rspi)
5114 return ENOMEM;
5115
5116 addr.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
5117 addr.channel = 0xf;
5118 addr.lun = 0;
5119
5120 data[0] = 0xe;
5121 data[1] = lan->cparm.privilege;
5122 msg.cmd = IPMI_GET_CHANNEL_AUTH_CAPABILITIES_CMD;
5123 msg.netfn = IPMI_APP_NETFN;
5124 msg.data = data;
5125 msg.data_len = 2;
5126 if ((((int) lan->cparm.authtype == IPMI_AUTHTYPE_DEFAULT)
5127 || ((int) lan->cparm.authtype == IPMI_AUTHTYPE_RMCP_PLUS))
5128 && !force_ipmiv15)
5129 {
5130 rsp_handler = auth_cap_done_p;
5131 data[0] |= 0x80; /* Get RMCP data. */
5132 } else {
5133 rsp_handler = auth_cap_done;
5134 }
5135
5136 rv = ipmi_lan_send_command_forceip(ipmi, addr_num,
5137 (ipmi_addr_t *) &addr, sizeof(addr),
5138 &msg, rsp_handler, rspi);
5139 if (rv)
5140 ipmi_mem_free(rspi);
5141 return rv;
5142 }
5143
5144 static int
lan_start_con(ipmi_con_t * ipmi)5145 lan_start_con(ipmi_con_t *ipmi)
5146 {
5147 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
5148 int rv;
5149 struct timeval timeout;
5150 unsigned int i;
5151
5152 ipmi_lock(lan->ip_lock);
5153 if (lan->started) {
5154 /* Only allow started to be called once, but make sure the
5155 connected callback gets called if started is called again
5156 (assuming the connection is up). This lets multiple users
5157 use the same connection. If the LAN is not connected, this
5158 doesn't matter, the callback will be called properly
5159 later. */
5160 if (lan->connected) {
5161 unsigned int i;
5162 int port_err[MAX_IP_ADDR];
5163
5164 for (i=0; i<lan->cparm.num_ip_addr; i++)
5165 port_err[i] = lan->ip[i].working ? 0 : EINVAL;
5166
5167 ipmi_lock(lan->con_change_lock);
5168 ipmi_unlock(lan->ip_lock);
5169
5170 for (i=0; i<lan->cparm.num_ip_addr; i++)
5171 call_con_change_handlers(lan, port_err[i], i, 1);
5172 ipmi_unlock(lan->con_change_lock);
5173 } else
5174 ipmi_unlock(lan->ip_lock);
5175 return 0;
5176 }
5177
5178 /* Start the timer to audit the connections. */
5179 lan->audit_info = ipmi_mem_alloc(sizeof(*(lan->audit_info)));
5180 if (!lan->audit_info) {
5181 rv = ENOMEM;
5182 goto out_err;
5183 }
5184
5185 lan->audit_info->cancelled = 0;
5186 lan->audit_info->ipmi = ipmi;
5187 rv = ipmi->os_hnd->alloc_timer(ipmi->os_hnd, &(lan->audit_timer));
5188 if (rv)
5189 goto out_err;
5190 timeout.tv_sec = LAN_AUDIT_TIMEOUT / 1000000;
5191 timeout.tv_usec = LAN_AUDIT_TIMEOUT % 1000000;
5192 rv = ipmi->os_hnd->start_timer(ipmi->os_hnd,
5193 lan->audit_timer,
5194 &timeout,
5195 audit_timeout_handler,
5196 lan->audit_info);
5197 if (rv) {
5198 ipmi_mem_free(lan->audit_info);
5199 lan->audit_info = NULL;
5200 ipmi->os_hnd->free_timer(ipmi->os_hnd, lan->audit_timer);
5201 lan->audit_timer = NULL;
5202 goto out_err;
5203 }
5204
5205 lan->started = 1;
5206 ipmi_unlock(lan->ip_lock);
5207
5208 for (i=0; i<lan->cparm.num_ip_addr; i++)
5209 /* Ignore failures, this gets retried. */
5210 send_auth_cap(ipmi, lan, i, 0);
5211
5212 return 0;
5213
5214 out_err:
5215 ipmi_unlock(lan->ip_lock);
5216 return rv;
5217 }
5218
5219 int
ipmi_lan_setup_con(struct in_addr * ip_addrs,int * ports,unsigned int num_ip_addrs,unsigned int authtype,unsigned int privilege,void * username,unsigned int username_len,void * password,unsigned int password_len,os_handler_t * handlers,void * user_data,ipmi_con_t ** new_con)5220 ipmi_lan_setup_con(struct in_addr *ip_addrs,
5221 int *ports,
5222 unsigned int num_ip_addrs,
5223 unsigned int authtype,
5224 unsigned int privilege,
5225 void *username,
5226 unsigned int username_len,
5227 void *password,
5228 unsigned int password_len,
5229 os_handler_t *handlers,
5230 void *user_data,
5231 ipmi_con_t **new_con)
5232 {
5233 char s_ip_addrs[MAX_IP_ADDR][20];
5234 char s_ports[MAX_IP_ADDR][10];
5235 char *paddrs[MAX_IP_ADDR], *pports[MAX_IP_ADDR];
5236 unsigned char *p;
5237 unsigned int i;
5238 int rv;
5239
5240 if ((num_ip_addrs < 1) || (num_ip_addrs > MAX_IP_ADDR))
5241 return EINVAL;
5242 for (i=0; i<num_ip_addrs; i++) {
5243 p = (unsigned char *)&(ip_addrs[i]);
5244 sprintf(s_ip_addrs[i], "%u.%u.%u.%u", *p, *(p+1), *(p+2), *(p+3));
5245 sprintf(s_ports[i], "%u", ports[i]);
5246 paddrs[i] = s_ip_addrs[i];
5247 pports[i]= s_ports[i];
5248 }
5249 rv = ipmi_ip_setup_con(paddrs,
5250 pports,
5251 num_ip_addrs,
5252 authtype,
5253 privilege,
5254 username,
5255 username_len,
5256 password,
5257 password_len,
5258 handlers,
5259 user_data,
5260 new_con);
5261 return rv;
5262 }
5263
5264 int
ipmi_ip_setup_con(char * const ip_addrs[],char * const ports[],unsigned int num_ip_addrs,unsigned int authtype,unsigned int privilege,void * username,unsigned int username_len,void * password,unsigned int password_len,os_handler_t * handlers,void * user_data,ipmi_con_t ** new_con)5265 ipmi_ip_setup_con(char * const ip_addrs[],
5266 char * const ports[],
5267 unsigned int num_ip_addrs,
5268 unsigned int authtype,
5269 unsigned int privilege,
5270 void *username,
5271 unsigned int username_len,
5272 void *password,
5273 unsigned int password_len,
5274 os_handler_t *handlers,
5275 void *user_data,
5276 ipmi_con_t **new_con)
5277 {
5278 ipmi_lanp_parm_t parms[6];
5279
5280 parms[0].parm_id = IPMI_LANP_PARMID_ADDRS;
5281 parms[0].parm_data = (void *) ip_addrs;
5282 parms[0].parm_data_len = num_ip_addrs;
5283 parms[1].parm_id = IPMI_LANP_PARMID_PORTS;
5284 parms[1].parm_data = (void *) ports;
5285 parms[1].parm_data_len = num_ip_addrs;
5286 parms[2].parm_id = IPMI_LANP_PARMID_AUTHTYPE;
5287 parms[2].parm_val = authtype;
5288 parms[3].parm_id = IPMI_LANP_PARMID_PRIVILEGE;
5289 parms[3].parm_val = privilege;
5290 parms[4].parm_id = IPMI_LANP_PARMID_USERNAME;
5291 parms[4].parm_data = username;
5292 parms[4].parm_data_len = username_len;
5293 parms[5].parm_id = IPMI_LANP_PARMID_PASSWORD;
5294 parms[5].parm_data = password;
5295 parms[5].parm_data_len = password_len;
5296 return ipmi_lanp_setup_con(parms, 6, handlers, user_data, new_con);
5297 }
5298
5299 static lan_data_t *
find_matching_lan(lan_conn_parms_t * cparm)5300 find_matching_lan(lan_conn_parms_t *cparm)
5301 {
5302 lan_link_t *l;
5303 lan_data_t *lan;
5304 unsigned int idx;
5305
5306 /* Look in the first IP addresses list. */
5307 idx = hash_lan_addr(&cparm->ip_addr[0].s_ipsock.s_addr0);
5308 ipmi_lock(lan_list_lock);
5309 l = lan_ip_list[idx].next;
5310 while (l->lan) {
5311 lan = l->lan;
5312 if (memcmp(&lan->cparm, cparm, sizeof(*cparm)) == 0) {
5313 /* Parms match up, use it */
5314 lan->users++;
5315 ipmi_unlock(lan_list_lock);
5316 return lan;
5317 }
5318 l = l->next;
5319 }
5320 ipmi_unlock(lan_list_lock);
5321 return NULL;
5322 }
5323
5324 static void
lan_use_connection(ipmi_con_t * ipmi)5325 lan_use_connection(ipmi_con_t *ipmi)
5326 {
5327 lan_data_t *lan = ipmi->con_data;
5328
5329 ipmi_lock(lan_list_lock);
5330 lan->users++;
5331 ipmi_unlock(lan_list_lock);
5332 }
5333
5334 static int
lan_register_stat_handler(ipmi_con_t * ipmi,ipmi_ll_stat_info_t * info)5335 lan_register_stat_handler(ipmi_con_t *ipmi,
5336 ipmi_ll_stat_info_t *info)
5337 {
5338 lan_stat_info_t *nstat;
5339 lan_data_t *lan = ipmi->con_data;
5340 int i;
5341
5342 nstat = ipmi_mem_alloc(sizeof(*nstat));
5343 if (!nstat)
5344 return ENOMEM;
5345 memset(nstat, 0, sizeof(*nstat));
5346
5347 for (i=0; i<NUM_STATS; i++)
5348 ipmi_ll_con_stat_call_register(info, lan_stat_names[i],
5349 ipmi->name, &(nstat->stats[i]));
5350
5351 if (!locked_list_add(lan->lan_stat_list, nstat, info)) {
5352 for (i=0; i<NUM_STATS; i++)
5353 if (nstat->stats[i]) {
5354 ipmi_ll_con_stat_call_unregister(info, nstat->stats[i]);
5355 nstat->stats[i] = NULL;
5356 }
5357 ipmi_mem_free(nstat);
5358 return ENOMEM;
5359 }
5360
5361 return 0;
5362 }
5363
5364 static int
lan_unregister_stat_handler(ipmi_con_t * ipmi,ipmi_ll_stat_info_t * info)5365 lan_unregister_stat_handler(ipmi_con_t *ipmi,
5366 ipmi_ll_stat_info_t *info)
5367 {
5368 lan_unreg_stat_info_t sinfo;
5369 lan_data_t *lan = ipmi->con_data;
5370
5371 sinfo.lan = lan;
5372 sinfo.cmpinfo = info;
5373 sinfo.found = 0;
5374 locked_list_iterate(lan->lan_stat_list, lan_unreg_stat_info,
5375 &sinfo);
5376 if (sinfo.found)
5377 return 0;
5378 else
5379 return EINVAL;
5380 }
5381
5382 static ipmi_args_t *get_startup_args(ipmi_con_t *ipmi);
5383
5384 static unsigned int conf_order[] = {
5385 IPMI_LANP_CONFIDENTIALITY_ALGORITHM_AES_CBC_128
5386 };
5387
5388 static unsigned int
most_secure_lanp_conf(void)5389 most_secure_lanp_conf(void)
5390 {
5391 unsigned int i, v;
5392 for (i=0; i<(sizeof(conf_order)/sizeof(unsigned int)); i++) {
5393 v = conf_order[i];
5394 if (confs[v])
5395 return v;
5396 }
5397
5398 return IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE;
5399 }
5400
5401 static unsigned int integ_order[] = {
5402 IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_SHA1_96,
5403 IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_MD5_128,
5404 IPMI_LANP_INTEGRITY_ALGORITHM_MD5_128
5405 };
5406
5407 static unsigned int
most_secure_lanp_integ(void)5408 most_secure_lanp_integ(void)
5409 {
5410 unsigned int i, v;
5411 for (i=0; i<(sizeof(integ_order)/sizeof(unsigned int)); i++) {
5412 v = integ_order[i];
5413 if (integs[v])
5414 return v;
5415 }
5416
5417 return IPMI_LANP_INTEGRITY_ALGORITHM_NONE;
5418 }
5419
5420 static unsigned int auth_order[] = {
5421 IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1,
5422 IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5
5423 };
5424
5425 static unsigned int
most_secure_lanp_auth(void)5426 most_secure_lanp_auth(void)
5427 {
5428 unsigned int i, v;
5429 for (i=0; i<(sizeof(auth_order)/sizeof(unsigned int)); i++) {
5430 v = auth_order[i];
5431 if (auths[v])
5432 return v;
5433 }
5434
5435 return IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE;
5436 }
5437
5438 static void
lan_disable(ipmi_con_t * ipmi)5439 lan_disable(ipmi_con_t *ipmi)
5440 {
5441 lan_data_t *lan = (lan_data_t *) ipmi->con_data;
5442
5443 lan->disabled = 1;
5444 }
5445
5446 int
ipmi_lanp_setup_con(ipmi_lanp_parm_t * parms,unsigned int num_parms,os_handler_t * handlers,void * user_data,ipmi_con_t ** new_con)5447 ipmi_lanp_setup_con(ipmi_lanp_parm_t *parms,
5448 unsigned int num_parms,
5449 os_handler_t *handlers,
5450 void *user_data,
5451 ipmi_con_t **new_con)
5452 {
5453 ipmi_con_t *ipmi = NULL;
5454 lan_data_t *lan = NULL;
5455 int rv;
5456 unsigned int i;
5457 unsigned int count;
5458 struct sockaddr_in *pa;
5459 char **ip_addrs = NULL;
5460 char *tports[MAX_IP_ADDR];
5461 char **ports = NULL;
5462 lan_conn_parms_t cparm;
5463 int max_outstanding_msg_count = DEFAULT_MAX_OUTSTANDING_MSG_COUNT;
5464 unsigned int addr_family = AF_UNSPEC;
5465 unsigned int set_addr_family = AF_UNSPEC;
5466
5467 memset(&cparm, 0, sizeof(cparm));
5468
5469 /* Pick some secure defaults. */
5470 cparm.authtype = IPMI_AUTHTYPE_DEFAULT;
5471 cparm.privilege = IPMI_PRIVILEGE_ADMIN;
5472 cparm.conf = most_secure_lanp_conf();
5473 cparm.integ = most_secure_lanp_integ();
5474 cparm.auth = most_secure_lanp_auth();
5475 cparm.name_lookup_only = 1;
5476
5477 for (i=0; i<num_parms; i++) {
5478 switch (parms[i].parm_id) {
5479 case IPMI_LANP_PARMID_AUTHTYPE:
5480 cparm.authtype = parms[i].parm_val;
5481 break;
5482
5483 case IPMI_LANP_PARMID_PRIVILEGE:
5484 cparm.privilege = parms[i].parm_val;
5485 break;
5486
5487 case IPMI_LANP_PARMID_PASSWORD:
5488 if (parms[i].parm_data_len > sizeof(cparm.password))
5489 return EINVAL;
5490 memcpy(cparm.password, parms[i].parm_data, parms[i].parm_data_len);
5491 cparm.password_len = parms[i].parm_data_len;
5492 break;
5493
5494 case IPMI_LANP_PARMID_USERNAME:
5495 if (parms[i].parm_data_len > sizeof(cparm.username))
5496 return EINVAL;
5497 memcpy(cparm.username, parms[i].parm_data, parms[i].parm_data_len);
5498 cparm.username_len = parms[i].parm_data_len;
5499 break;
5500
5501 case IPMI_LANP_PARMID_ADDRS:
5502 if (cparm.num_ip_addr
5503 && (cparm.num_ip_addr != parms[i].parm_data_len))
5504 return EINVAL;
5505 if (parms[i].parm_data_len > MAX_IP_ADDR)
5506 return EINVAL;
5507 ip_addrs = parms[i].parm_data;
5508 cparm.num_ip_addr = parms[i].parm_data_len;
5509 break;
5510
5511 case IPMI_LANP_PARMID_PORTS:
5512 if (cparm.num_ip_addr
5513 && (cparm.num_ip_addr != parms[i].parm_data_len))
5514 return EINVAL;
5515 if (parms[i].parm_data_len > MAX_IP_ADDR)
5516 return EINVAL;
5517 ports = parms[i].parm_data;
5518 cparm.num_ip_addr = parms[i].parm_data_len;
5519 break;
5520
5521 case IPMI_LANP_AUTHENTICATION_ALGORITHM:
5522 cparm.auth = parms[i].parm_val;
5523 if ((int) cparm.auth != IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK)
5524 {
5525 if (cparm.auth >= 64)
5526 return EINVAL;
5527 if ((cparm.auth < 0x30) && (!auths[cparm.auth]))
5528 return ENOSYS;
5529 }
5530 break;
5531
5532 case IPMI_LANP_INTEGRITY_ALGORITHM:
5533 cparm.integ = parms[i].parm_val;
5534 if ((int) cparm.integ != IPMI_LANP_INTEGRITY_ALGORITHM_BMCPICK)
5535 {
5536 if (cparm.integ >= 64)
5537 return EINVAL;
5538 if (cparm.integ
5539 && ((cparm.integ < 0x30) && (!integs[cparm.integ])))
5540 return ENOSYS;
5541 }
5542 break;
5543
5544 case IPMI_LANP_CONFIDENTIALITY_ALGORITHM:
5545 cparm.conf = parms[i].parm_val;
5546 if ((int)cparm.conf != IPMI_LANP_CONFIDENTIALITY_ALGORITHM_BMCPICK)
5547 {
5548 if (cparm.conf >= 64)
5549 return EINVAL;
5550 if (cparm.conf
5551 && ((cparm.conf < 0x30) && (!confs[cparm.conf])))
5552 return ENOSYS;
5553 }
5554 break;
5555
5556 case IPMI_LANP_NAME_LOOKUP_ONLY:
5557 cparm.name_lookup_only = parms[i].parm_val != 0;
5558 break;
5559
5560 case IPMI_LANP_BMC_KEY:
5561 if (parms[i].parm_data_len > sizeof(cparm.bmc_key))
5562 return EINVAL;
5563 memcpy(cparm.bmc_key, parms[i].parm_data, parms[i].parm_data_len);
5564 cparm.bmc_key_len = parms[i].parm_data_len;
5565 break;
5566
5567 case IPMI_LANP_MAX_OUTSTANDING_MSG_COUNT:
5568 if ((parms[i].parm_val < 1)
5569 || (parms[i].parm_val > MAX_POSSIBLE_OUTSTANDING_MSG_COUNT))
5570 return EINVAL;
5571 max_outstanding_msg_count = parms[i].parm_val;
5572 break;
5573
5574 case IPMI_LANP_ADDRESS_FAMILY:
5575 set_addr_family = addr_family = parms[i].parm_val;
5576 break;
5577
5578 default:
5579 return EINVAL;
5580 }
5581 }
5582
5583 if ((cparm.num_ip_addr == 0) || (ip_addrs == NULL))
5584 return EINVAL;
5585 if (((int) cparm.authtype != IPMI_AUTHTYPE_DEFAULT)
5586 && (cparm.authtype != IPMI_AUTHTYPE_RMCP_PLUS)
5587 && ((cparm.authtype >= MAX_IPMI_AUTHS)
5588 || (ipmi_auths[cparm.authtype].authcode_init == NULL)))
5589 return EINVAL;
5590 if ((cparm.num_ip_addr < 1) || (cparm.num_ip_addr > MAX_IP_ADDR))
5591 return EINVAL;
5592
5593 if (ports) {
5594 for (i=0; i<MAX_IP_ADDR; i++)
5595 tports[i] = ports[i];
5596 ports = tports;
5597 } else {
5598 ports = tports;
5599 for (i=0; i<MAX_IP_ADDR; i++)
5600 ports[i] = NULL;
5601 }
5602 for (i=0; i<MAX_IP_ADDR; i++) {
5603 if (!ports[i])
5604 ports[i] = IPMI_LAN_STD_PORT_STR;
5605 }
5606
5607 count = 0;
5608 #ifdef HAVE_GETADDRINFO
5609 for (i=0; i<cparm.num_ip_addr; i++) {
5610 struct addrinfo hints, *res0;
5611
5612 memset(&hints, 0, sizeof(hints));
5613 if (count == 0)
5614 hints.ai_family = addr_family;
5615 else {
5616 /* Make sure all ip address are in the same protocol family*/
5617 struct sockaddr_in *paddr;
5618 paddr = (struct sockaddr_in *)&(cparm.ip_addr[0]);
5619 hints.ai_family = paddr->sin_family;
5620 }
5621 hints.ai_socktype = SOCK_DGRAM;
5622 rv = getaddrinfo(ip_addrs[i], ports[i], &hints, &res0);
5623 if (rv)
5624 return EINVAL;
5625
5626 if (res0->ai_addrlen > sizeof(cparm.ip_addr[count].s_ipsock)) {
5627 freeaddrinfo(res0);
5628 return EFBIG;
5629 }
5630
5631 /* Only get the first choices */
5632 memcpy(&(cparm.ip_addr[count].s_ipsock), res0->ai_addr,
5633 res0->ai_addrlen);
5634 cparm.ip_addr[count].ip_addr_len = res0->ai_addrlen;
5635 count++;
5636 freeaddrinfo(res0);
5637 }
5638 #else
5639 /* System does not support getaddrinfo, just for IPv4 */
5640 if (addr_family == AF_UNSPEC)
5641 addr_family = AF_INET;
5642 else if (addr_family != AF_INET)
5643 return EINVAL;
5644 for (i=0; i<cparm.num_ip_addr; i++) {
5645 struct hostent *ent;
5646 struct sockaddr_in *paddr;
5647 ent = gethostbyname(ip_addrs[i]);
5648 if (!ent)
5649 return EINVAL;
5650 paddr = (struct sockaddr_in *)&(cparm.ip_addr[i]);
5651 paddr->sin_family = AF_INET;
5652 paddr->sin_port = htons(atoi(ports[i]));
5653 if (ent->h_length > sizeof(paddr->sin_addr))
5654 return EFBIG;
5655
5656 memcpy(&(paddr->sin_addr), ent->h_addr_list[0], ent->h_length);
5657 cparm.ip_addr[count].ip_addr_len = ent->h_length;
5658 count++;
5659 }
5660 #endif
5661 if (count == 0)
5662 return EINVAL;
5663 cparm.num_ip_addr = count;
5664
5665 /* At this point we have a validated set of parms in cparm. See
5666 if we alreay have one that matches. */
5667 lan = find_matching_lan(&cparm);
5668 if (lan) {
5669 *new_con = lan->ipmi;
5670 return 0;
5671 }
5672
5673 ipmi = ipmi_mem_alloc(sizeof(*ipmi));
5674 if (!ipmi)
5675 return ENOMEM;
5676 memset(ipmi, 0, sizeof(*ipmi));
5677
5678 ipmi->user_data = user_data;
5679 ipmi->os_hnd = handlers;
5680 ipmi->con_type = "rmcp";
5681 ipmi->priv_level = cparm.privilege;
5682 for (i=0; i<MAX_IPMI_USED_CHANNELS; i++)
5683 ipmi->ipmb_addr[i] = 0x20; /* Assume this until told otherwise */
5684
5685 rv = ipmi_con_attr_init(ipmi);
5686 if (rv)
5687 goto out_err;
5688
5689 lan = ipmi_mem_alloc(sizeof(*lan));
5690 if (!lan) {
5691 rv = ENOMEM;
5692 goto out_err;
5693 }
5694 memset(lan, 0, sizeof(*lan));
5695 ipmi->con_data = lan;
5696 lan->cparm = cparm;
5697 for (i=0; i<cparm.num_ip_addr; i++) {
5698 lan->cparm.ip_addr_str[i] = ipmi_strdup(ip_addrs[i]);
5699 if (!lan->cparm.ip_addr_str[i]) {
5700 rv = ENOMEM;
5701 goto out_err;
5702 }
5703 lan->cparm.ip_port_str[i] = ipmi_strdup(ports[i]);
5704 if (!lan->cparm.ip_port_str[i]) {
5705 rv = ENOMEM;
5706 goto out_err;
5707 }
5708 }
5709
5710 lan->refcount = 1;
5711 lan->users = 1;
5712 lan->ipmi = ipmi;
5713 for (i=0; i<MAX_IPMI_USED_CHANNELS; i++)
5714 lan->slave_addr[i] = 0x20; /* Assume this until told otherwise */
5715 lan->is_active = 1;
5716 lan->chosen_authtype = IPMI_AUTHTYPE_DEFAULT;
5717 lan->curr_ip_addr = 0;
5718 lan->num_sends = 0;
5719 lan->connected = 0;
5720 lan->initialized = 0;
5721
5722 lan->outstanding_msg_count = 0;
5723 lan->max_outstanding_msg_count = max_outstanding_msg_count;
5724 lan->addr_family = set_addr_family;
5725 lan->wait_q = NULL;
5726 lan->wait_q_tail = NULL;
5727
5728 pa = (struct sockaddr_in *)&(lan->cparm.ip_addr[0]);
5729 lan->fd = find_free_lan_fd(pa->sin_family, lan, &lan->fd_slot);
5730 if (! lan->fd) {
5731 rv = errno;
5732 goto out_err;
5733 }
5734
5735 /* Create the locks if they are available. */
5736 rv = ipmi_create_lock_os_hnd(handlers, &lan->seq_num_lock);
5737 if (rv)
5738 goto out_err;
5739
5740 rv = ipmi_create_lock_os_hnd(handlers, &lan->ip_lock);
5741 if (rv)
5742 goto out_err;
5743
5744 lan->con_change_handlers = locked_list_alloc(handlers);
5745 if (!lan->con_change_handlers) {
5746 rv = ENOMEM;
5747 goto out_err;
5748 }
5749
5750 lan->event_handlers = locked_list_alloc(handlers);
5751 if (!lan->event_handlers) {
5752 rv = ENOMEM;
5753 goto out_err;
5754 }
5755
5756 lan->ipmb_change_handlers = locked_list_alloc(handlers);
5757 if (!lan->ipmb_change_handlers) {
5758 rv = ENOMEM;
5759 goto out_err;
5760 }
5761
5762 rv = ipmi_create_lock_os_hnd(handlers, &lan->con_change_lock);
5763 if (rv)
5764 goto out_err;
5765
5766 lan->lan_stat_list = locked_list_alloc(handlers);
5767 if (!lan->lan_stat_list) {
5768 rv = ENOMEM;
5769 goto out_err;
5770 }
5771
5772 ipmi->start_con = lan_start_con;
5773 ipmi->set_ipmb_addr = lan_set_ipmb_addr;
5774 ipmi->add_ipmb_addr_handler = lan_add_ipmb_addr_handler;
5775 ipmi->remove_ipmb_addr_handler = lan_remove_ipmb_addr_handler;
5776 ipmi->add_con_change_handler = lan_add_con_change_handler;
5777 ipmi->remove_con_change_handler = lan_remove_con_change_handler;
5778 ipmi->send_command = lan_send_command;
5779 ipmi->add_event_handler = lan_add_event_handler;
5780 ipmi->remove_event_handler = lan_remove_event_handler;
5781 ipmi->send_response = lan_send_response;
5782 ipmi->register_for_command = lan_register_for_command;
5783 ipmi->deregister_for_command = lan_deregister_for_command;
5784 ipmi->close_connection = lan_close_connection;
5785 ipmi->close_connection_done = lan_close_connection_done;
5786 ipmi->handle_async_event = handle_async_event;
5787 ipmi->get_startup_args = get_startup_args;
5788 ipmi->use_connection = lan_use_connection;
5789 ipmi->send_command_option = lan_send_command_option;
5790 ipmi->get_num_ports = lan_get_num_ports;
5791 ipmi->get_port_info = lan_get_port_info;
5792 ipmi->register_stat_handler = lan_register_stat_handler;
5793 ipmi->unregister_stat_handler = lan_unregister_stat_handler;
5794 ipmi->disable = lan_disable;
5795
5796 /* Add it to the list of valid IPMIs so it will validate. This
5797 must be done last, after a point where it cannot fail. */
5798 lan_add_con(lan);
5799
5800 *new_con = ipmi;
5801
5802 return 0;
5803
5804 out_err:
5805 cleanup_con(ipmi);
5806 return rv;
5807 }
5808
5809 static void
snmp_got_match(lan_data_t * lan,const ipmi_msg_t * msg,const unsigned char * pet_ack)5810 snmp_got_match(lan_data_t *lan,
5811 const ipmi_msg_t *msg,
5812 const unsigned char *pet_ack)
5813 {
5814 ipmi_system_interface_addr_t si;
5815 ipmi_msg_t ack;
5816 int dummy_send_ip;
5817
5818 si.addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE;
5819 si.channel = 0xf;
5820 si.lun = 0;
5821 handle_async_event(lan->ipmi, (ipmi_addr_t *) &si, sizeof(si), msg);
5822
5823 /* Send the ack directly. */
5824 ack.netfn = IPMI_SENSOR_EVENT_NETFN;
5825 ack.cmd = IPMI_PET_ACKNOWLEDGE_CMD;
5826 ack.data = (unsigned char *) pet_ack;
5827 ack.data_len = 12;
5828 lan_send(lan, (ipmi_addr_t *) &si, sizeof(si), &ack, 0, &dummy_send_ip,
5829 NULL);
5830 }
5831
5832 typedef struct lan_do_evt_s
5833 {
5834 lan_data_t *lan;
5835 struct lan_do_evt_s *next;
5836 } lan_do_evt_t;
5837
5838 int
ipmi_lan_handle_external_event(const struct sockaddr * src_addr,const ipmi_msg_t * msg,const unsigned char * pet_ack)5839 ipmi_lan_handle_external_event(const struct sockaddr *src_addr,
5840 const ipmi_msg_t *msg,
5841 const unsigned char *pet_ack)
5842 {
5843 lan_link_t *l;
5844 lan_data_t *lan;
5845 unsigned int i;
5846 unsigned int idx;
5847 lan_do_evt_t *found = NULL;
5848 lan_do_evt_t *next = NULL;
5849
5850 idx = hash_lan_addr(src_addr);
5851 ipmi_lock(lan_list_lock);
5852 l = lan_ip_list[idx].next;
5853 /* Note that we call all the connections with the given IP
5854 address, not just the first one we find. There may be more
5855 than one. */
5856 while (l->lan) {
5857 lan = NULL;
5858 for (i=0; i<l->lan->cparm.num_ip_addr; i++) {
5859 if (l->lan->cparm.ip_addr[i].s_ipsock.s_addr0.sa_family
5860 != src_addr->sa_family)
5861 {
5862 continue;
5863 }
5864 switch (src_addr->sa_family)
5865 {
5866 case PF_INET:
5867 {
5868 struct sockaddr_in *src, *dst;
5869 src = (struct sockaddr_in *) src_addr;
5870 dst = &(l->lan->cparm.ip_addr[i].s_ipsock.s_addr4);
5871 if (dst->sin_addr.s_addr == src->sin_addr.s_addr) {
5872 /* We have a match, handle it */
5873 lan = l->lan;
5874 lan->refcount++;
5875 }
5876 }
5877 break;
5878 #ifdef PF_INET6
5879 case PF_INET6:
5880 {
5881 struct sockaddr_in6 *src, *dst;
5882 src = (struct sockaddr_in6 *) src_addr;
5883 dst = &(l->lan->cparm.ip_addr[i].s_ipsock.s_addr6);
5884 if (memcmp(dst->sin6_addr.s6_addr,
5885 src->sin6_addr.s6_addr,
5886 sizeof(struct in6_addr))
5887 == 0)
5888 {
5889 /* We have a match, handle it */
5890 lan = l->lan;
5891 lan->refcount++;
5892 }
5893 }
5894 break;
5895 #endif
5896 }
5897
5898 if (lan) {
5899 next = ipmi_mem_alloc(sizeof(*next));
5900 if (!next)
5901 /* Can't do anything, just go on. It's not
5902 fatal, it just delays things. */
5903 continue;
5904 next->lan = lan;
5905 next->next = found;
5906 found = next;
5907 }
5908 }
5909 l = l->next;
5910 }
5911 ipmi_unlock(lan_list_lock);
5912
5913 while (found) {
5914 next = found;
5915 found = found->next;
5916 snmp_got_match(next->lan, msg, pet_ack);
5917 lan_put(next->lan->ipmi);
5918 ipmi_mem_free(next);
5919 }
5920
5921 /* Next will be left non-NULL if something was delivered, it will
5922 be NULL if nothing was delivered. */
5923 return next != NULL;
5924 }
5925
5926 typedef struct lan_args_s
5927 {
5928 char *str_addr[2]; /* parms 0, 1 */
5929 char *str_port[2]; /* parms 2, 3 */
5930 int num_addr;
5931 unsigned int authtype; /* parm 4 */
5932 unsigned int privilege; /* parm 5 */
5933 int username_set;
5934 char username[16]; /* parm 6 */
5935 unsigned int username_len;
5936 int password_set;
5937 char password[20]; /* parm 7 */
5938 unsigned int password_len;
5939
5940 unsigned int auth_alg; /* parm 8 */
5941 unsigned int integ_alg; /* parm 9 */
5942 unsigned int conf_alg; /* parm 10 */
5943 unsigned int name_lookup_only; /* parm 11 */
5944 int bmc_key_set;
5945 char bmc_key[20]; /* parm 12 */
5946 unsigned int bmc_key_len;
5947
5948 unsigned int hacks; /* parms 13, 14 */
5949 unsigned int max_outstanding_msgs;/* parm 15 */
5950
5951 unsigned int addr_family; /* parm 16 */
5952 } lan_args_t;
5953
5954 static const char *auth_range[] = { "default", "none", "md2", "md5",
5955 "straight", "oem", "rmcp+", NULL };
5956 static int auth_vals[] = { IPMI_AUTHTYPE_DEFAULT,
5957 IPMI_AUTHTYPE_NONE,
5958 IPMI_AUTHTYPE_MD2,
5959 IPMI_AUTHTYPE_MD5,
5960 IPMI_AUTHTYPE_STRAIGHT,
5961 IPMI_AUTHTYPE_OEM,
5962 IPMI_AUTHTYPE_RMCP_PLUS };
5963
5964 static const char *priv_range[] = { "callback", "user", "operator", "admin",
5965 "oem", NULL };
5966 static int priv_vals[] = { IPMI_PRIVILEGE_CALLBACK,
5967 IPMI_PRIVILEGE_USER,
5968 IPMI_PRIVILEGE_OPERATOR,
5969 IPMI_PRIVILEGE_ADMIN,
5970 IPMI_PRIVILEGE_OEM };
5971
5972 static const char *auth_alg_range[] = { "bmcpick", "rakp_none",
5973 "rakp_hmac_sha1", "rakp_hmac_md5",
5974 NULL };
5975 static int auth_alg_vals[] = { IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK,
5976 IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE,
5977 IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1,
5978 IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5 };
5979 static const char *integ_alg_range[] = { "bmcpick", "none", "hmac_sha1",
5980 "hmac_md5", "md5", NULL };
5981 static int integ_alg_vals[] = { IPMI_LANP_INTEGRITY_ALGORITHM_BMCPICK,
5982 IPMI_LANP_INTEGRITY_ALGORITHM_NONE,
5983 IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_SHA1_96,
5984 IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_MD5_128,
5985 IPMI_LANP_INTEGRITY_ALGORITHM_MD5_128 };
5986
5987 static const char *conf_alg_range[] = { "bmcpick", "none", "aes_cbc_128",
5988 "xrc4_128", "xrc4_40", NULL };
5989 static int conf_alg_vals[] = { IPMI_LANP_CONFIDENTIALITY_ALGORITHM_BMCPICK,
5990 IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE,
5991 IPMI_LANP_CONFIDENTIALITY_ALGORITHM_AES_CBC_128,
5992 IPMI_LANP_CONFIDENTIALITY_ALGORITHM_xRC4_128,
5993 IPMI_LANP_CONFIDENTIALITY_ALGORITHM_xRC4_40 };
5994
5995 static const char *addr_family_range[] = { "af_unspec", "af_inet",
5996 #ifdef AF_INET6
5997 "af_inet6",
5998 #endif
5999 NULL };
6000 static int addr_family_vals[] = { AF_UNSPEC, AF_INET
6001 #ifdef AF_INET6
6002 , AF_INET6
6003 #endif
6004 };
6005
6006
6007 static struct lan_argnum_info_s
6008 {
6009 const char *name;
6010 const char *type;
6011 const char *help;
6012 const char **range;
6013 const int *values;
6014 } lan_argnum_info[18] =
6015 {
6016 { "Address", "str",
6017 "*IP name or address of the MC",
6018 NULL, NULL },
6019 { "Port", "str",
6020 "*IP port or port name for the MC",
6021 NULL, NULL },
6022 { "Address2", "str",
6023 "IP name or address of a second connection to the same MC",
6024 NULL, NULL },
6025 { "Port2", "str",
6026 "IP port or portname for a second connection to the same MC",
6027 NULL, NULL },
6028 { "Authtype", "enum",
6029 "Authentication to use for the connection",
6030 auth_range, auth_vals },
6031 { "Privilege", "enum",
6032 "Privilege level to use for the connection",
6033 priv_range, priv_vals },
6034 { "Username", "str",
6035 "The user name to use for the connection",
6036 NULL, NULL },
6037 { "Password", "str",
6038 "!The password to use for the connection",
6039 NULL, NULL },
6040 { "Authentication_Algorithm", "enum",
6041 "Authentication algorithm to use for the connection, for RMCP+ only",
6042 auth_alg_range, auth_alg_vals },
6043 { "Integrity_Algorithm", "enum",
6044 "Integrity algorithm to use for the connection, for RMCP+ only",
6045 integ_alg_range, integ_alg_vals },
6046 { "Confidentiality_Algorithm", "enum",
6047 "Confidentiality algorithm to use for the connection, for RMCP+ only",
6048 conf_alg_range, conf_alg_vals },
6049 { "Name_Lookup_Only", "bool",
6050 "Use only the name, not the privilege, for selecting the password",
6051 NULL, NULL },
6052 { "BMC_Key", "str",
6053 "The key to use for connecting to the BMC, may or may not be required",
6054 NULL, NULL },
6055 { "RAKP3_Wrong_RoleM", "bool",
6056 "Some systems use the wrong RoleM value for RAKP3, a common problem",
6057 NULL, NULL },
6058 { "RMCP_Integ_SIK", "bool",
6059 "The IPMI 2.0 Spec was unclear which integrity key to use",
6060 NULL, NULL },
6061 { "Max_Outstanding_Msgs", "int",
6062 "How many outstanding messages on the connection, range 1-63",
6063 NULL, NULL },
6064 { "Address_Family", "enum",
6065 "Specified address family (AF_INET or AF_INET6) or AF_UNSPEC",
6066 addr_family_range, addr_family_vals },
6067
6068 { NULL },
6069 };
6070
6071 static ipmi_args_t *lan_con_alloc_args(void);
6072
6073 static void
lan_free_args(ipmi_args_t * args)6074 lan_free_args(ipmi_args_t *args)
6075 {
6076 lan_args_t *largs = i_ipmi_args_get_extra_data(args);
6077
6078 if (largs->str_addr[0])
6079 ipmi_mem_free(largs->str_addr[0]);
6080 if (largs->str_addr[1])
6081 ipmi_mem_free(largs->str_addr[1]);
6082 if (largs->str_port[0])
6083 ipmi_mem_free(largs->str_port[0]);
6084 if (largs->str_port[1])
6085 ipmi_mem_free(largs->str_port[1]);
6086 /* paranoia */
6087 memset(largs->password, 0, sizeof(largs->password));
6088 memset(largs->bmc_key, 0, sizeof(largs->bmc_key));
6089 }
6090
6091 static ipmi_args_t *
get_startup_args(ipmi_con_t * ipmi)6092 get_startup_args(ipmi_con_t *ipmi)
6093 {
6094 ipmi_args_t *args;
6095 lan_args_t *largs;
6096 lan_data_t *lan;
6097 lan_conn_parms_t *cparm;
6098
6099 args = lan_con_alloc_args();
6100 if (! args)
6101 return NULL;
6102 largs = i_ipmi_args_get_extra_data(args);
6103 lan = (lan_data_t *) ipmi->con_data;
6104 cparm = &lan->cparm;
6105 largs->str_addr[0] = ipmi_strdup(cparm->ip_addr_str[0]);
6106 if (!largs->str_addr[0])
6107 goto out_err;
6108 largs->str_port[0] = ipmi_strdup(cparm->ip_port_str[0]);
6109 if (!largs->str_port[0])
6110 goto out_err;
6111 if (cparm->num_ip_addr > 1) {
6112 largs->str_addr[1] = ipmi_strdup(cparm->ip_addr_str[1]);
6113 if (!largs->str_addr[1])
6114 goto out_err;
6115 largs->str_port[1] = ipmi_strdup(cparm->ip_port_str[1]);
6116 if (!largs->str_port[1])
6117 goto out_err;
6118 }
6119 largs->num_addr = cparm->num_ip_addr;
6120 largs->authtype = cparm->authtype;
6121 largs->privilege = cparm->privilege;
6122 if (cparm->username_len) {
6123 largs->username_len = cparm->username_len ;
6124 memcpy(largs->username, cparm->username, cparm->username_len);
6125 largs->username_set = 1;
6126 }
6127 if (cparm->password_len) {
6128 largs->password_len = cparm->password_len ;
6129 memcpy(largs->password, cparm->password, cparm->password_len);
6130 largs->password_set = 1;
6131 }
6132 largs->conf_alg = cparm->conf;
6133 largs->auth_alg = cparm->auth;
6134 largs->integ_alg = cparm->integ;
6135 largs->name_lookup_only = cparm->name_lookup_only;
6136 largs->hacks = ipmi->hacks;
6137 if (cparm->bmc_key_len) {
6138 largs->bmc_key_len = cparm->bmc_key_len ;
6139 memcpy(largs->bmc_key, cparm->bmc_key, cparm->bmc_key_len);
6140 largs->bmc_key_set = 1;
6141 }
6142 largs->max_outstanding_msgs = lan->max_outstanding_msg_count;
6143 largs->addr_family = lan->addr_family;
6144 return args;
6145
6146 out_err:
6147 lan_free_args(args);
6148 return NULL;
6149 }
6150
6151 static int
lan_connect_args(ipmi_args_t * args,os_handler_t * handlers,void * user_data,ipmi_con_t ** con)6152 lan_connect_args(ipmi_args_t *args,
6153 os_handler_t *handlers,
6154 void *user_data,
6155 ipmi_con_t **con)
6156 {
6157 lan_args_t *largs = i_ipmi_args_get_extra_data(args);
6158 int i;
6159 ipmi_lanp_parm_t parms[13];
6160 int rv;
6161
6162 i = 0;
6163 parms[i].parm_id = IPMI_LANP_PARMID_ADDRS;
6164 parms[i].parm_data = largs->str_addr;
6165 parms[i].parm_data_len = largs->num_addr;
6166 i++;
6167 parms[i].parm_id = IPMI_LANP_PARMID_PORTS;
6168 parms[i].parm_data = largs->str_port;
6169 parms[i].parm_data_len = largs->num_addr;
6170 i++;
6171 parms[i].parm_id = IPMI_LANP_PARMID_AUTHTYPE;
6172 parms[i].parm_val = largs->authtype;
6173 i++;
6174 parms[i].parm_id = IPMI_LANP_PARMID_PRIVILEGE;
6175 parms[i].parm_val = largs->privilege;
6176 i++;
6177 if (largs->username_set) {
6178 parms[i].parm_id = IPMI_LANP_PARMID_USERNAME;
6179 parms[i].parm_data = largs->username;
6180 parms[i].parm_data_len = largs->username_len;
6181 i++;
6182 }
6183 if (largs->password_set) {
6184 parms[i].parm_id = IPMI_LANP_PARMID_PASSWORD;
6185 parms[i].parm_data = largs->password;
6186 parms[i].parm_data_len = largs->password_len;
6187 i++;
6188 }
6189 parms[i].parm_id = IPMI_LANP_AUTHENTICATION_ALGORITHM;
6190 parms[i].parm_val = largs->auth_alg;
6191 i++;
6192 parms[i].parm_id = IPMI_LANP_INTEGRITY_ALGORITHM;
6193 parms[i].parm_val = largs->integ_alg;
6194 i++;
6195 parms[i].parm_id = IPMI_LANP_CONFIDENTIALITY_ALGORITHM;
6196 parms[i].parm_val = largs->conf_alg;
6197 i++;
6198 parms[i].parm_id = IPMI_LANP_NAME_LOOKUP_ONLY;
6199 parms[i].parm_val = largs->name_lookup_only;
6200 i++;
6201 if (largs->bmc_key_set) {
6202 parms[i].parm_id = IPMI_LANP_BMC_KEY;
6203 parms[i].parm_data = largs->bmc_key;
6204 parms[i].parm_data_len = largs->bmc_key_len;
6205 i++;
6206 }
6207 parms[i].parm_id = IPMI_LANP_MAX_OUTSTANDING_MSG_COUNT;
6208 parms[i].parm_val = largs->max_outstanding_msgs;
6209 i++;
6210 parms[i].parm_id = IPMI_LANP_ADDRESS_FAMILY;
6211 parms[i].parm_val = largs->addr_family;
6212 i++;
6213 rv = ipmi_lanp_setup_con(parms, i, handlers, user_data, con);
6214 if (!rv)
6215 (*con)->hacks = largs->hacks;
6216 return rv;
6217 }
6218
6219 static int
get_str_val(char ** dest,const char * data,int * is_set,unsigned int * len)6220 get_str_val(char **dest, const char *data, int *is_set, unsigned int *len)
6221 {
6222 char *rval = NULL;
6223 if (!dest)
6224 return 0;
6225 if (is_set && (! *is_set)) {
6226 *dest = NULL;
6227 return 0;
6228 }
6229 if (data) {
6230 if (len) {
6231 rval = ipmi_mem_alloc(*len+1);
6232 if (!rval)
6233 return ENOMEM;
6234 memcpy(rval, data, *len);
6235 rval[*len] = '\0';
6236 } else {
6237 rval = ipmi_strdup(data);
6238 if (!rval)
6239 return ENOMEM;
6240 }
6241 *dest = rval;
6242 } else {
6243 *dest = NULL;
6244 }
6245 return 0;
6246 }
6247
6248 static int
get_enum_val(int argnum,char ** dest,int data,const char *** rrange)6249 get_enum_val(int argnum, char **dest, int data, const char ***rrange)
6250 {
6251 char *rval = NULL;
6252 const int *values;
6253 const char **range;
6254 int i;
6255
6256 if (rrange)
6257 *rrange = lan_argnum_info[argnum].range;
6258
6259 if (!dest)
6260 return 0;
6261
6262 values = lan_argnum_info[argnum].values;
6263 range = lan_argnum_info[argnum].range;
6264 for (i=0; range[i]; i++) {
6265 if (values[i] == data) {
6266 rval = ipmi_strdup(lan_argnum_info[argnum].range[i]);
6267 if (!rval)
6268 return ENOMEM;
6269 *dest = rval;
6270 return 0;
6271 }
6272 }
6273 return EINVAL;
6274 }
6275
6276 static int
get_bool_val(char ** dest,int data,unsigned int bit)6277 get_bool_val(char **dest, int data, unsigned int bit)
6278 {
6279 char *rval = NULL;
6280
6281 if (!dest)
6282 return 0;
6283 if (data & bit)
6284 rval = ipmi_strdup("true");
6285 else
6286 rval = ipmi_strdup("false");
6287 if (!rval)
6288 return ENOMEM;
6289 *dest = rval;
6290 return 0;
6291 }
6292
6293 static int
get_int_val(char ** dest,int data)6294 get_int_val(char **dest, int data)
6295 {
6296 char *rval = NULL;
6297 int len;
6298
6299 if (!dest)
6300 return 0;
6301 len = snprintf(NULL, 0, "%d", data);
6302 rval = malloc(len+1);
6303 if (!rval)
6304 return ENOMEM;
6305 snprintf(rval, len+1, "%d", data);
6306 *dest = rval;
6307 return 0;
6308 }
6309
6310 static const char *
lan_args_get_type(ipmi_args_t * args)6311 lan_args_get_type(ipmi_args_t *args)
6312 {
6313 return "lan";
6314 }
6315
6316 static int
lan_args_get_val(ipmi_args_t * args,unsigned int argnum,const char ** name,const char ** type,const char ** help,char ** value,const char *** range)6317 lan_args_get_val(ipmi_args_t *args,
6318 unsigned int argnum,
6319 const char **name,
6320 const char **type,
6321 const char **help,
6322 char **value,
6323 const char ***range)
6324 {
6325 lan_args_t *largs = i_ipmi_args_get_extra_data(args);
6326 int rv;
6327
6328 switch(argnum) {
6329 case 0:
6330 rv = get_str_val(value, largs->str_addr[0], NULL, NULL);
6331 break;
6332
6333 case 1:
6334 rv = get_str_val(value, largs->str_port[0], NULL, NULL);
6335 break;
6336
6337 case 2:
6338 rv = get_str_val(value, largs->str_addr[1], NULL, NULL);
6339 break;
6340
6341 case 3:
6342 rv = get_str_val(value, largs->str_port[1], NULL, NULL);
6343 break;
6344
6345 case 4:
6346 rv = get_enum_val(argnum, value, largs->authtype, range);
6347 break;
6348
6349 case 5:
6350 rv = get_enum_val(argnum, value, largs->privilege, range);
6351 break;
6352
6353 case 6:
6354 rv = get_str_val(value, largs->username, &largs->username_set,
6355 &largs->username_len);
6356 break;
6357
6358 case 7:
6359 rv = get_str_val(value, largs->password, &largs->password_set,
6360 &largs->password_len);
6361 break;
6362
6363 case 8:
6364 rv = get_enum_val(argnum, value, largs->auth_alg, range);
6365 break;
6366
6367 case 9:
6368 rv = get_enum_val(argnum, value, largs->integ_alg, range);
6369 break;
6370
6371 case 10:
6372 rv = get_enum_val(argnum, value, largs->conf_alg, range);
6373 break;
6374
6375 case 11:
6376 rv = get_bool_val(value, largs->name_lookup_only, 1);
6377 break;
6378
6379 case 12:
6380 rv = get_str_val(value, largs->bmc_key, &largs->bmc_key_set,
6381 &largs->bmc_key_len);
6382 break;
6383
6384 case 13:
6385 rv = get_bool_val(value, largs->hacks,
6386 IPMI_CONN_HACK_RAKP3_WRONG_ROLEM);
6387 break;
6388
6389 case 14:
6390 rv = get_bool_val(value, largs->hacks,
6391 IPMI_CONN_HACK_RMCPP_INTEG_SIK);
6392 break;
6393
6394 case 15:
6395 rv = get_int_val(value, largs->max_outstanding_msgs);
6396 break;
6397
6398 case 16:
6399 rv = get_enum_val(argnum, value, largs->addr_family, range);
6400 break;
6401
6402 default:
6403 return E2BIG;
6404 }
6405
6406 if (rv)
6407 return rv;
6408
6409 if (name)
6410 *name = lan_argnum_info[argnum].name;
6411 if (type)
6412 *type = lan_argnum_info[argnum].type;
6413 if (help)
6414 *help = lan_argnum_info[argnum].help;
6415
6416 return 0;
6417 }
6418
6419 static int
set_str_val(char ** dest,const char * value,int null_ok,int * is_set,unsigned int * len,unsigned int max_len)6420 set_str_val(char **dest, const char *value, int null_ok, int *is_set,
6421 unsigned int *len, unsigned int max_len)
6422 {
6423 char *rval;
6424
6425 if (! value) {
6426 if (! null_ok)
6427 return EINVAL;
6428 *dest = NULL;
6429 if (is_set)
6430 *is_set = 0;
6431 return 0;
6432 }
6433
6434 if (len) {
6435 unsigned int nlen = strlen(value);
6436 if (nlen > max_len)
6437 return EINVAL;
6438 memcpy(*dest, value, nlen);
6439 *len = nlen;
6440 } else {
6441 rval = ipmi_strdup(value);
6442 if (!rval)
6443 return ENOMEM;
6444 if (*dest)
6445 ipmi_mem_free(*dest);
6446 *dest = rval;
6447 }
6448 if (is_set)
6449 *is_set = 1;
6450 return 0;
6451 }
6452
6453 static int
set_enum_val(int argnum,unsigned int * dest,const char * value)6454 set_enum_val(int argnum, unsigned int *dest, const char *value)
6455 {
6456 const char **range;
6457 int i;
6458
6459 if (! value)
6460 return EINVAL;
6461
6462 range = lan_argnum_info[argnum].range;
6463 for (i=0; range[i]; i++) {
6464 if (strcmp(range[i], value) == 0) {
6465 *dest = lan_argnum_info[argnum].values[i];
6466 return 0;
6467 }
6468 }
6469 return EINVAL;
6470 }
6471
6472 static int
set_bool_val(unsigned int * dest,const char * value,unsigned int bit)6473 set_bool_val(unsigned int *dest, const char *value, unsigned int bit)
6474 {
6475 if (! value)
6476 return EINVAL;
6477
6478 if (strcmp(value, "true") == 0)
6479 *dest |= bit;
6480 else if (strcmp(value, "false") == 0)
6481 *dest &= ~bit;
6482 else
6483 return EINVAL;
6484 return 0;
6485 }
6486
6487 static int
set_uint_val(unsigned int * dest,const char * value)6488 set_uint_val(unsigned int *dest, const char *value)
6489 {
6490 int val;
6491 char *end;
6492
6493 if (! value)
6494 return EINVAL;
6495 if (*value == '\0')
6496 return EINVAL;
6497
6498 val = strtoul(value, &end, 0);
6499 if (*end != '\0')
6500 return EINVAL;
6501 *dest = val;
6502 return 0;
6503 }
6504
6505 static int
lan_args_set_val(ipmi_args_t * args,unsigned int argnum,const char * name,const char * value)6506 lan_args_set_val(ipmi_args_t *args,
6507 unsigned int argnum,
6508 const char *name,
6509 const char *value)
6510 {
6511 lan_args_t *largs = i_ipmi_args_get_extra_data(args);
6512 int rv;
6513 char *sval;
6514
6515 if (name) {
6516 int i;
6517 for (i=0; lan_argnum_info[i].name; i++) {
6518 if (strcmp(lan_argnum_info[i].name, name) == 0)
6519 break;
6520 }
6521 if (! lan_argnum_info[i].name)
6522 return EINVAL;
6523 argnum = i;
6524 }
6525
6526 switch (argnum) {
6527 case 0:
6528 rv = set_str_val(&(largs->str_addr[0]), value, 0, NULL, NULL, 0);
6529 if (!rv && (largs->num_addr == 0))
6530 largs->num_addr = 1;
6531 break;
6532
6533 case 1:
6534 rv = set_str_val(&(largs->str_port[0]), value, 1, NULL, NULL, 0);
6535 break;
6536
6537 case 2:
6538 rv = set_str_val(&(largs->str_addr[1]), value, 1, NULL, NULL, 0);
6539 if (!rv) {
6540 if (largs->str_addr[1]) {
6541 if (largs->num_addr < 2)
6542 largs->num_addr = 2;
6543 } else {
6544 if (largs->str_addr[0])
6545 largs->num_addr = 1;
6546 else
6547 largs->num_addr = 0;
6548 }
6549 }
6550 break;
6551
6552 case 3:
6553 rv = set_str_val(&(largs->str_port[1]), value, 1, NULL, NULL, 0);
6554 break;
6555
6556 case 4:
6557 rv = set_enum_val(argnum, &largs->authtype, value);
6558 break;
6559
6560 case 5:
6561 rv = set_enum_val(argnum, &largs->privilege, value);
6562 break;
6563
6564 case 6:
6565 sval = largs->username;
6566 rv = set_str_val(&sval, value, 1, &largs->username_set,
6567 &largs->username_len, 16);
6568 break;
6569
6570 case 7:
6571 sval = largs->password;
6572 rv = set_str_val(&sval, value, 1, &largs->password_set,
6573 &largs->password_len, 20);
6574 break;
6575
6576 case 8:
6577 rv = set_enum_val(argnum, &largs->auth_alg, value);
6578 break;
6579
6580 case 9:
6581 rv = set_enum_val(argnum, &largs->integ_alg, value);
6582 break;
6583
6584 case 10:
6585 rv = set_enum_val(argnum, &largs->conf_alg, value);
6586 break;
6587
6588 case 11:
6589 rv = set_bool_val(&largs->name_lookup_only, value, 1);
6590 break;
6591
6592 case 12:
6593 sval = largs->bmc_key;
6594 rv = set_str_val(&sval, value, 1, &largs->bmc_key_set,
6595 &largs->bmc_key_len, 20);
6596 break;
6597
6598 case 13:
6599 rv = set_bool_val(&largs->hacks, value,
6600 IPMI_CONN_HACK_RAKP3_WRONG_ROLEM);
6601 break;
6602
6603 case 14:
6604 rv = set_bool_val(&largs->hacks, value,
6605 IPMI_CONN_HACK_RMCPP_INTEG_SIK);
6606 break;
6607
6608 case 15:
6609 rv = set_uint_val(&largs->max_outstanding_msgs, value);
6610 break;
6611
6612 case 16:
6613 rv = set_enum_val(argnum, &largs->addr_family, value);
6614 break;
6615
6616 default:
6617 rv = E2BIG;
6618 }
6619
6620 return rv;
6621 }
6622
6623 static ipmi_args_t *
lan_args_copy(ipmi_args_t * args)6624 lan_args_copy(ipmi_args_t *args)
6625 {
6626 ipmi_args_t *nargs;
6627 lan_args_t *largs = i_ipmi_args_get_extra_data(args);
6628 lan_args_t *nlargs;
6629
6630 nargs = lan_con_alloc_args();
6631 if (!nargs)
6632 return NULL;
6633 nlargs = i_ipmi_args_get_extra_data(nargs);
6634 *nlargs = *largs;
6635
6636 nlargs->str_addr[0] = NULL;
6637 nlargs->str_addr[1] = NULL;
6638 nlargs->str_port[0] = NULL;
6639 nlargs->str_port[1] = NULL;
6640
6641 nlargs->str_addr[0] = ipmi_strdup(largs->str_addr[0]);
6642 if (! nlargs->str_addr[0])
6643 goto out_err;
6644 nlargs->str_addr[1] = ipmi_strdup(largs->str_addr[1]);
6645 if (! nlargs->str_addr[1])
6646 goto out_err;
6647 nlargs->str_port[0] = ipmi_strdup(largs->str_port[0]);
6648 if (! nlargs->str_port[0])
6649 goto out_err;
6650 nlargs->str_port[1] = ipmi_strdup(largs->str_port[1]);
6651 if (! nlargs->str_port[1])
6652 goto out_err;
6653
6654 return nargs;
6655
6656 out_err:
6657 lan_free_args(nargs);
6658 return NULL;
6659 }
6660
6661 static int
lan_args_validate(ipmi_args_t * args,int * argnum)6662 lan_args_validate(ipmi_args_t *args, int *argnum)
6663 {
6664 return 1; /* Can't be invalid */
6665 }
6666
6667 static void
lan_args_free_val(ipmi_args_t * args,char * value)6668 lan_args_free_val(ipmi_args_t *args, char *value)
6669 {
6670 ipmi_mem_free(value);
6671 }
6672
6673 #define CHECK_ARG \
6674 do { \
6675 if (*curr_arg >= arg_count) { \
6676 rv = EINVAL; \
6677 goto out_err; \
6678 } \
6679 } while(0)
6680
6681 static int
lan_parse_args(int * curr_arg,int arg_count,char * const * args,ipmi_args_t ** iargs)6682 lan_parse_args(int *curr_arg,
6683 int arg_count,
6684 char * const *args,
6685 ipmi_args_t **iargs)
6686 {
6687 int rv;
6688 ipmi_args_t *p = NULL;
6689 lan_args_t *largs;
6690 int i;
6691 int len;
6692
6693 CHECK_ARG;
6694
6695 p = lan_con_alloc_args();
6696 if (!p)
6697 return ENOMEM;
6698
6699 largs = i_ipmi_args_get_extra_data(p);
6700 largs->num_addr = 1;
6701
6702 while (*curr_arg < arg_count) {
6703 if (args[*curr_arg][0] != '-') {
6704 break;
6705 }
6706
6707 if (strcmp(args[*curr_arg], "-U") == 0) {
6708 (*curr_arg)++; CHECK_ARG;
6709 len = strlen(args[*curr_arg]);
6710 if (len > 16)
6711 len = 16;
6712 memcpy(largs->username, args[*curr_arg], len);
6713 largs->username_set = 1;
6714 largs->username_len = len;
6715 } else if (strcmp(args[*curr_arg], "-P") == 0) {
6716 (*curr_arg)++; CHECK_ARG;
6717 len = strlen(args[*curr_arg]);
6718 if (len > 20)
6719 len = 20;
6720 memcpy(largs->password, args[*curr_arg], len);
6721 largs->password_set = 1;
6722 largs->password_len = len;
6723 } else if (strcmp(args[*curr_arg], "-H") == 0) {
6724 (*curr_arg)++; CHECK_ARG;
6725 if (strcmp(args[*curr_arg], "intelplus") == 0)
6726 largs->hacks |= IPMI_CONN_HACK_RAKP3_WRONG_ROLEM;
6727 else if (strcmp(args[*curr_arg], "rakp3_wrong_rolem") == 0)
6728 largs->hacks |= IPMI_CONN_HACK_RAKP3_WRONG_ROLEM;
6729 else if (strcmp(args[*curr_arg], "rmcpp_integ_sik") == 0)
6730 largs->hacks |= IPMI_CONN_HACK_RMCPP_INTEG_SIK;
6731 /* Ignore unknown hacks. */
6732 } else if (strcmp(args[*curr_arg], "-4") == 0) {
6733 largs->addr_family = AF_INET;
6734 #ifdef AF_INET6
6735 } else if (strcmp(args[*curr_arg], "-6") == 0) {
6736 largs->addr_family = AF_INET6;
6737 #endif
6738 } else if (strcmp(args[*curr_arg], "-s") == 0) {
6739 largs->num_addr = 2;
6740 } else if (strcmp(args[*curr_arg], "-A") == 0) {
6741 (*curr_arg)++; CHECK_ARG;
6742 if (strcmp(args[*curr_arg], "none") == 0) {
6743 largs->authtype = IPMI_AUTHTYPE_NONE;
6744 } else if (strcmp(args[*curr_arg], "md2") == 0) {
6745 largs->authtype = IPMI_AUTHTYPE_MD2;
6746 } else if (strcmp(args[*curr_arg], "md5") == 0) {
6747 largs->authtype = IPMI_AUTHTYPE_MD5;
6748 } else if (strcmp(args[*curr_arg], "straight") == 0) {
6749 largs->authtype = IPMI_AUTHTYPE_STRAIGHT;
6750 } else if (strcmp(args[*curr_arg], "rmcp+") == 0) {
6751 largs->authtype = IPMI_AUTHTYPE_RMCP_PLUS;
6752 } else {
6753 rv = EINVAL;
6754 goto out_err;
6755 }
6756 } else if (strcmp(args[*curr_arg], "-L") == 0) {
6757 (*curr_arg)++; CHECK_ARG;
6758
6759 if (strcmp(args[*curr_arg], "callback") == 0) {
6760 largs->privilege = IPMI_PRIVILEGE_CALLBACK;
6761 } else if (strcmp(args[*curr_arg], "user") == 0) {
6762 largs->privilege = IPMI_PRIVILEGE_USER;
6763 } else if (strcmp(args[*curr_arg], "operator") == 0) {
6764 largs->privilege = IPMI_PRIVILEGE_OPERATOR;
6765 } else if (strcmp(args[*curr_arg], "admin") == 0) {
6766 largs->privilege = IPMI_PRIVILEGE_ADMIN;
6767 } else if (strcmp(args[*curr_arg], "oem") == 0) {
6768 largs->privilege = IPMI_PRIVILEGE_OEM;
6769 } else {
6770 rv = EINVAL;
6771 goto out_err;
6772 }
6773 } else if (strcmp(args[*curr_arg], "-p") == 0) {
6774 (*curr_arg)++; CHECK_ARG;
6775 largs->str_port[0] = ipmi_strdup(args[*curr_arg]);
6776 if (largs->str_port[0] == NULL) {
6777 rv = ENOMEM;
6778 goto out_err;
6779 }
6780 } else if (strcmp(args[*curr_arg], "-p2") == 0) {
6781 (*curr_arg)++; CHECK_ARG;
6782 largs->str_port[1] = ipmi_strdup(args[*curr_arg]);
6783 if (largs->str_port[1] == NULL) {
6784 rv = ENOMEM;
6785 goto out_err;
6786 }
6787 } else if (strcmp(args[*curr_arg], "-Ra") == 0) {
6788 (*curr_arg)++; CHECK_ARG;
6789
6790 if (strcmp(args[*curr_arg], "bmcpick") == 0) {
6791 largs->auth_alg = IPMI_LANP_AUTHENTICATION_ALGORITHM_BMCPICK;
6792 } else if (strcmp(args[*curr_arg], "rakp_none") == 0) {
6793 largs->auth_alg = IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_NONE;
6794 } else if (strcmp(args[*curr_arg], "rakp_hmac_sha1") == 0) {
6795 largs->auth_alg = IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_SHA1;
6796 } else if (strcmp(args[*curr_arg], "rakp_hmac_md5") == 0) {
6797 largs->auth_alg = IPMI_LANP_AUTHENTICATION_ALGORITHM_RAKP_HMAC_MD5;
6798 } else {
6799 rv = EINVAL;
6800 goto out_err;
6801 }
6802 } else if (strcmp(args[*curr_arg], "-Ri") == 0) {
6803 (*curr_arg)++; CHECK_ARG;
6804
6805 if (strcmp(args[*curr_arg], "bmcpick") == 0) {
6806 largs->integ_alg = IPMI_LANP_INTEGRITY_ALGORITHM_BMCPICK;
6807 } else if (strcmp(args[*curr_arg], "none") == 0) {
6808 largs->integ_alg = IPMI_LANP_INTEGRITY_ALGORITHM_NONE;
6809 } else if (strcmp(args[*curr_arg], "hmac_sha1") == 0) {
6810 largs->integ_alg = IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_SHA1_96;
6811 } else if (strcmp(args[*curr_arg], "hmac_md5") == 0) {
6812 largs->integ_alg = IPMI_LANP_INTEGRITY_ALGORITHM_HMAC_MD5_128;
6813 } else if (strcmp(args[*curr_arg], "md5") == 0) {
6814 largs->integ_alg = IPMI_LANP_INTEGRITY_ALGORITHM_MD5_128;
6815 } else {
6816 rv = EINVAL;
6817 goto out_err;
6818 }
6819 } else if (strcmp(args[*curr_arg], "-Rc") == 0) {
6820 (*curr_arg)++; CHECK_ARG;
6821
6822 if (strcmp(args[*curr_arg], "bmcpick") == 0) {
6823 largs->conf_alg = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_BMCPICK;
6824 } else if (strcmp(args[*curr_arg], "none") == 0) {
6825 largs->conf_alg = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_NONE;
6826 } else if (strcmp(args[*curr_arg], "aes_cbc_128") == 0) {
6827 largs->conf_alg = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_AES_CBC_128;
6828 } else if (strcmp(args[*curr_arg], "xrc4_128") == 0) {
6829 largs->conf_alg = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_xRC4_128;
6830 } else if (strcmp(args[*curr_arg], "xrc4_40") == 0) {
6831 largs->conf_alg = IPMI_LANP_CONFIDENTIALITY_ALGORITHM_xRC4_40;
6832 } else {
6833 rv = EINVAL;
6834 goto out_err;
6835 }
6836 } else if (strcmp(args[*curr_arg], "-Rl") == 0) {
6837 largs->name_lookup_only = 0;
6838 } else if (strcmp(args[*curr_arg], "-Rk") == 0) {
6839 (*curr_arg)++; CHECK_ARG;
6840 len = strlen(args[*curr_arg]);
6841 if (len > 20)
6842 len = 20;
6843 memcpy(largs->bmc_key, args[*curr_arg], len);
6844 largs->bmc_key_set = 1;
6845 largs->bmc_key_len = len;
6846 } else if (strcmp(args[*curr_arg], "-M") == 0) {
6847 char *end;
6848 int val;
6849 (*curr_arg)++; CHECK_ARG;
6850 if (args[*curr_arg][0] == '\0') {
6851 rv = EINVAL;
6852 goto out_err;
6853 }
6854 val = strtol(args[*curr_arg], &end, 0);
6855 if (*end != '\0') {
6856 rv = EINVAL;
6857 goto out_err;
6858 }
6859 largs->max_outstanding_msgs = val;
6860 }
6861 (*curr_arg)++;
6862 }
6863
6864 for (i=0; i<largs->num_addr; i++) {
6865 CHECK_ARG;
6866 largs->str_addr[i] = ipmi_strdup(args[*curr_arg]);
6867 if (largs->str_addr[i] == NULL) {
6868 rv = ENOMEM;
6869 goto out_err;
6870 }
6871 (*curr_arg)++;
6872 if (! largs->str_port[i]) {
6873 largs->str_port[i] = ipmi_strdup("623");
6874 if (largs->str_port[i] == NULL) {
6875 rv = ENOMEM;
6876 goto out_err;
6877 }
6878 }
6879 }
6880
6881 *iargs = p;
6882 return 0;
6883
6884 out_err:
6885 if (p)
6886 ipmi_free_args(p);
6887 return rv;
6888 }
6889
6890 static const char *
lan_parse_help(void)6891 lan_parse_help(void)
6892 {
6893 return
6894 "\n"
6895 " lan [-U <username>] [-P <password>] [-p[2] port] [-A <authtype>]\n"
6896 " [-L <privilege>] [-s] [-Ra <auth alg>] [-Ri <integ alg>]\n"
6897 " [-Rc <conf algo>] [-Rl] [-Rk <bmc key>] [-H <hackname>]\n"
6898 " [-4] [-6] [-M <max outstanding msgs>] <host1> [<host2>]\n"
6899 "If -s is supplied, then two host names are taken (the second port\n"
6900 "may be specified with -p2). Otherwise, only one hostname is\n"
6901 "taken. The defaults are an empty username and password (anonymous),\n"
6902 "port 623, admin privilege, and authtype defaulting to the most\n"
6903 "secure one available.\n"
6904 "privilege is one of: callback, user, operator, admin, or oem. These\n"
6905 "select the specific commands that are available to the connection.\n"
6906 "Higher privileges (ones further to the right in the above list) have\n"
6907 "more commands available to them.\n"
6908 "authtype is one of the following: rmcp+, md5, md2, straight, or none.\n"
6909 "Setting this to anything but rmcp+ forces normal rmcp\n"
6910 "authentication. By default the most secure method available is\n"
6911 "chosen, in the order given above.\n"
6912 "For RMCP+ connections, the authentication algorithms supported (-Ra)\n"
6913 "are: bmcpick, rakp_none, rakp_hmac_sha1, and rakp_hmac_md5. The\n"
6914 "integrity algorithms (-Ri) supported are: bmcpick, none, hmac_sha1,\n"
6915 "hmac_md5, and md5. The confidentiality algorithms (-Rc) are: bmcpick,\n"
6916 "aes_cbc_128, xrc4_128, and xrc_40. The defaults are\n"
6917 "rackp_hmac_sha1, hmac_sha1, and aes_cb_128. -Rl turns on lookup up\n"
6918 "names by the name and the privilege level (allowing the same name with\n"
6919 "different privileges and different passwords), the default is straight\n"
6920 "name lookup. -Rk sets the BMC key, needed if the system does two-key\n"
6921 "lookups. The -M option sets the maximum outstanding messages.\n"
6922 "The default is 2, ranges 1-63.\n"
6923 "-4 and -6 force IPv4 and IPv6. The default is unspecified.\n"
6924 "The -H option enables certain hacks for broken platforms. This may\n"
6925 "be listed multiple times to enable multiple hacks. The currently\n"
6926 "available hacks are:\n"
6927 " intelplus - For Intel platforms that have broken RMCP+.\n"
6928 " rakp3_wrong_rolem - For systems that truncate role(m) in the RAKP3"
6929 " msg.\n"
6930 " rmcpp_integ_sik - For systems that use SIK instead of K(1) for"
6931 " integrity.";
6932 }
6933
6934 static ipmi_args_t *
lan_con_alloc_args(void)6935 lan_con_alloc_args(void)
6936 {
6937 ipmi_args_t *args;
6938 lan_args_t *largs;
6939 args = i_ipmi_args_alloc(lan_free_args, lan_connect_args,
6940 lan_args_get_val, lan_args_set_val,
6941 lan_args_copy, lan_args_validate,
6942 lan_args_free_val, lan_args_get_type,
6943 sizeof(lan_args_t));
6944 if (!args)
6945 return NULL;
6946
6947 largs = i_ipmi_args_get_extra_data(args);
6948
6949 /* Set defaults */
6950 largs->authtype = IPMI_AUTHTYPE_DEFAULT;
6951 largs->privilege = IPMI_PRIVILEGE_ADMIN;
6952 largs->conf_alg = most_secure_lanp_conf();
6953 largs->integ_alg = most_secure_lanp_integ();
6954 largs->auth_alg = most_secure_lanp_auth();
6955 largs->name_lookup_only = 1;
6956 largs->max_outstanding_msgs = DEFAULT_MAX_OUTSTANDING_MSG_COUNT;
6957 /* largs->hacks = IPMI_CONN_HACK_RAKP3_WRONG_ROLEM; */
6958 largs->addr_family = AF_UNSPEC;
6959 return args;
6960 }
6961
6962 static ipmi_con_setup_t *lan_setup;
6963
6964 int
i_ipmi_lan_init(os_handler_t * os_hnd)6965 i_ipmi_lan_init(os_handler_t *os_hnd)
6966 {
6967 int rv;
6968 int i;
6969
6970 rv = ipmi_create_global_lock(&lan_list_lock);
6971 if (rv)
6972 return rv;
6973
6974 rv = ipmi_create_global_lock(&fd_list_lock);
6975 if (rv)
6976 return rv;
6977 memset(&fd_list, 0, sizeof(fd_list));
6978 fd_list.next = &fd_list;
6979 fd_list.prev = &fd_list;
6980 fd_list.cons_in_use = MAX_CONS_PER_FD;
6981
6982 #ifdef PF_INET6
6983 rv = ipmi_create_global_lock(&fd6_list_lock);
6984 if (rv)
6985 return rv;
6986 memset(&fd6_list, 0, sizeof(fd6_list));
6987 fd6_list.next = &fd6_list;
6988 fd6_list.prev = &fd6_list;
6989 fd6_list.cons_in_use = MAX_CONS_PER_FD;
6990 #endif
6991
6992 for (i=0; i<LAN_HASH_SIZE; i++) {
6993 lan_list[i].next = &(lan_list[i]);
6994 lan_list[i].prev = &(lan_list[i]);
6995 lan_list[i].lan = NULL;
6996 lan_ip_list[i].next = &(lan_ip_list[i]);
6997 lan_ip_list[i].prev = &(lan_ip_list[i]);
6998 lan_ip_list[i].lan = NULL;
6999 }
7000
7001 rv = ipmi_create_global_lock(&lan_payload_lock);
7002 if (rv)
7003 return rv;
7004
7005 rv = ipmi_create_global_lock(&lan_auth_lock);
7006 if (rv)
7007 return rv;
7008
7009 lan_setup = i_ipmi_alloc_con_setup(lan_parse_args, lan_parse_help,
7010 lan_con_alloc_args);
7011 if (! lan_setup)
7012 return ENOMEM;
7013
7014 rv = i_ipmi_register_con_type("lan", lan_setup);
7015 if (rv)
7016 return rv;
7017
7018 lan_os_hnd = os_hnd;
7019
7020 return 0;
7021 }
7022
7023 void
i_ipmi_lan_shutdown(void)7024 i_ipmi_lan_shutdown(void)
7025 {
7026 i_ipmi_unregister_con_type("lan", lan_setup);
7027 i_ipmi_free_con_setup(lan_setup);
7028 lan_setup = NULL;
7029
7030 if (lan_list_lock) {
7031 ipmi_destroy_lock(lan_list_lock);
7032 lan_list_lock = NULL;
7033 }
7034 if (lan_payload_lock) {
7035 ipmi_destroy_lock(lan_payload_lock);
7036 lan_payload_lock = NULL;
7037 }
7038 while (oem_payload_list) {
7039 payload_entry_t *e = oem_payload_list;
7040 oem_payload_list = e->next;
7041 ipmi_mem_free(e);
7042 }
7043 if (lan_auth_lock) {
7044 ipmi_destroy_lock(lan_auth_lock);
7045 lan_auth_lock = NULL;
7046 }
7047 while (oem_auth_list) {
7048 auth_entry_t *e = oem_auth_list;
7049 oem_auth_list = e->next;
7050 ipmi_mem_free(e);
7051 }
7052 while (oem_conf_list) {
7053 conf_entry_t *e = oem_conf_list;
7054 oem_conf_list = e->next;
7055 ipmi_mem_free(e);
7056 }
7057 while (oem_integ_list) {
7058 integ_entry_t *e = oem_integ_list;
7059 oem_integ_list = e->next;
7060 ipmi_mem_free(e);
7061 }
7062 if (fd_list_lock) {
7063 ipmi_destroy_lock(fd_list_lock);
7064 fd_list_lock = NULL;
7065 }
7066 while (fd_list.next != &fd_list) {
7067 lan_fd_t *e = fd_list.next;
7068 e->next->prev = e->prev;
7069 e->prev->next = e->next;
7070 lan_os_hnd->remove_fd_to_wait_for(lan_os_hnd, e->fd_wait_id);
7071 close(e->fd);
7072 ipmi_destroy_lock(e->con_lock);
7073 ipmi_mem_free(e);
7074 }
7075 while (fd_free_list) {
7076 lan_fd_t *e = fd_free_list;
7077 fd_free_list = e->next;
7078 ipmi_destroy_lock(e->con_lock);
7079 ipmi_mem_free(e);
7080 }
7081 #ifdef PF_INET6
7082 if (fd6_list_lock) {
7083 ipmi_destroy_lock(fd6_list_lock);
7084 fd6_list_lock = NULL;
7085 }
7086 while (fd6_list.next != &fd6_list) {
7087 lan_fd_t *e = fd6_list.next;
7088 e->next->prev = e->prev;
7089 e->prev->next = e->next;
7090 lan_os_hnd->remove_fd_to_wait_for(lan_os_hnd, e->fd_wait_id);
7091 close(e->fd);
7092 ipmi_destroy_lock(e->con_lock);
7093 ipmi_mem_free(e);
7094 }
7095 while (fd6_free_list) {
7096 lan_fd_t *e = fd6_free_list;
7097 fd6_free_list = e->next;
7098 ipmi_destroy_lock(e->con_lock);
7099 ipmi_mem_free(e);
7100 }
7101 #endif
7102 lan_os_hnd = NULL;
7103 }
7104