void ipmiconsole_ctx_set_errnum (ipmiconsole_ctx_t c, int errnum) { int perr; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); /* What do we do if a mutex lock/unlock fails here? Ignore for * now. */ if ((perr = pthread_mutex_lock (&(c->errnum_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); /* If the errnum is ERR_SUCCESS, it is not required for the user * to retrieve it */ if (c->errnum_retrieved || c->errnum == IPMICONSOLE_ERR_SUCCESS) { c->errnum = errnum; if (errnum == IPMICONSOLE_ERR_SUCCESS) c->errnum_retrieved = 1; else c->errnum_retrieved = 0; } else IPMICONSOLE_DEBUG (("could not set errnum: current = %d, desired = %d", c->errnum, errnum)); if ((perr = pthread_mutex_unlock (&(c->errnum_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); }
int ipmiconsole_set_closeonexec (ipmiconsole_ctx_t c, int fd) { int closeonexec; /* User need not pass in valid context for this function */ if ((closeonexec = fcntl (fd, F_GETFD, 0)) < 0) { IPMICONSOLE_DEBUG (("fcntl: %s", strerror (errno))); if (c && c->magic == IPMICONSOLE_CTX_MAGIC) ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); return (-1); } closeonexec |= FD_CLOEXEC; if (fcntl (fd, F_SETFD, closeonexec) < 0) { IPMICONSOLE_DEBUG (("fcntl: %s", strerror (errno))); if (c && c->magic == IPMICONSOLE_CTX_MAGIC) ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); return (-1); } return (0); }
static int _ipmiconsole_poll (struct pollfd *ufds, unsigned int nfds, int timeout) { int n; struct timeval tv, tv_orig; struct timeval start, end, delta; assert (ufds); /* prep for EINTR handling */ if (timeout >= 0) { /* poll uses timeout in milliseconds */ tv_orig.tv_sec = (long)timeout/1000; tv_orig.tv_usec = (timeout % 1000) * 1000; if (gettimeofday(&start, NULL) < 0) { IPMICONSOLE_DEBUG (("gettimeofday: %s", strerror (errno))); return (-1); } } else { tv_orig.tv_sec = 0; tv_orig.tv_usec = 0; } /* repeat poll if interrupted */ do { n = poll(ufds, nfds, timeout); if (n < 0 && errno != EINTR) /* unrecov error */ { IPMICONSOLE_DEBUG (("poll: %s", strerror (errno))); return (-1); } if (n < 0 && timeout >= 0) /* EINTR - adjust timeout */ { if (gettimeofday(&end, NULL) < 0) { IPMICONSOLE_DEBUG (("gettimeofday: %s", strerror (errno))); return (-1); } timersub(&end, &start, &delta); /* delta = end-start */ timersub(&tv_orig, &delta, &tv); /* tv = tvsave-delta */ timeout = (tv.tv_sec * 1000) + (tv.tv_usec/1000); } } while (n < 0); return n; }
int ipmiconsole_engine_is_setup (void) { int is_setup, perr; if ((perr = pthread_mutex_lock (&console_engine_is_setup_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); return (-1); } is_setup = console_engine_is_setup; if ((perr = pthread_mutex_unlock (&console_engine_is_setup_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (-1); } return (is_setup); }
int ipmiconsole_engine_thread_count (void) { int thread_count, perr; if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); return (-1); } if (console_engine_thread_count > INT_MAX) thread_count = INT_MAX; else thread_count = console_engine_thread_count; if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (-1); } return (thread_count); }
int ipmiconsole_ctx_get_errnum (ipmiconsole_ctx_t c) { int perr; int errnum; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); /* What do we do if a mutex lock/unlock fails here? Ignore for * now. */ if ((perr = pthread_mutex_lock (&(c->errnum_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); errnum = c->errnum; c->errnum_retrieved++; if ((perr = pthread_mutex_unlock (&(c->errnum_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (errnum); }
static void * _ipmiconsole_engine (void *arg) { int perr, ctxs_count = 0; unsigned int index; unsigned int teardown_flag = 0; unsigned int teardown_initiated = 0; assert (arg); index = *((unsigned int *)arg); assert (index < IPMICONSOLE_THREAD_COUNT_MAX); free (arg); /* No need to exit on failure, probability is low we'll SIGPIPE anyways */ if (signal (SIGPIPE, SIG_IGN) == SIG_ERR) IPMICONSOLE_DEBUG (("signal: %s", strerror (errno))); while (!teardown_flag || ctxs_count) { struct _ipmiconsole_poll_data poll_data; int count; unsigned int timeout_len; unsigned int i; int unlock_console_engine_ctxs_mutex_flag = 0; int spin_wait_flag = 0; char buf[IPMICONSOLE_PIPE_BUFLEN]; memset (&poll_data, '\0', sizeof (struct _ipmiconsole_poll_data)); if ((perr = pthread_mutex_lock (&console_engine_teardown_mutex))) { /* This is one of the only truly "fatal" conditions */ IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); teardown_flag = 1; } if (console_engine_teardown_immediate) { if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); break; } if (console_engine_teardown) teardown_flag = 1; if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex))) { /* This is one of the only truly "fatal" conditions */ IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); teardown_flag = 1; } /* Notes: * * We must lock the list from here till all context data and pointers * are retrieved. */ if ((perr = pthread_mutex_lock (&console_engine_ctxs_mutex[index]))) { /* This is one of the only truly "fatal" conditions */ IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); teardown_flag = 1; } /* Note: Set close_session_flag in the contexts before * ipmiconsole_process_ctxs(), so the initiation of the closing * down will begin now rather than the next iteration of the * loop. */ if (teardown_flag && !teardown_initiated) { /* XXX: Umm, if this fails, we may not be able to teardown * cleanly. Break out of the loop I guess. */ if (list_for_each (console_engine_ctxs[index], _teardown_initiate, NULL) < 0) { IPMICONSOLE_DEBUG (("list_for_each: %s", strerror (errno))); break; } teardown_initiated++; } if ((ctxs_count = ipmiconsole_process_ctxs (console_engine_ctxs[index], &timeout_len)) < 0) goto continue_loop; if (!ctxs_count && teardown_flag) continue; if (!ctxs_count) { spin_wait_flag++; goto continue_loop; } poll_data.ctxs_len = ctxs_count; /* achu: I always wonder if this poll() loop could be done far * more elegantly and efficiently without all this crazy * indexing, perhaps through a callback/event mechanism. It'd * probably be more efficient, since most callback/event based * models have min-heap like structures inside for determining * what things timed out. Overall though, I don't think the O(n) * (n being hosts/fds) processing is really that inefficient for * this particular application and is not worth going back and * changing. By going to a callback/event mechanism, there will * still be some O(n) activities within the code, so I am only * going to create a more efficient O(n) poll loop. */ /* * There are 3 pfds per ctx. One for 'ipmi_fd', 'asynccomm[0]', and 'ipmiconsole_fd'. * * There is + 1 pfds for the "console_engine_ctxs_notifier". * This will be set up manually here, and not in _poll_setup(). */ if (!(poll_data.pfds = (struct pollfd *)malloc (((poll_data.ctxs_len * 3) + 1) * sizeof (struct pollfd)))) { IPMICONSOLE_DEBUG (("malloc: %s", strerror (errno))); goto continue_loop; } if (!(poll_data.pfds_ctxs = (ipmiconsole_ctx_t *)malloc (poll_data.ctxs_len * sizeof (ipmiconsole_ctx_t)))) { IPMICONSOLE_DEBUG (("malloc: %s", strerror (errno))); goto continue_loop; } if ((count = list_for_each (console_engine_ctxs[index], _poll_setup, &poll_data)) < 0) { IPMICONSOLE_DEBUG (("list_for_each: %s", strerror (errno))); goto continue_loop; } if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[index]))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); unlock_console_engine_ctxs_mutex_flag++; /* Setup notifier pipe as last remaining poll data */ poll_data.pfds[(poll_data.ctxs_len * 3)].fd = console_engine_ctxs_notifier[index][0]; poll_data.pfds[(poll_data.ctxs_len * 3)].events = POLLIN; poll_data.pfds[(poll_data.ctxs_len * 3)].revents = 0; if (count != ctxs_count) { IPMICONSOLE_DEBUG (("list_for_each: invalid length returned: %d", count)); goto continue_loop; } if (poll_data.pfds_index != ctxs_count) { IPMICONSOLE_DEBUG (("invalid index set on returned: %d", poll_data.pfds_index)); goto continue_loop; } if (_ipmiconsole_poll (poll_data.pfds, (poll_data.ctxs_len * 3) + 1, timeout_len) < 0) { IPMICONSOLE_DEBUG (("poll: %s", strerror (errno))); goto continue_loop; } for (i = 0; i < poll_data.ctxs_len; i++) { if (poll_data.pfds[i*3].revents & POLLERR) { IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR")); /* See comments in _ipmi_recvfrom() regarding ECONNRESET/ECONNREFUSED */ if (_ipmi_recvfrom (poll_data.pfds_ctxs[i]) < 0) { ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SYSTEM_ERROR); poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (!poll_data.pfds_ctxs[i]->session.close_session_flag) { if (poll_data.pfds[i*3+1].revents & POLLNVAL) { /* This indicates the user closed the asynccomm file descriptors * which is ok. */ IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLNVAL")); ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SUCCESS); poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } if (poll_data.pfds[i*3+2].revents & POLLHUP) { /* This indicates the user closed the other end of * the socketpair so it's ok. */ IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLHUP")); ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_SUCCESS); poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } if (poll_data.pfds[i*3+1].revents & POLLERR) { IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR")); ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_INTERNAL_ERROR); poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } if (poll_data.pfds[i*3+2].revents & POLLERR) { IPMICONSOLE_CTX_DEBUG (poll_data.pfds_ctxs[i], ("POLLERR")); ipmiconsole_ctx_set_errnum (poll_data.pfds_ctxs[i], IPMICONSOLE_ERR_INTERNAL_ERROR); poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (poll_data.pfds[i*3].revents & POLLIN) { if (_ipmi_recvfrom (poll_data.pfds_ctxs[i]) < 0) { poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (poll_data.pfds[i*3].revents & POLLOUT) { if (_ipmi_sendto (poll_data.pfds_ctxs[i]) < 0) { poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (poll_data.pfds[i*3 + 1].revents & POLLIN) { if (_asynccomm (poll_data.pfds_ctxs[i]) < 0) { poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (!poll_data.pfds_ctxs[i]->session.close_session_flag) { if (poll_data.pfds[i*3+2].revents & POLLIN) { if (_console_read (poll_data.pfds_ctxs[i]) < 0) { poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } if (poll_data.pfds[i*3+2].revents & POLLOUT) { if (_console_write (poll_data.pfds_ctxs[i]) < 0) { poll_data.pfds_ctxs[i]->session.close_session_flag++; continue; } } } } /* We don't care what's read, just get it off the fd */ if (poll_data.pfds[(poll_data.ctxs_len * 3)].revents & POLLIN) { if (read (console_engine_ctxs_notifier[index][0], buf, IPMICONSOLE_PIPE_BUFLEN) < 0) IPMICONSOLE_DEBUG (("read: %s", strerror (errno))); } continue_loop: if (!unlock_console_engine_ctxs_mutex_flag) { if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[index]))) { /* This is one of the only truly "fatal" conditions */ IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); teardown_flag = 1; } } if (spin_wait_flag) { /* No contexts stored, either because they all died or none * have been submitted yet. Sleep a little bit to kill some * time and avoid spinning. */ /* XXX: Is this portable? */ usleep (IPMICONSOLE_SPIN_WAIT_TIME); } free (poll_data.pfds); free (poll_data.pfds_ctxs); } /* No way to return error, so just continue on even if there is a failure */ if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); console_engine_thread_count--; if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (NULL); }
/* Notes: One of the reason we do not create the threads in this * function, is that it would make it more difficult to properly * "cleanup" on an error. We wouldn't know how many threads were * created, flags for setup completion may not be set yet, etc. * * Therefore ipmiconsole_engine_thread_create() is done outside of * this function and is done elsewhere. */ int ipmiconsole_engine_setup (unsigned int thread_count) { unsigned int i; int perr; assert (!console_engine_thread_count); assert (thread_count && thread_count <= IPMICONSOLE_THREAD_COUNT_MAX); if ((perr = pthread_mutex_lock (&console_engine_is_setup_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); errno = perr; return (-1); } memset (console_engine_ctxs, '\0', IPMICONSOLE_THREAD_COUNT_MAX * sizeof (List)); memset (console_engine_ctxs_count, '\0', IPMICONSOLE_THREAD_COUNT_MAX * sizeof (unsigned int)); memset (console_engine_ctxs_mutex, '\0', IPMICONSOLE_THREAD_COUNT_MAX * sizeof (pthread_mutex_t)); for (i = 0; i < IPMICONSOLE_THREAD_COUNT_MAX; i++) { console_engine_ctxs_notifier[i][0] = -1; console_engine_ctxs_notifier[i][1] = -1; } garbage_collector_notifier[0] = -1; garbage_collector_notifier[1] = -1; if (ipmi_rmcpplus_init () < 0) { if (errno == EPERM) IPMICONSOLE_DEBUG (("ipmi_rmcpplus_init: incompatible crypto library")); else IPMICONSOLE_DEBUG (("ipmi_rmcpplus_init: %s", strerror (errno))); goto cleanup; } for (i = 0; i < IPMICONSOLE_THREAD_COUNT_MAX; i++) { if (!(console_engine_ctxs[i] = list_create ((ListDelF)ipmiconsole_ctx_connection_cleanup_session_submitted))) { IPMICONSOLE_DEBUG (("list_create: %s", strerror (errno))); goto cleanup; } console_engine_ctxs_count[i] = 0; if ((perr = pthread_mutex_init (&console_engine_ctxs_mutex[i], NULL)) != 0) { IPMICONSOLE_DEBUG (("pthread_mutex_init: %s", strerror (perr))); goto cleanup; } } /* Don't create fds for all ctxs_notifier to limit fd creation */ console_engine_ctxs_notifier_num = thread_count; for (i = 0; i < console_engine_ctxs_notifier_num; i++) { if (pipe (console_engine_ctxs_notifier[i]) < 0) { IPMICONSOLE_DEBUG (("pipe: %s", strerror (errno))); goto cleanup; } if (ipmiconsole_set_closeonexec (NULL, console_engine_ctxs_notifier[i][0]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } if (ipmiconsole_set_closeonexec (NULL, console_engine_ctxs_notifier[i][1]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } } if (pipe (garbage_collector_notifier) < 0) { IPMICONSOLE_DEBUG (("pipe: %s", strerror (errno))); goto cleanup; } if (ipmiconsole_set_closeonexec (NULL, garbage_collector_notifier[0]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } if (ipmiconsole_set_closeonexec (NULL, garbage_collector_notifier[1]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } if (!(console_engine_ctxs_to_destroy = list_create ((ListDelF)ipmiconsole_ctx_list_cleanup))) { IPMICONSOLE_DEBUG (("list_create: %s", strerror (errno))); goto cleanup; } if ((dummy_fd = socket (AF_INET, SOCK_STREAM, 0)) < 0) { IPMICONSOLE_DEBUG (("socket: %s", strerror (errno))); goto cleanup; } if (_ipmiconsole_garbage_collector_create () < 0) goto cleanup; console_engine_is_setup++; console_engine_teardown = 0; console_engine_teardown_immediate = 0; if ((perr = pthread_mutex_unlock (&console_engine_is_setup_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); errno = perr; goto cleanup; } return (0); cleanup: for (i = 0; i < IPMICONSOLE_THREAD_COUNT_MAX; i++) { if (console_engine_ctxs[i]) { list_destroy (console_engine_ctxs[i]); pthread_mutex_destroy (&console_engine_ctxs_mutex[i]); } console_engine_ctxs[i] = NULL; /* ignore potential error, cleanup path */ close (console_engine_ctxs_notifier[i][0]); /* ignore potential error, cleanup path */ close (console_engine_ctxs_notifier[i][1]); } if (console_engine_ctxs_to_destroy) list_destroy (console_engine_ctxs_to_destroy); console_engine_ctxs_to_destroy = NULL; garbage_collector_notifier[0] = -1; garbage_collector_notifier[1] = -1; /* ignore potential error, cleanup path */ close (dummy_fd); dummy_fd = -1; if ((perr = pthread_mutex_unlock (&console_engine_is_setup_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (-1); }
int ipmiconsole_engine_cleanup (int cleanup_sol_sessions) { unsigned int i; unsigned int thread_count; int perr, rv = -1; if ((perr = pthread_mutex_lock (&console_engine_is_setup_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); return (-1); } if (!console_engine_is_setup) goto unlock_is_setup_mutex; if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto unlock_is_setup_mutex; } thread_count = console_engine_thread_count; if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto unlock_is_setup_mutex; } if (!thread_count) { rv = 0; goto engine_cleanup; } if ((perr = pthread_mutex_lock (&console_engine_teardown_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto engine_cleanup; } console_engine_teardown++; if (!cleanup_sol_sessions) console_engine_teardown_immediate++; if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto engine_cleanup; } /* "Interrupt" the engine thread and tell it to get moving along */ for (i = 0; i < console_engine_ctxs_notifier_num; i++) { if (write (console_engine_ctxs_notifier[i][1], "1", 1) < 0) IPMICONSOLE_DEBUG (("write: %s", strerror (errno))); } if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto engine_cleanup; } while (console_engine_thread_count) { if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto engine_cleanup; } /* Wait awhile then try again */ /* XXX: Is this portable? */ usleep (IPMICONSOLE_SPIN_WAIT_TIME); if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto engine_cleanup; } } if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto engine_cleanup; } /* "Interrupt" the garbage collector and tell it to quit */ if (write (garbage_collector_notifier[1], "1", 1) < 0) IPMICONSOLE_DEBUG (("write: %s", strerror (errno))); if ((perr = pthread_mutex_lock (&garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto engine_cleanup; } while (garbage_collector_active) { if ((perr = pthread_cond_wait (&garbage_collector_active_cond, &garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_cond_wait: %s", strerror (perr))); goto engine_cleanup; } } if ((perr = pthread_mutex_unlock (&garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto engine_cleanup; } engine_cleanup: for (i = 0; i < IPMICONSOLE_THREAD_COUNT_MAX; i++) { if (console_engine_ctxs[i]) list_destroy (console_engine_ctxs[i]); console_engine_ctxs[i] = NULL; console_engine_ctxs[i] = 0; pthread_mutex_destroy (&console_engine_ctxs_mutex[i]); /* ignore potential error, cleanup path */ close (console_engine_ctxs_notifier[i][0]); /* ignore potential error, cleanup path */ close (console_engine_ctxs_notifier[i][1]); } /* ignore potential error, cleanup path */ close (garbage_collector_notifier[0]); /* ignore potential error, cleanup path */ close (garbage_collector_notifier[1]); /* achu: The engine threads have been torn down, all the contexts * managed by those threads have been moved to * console_engine_ctxs_to_destroy, and the garbage collector has * been shut down. So we don't need to lock w/ the * console_engine_ctxs_to_destroy_mutex. * * This list destruction could race w/ API code b/c the user could * still be running around trying to use the contexts post * engine_teardown() (e.g. calling ipmiconsole_ctx_destroy() after * calling ipmiconsole_engine_teardown()). We assume the user won't * do this. */ list_destroy (console_engine_ctxs_to_destroy); console_engine_ctxs_to_destroy = NULL; /* ignore potential error, cleanup path */ close (dummy_fd); dummy_fd = -1; console_engine_is_setup = 0; if ((perr = pthread_mutex_lock (&console_engine_teardown_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); goto unlock_is_setup_mutex; } console_engine_teardown = 0; console_engine_teardown_immediate = 0; if ((perr = pthread_mutex_unlock (&console_engine_teardown_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto unlock_is_setup_mutex; } rv = 0; unlock_is_setup_mutex: if ((perr = pthread_mutex_unlock (&console_engine_is_setup_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (rv); }
int ipmiconsole_engine_submit_ctx (ipmiconsole_ctx_t c) { void *ptr; unsigned int i; int perr, ret = -1; unsigned int min_submitted = UINT_MAX; int index = 0; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); assert (!(c->session_submitted)); assert (console_engine_is_setup); if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); return (-1); } for (i = 0; i < console_engine_thread_count; i++) { if ((perr = pthread_mutex_lock (&console_engine_ctxs_mutex[i]))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); goto cleanup_thread_count; } if (console_engine_ctxs_count[i] < min_submitted) { min_submitted = console_engine_ctxs_count[i]; index = i; } if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[i]))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); goto cleanup_thread_count; } } if ((perr = pthread_mutex_lock (&console_engine_ctxs_mutex[index]))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); goto cleanup_thread_count; } if (!(ptr = list_append (console_engine_ctxs[index], c))) { /* Note: Don't do a CTX debug, this is more of a global debug */ IPMICONSOLE_DEBUG (("list_append: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); goto cleanup_ctxs; } if (ptr != (void *)c) { IPMICONSOLE_DEBUG (("list_append: invalid pointer: ptr=%p; c=%p", ptr, c)); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); goto cleanup_ctxs; } console_engine_ctxs_count[index]++; ret = 0; /* achu: * * Necessary to set this here b/c at this point in time, the context * is submitted, so the engine will be doing its own cleanup * (garbage collector, etc.). */ c->session_submitted++; /* "Interrupt" the engine and tell it to get moving along w/ the new context */ if (write (console_engine_ctxs_notifier[index][1], "1", 1) < 0) IPMICONSOLE_DEBUG (("write: %s", strerror (errno))); cleanup_ctxs: if ((perr = pthread_mutex_unlock (&console_engine_ctxs_mutex[index]))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); goto cleanup_thread_count; } cleanup_thread_count: if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); return (ret); }
static int _ipmiconsole_garbage_collector_create (void) { pthread_t thread; pthread_attr_t attr; int perr, rv = -1; assert (!console_engine_is_setup); if ((perr = pthread_attr_init (&attr))) { IPMICONSOLE_DEBUG (("pthread_attr_init: %s", strerror (perr))); errno = perr; goto cleanup; } if ((perr = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))) { IPMICONSOLE_DEBUG (("pthread_attr_setdetachstate: %s", strerror (perr))); errno = perr; goto cleanup; } if ((perr = pthread_create (&thread, &attr, ipmiconsole_garbage_collector, NULL))) { IPMICONSOLE_DEBUG (("pthread_create: %s", strerror (perr))); errno = perr; goto cleanup; } /* Who cares if this fails */ if ((perr = pthread_attr_destroy (&attr))) IPMICONSOLE_DEBUG (("pthread_attr_destroy: %s", strerror (perr))); if ((perr = pthread_mutex_lock (&garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); errno = perr; goto cleanup; } while (!garbage_collector_active) { if ((perr = pthread_cond_wait (&garbage_collector_active_cond, &garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_cond_wait: %s", strerror (perr))); errno = perr; goto cleanup; } } if ((perr = pthread_mutex_unlock (&garbage_collector_active_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); errno = perr; goto cleanup; } rv = 0; cleanup: return (rv); }
/* Notes: On an error, it is the responsibility of the caller to call * ipmiconsole_engine_cleanup() to destroy all previously created * threads. */ int ipmiconsole_engine_thread_create (void) { pthread_t thread; pthread_attr_t attr; unsigned int *index = NULL; int perr, rv = -1; assert (console_engine_is_setup); if ((perr = pthread_mutex_lock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); errno = perr; return (-1); } assert (console_engine_thread_count < IPMICONSOLE_THREAD_COUNT_MAX); if ((perr = pthread_attr_init (&attr))) { IPMICONSOLE_DEBUG (("pthread_attr_init: %s", strerror (perr))); errno = perr; goto cleanup; } if ((perr = pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED))) { IPMICONSOLE_DEBUG (("pthread_attr_setdetachstate: %s", strerror (perr))); errno = perr; goto cleanup; } if (!(index = (unsigned int *)malloc (sizeof (unsigned int)))) { IPMICONSOLE_DEBUG (("malloc: %s", strerror (errno))); goto cleanup; } *index = console_engine_thread_count; if ((perr = pthread_create (&thread, &attr, _ipmiconsole_engine, index))) { IPMICONSOLE_DEBUG (("pthread_create: %s", strerror (perr))); errno = perr; goto cleanup; } /* Who cares if this fails */ if ((perr = pthread_attr_destroy (&attr))) IPMICONSOLE_DEBUG (("pthread_attr_destroy: %s", strerror (perr))); console_engine_thread_count++; rv = 0; cleanup: if ((perr = pthread_mutex_unlock (&console_engine_thread_count_mutex))) { IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); errno = perr; return (-1); } return (rv); }
static void __ipmiconsole_ctx_connection_cleanup (ipmiconsole_ctx_t c, int session_submitted) { int blocking_requested = 0; int status_initial = 0; int secure_malloc_flag; int perr; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0; /* We have to cleanup, so in general continue on even if locking fails */ if ((perr = pthread_mutex_lock (&(c->signal.status_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); /* Don't change status if it's already been set before */ if (c->signal.status != IPMICONSOLE_CTX_STATUS_SOL_ESTABLISHED) { c->signal.status = IPMICONSOLE_CTX_STATUS_SOL_ERROR; status_initial++; } if ((perr = pthread_mutex_unlock (&(c->signal.status_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); if ((perr = pthread_mutex_lock (&(c->blocking.blocking_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); if (c->blocking.blocking_submit_requested && !c->blocking.sol_session_established) { uint8_t tmpbyte; blocking_requested++; if (c->config.behavior_flags & IPMICONSOLE_BEHAVIOR_DEACTIVATE_ONLY && c->session.deactivate_only_succeeded_flag) tmpbyte = IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_DEACTIVATED; else tmpbyte = IPMICONSOLE_BLOCKING_NOTIFICATION_SOL_SESSION_ERROR; if (write (c->blocking.blocking_notification[1], &tmpbyte, 1) < 0) IPMICONSOLE_CTX_DEBUG (c, ("write: %s", strerror (errno))); } if ((perr = pthread_mutex_unlock (&(c->blocking.blocking_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); /* only call the callback if it's an initial SOL error and blocking * was not requested and the session was submitted. We do not want * to call the callback if an error happened in API land and we are * calling in via * ipmiconsole_ctx_connection_cleanup_session_not_submitted(). */ if (status_initial && !blocking_requested && session_submitted && c->non_blocking.callback) (*(c->non_blocking.callback))(c->non_blocking.callback_arg); /* Under default circumstances, close only the ipmiconsole_fd so * that an error will be detected by the user via a EOF on a read() * or EPIPE on a write() when reading/writing on their file * descriptor. * * On error situations (i.e. ipmiconsole_engine_submit() doesn't * return to the user w/ success), it is the responsibility of other * code to call _ipmiconsole_ctx_api_managed_session_data_cleanup(). * * The exception to this is when the user specifies the * IPMICONSOLE_ENGINE_CLOSE_FD flag. Then we close it here */ if (c->config.engine_flags & IPMICONSOLE_ENGINE_CLOSE_FD) { /* ignore potential error, cleanup path */ if (c->connection.user_fd >= 0) close (c->connection.user_fd); } /* ignore potential error, cleanup path */ if (c->connection.ipmiconsole_fd >= 0) close (c->connection.ipmiconsole_fd); if (c->connection.console_remote_console_to_bmc) scbuf_destroy (c->connection.console_remote_console_to_bmc, secure_malloc_flag); if (c->connection.console_bmc_to_remote_console) scbuf_destroy (c->connection.console_bmc_to_remote_console, secure_malloc_flag); /* ignore potential error, cleanup path */ if (c->connection.ipmi_fd >= 0) close (c->connection.ipmi_fd); if (c->connection.ipmi_from_bmc) scbuf_destroy (c->connection.ipmi_from_bmc, secure_malloc_flag); if (c->connection.ipmi_to_bmc) scbuf_destroy (c->connection.ipmi_to_bmc, secure_malloc_flag); /* Similarly to the user_fd above, it is the responsibility of other * code to close asynccomm[0] and asynccomm[1], which is replicated * in the context. */ if (c->connection.obj_rmcp_hdr_rq) fiid_obj_destroy (c->connection.obj_rmcp_hdr_rq); if (c->connection.obj_rmcp_hdr_rs) fiid_obj_destroy (c->connection.obj_rmcp_hdr_rs); if (c->connection.obj_lan_session_hdr_rq) fiid_obj_destroy (c->connection.obj_lan_session_hdr_rq); if (c->connection.obj_lan_session_hdr_rs) fiid_obj_destroy (c->connection.obj_lan_session_hdr_rs); if (c->connection.obj_lan_msg_hdr_rq) fiid_obj_destroy (c->connection.obj_lan_msg_hdr_rq); if (c->connection.obj_lan_msg_hdr_rs) fiid_obj_destroy (c->connection.obj_lan_msg_hdr_rs); if (c->connection.obj_lan_msg_trlr_rs) fiid_obj_destroy (c->connection.obj_lan_msg_trlr_rs); if (c->connection.obj_rmcpplus_session_hdr_rq) fiid_obj_destroy (c->connection.obj_rmcpplus_session_hdr_rq); if (c->connection.obj_rmcpplus_session_hdr_rs) fiid_obj_destroy (c->connection.obj_rmcpplus_session_hdr_rs); if (c->connection.obj_rmcpplus_payload_rs) fiid_obj_destroy (c->connection.obj_rmcpplus_payload_rs); if (c->connection.obj_rmcpplus_session_trlr_rq) fiid_obj_destroy (c->connection.obj_rmcpplus_session_trlr_rq); if (c->connection.obj_rmcpplus_session_trlr_rs) fiid_obj_destroy (c->connection.obj_rmcpplus_session_trlr_rs); if (c->connection.obj_authentication_capabilities_rq) fiid_obj_destroy (c->connection.obj_authentication_capabilities_rq); if (c->connection.obj_authentication_capabilities_rs) fiid_obj_destroy (c->connection.obj_authentication_capabilities_rs); if (c->connection.obj_open_session_request) fiid_obj_destroy (c->connection.obj_open_session_request); if (c->connection.obj_open_session_response) fiid_obj_destroy (c->connection.obj_open_session_response); if (c->connection.obj_rakp_message_1) fiid_obj_destroy (c->connection.obj_rakp_message_1); if (c->connection.obj_rakp_message_2) fiid_obj_destroy (c->connection.obj_rakp_message_2); if (c->connection.obj_rakp_message_3) fiid_obj_destroy (c->connection.obj_rakp_message_3); if (c->connection.obj_rakp_message_4) fiid_obj_destroy (c->connection.obj_rakp_message_4); if (c->connection.obj_set_session_privilege_level_rq) fiid_obj_destroy (c->connection.obj_set_session_privilege_level_rq); if (c->connection.obj_set_session_privilege_level_rs) fiid_obj_destroy (c->connection.obj_set_session_privilege_level_rs); if (c->connection.obj_get_channel_payload_support_rq) fiid_obj_destroy (c->connection.obj_get_channel_payload_support_rq); if (c->connection.obj_get_channel_payload_support_rs) fiid_obj_destroy (c->connection.obj_get_channel_payload_support_rs); if (c->connection.obj_get_payload_activation_status_rq) fiid_obj_destroy (c->connection.obj_get_payload_activation_status_rq); if (c->connection.obj_get_payload_activation_status_rs) fiid_obj_destroy (c->connection.obj_get_payload_activation_status_rs); if (c->connection.obj_activate_payload_rq) fiid_obj_destroy (c->connection.obj_activate_payload_rq); if (c->connection.obj_activate_payload_rs) fiid_obj_destroy (c->connection.obj_activate_payload_rs); if (c->connection.obj_sol_payload_data_rq) fiid_obj_destroy (c->connection.obj_sol_payload_data_rq); if (c->connection.obj_sol_payload_data_rs) fiid_obj_destroy (c->connection.obj_sol_payload_data_rs); if (c->connection.obj_get_channel_payload_version_rq) fiid_obj_destroy (c->connection.obj_get_channel_payload_version_rq); if (c->connection.obj_get_channel_payload_version_rs) fiid_obj_destroy (c->connection.obj_get_channel_payload_version_rs); if (c->connection.obj_deactivate_payload_rq) fiid_obj_destroy (c->connection.obj_deactivate_payload_rq); if (c->connection.obj_deactivate_payload_rs) fiid_obj_destroy (c->connection.obj_deactivate_payload_rs); if (c->connection.obj_close_session_rq) fiid_obj_destroy (c->connection.obj_close_session_rq); if (c->connection.obj_close_session_rs) fiid_obj_destroy (c->connection.obj_close_session_rs); _ipmiconsole_ctx_connection_init (c); /* If the session was never submitted (i.e. error in API land), don't * move this around. */ /* achu: See note in ipmiconsole_defs.h about the * c->session_submitted flag. That flag is only used in API land * for the user to know if a session was submitted or not. The * session_submitted flag passed into this function is the "real" * one that is known by the engine, and is not dependent on any race * conditions with the API level. */ if (!session_submitted) return; /* Be careful, if the user requested to destroy the context, we can * destroy it here. But if we destroy it, there is no mutex to * unlock. */ /* Note: the code in __ipmiconsole_ctx_connection_cleanup() and * ipmiconsole_garbage_collector() may look like it may race and * could deadlock. (ABBA and BAAB deadlock situation). However, * the context mutex c->signal.destroyed_mutex is accessed in * __ipmiconsole_ctx_connection_cleanup() when trying to add this item * to the console_engine_ctxs_to_destroy list. It is accessed in * ipmiconsole_garbage_collector() only on the items already in the * console_engine_ctxs_to_destroy list. So the * c->signal.destroyed_mutex can never be raced against in these two * functions. */ if ((perr = pthread_mutex_lock (&(c->signal.destroyed_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); if (c->signal.user_has_destroyed) { ipmiconsole_ctx_debug_cleanup (c); ipmiconsole_ctx_signal_cleanup (c); ipmiconsole_ctx_blocking_cleanup (c); ipmiconsole_ctx_cleanup (c); } else { if (!c->signal.moved_to_destroyed) { void *ptr; c->signal.moved_to_destroyed++; /* I suppose if we fail here, we mem-leak?? Log for now ... */ if ((perr = pthread_mutex_lock (&(console_engine_ctxs_to_destroy_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_lock: %s", strerror (perr))); if (!(ptr = list_append (console_engine_ctxs_to_destroy, c))) IPMICONSOLE_DEBUG (("list_append: %s", strerror (errno))); if (ptr != (void *)c) IPMICONSOLE_DEBUG (("list_append: invalid pointer: ptr=%p; c=%p", ptr, c)); if ((perr = pthread_mutex_unlock (&(console_engine_ctxs_to_destroy_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); } if ((perr = pthread_mutex_unlock (&(c->signal.destroyed_mutex))) != 0) IPMICONSOLE_DEBUG (("pthread_mutex_unlock: %s", strerror (perr))); } }
int ipmiconsole_ctx_connection_setup (ipmiconsole_ctx_t c) { struct sockaddr_in srcaddr; int sv[2]; int secure_malloc_flag; assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); assert (!(c->session_submitted)); _ipmiconsole_ctx_connection_init (c); /* File Descriptor User Interface */ if (socketpair (AF_UNIX, SOCK_STREAM, 0, sv) < 0) { IPMICONSOLE_DEBUG (("socketpair: %s", strerror (errno))); if (errno == EMFILE) ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES); else ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); goto cleanup; } c->connection.user_fd = sv[0]; c->connection.ipmiconsole_fd = sv[1]; if (ipmiconsole_set_closeonexec (c, c->connection.user_fd) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } if (ipmiconsole_set_closeonexec (c, c->connection.ipmiconsole_fd) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } /* Copy for API level */ c->fds.user_fd = c->connection.user_fd; secure_malloc_flag = (c->config.engine_flags & IPMICONSOLE_ENGINE_LOCK_MEMORY) ? 1 : 0; if (!(c->connection.console_remote_console_to_bmc = scbuf_create (CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MIN, CONSOLE_REMOTE_CONSOLE_TO_BMC_BUF_MAX, secure_malloc_flag))) { IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.console_bmc_to_remote_console = scbuf_create (CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MIN, CONSOLE_BMC_TO_REMOTE_CONSOLE_BUF_MAX, secure_malloc_flag))) { IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } /* Connection Data */ if ((c->connection.ipmi_fd = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { IPMICONSOLE_DEBUG (("socket: %s", strerror (errno))); if (errno == EMFILE) ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES); else ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); goto cleanup; } if (ipmiconsole_set_closeonexec (c, c->connection.ipmi_fd) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } memset (&srcaddr, '\0', sizeof (struct sockaddr_in)); srcaddr.sin_family = AF_INET; srcaddr.sin_port = htons (0); srcaddr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (c->connection.ipmi_fd, (struct sockaddr *)&srcaddr, sizeof (struct sockaddr_in)) < 0) { IPMICONSOLE_DEBUG (("bind: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); goto cleanup; } if (!(c->connection.ipmi_from_bmc = scbuf_create (IPMI_FROM_BMC_BUF_MIN, IPMI_FROM_BMC_BUF_MAX, secure_malloc_flag))) { IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.ipmi_to_bmc = scbuf_create (IPMI_TO_BMC_BUF_MIN, IPMI_TO_BMC_BUF_MAX, secure_malloc_flag))) { IPMICONSOLE_DEBUG (("scbuf_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } /* Pipe for non-fd communication */ if (pipe (c->connection.asynccomm) < 0) { IPMICONSOLE_DEBUG (("pipe: %s", strerror (errno))); if (errno == EMFILE) ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_TOO_MANY_OPEN_FILES); else ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); goto cleanup; } if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[0]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } if (ipmiconsole_set_closeonexec (c, c->connection.asynccomm[1]) < 0) { IPMICONSOLE_DEBUG (("closeonexec error")); goto cleanup; } /* Copy for API level */ c->fds.asynccomm[0] = c->connection.asynccomm[0]; c->fds.asynccomm[1] = c->connection.asynccomm[1]; /* Fiid Objects */ if (!(c->connection.obj_rmcp_hdr_rq = fiid_obj_create (tmpl_rmcp_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcp_hdr_rs = fiid_obj_create (tmpl_rmcp_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_lan_session_hdr_rq = fiid_obj_create (tmpl_lan_session_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_lan_session_hdr_rs = fiid_obj_create (tmpl_lan_session_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_lan_msg_hdr_rq = fiid_obj_create (tmpl_lan_msg_hdr_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_lan_msg_hdr_rs = fiid_obj_create (tmpl_lan_msg_hdr_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_lan_msg_trlr_rs = fiid_obj_create (tmpl_lan_msg_trlr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcpplus_session_hdr_rq = fiid_obj_create (tmpl_rmcpplus_session_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcpplus_session_hdr_rs = fiid_obj_create (tmpl_rmcpplus_session_hdr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcpplus_payload_rs = fiid_obj_create (tmpl_rmcpplus_payload))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcpplus_session_trlr_rq = fiid_obj_create (tmpl_rmcpplus_session_trlr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rmcpplus_session_trlr_rs = fiid_obj_create (tmpl_rmcpplus_session_trlr))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_authentication_capabilities_rq = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_authentication_capabilities_rs = fiid_obj_create (tmpl_cmd_get_channel_authentication_capabilities_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_open_session_request = fiid_obj_create (tmpl_rmcpplus_open_session_request))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_open_session_response = fiid_obj_create (tmpl_rmcpplus_open_session_response))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rakp_message_1 = fiid_obj_create (tmpl_rmcpplus_rakp_message_1))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rakp_message_2 = fiid_obj_create (tmpl_rmcpplus_rakp_message_2))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rakp_message_3 = fiid_obj_create (tmpl_rmcpplus_rakp_message_3))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_rakp_message_4 = fiid_obj_create (tmpl_rmcpplus_rakp_message_4))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_set_session_privilege_level_rq = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_set_session_privilege_level_rs = fiid_obj_create (tmpl_cmd_set_session_privilege_level_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_channel_payload_support_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_channel_payload_support_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_support_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_payload_activation_status_rq = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_payload_activation_status_rs = fiid_obj_create (tmpl_cmd_get_payload_activation_status_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_activate_payload_rq = fiid_obj_create (tmpl_cmd_activate_payload_sol_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_activate_payload_rs = fiid_obj_create (tmpl_cmd_activate_payload_sol_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_sol_payload_data_rq = fiid_obj_create (tmpl_sol_payload_data_remote_console_to_bmc))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_sol_payload_data_rs = fiid_obj_create (tmpl_sol_payload_data_bmc_to_remote_console))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_channel_payload_version_rq = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_get_channel_payload_version_rs = fiid_obj_create (tmpl_cmd_get_channel_payload_version_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_deactivate_payload_rq = fiid_obj_create (tmpl_cmd_deactivate_payload_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_deactivate_payload_rs = fiid_obj_create (tmpl_cmd_deactivate_payload_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_close_session_rq = fiid_obj_create (tmpl_cmd_close_session_rq))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } if (!(c->connection.obj_close_session_rs = fiid_obj_create (tmpl_cmd_close_session_rs))) { IPMICONSOLE_CTX_DEBUG (c, ("fiid_obj_create: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_OUT_OF_MEMORY); goto cleanup; } return (0); cleanup: /* Previously called here, but this is now supposed to be handled in API land */ /* ipmiconsole_ctx_connection_cleanup(c) */ /* _ipmiconsole_ctx_fds_cleanup(c); */ /* _ipmiconsole_ctx_fds_setup(c); */ return (-1); }
int ipmiconsole_ctx_config_setup (ipmiconsole_ctx_t c, const char *hostname, uint16_t port, struct ipmiconsole_ipmi_config *ipmi_config, struct ipmiconsole_protocol_config *protocol_config, struct ipmiconsole_engine_config *engine_config) { assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); assert (hostname); assert (port); strcpy (c->config.hostname, hostname); c->config.port = port; if (ipmi_config->username) strcpy (c->config.username, ipmi_config->username); else strcpy (c->config.username, default_config.username); if (ipmi_config->password) strcpy (c->config.password, ipmi_config->password); else strcpy (c->config.password, default_config.password); /* k_g may contain nulls */ /* don't load defaults if k_g is not NULL */ if (ipmi_config->k_g) { if (ipmi_config->k_g_len) { memcpy (c->config.k_g, ipmi_config->k_g, ipmi_config->k_g_len); c->config.k_g_len = ipmi_config->k_g_len; } else { memset (c->config.k_g, '\0', IPMI_MAX_K_G_LENGTH + 1); c->config.k_g_len = 0; } } else { memcpy (c->config.k_g, default_config.k_g, default_config.k_g_len); c->config.k_g_len = default_config.k_g_len; } if (c->config.k_g_len) { unsigned int i; int all_zeroes = 1; /* Special case, check to make sure user didn't input zero as a * k_g key. */ for (i = 0; i < IPMI_MAX_K_G_LENGTH; i++) { if (c->config.k_g[i] != 0) { all_zeroes = 0; break; } } if (all_zeroes) c->config.k_g_len = 0; } if (ipmi_config->privilege_level >= 0) { if (ipmi_config->privilege_level == IPMICONSOLE_PRIVILEGE_USER) c->config.privilege_level = IPMI_PRIVILEGE_LEVEL_USER; else if (ipmi_config->privilege_level == IPMICONSOLE_PRIVILEGE_OPERATOR) c->config.privilege_level = IPMI_PRIVILEGE_LEVEL_OPERATOR; else c->config.privilege_level = IPMI_PRIVILEGE_LEVEL_ADMIN; } else c->config.privilege_level = default_config.privilege_level; if (ipmi_config->cipher_suite_id >= IPMI_CIPHER_SUITE_ID_MIN) c->config.cipher_suite_id = ipmi_config->cipher_suite_id; else c->config.cipher_suite_id = default_config.cipher_suite_id; if (ipmi_config->workaround_flags != IPMICONSOLE_WORKAROUND_DEFAULT) c->config.workaround_flags = ipmi_config->workaround_flags; else c->config.workaround_flags = default_config.workaround_flags; if (protocol_config->session_timeout_len > 0) c->config.session_timeout_len = protocol_config->session_timeout_len; else c->config.session_timeout_len = default_config.session_timeout_len; if (protocol_config->retransmission_timeout_len > 0) c->config.retransmission_timeout_len = protocol_config->retransmission_timeout_len; else c->config.retransmission_timeout_len = default_config.retransmission_timeout_len; if (protocol_config->retransmission_backoff_count > 0) c->config.retransmission_backoff_count = protocol_config->retransmission_backoff_count; else c->config.retransmission_backoff_count = default_config.retransmission_backoff_count; if (protocol_config->keepalive_timeout_len > 0) c->config.keepalive_timeout_len = protocol_config->keepalive_timeout_len; else c->config.keepalive_timeout_len = default_config.keepalive_timeout_len; if (protocol_config->retransmission_keepalive_timeout_len > 0) c->config.retransmission_keepalive_timeout_len = protocol_config->retransmission_keepalive_timeout_len; else c->config.retransmission_keepalive_timeout_len = default_config.retransmission_keepalive_timeout_len; if (protocol_config->acceptable_packet_errors_count > 0) c->config.acceptable_packet_errors_count = protocol_config->acceptable_packet_errors_count; else c->config.acceptable_packet_errors_count = default_config.acceptable_packet_errors_count; if (protocol_config->maximum_retransmission_count > 0) c->config.maximum_retransmission_count = protocol_config->maximum_retransmission_count; else c->config.maximum_retransmission_count = default_config.maximum_retransmission_count; if (engine_config->engine_flags != IPMICONSOLE_ENGINE_DEFAULT) c->config.engine_flags = engine_config->engine_flags; else c->config.engine_flags = default_config.engine_flags; if (engine_config->behavior_flags != IPMICONSOLE_BEHAVIOR_DEFAULT) c->config.behavior_flags = engine_config->behavior_flags; else c->config.behavior_flags = default_config.behavior_flags; if (engine_config->debug_flags != IPMICONSOLE_DEBUG_DEFAULT) c->config.debug_flags = engine_config->debug_flags; else c->config.debug_flags = default_config.debug_flags; c->config.sol_payload_instance = default_config.sol_payload_instance; /* Data based on Configuration Parameters */ if (ipmi_cipher_suite_id_to_algorithms (c->config.cipher_suite_id, &(c->config.authentication_algorithm), &(c->config.integrity_algorithm), &(c->config.confidentiality_algorithm)) < 0) { IPMICONSOLE_DEBUG (("ipmi_cipher_suite_id_to_algorithms: %s", strerror (errno))); return (-1); } /* Retransmission timeout cannot be larger than the session timeout */ if (c->config.retransmission_timeout_len > c->config.session_timeout_len) { IPMICONSOLE_DEBUG (("retransmission_timeout_len (%u) > session_timeout_len (%u)", c->config.retransmission_timeout_len, c->config.session_timeout_len)); errno = EINVAL; return (-1); } /* Keepalive timeout cannot be larger than the session timeout */ if (c->config.keepalive_timeout_len > c->config.session_timeout_len) { IPMICONSOLE_DEBUG (("keepalive_timeout_len (%u) > session_timeout_len (%u)", c->config.keepalive_timeout_len, c->config.session_timeout_len)); errno = EINVAL; return (-1); } /* Retransmission timeout cannot be larger than the keepalive timeout */ if (c->config.retransmission_timeout_len > c->config.keepalive_timeout_len) { IPMICONSOLE_DEBUG (("retransmission_timeout_len (%u) > keepalive_timeout_len (%u)", c->config.retransmission_timeout_len, c->config.keepalive_timeout_len)); errno = EINVAL; return (-1); } /* Retransmission keepalive timeout cannot be larger than the keepalive timeout */ if (c->config.retransmission_keepalive_timeout_len > c->config.keepalive_timeout_len) { IPMICONSOLE_DEBUG (("retransmission_keepalive_timeout_len (%u) > keepalive_timeout_len (%u)", c->config.retransmission_keepalive_timeout_len, c->config.keepalive_timeout_len)); errno = EINVAL; return (-1); } return (0); }
int ipmiconsole_ctx_session_setup (ipmiconsole_ctx_t c) { struct hostent hent; int h_errnop; char buf[GETHOSTBYNAME_AUX_BUFLEN]; #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) struct hostent *hptr; #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) #else /* !HAVE_FUNC_GETHOSTBYNAME_R */ struct hostent *hptr; #endif /* !HAVE_FUNC_GETHOSTBYNAME_R */ assert (c); assert (c->magic == IPMICONSOLE_CTX_MAGIC); c->session.console_port = c->config.port; memset (&(c->session.addr), '\0', sizeof (struct sockaddr_in)); c->session.addr.sin_family = AF_INET; c->session.addr.sin_port = htons (c->session.console_port); timeval_clear (&(c->session.last_ipmi_packet_sent)); /* Note: * * Initial last_ipmi_packet_received and last_sol_packet_received to * current time, so appropriate timeouts can be calculated in the * beginning if necessary. */ if (gettimeofday (&(c->session.last_ipmi_packet_received), NULL) < 0) { IPMICONSOLE_DEBUG (("gettimeofday: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); return (-1); } timeval_clear (&(c->session.last_keepalive_packet_sent)); if (gettimeofday (&(c->session.last_sol_packet_received), NULL) < 0) { IPMICONSOLE_DEBUG (("gettimeofday: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); return (-1); } memset (&hent, '\0', sizeof (struct hostent)); #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) if (gethostbyname_r (c->config.hostname, &hent, buf, GETHOSTBYNAME_AUX_BUFLEN, &hptr, &h_errnop)) #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) /* Jan Forch - Solaris gethostbyname_r returns ptr, not integer */ if (!gethostbyname_r (c->config.hostname, &hent, buf, GETHOSTBYNAME_AUX_BUFLEN, &h_errnop)) #else /* !HAVE_FUNC_GETHOSTBYNAME_R */ if (freeipmi_gethostbyname_r (c->config.hostname, &hent, buf, GETHOSTBYNAME_AUX_BUFLEN, &hptr, &h_errnop)) #endif /* !HAVE_FUNC_GETHOSTBYNAME_R */ { if (h_errnop == HOST_NOT_FOUND || h_errnop == NO_ADDRESS || h_errnop == NO_DATA) { ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_HOSTNAME_INVALID); return (-1); } #if HAVE_HSTRERROR IPMICONSOLE_DEBUG (("gethostbyname_r: %s", hstrerror (h_errnop))); #else /* !HAVE_HSTRERROR */ IPMICONSOLE_DEBUG (("gethostbyname_r: h_errno = %d", h_errnop)); #endif /* !HAVE_HSTRERROR */ ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_SYSTEM_ERROR); return (-1); } #if defined(HAVE_FUNC_GETHOSTBYNAME_R_6) if (!hptr) { ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_HOSTNAME_INVALID); return (-1); } #elif defined(HAVE_FUNC_GETHOSTBYNAME_R_5) #else /* !HAVE_FUNC_GETHOSTBYNAME_R */ if (!hptr) { ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_HOSTNAME_INVALID); return (-1); } #endif /* !HAVE_FUNC_GETHOSTBYNAME_R */ c->session.addr.sin_addr = *((struct in_addr *)hent.h_addr); c->session.protocol_state = IPMICONSOLE_PROTOCOL_STATE_START; c->session.close_session_flag = 0; c->session.try_new_port_flag = 0; c->session.deactivate_payload_instances = 0; c->session.deactivate_payload_instances_and_try_again_flag = 0; c->session.close_timeout_flag = 0; c->session.deactivate_only_succeeded_flag = 0; c->session.retransmission_count = 0; c->session.errors_count = 0; c->session.session_sequence_number_errors_count = 0; c->session.activate_payloads_count = 0; c->session.deactivate_active_payloads_count = 0; if (ipmi_check_session_sequence_number_2_0_init (&(c->session.highest_received_sequence_number), &(c->session.previously_received_list)) < 0) { IPMICONSOLE_DEBUG (("ipmi_check_session_sequence_number_2_0_init: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (ipmi_get_random (&(c->session.message_tag), sizeof (c->session.message_tag)) < 0) { IPMICONSOLE_DEBUG (("ipmi_get_random: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } if (ipmi_get_random (&(c->session.requester_sequence_number), sizeof (c->session.requester_sequence_number)) < 0) { IPMICONSOLE_DEBUG (("ipmi_get_random: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } c->session.requester_sequence_number %= (IPMI_LAN_REQUESTER_SEQUENCE_NUMBER_MAX + 1); c->session.session_sequence_number = 0; /* 0, so initial increment puts it at 1 */ c->session.name_only_lookup = IPMI_NAME_ONLY_LOOKUP; /* In IPMI 2.0, session_ids of 0 are special */ do { if (ipmi_get_random (&(c->session.remote_console_session_id), sizeof (c->session.remote_console_session_id)) < 0) { IPMICONSOLE_DEBUG (("ipmi_get_random: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } } while (!c->session.remote_console_session_id); if (ipmi_get_random (c->session.remote_console_random_number, IPMI_REMOTE_CONSOLE_RANDOM_NUMBER_LENGTH) < 0) { IPMICONSOLE_DEBUG (("ipmi_get_random: %s", strerror (errno))); ipmiconsole_ctx_set_errnum (c, IPMICONSOLE_ERR_INTERNAL_ERROR); return (-1); } /* Keys and ptrs will be calculated during session setup. We just * memet/clear here. */ memset (c->session.sik_key, '\0', IPMI_MAX_SIK_KEY_LENGTH); c->session.sik_key_ptr = c->session.sik_key; c->session.sik_key_len = IPMI_MAX_SIK_KEY_LENGTH; memset (c->session.integrity_key, '\0', IPMI_MAX_INTEGRITY_KEY_LENGTH); c->session.integrity_key_ptr = c->session.integrity_key; c->session.integrity_key_len = IPMI_MAX_INTEGRITY_KEY_LENGTH; memset (c->session.confidentiality_key, '\0', IPMI_MAX_CONFIDENTIALITY_KEY_LENGTH); c->session.confidentiality_key_ptr = c->session.confidentiality_key; c->session.confidentiality_key_len = IPMI_MAX_CONFIDENTIALITY_KEY_LENGTH; /* Following 3 will be calculated during session setup. We only * memset/clear it here */ c->session.sol_instance_capacity = 0; memset (c->session.sol_instances_activated, '\0', IPMI_INSTANCES_ACTIVATED_LENGTH); c->session.sol_instances_activated_count = 0; /* this is used just to index the number of instances deactivated */ c->session.sol_instances_deactivated_count = 0; /* Calculated during the session setup. */ c->session.max_sol_character_send_size = 0; /* Serial Break Maintenance */ c->session.break_requested = 0; c->session.console_remote_console_to_bmc_bytes_before_break = 0; /* SOL Input (remote console to BMC) */ c->session.sol_input_waiting_for_ack = 0; c->session.sol_input_waiting_for_break_ack = 0; timeval_clear (&(c->session.last_sol_input_packet_sent)); c->session.sol_input_packet_sequence_number = 0; /* 0, so initial increment puts it at 1 */ memset (c->session.sol_input_character_data, '\0', IPMICONSOLE_MAX_CHARACTER_DATA+1); c->session.sol_input_character_data_len = 0; /* SOL Output (BMC to remote console) */ c->session.last_sol_output_packet_sequence_number = 0; c->session.last_sol_output_accepted_character_count = 0; return (0); }