/* * Teardown any transport infrastructure after all connections are closed. * Return 0 for success, or nonzero for failure. */ int etm_xport_fini(fmd_hdl_t *hdl, etm_xport_hdl_t tlhdl) { exs_hdl_t *hp = (exs_hdl_t *)tlhdl; exs_hdl_t *xp, **ppx; (void) pthread_mutex_lock(&List_lock); ppx = &Exh_head; for (xp = *ppx; xp; xp = xp->h_next) { if (xp != hp) ppx = &xp->h_next; else break; } if (xp != hp) { (void) pthread_mutex_unlock(&List_lock); fmd_hdl_abort(hdl, "xport - fini failed, tlhdl %p not on list", (void *)hp); } *ppx = hp->h_next; hp->h_next = NULL; if (hp->h_tid != EXS_TID_FREE) { hp->h_quit = 1; fmd_thr_signal(hdl, hp->h_tid); fmd_thr_destroy(hdl, hp->h_tid); } if (hp->h_server.c_sd != EXS_SD_FREE) (void) close(hp->h_server.c_sd); if (hp->h_client.c_sd != EXS_SD_FREE) (void) close(hp->h_client.c_sd); fmd_hdl_strfree(hdl, hp->h_endpt_id); fmd_hdl_free(hdl, hp, sizeof (exs_hdl_t)); if (Exh_head == NULL) { /* Undo one-time initializations */ exs_filter_fini(hdl); /* Destroy the accept/listen thread */ if (Acc_tid != EXS_TID_FREE) { Acc_quit = 1; fmd_thr_signal(hdl, Acc_tid); fmd_thr_destroy(hdl, Acc_tid); } if (Acc.c_sd != EXS_SD_FREE) EXS_CLOSE_CLR(Acc); } (void) pthread_mutex_unlock(&List_lock); return (0); }
/* * Open a connection with the given endpoint, * Return etm_xport_conn_t for success, NULL and set errno for failure. */ etm_xport_conn_t etm_xport_open(fmd_hdl_t *hdl, etm_xport_hdl_t tlhdl) { int flags; exs_hdl_t *hp = (exs_hdl_t *)tlhdl; if (hp->h_destroy) { fmd_thr_destroy(hp->h_hdl, hp->h_tid); hp->h_tid = EXS_TID_FREE; hp->h_destroy = 0; } if (hp->h_client.c_sd == EXS_SD_FREE) { if (exs_prep_client(hp) != 0) return (NULL); } /* Set the socket to be non-blocking */ flags = fcntl(hp->h_client.c_sd, F_GETFL, 0); (void) fcntl(hp->h_client.c_sd, F_SETFL, flags | O_NONBLOCK); if ((connect(hp->h_client.c_sd, (struct sockaddr *)&hp->h_client.c_saddr, hp->h_client.c_len)) == -1) { if (errno != EINPROGRESS) { fmd_hdl_debug(hdl, "xport - failed to connect to %s", hp->h_endpt_id); EXS_CLOSE_CLR(hp->h_client); return (NULL); } } fmd_hdl_debug(hdl, "xport - connected client socket for %s", hp->h_endpt_id); return (&hp->h_client); }
/* * Accept a new incoming connection. */ static void exs_accept(fmd_hdl_t *hdl) { int new_sd, dom, flags, rv; struct sockaddr_in new_saddr; socklen_t new_len = sizeof (struct sockaddr); exs_hdl_t *hp; if ((new_sd = accept(Acc.c_sd, (struct sockaddr *)&new_saddr, &new_len)) != -1) { /* Translate saddr to domain id */ if ((rv = dscpIdent((struct sockaddr *)&new_saddr, (int)new_len, &dom)) != DSCP_OK) { fmd_hdl_error(hdl, "dscpIdent failed : rv = %d\n", rv); (void) close(new_sd); return; } /* Find the exs_hdl_t for the domain trying to connect */ (void) pthread_mutex_lock(&List_lock); for (hp = Exh_head; hp; hp = hp->h_next) { if (hp->h_dom == dom) break; } (void) pthread_mutex_unlock(&List_lock); if (hp == NULL) { fmd_hdl_error(hdl, "Not configured to accept a " "connection from domain %d. Check " "event-transport.conf\n", dom); (void) close(new_sd); return; } /* Authenticate this connection request */ if ((rv = dscpAuth(dom, (struct sockaddr *)&new_saddr, (int)new_len)) != DSCP_OK) { fmd_hdl_error(hdl, "dscpAuth failed for %s : rv = %d ", " Possible spoofing attack\n", hp->h_endpt_id, rv); (void) close(new_sd); return; } if (hp->h_tid != EXS_TID_FREE) { hp->h_quit = 1; fmd_thr_signal(hp->h_hdl, hp->h_tid); fmd_thr_destroy(hp->h_hdl, hp->h_tid); hp->h_destroy = 0; hp->h_quit = 0; } if (hp->h_server.c_sd != EXS_SD_FREE) EXS_CLOSE_CLR(hp->h_server); /* Set the socket to be non-blocking */ flags = fcntl(new_sd, F_GETFL, 0); (void) fcntl(new_sd, F_SETFL, flags | O_NONBLOCK); hp->h_server.c_sd = new_sd; hp->h_tid = fmd_thr_create(hdl, exs_server, hp); } else { fmd_hdl_error(hp->h_hdl, "Failed to accept() a new connection"); } }
/* * Prepare to accept a connection. * Return 0 for success, nonzero for failure. */ void exs_prep_accept(fmd_hdl_t *hdl, int dom) { int flags, optval = 1; int rv; if (Acc.c_sd != EXS_SD_FREE) return; /* nothing to do */ if (Acc_destroy) { fmd_thr_destroy(hdl, Acc_tid); Acc_tid = EXS_TID_FREE; } /* Check to see if the DSCP interface is configured */ if ((rv = dscpAddr(dom, DSCP_ADDR_LOCAL, (struct sockaddr *)&Acc.c_saddr, &Acc.c_len)) != DSCP_OK) { fmd_hdl_debug(hdl, "xport - dscpAddr on the accept socket " "failed for domain %d : rv = %d", dom, rv); return; } if ((Acc.c_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fmd_hdl_error(hdl, "Failed to create the accept socket"); return; } if (setsockopt(Acc.c_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval))) { fmd_hdl_error(hdl, "Failed to set REUSEADDR for the accept " "socket"); EXS_CLOSE_CLR(Acc); return; } /* Bind the socket to the local IP address of the DSCP link */ if ((rv = dscpBind(dom, Acc.c_sd, EXS_SERVER_PORT)) != DSCP_OK) { if (rv == DSCP_ERROR_DOWN) { fmd_hdl_debug(hdl, "xport - dscp link for domain %d " "is down", dom); } else { fmd_hdl_error(hdl, "dscpBind on the accept socket " "failed : rv = %d\n", rv); } EXS_CLOSE_CLR(Acc); return; } /* Activate IPsec security policy for this socket */ if ((rv = dscpSecure(dom, Acc.c_sd)) != DSCP_OK) { fmd_hdl_error(hdl, "dscpSecure on the accept socket failed : " "rv = %d\n", dom, rv); EXS_CLOSE_CLR(Acc); return; } if ((listen(Acc.c_sd, EXS_NUM_SOCKS)) == -1) { fmd_hdl_debug(hdl, "Failed to listen() for connections"); EXS_CLOSE_CLR(Acc); return; } flags = fcntl(Acc.c_sd, F_GETFL, 0); (void) fcntl(Acc.c_sd, F_SETFL, flags | O_NONBLOCK); Acc_tid = fmd_thr_create(hdl, exs_listen, hdl); }
void dm_plugin_thr_destroy(pthread_t tid) { fmd_thr_destroy(g_fm_hdl, tid); }