/* * Translate endpoint_id string to int. * Return the domain ID via "dom_id". * Return 0 for success, nonzero for failure */ static int exs_get_id(fmd_hdl_t *hdl, char *endpoint_id, int *dom_id) { char *ptr; if (strstr(endpoint_id, EXS_SP_PREFIX) != NULL) { /* Remote endpoint is the SP */ *dom_id = DSCP_IDENT_SP; return (0); } else { if ((ptr = strstr(endpoint_id, EXS_DOMAIN_PREFIX)) == NULL) { fmd_hdl_error(hdl, "Property parsing error : %s not " "found in %s. Check event-transport.conf\n", EXS_DOMAIN_PREFIX, endpoint_id); return (1); } ptr += EXS_DOMAIN_PREFIX_LEN; if ((sscanf(ptr, "%d", dom_id)) != 1) { fmd_hdl_error(hdl, "Property parsing error : no " "integer found in %s. Check event-transport.conf\n", endpoint_id); return (2); } } return (0); }
/* * Walk all of the topology nodes looking for DISKs that match the structure * described in the overview. Once we find them, check their fault status * and update their fault indiciator accordingly. */ static void dl_examine_topo(disk_lights_t *dl) { int err; topo_hdl_t *thp = NULL; topo_walk_t *twp = NULL; thp = fmd_hdl_topo_hold(dl->dl_fmd, TOPO_VERSION); if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC, dl_fault_walk_outer, dl, &err)) == NULL) { fmd_hdl_error(dl->dl_fmd, "failed to get topology: %s\n", topo_strerror(err)); goto out; } if (topo_walk_step(twp, TOPO_WALK_CHILD) == TOPO_WALK_ERR) { fmd_hdl_error(dl->dl_fmd, "failed to walk topology: %s\n", topo_strerror(err)); goto out; } out: if (twp != NULL) topo_walk_fini(twp); if (thp != NULL) fmd_hdl_topo_rele(dl->dl_fmd, thp); }
/* * Convert a shorthand svc FMRI into a full svc FMRI nvlist */ static nvlist_t * shortfmri_to_fmri(fmd_hdl_t *hdl, const char *shortfmristr) { nvlist_t *ret, *fmri; topo_hdl_t *thp; char *fmristr; int err; if ((fmristr = shortfmri_to_fmristr(hdl, shortfmristr)) == NULL) return (NULL); thp = fmd_hdl_topo_hold(hdl, TOPO_VERSION); if (topo_fmri_str2nvl(thp, fmristr, &fmri, &err) != 0) { fmd_hdl_error(hdl, "failed to convert '%s' to nvlist\n", fmristr); fmd_hdl_strfree(hdl, fmristr); fmd_hdl_topo_rele(hdl, thp); return (NULL); } fmd_hdl_strfree(hdl, fmristr); if ((ret = fmd_nvl_dup(hdl, fmri, FMD_SLEEP)) == NULL) { fmd_hdl_error(hdl, "failed to dup fmri\n"); nvlist_free(fmri); fmd_hdl_topo_rele(hdl, thp); return (NULL); } nvlist_free(fmri); fmd_hdl_topo_rele(hdl, thp); return (ret); }
nvlist_t * cmd_fault_add_location(fmd_hdl_t *hdl, nvlist_t *flt, const char *locstr) { char *t, *s; if (nvlist_lookup_string(flt, FM_FAULT_LOCATION, &t) == 0) return (flt); /* already has location value */ /* Replace occurrence of ": " with "/" to avoid confusing ILOM. */ t = fmd_hdl_zalloc(hdl, strlen(locstr) + 1, FMD_SLEEP); s = strstr(locstr, ": "); if (s != NULL) { (void) strncpy(t, locstr, s - locstr); (void) strcat(t, "/"); (void) strcat(t, s + 2); } else { (void) strcpy(t, locstr); } /* Also, remove any J number from end of this string. */ s = strstr(t, "/J"); if (s != NULL) *s = '\0'; if (nvlist_add_string(flt, FM_FAULT_LOCATION, t) != 0) fmd_hdl_error(hdl, "unable to alloc location for fault\n"); fmd_hdl_free(hdl, t, strlen(locstr) + 1); return (flt); }
/* * 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); }
/* * 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 the client connection. * Return 0 for success, nonzero for failure. */ static int exs_prep_client(exs_hdl_t *hp) { int rv, optval = 1; struct linger ling; /* Find the DSCP address for the remote endpoint */ if ((rv = dscpAddr(hp->h_dom, DSCP_ADDR_REMOTE, (struct sockaddr *)&hp->h_client.c_saddr, &hp->h_client.c_len)) != DSCP_OK) { fmd_hdl_debug(hp->h_hdl, "dscpAddr on the client socket " "failed for %s : rv = %d\n", hp->h_endpt_id, rv); return (1); } if ((hp->h_client.c_sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fmd_hdl_error(hp->h_hdl, "Failed to create the client socket " "for %s", hp->h_endpt_id); return (2); } if (setsockopt(hp->h_client.c_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval))) { fmd_hdl_error(hp->h_hdl, "Failed to set REUSEADDR on the " "client socket for %s", hp->h_endpt_id); EXS_CLOSE_CLR(hp->h_client); return (3); } /* * Set SO_LINGER so TCP aborts the connection when closed. * If the domain's client socket goes into the TIME_WAIT state, * ETM will be unable to connect to the SP until this clears. * This connection is over DSCP, which is a simple point-to-point * connection and therefore has no routers or multiple forwarding. * The risk of receiving old packets from a previously terminated * connection is very small. */ ling.l_onoff = 1; ling.l_linger = 0; if (setsockopt(hp->h_client.c_sd, SOL_SOCKET, SO_LINGER, &ling, sizeof (ling))) { fmd_hdl_error(hp->h_hdl, "Failed to set SO_LINGER on the " "client socket for %s", hp->h_endpt_id); EXS_CLOSE_CLR(hp->h_client); return (4); } /* Bind the socket to the local IP address of the DSCP link */ if ((rv = dscpBind(hp->h_dom, hp->h_client.c_sd, EXS_CLIENT_PORT)) != DSCP_OK) { if (rv == DSCP_ERROR_DOWN) { fmd_hdl_debug(hp->h_hdl, "xport - dscp link for %s " "is down", hp->h_endpt_id); } else { fmd_hdl_error(hp->h_hdl, "dscpBind on the client " "socket failed : rv = %d\n", rv); } EXS_CLOSE_CLR(hp->h_client); return (5); } hp->h_client.c_saddr.sin_port = htons(EXS_SERVER_PORT); /* Set IPsec security policy for this socket */ if ((rv = dscpSecure(hp->h_dom, hp->h_client.c_sd)) != DSCP_OK) { fmd_hdl_error(hp->h_hdl, "dscpSecure on the client socket " "failed for %s : rv = %d\n", hp->h_endpt_id, rv); EXS_CLOSE_CLR(hp->h_client); return (6); } return (0); }
int etm_xport_init(fmd_hdl_t *hdl) { _etm_xport_addr_t **_addrv; /* address vector */ int i; /* vector index */ ssize_t n; /* gen use */ int rv; /* ret val */ struct stat stat_buf; /* file stat struct */ char *fn; /* filename of dev node */ rv = 0; /* assume good */ _addrv = NULL; if (hdl == NULL) { rv = (-EINVAL); goto func_ret; } fmd_hdl_debug(hdl, "info: xport initializing\n"); /* setup statistics and properties from FMD */ (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, sizeof (etm_xport_stats) / sizeof (fmd_stat_t), (fmd_stat_t *)&etm_xport_stats); etm_xport_debug_lvl = fmd_prop_get_int32(hdl, ETM_PROP_NM_DEBUG_LVL); etm_xport_addrs = fmd_prop_get_string(hdl, ETM_PROP_NM_XPORT_ADDRS); fmd_hdl_debug(hdl, "info: etm_xport_debug_lvl %d\n", etm_xport_debug_lvl); fmd_hdl_debug(hdl, "info: etm_xport_addrs %s\n", etm_xport_addrs); /* decide whether to fake [some of] the device driver behavior */ etm_xport_should_fake_dd = 0; /* default to false */ fn = etm_xport_get_fn(hdl, ETM_IO_OP_RD); if (stat(fn, &stat_buf) < 0) { /* errno assumed set by above call */ fmd_hdl_error(hdl, "error: bad device node %s errno %d\n", fn, errno); rv = (-errno); goto func_ret; } if (!S_ISCHR(stat_buf.st_mode) && use_vldc == 0) { etm_xport_should_fake_dd = 1; /* not a char driver */ } fmd_hdl_debug(hdl, "info: etm_xport_should_fake_dd %d\n", etm_xport_should_fake_dd); /* validate each default dst transport address */ if ((_addrv = (void *)etm_xport_get_ev_addrv(hdl, NULL)) == NULL) { /* errno assumed set by above call */ rv = (-errno); goto func_ret; } for (i = 0; _addrv[i] != NULL; i++) { if ((n = etm_xport_valid_addr(_addrv[i])) < 0) { fmd_hdl_error(hdl, "error: bad xport addr %p\n", _addrv[i]); rv = n; goto func_ret; } } /* foreach dst addr */ if (use_vldc) { etm_xport_vldc_conn = etm_xport_open(hdl, _addrv[0]); if (etm_xport_vldc_conn == NULL) { fmd_hdl_debug(hdl, "info: etm_xport_open() failed\n"); } } func_ret: if (_addrv != NULL) { etm_xport_free_addrv(hdl, (void *)_addrv); } if (rv >= 0) { fmd_hdl_debug(hdl, "info: xport initialized ok\n"); } return (rv); } /* etm_xport_init() */