Esempio n. 1
0
/*
 * 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);
}
Esempio n. 2
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);
}
Esempio n. 3
0
/*
 * 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);
}
Esempio n. 4
0
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);
}
Esempio n. 5
0
/*
 * 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);
}
Esempio n. 6
0
/*
 * 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");
	}
}
Esempio n. 7
0
/*
 * 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);
}
Esempio n. 8
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() */