Esempio n. 1
0
static void
posix_formatter(char *var, char *prefix, char *val)
{
    /* +40 bytes for max PCP env variable name */
    char	envbuf[MAXPATHLEN+40];
    char	*vp;
    char	*vend;

    snprintf(envbuf, sizeof(envbuf), "%s=", var);
    vend = &val[strlen(val)-1];
    if (val[0] == *vend && (val[0] == '\'' || val[0] == '"')) {
	/*
	 * have quoted value like "gawk --posix" for $PCP_AWK_PROG ...
	 * strip quotes
	 */
	vp = &val[1];
	vend--;
    }
    else
	vp = val;
    strncat(envbuf, vp, vend-vp+1);
    envbuf[strlen(var)+1+vend-vp+1+1] = '\0';

    PM_LOCK(__pmLock_libpcp);
    putenv(strdup(envbuf));
    PM_UNLOCK(__pmLock_libpcp);
    (void)prefix;
}
Esempio n. 2
0
static int
ping_pmcd(int ctx)
{
    /*
     * We're going to leveraging an existing host context, just make sure
     * pmcd is still alive at the other end ... we don't have a "ping"
     * pdu, but sending a pmDesc request for PM_ID_NULL is pretty much
     * the same thing ... expect a PM_ERR_PMID error PDU back.
     * The code here is based on pmLookupDesc() with some short cuts
     * because we know it is a host context and we already hold the
     * __pmLock_libpcp lock
     */
    __pmContext	*ctxp = contexts[ctx];
    int		sts;

    PM_LOCK(ctxp->c_pmcd->pc_lock);
    if ((sts = __pmSendDescReq(ctxp->c_pmcd->pc_fd, ctx, PM_ID_NULL)) >= 0) {
	int	pinpdu;
	__pmPDU	*pb;
	pinpdu = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
				    ctxp->c_pmcd->pc_tout_sec, &pb);
	if (pinpdu == PDU_ERROR)
	    __pmDecodeError(pb, &sts);
	if (pinpdu > 0)
	    __pmUnpinPDUBuf(pb);
    }
    PM_UNLOCK(ctxp->c_pmcd->pc_lock);

    if (sts != PM_ERR_PMID) {
	/* pmcd is not well on this context ... */
	return 0;
    }
    return 1;
}
Esempio n. 3
0
File: pdu.c Progetto: rwongone/pcp
const struct timeval *
__pmDefaultRequestTimeout(void)
{
    static int		done_default = 0;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (!done_default) {
	char	*timeout_str;
	char	*end_ptr;
	if ((timeout_str = getenv("PMCD_REQUEST_TIMEOUT")) != NULL) {
	    def_timeout = strtod(timeout_str, &end_ptr);
	    if (*end_ptr != '\0' || def_timeout < 0.0) {
		__pmNotifyErr(LOG_WARNING,
			      "ignored bad PMCD_REQUEST_TIMEOUT = '%s'\n",
			      timeout_str);
	    }
	    else {
		__pmtimevalFromReal(def_timeout, &def_wait);
	    }
	}
	done_default = 1;
    }
    PM_UNLOCK(__pmLock_libpcp);
    return (&def_wait);
}
Esempio n. 4
0
int
__pmSecureServerCertificateSetup(const char *db, const char *passwd, const char *cert_nickname)
{
    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);

    /* Configure optional (cmdline) password file in case DB locked */
    secure_server.password_file = passwd;

    /*
     * Configure location of the NSS database with a sane default.
     * For servers, we default to the shared (sql) system-wide database.
     * If command line db specified, pass it directly through - allowing
     * any old database format, at the users discretion.
     */
    if (db) {
	/* shortened-buffer-size (-2) guarantees null-termination */
	strncpy(secure_server.database_path, db, MAXPATHLEN-2);
    }

    if (cert_nickname) {
	strncpy(secure_server.cert_nickname, cert_nickname, MAX_CERT_NAME_LENGTH-2);
    }
    else {
	strncpy(secure_server.cert_nickname, SECURE_SERVER_CERTIFICATE, MAX_CERT_NAME_LENGTH-2);
    }

    PM_UNLOCK(secureserver_lock);
    return 0;
}
Esempio n. 5
0
int
main(int argc, char **argv)
{
    char		*p;
    struct timeval	delta = { 1, 0 };

    if (argc != 2) _usage();

    __pmAFregister(&delta, NULL, timeout);
#ifdef DBG_TRACE_DESPERATE
    pmDebug |= DBG_TRACE_DESPERATE;
#endif

    for (p = argv[1]; *p; p++) {
	switch (*p) {
	    case 'i':
	    	fprintf(stderr, "initialize\n");
		PM_INIT_LOCKS();
		break;
	    case 'l':
	    	fprintf(stderr, "lock\n");
		PM_LOCK(__pmLock_libpcp);
		break;
	    case 'u':
	    	fprintf(stderr, "unlock\n");
		PM_UNLOCK(__pmLock_libpcp);
		break;
	    default:
		_usage();
	}
    }

    return 0;
}
Esempio n. 6
0
File: config.c Progetto: Aconex/pcp
void
__pmConfig(__pmConfigCallback formatter)
{
    /*
     * Scan ${PCP_CONF-$PCP_DIR/etc/pcp.conf} and put all PCP config
     * variables found therein into the environment.
     */
    FILE *fp;
    char confpath[32];
    char dir[MAXPATHLEN];
    char var[MAXPATHLEN];
    char *prefix;
    char *conf;
    char *val;
    char *p;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    prefix = getenv("PCP_DIR");
    if ((conf = getenv("PCP_CONF")) == NULL) {
	strncpy(confpath, "/etc/pcp.conf", sizeof(confpath));
	if (prefix == NULL)
	    conf = __pmNativePath(confpath);
	else {
	    snprintf(dir, sizeof(dir),
			 "%s%s", prefix, __pmNativePath(confpath));
	    conf = dir;
	}
    }

    if (access((const char *)conf, R_OK) < 0 ||
	(fp = fopen(conf, "r")) == (FILE *)NULL) {
	char	errmsg[PM_MAXERRMSGLEN];
	pmprintf("FATAL PCP ERROR: could not open config file \"%s\" : %s\n",
		conf, osstrerror_r(errmsg, sizeof(errmsg)));
	pmprintf("You may need to set PCP_CONF or PCP_DIR in your environment.\n");
	pmflush();
	PM_UNLOCK(__pmLock_libpcp);
	exit(1);
    }

    while (fgets(var, sizeof(var), fp) != NULL) {
	if (var[0] == '#' || (p = strchr(var, '=')) == NULL)
	    continue;
	*p = '\0';
	val = p+1;
	if ((p = strrchr(val, '\n')) != NULL)
	    *p = '\0';
	if ((p = getenv(var)) != NULL)
	    val = p;
	else
	    formatter(var, prefix, val);

	if (pmDebug & DBG_TRACE_CONFIG)
	    fprintf(stderr, "pmGetConfig: (init) %s=%s\n", var, val);
    }
    fclose(fp);
    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 7
0
int
__pmUnpinPDUBuf(void *handle)
{
    bufctl_t	*pcp, pcp_search;
    void	*bcp;

    assert(((__psint_t)handle % sizeof(int)) == 0);
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);

    /*
     * Initialize a dummy bufctl_t to use only as search key;
     * only its bc_buf & bc_size fields need to be set, as that's
     * all that bufctl_t_compare will look at.
     */
    pcp_search.bc_buf = handle;
    pcp_search.bc_size = 1;

    bcp = tfind(&pcp_search, &buf_tree, &bufctl_t_compare);
    /*
     * NB: don't release the lock until final disposition of this object;
     * we don't want to play TOCTOU.
     */
    if (likely(bcp != NULL)) {
	pcp = *(bufctl_t **)bcp;
    } else {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_PDUBUF) {
	    fprintf(stderr, "__pmUnpinPDUBuf(" PRINTF_P_PFX "%p) -> fails\n",
		    handle);
	    pdubufdump();
	}
#endif
	PM_UNLOCK(__pmLock_libpcp);
	return 0;
    }

#ifdef PCP_DEBUG
    if (unlikely(pmDebug & DBG_TRACE_PDUBUF))
	fprintf(stderr, "__pmUnpinPDUBuf(" PRINTF_P_PFX "%p) -> pdubuf="
			PRINTF_P_PFX "%p, pincnt=%d\n", handle,
		pcp->bc_buf, pcp->bc_pincnt - 1);
#endif

    assert((&pcp->bc_buf[0] <= (char*)handle) &&
	   ((char*)handle < &pcp->bc_buf[pcp->bc_size]));

    if (likely(--pcp->bc_pincnt == 0)) {
	tdelete(pcp, &buf_tree, &bufctl_t_compare);
	PM_UNLOCK(__pmLock_libpcp);
	free(pcp);
    }
    else {
	PM_UNLOCK(__pmLock_libpcp);
    }

    return 1;
}
Esempio n. 8
0
/*
 * On success, context is locked and caller should unlock it
 */
__pmContext *
__pmHandleToPtr(int handle)
{
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (handle < 0 || handle >= contexts_len ||
	contexts[handle]->c_type == PM_CONTEXT_FREE) {
	PM_UNLOCK(__pmLock_libpcp);
	return NULL;
    }
    else {
	__pmContext	*sts;
	sts = contexts[handle];
	PM_UNLOCK(__pmLock_libpcp);
	PM_LOCK(sts->c_lock);
	return sts;
    }
}
Esempio n. 9
0
/*
 * For native Win32 console tools, we need to translate the paths
 * used in scripts to native paths with PCP_DIR prefix prepended.
 *
 * For Win32 MSYS shell usage, we need to translate the paths
 * used in scripts to paths with PCP_DIR prefix prepended AND
 * drive letter path mapping done AND posix-style separators.
 *
 * Choose which way to go based on our environment (SHELL).
 */
static int posix_style(void)
{
    char	*s;
    int		sts;
    PM_LOCK(__pmLock_libpcp);
    s = getenv("SHELL");
    sts = (s && strncmp(s, "/bin/", 5) == 0);
    PM_UNLOCK(__pmLock_libpcp);
    return sts;
}
Esempio n. 10
0
static char *
pmgetconfig(const char *name, int fatal)
{
    /*
     * state controls one-trip initialization, and recursion guard
     * for pathological failures in initialization
     */
    static int		state = 0;
    char		*val;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (state == 0) {
	state = 1;
	PM_UNLOCK(__pmLock_libpcp);
	__pmconfig(__pmNativeConfig, fatal);
	PM_LOCK(__pmLock_libpcp);
	state = 2;
    }
    else if (state == 1) {
	/* recursion from error in __pmConfig() ... no value is possible */
	PM_UNLOCK(__pmLock_libpcp);
	if (pmDebug & DBG_TRACE_CONFIG)
	    fprintf(stderr, "pmgetconfig: %s= ... recursion error\n", name);
	if (!fatal)
	    return NULL;
	val = "";
	return val;
    }
    PM_UNLOCK(__pmLock_libpcp);

    if ((val = getenv(name)) == NULL) {
	if (!fatal)
	    return NULL;
	val = "";
    }

    if (pmDebug & DBG_TRACE_CONFIG)
	fprintf(stderr, "pmgetconfig: %s=%s\n", name, val);

    return val;
}
Esempio n. 11
0
File: AF.c Progetto: tongfw/pcp
static void AFsetup(void)
{
    PM_LOCK(__pmLock_libpcp);
    if (afsetup) {
	PM_UNLOCK(__pmLock_libpcp);
	return;
    }
    afsetup = 1;
    afblock = CreateMutex(NULL, FALSE, NULL);
    aftimer = CreateWaitableTimer(NULL, TRUE, NULL);
    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 12
0
static int
__pmSecureServerNegotiation(int fd, int *strength)
{
    PRIntervalTime timer;
    PRFileDesc *sslsocket;
    SECStatus secsts;
    int enabled, keysize;
    int msec;

    sslsocket = (PRFileDesc *)__pmGetSecureSocket(fd);
    if (!sslsocket)
	return PM_ERR_IPC;

    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);
    secsts = SSL_ConfigSecureServer(sslsocket,
			secure_server.certificate,
			secure_server.private_key,
			secure_server.certificate_KEA);
    PM_UNLOCK(secureserver_lock);

    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Unable to configure secure server: %s",
			    pmErrStr(__pmSecureSocketsError(PR_GetError())));
	return PM_ERR_IPC;
    }

    secsts = SSL_ResetHandshake(sslsocket, PR_TRUE /*server*/);
    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Unable to reset secure handshake: %s",
			    pmErrStr(__pmSecureSocketsError(PR_GetError())));
	return PM_ERR_IPC;
    }

    /* Server initiates handshake now to get early visibility of errors */
    msec = __pmConvertTimeout(TIMEOUT_DEFAULT);
    timer = PR_MillisecondsToInterval(msec);
    secsts = SSL_ForceHandshakeWithTimeout(sslsocket, timer);
    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Unable to force secure handshake: %s",
			    pmErrStr(__pmSecureSocketsError(PR_GetError())));
	return PM_ERR_IPC;
    }

    secsts = SSL_SecurityStatus(sslsocket, &enabled, NULL, &keysize, NULL, NULL, NULL);
    if (secsts != SECSuccess)
	return __pmSecureSocketsError(PR_GetError());

    *strength = (enabled > 0) ? keysize : DEFAULT_SECURITY_STRENGTH;
    return 0;
}
Esempio n. 13
0
File: connect.c Progetto: tongfw/pcp
void
__pmConnectGetPorts(pmHostSpec *host)
{
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    load_pmcd_ports();
    if (__pmAddHostPorts(host, global_portlist, global_nports) < 0) {
	__pmNotifyErr(LOG_WARNING,
		"__pmConnectGetPorts: portlist dup failed, "
		"using default PMCD_PORT (%d)\n", SERVER_PORT);
	host->ports[0] = SERVER_PORT;
	host->nports = 1;
    }
    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 14
0
static void
pdubufdump(void)
{
    /*
     * There is no longer a pdubuf free list, ergo no
     * fprintf(stderr, "   free pdubuf[size]:\n");
     */
    PM_LOCK(__pmLock_libpcp);
    if (buf_tree != NULL) {
	fprintf(stderr, "   pinned pdubuf[size](pincnt):");
	twalk(buf_tree, &pdubufdump1);
	fprintf(stderr, "\n");
    }
    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 15
0
int
__pmPtrToHandle(__pmContext *ctxp)
{
    int		i;
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    for (i = 0; i < contexts_len; i++) {
	if (ctxp == contexts[i]) {
	    PM_UNLOCK(__pmLock_libpcp);
	    return i;
	}
    }
    PM_UNLOCK(__pmLock_libpcp);
    return PM_CONTEXT_UNDEF;
}
Esempio n. 16
0
void
__pmCountPDUBuf(int need, int *alloc, int *free)
{
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);

    pdu_bufcnt_need = need;
    pdu_bufcnt = 0;
    twalk(buf_tree, &pdubufcount);
    *alloc = pdu_bufcnt;

    *free = 0;			/* We don't retain freed nodes. */

    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 17
0
static void
waitawhile(__pmPMCDCtl *ctl)
{
    /*
     * after failure, compute delay before trying again ...
     */
    PM_LOCK(__pmLock_libpcp);
    if (n_backoff == 0) {
	char	*q;
	/* first time ... try for PMCD_RECONNECT_TIMEOUT from env */
	if ((q = getenv("PMCD_RECONNECT_TIMEOUT")) != NULL) {
	    char	*pend;
	    char	*p;
	    int		val;

	    for (p = q; *p != '\0'; ) {
		val = (int)strtol(p, &pend, 10);
		if (val <= 0 || (*pend != ',' && *pend != '\0')) {
		    __pmNotifyErr(LOG_WARNING,
				 "pmReconnectContext: ignored bad PMCD_RECONNECT_TIMEOUT = '%s'\n",
				 q);
		    n_backoff = 0;
		    if (backoff != NULL)
			free(backoff);
		    break;
		}
		if ((backoff = (int *)realloc(backoff, (n_backoff+1) * sizeof(backoff[0]))) == NULL) {
		    __pmNoMem("pmReconnectContext", (n_backoff+1) * sizeof(backoff[0]), PM_FATAL_ERR);
		}
		backoff[n_backoff++] = val;
		if (*pend == '\0')
		    break;
		p = &pend[1];
	    }
	}
	if (n_backoff == 0) {
	    /* use default */
	    n_backoff = 5;
	    backoff = def_backoff;
	}
    }
    PM_UNLOCK(__pmLock_libpcp);
    if (ctl->pc_timeout == 0)
	ctl->pc_timeout = 1;
    else if (ctl->pc_timeout < n_backoff)
	ctl->pc_timeout++;
    ctl->pc_again = time(NULL) + backoff[ctl->pc_timeout-1];
}
Esempio n. 18
0
static void
dos_formatter(char *var, char *prefix, char *val)
{
    char envbuf[MAXPATHLEN];
    int msys = posix_style();

    if (prefix && dos_rewrite_path(var, val, msys)) {
	char *p = msys ? msys_native_path(prefix) : prefix;
	snprintf(envbuf, sizeof(envbuf), "%s=%s%s", var, p, val);
    }
    else {
	snprintf(envbuf, sizeof(envbuf), "%s=%s", var, val);
    }
    PM_LOCK(__pmLock_libpcp);
    putenv(strdup(envbuf));
    PM_UNLOCK(__pmLock_libpcp);
}
Esempio n. 19
0
__pmPDU *
__pmFindPDUBuf(int need)
{
    bufctl_t	*pcp;
    void	*bcp;

    PM_INIT_LOCKS();

    if (unlikely(need < 0)) {
	/* special diagnostic case ... dump buffer state */
#ifdef PCP_DEBUG
	fprintf(stderr, "__pmFindPDUBuf(DEBUG)\n");
	pdubufdump();
#endif
	return NULL;
    }

    if ((pcp = (bufctl_t *)malloc(sizeof(*pcp) + need)) == NULL) {
	return NULL;
    }

    pcp->bc_pincnt = 1;
    pcp->bc_size = need;
    pcp->bc_buf = ((char *)pcp) + sizeof(*pcp);

    PM_LOCK(__pmLock_libpcp);
    /* Insert the node in the tree. */
    bcp = tsearch((void *)pcp, &buf_tree, &bufctl_t_compare);
    if (unlikely(bcp == NULL)) {	/* ENOMEM */
	PM_UNLOCK(__pmLock_libpcp);
	free(pcp);
	return NULL;
    }
    PM_UNLOCK(__pmLock_libpcp);

#ifdef PCP_DEBUG
    if (unlikely(pmDebug & DBG_TRACE_PDUBUF)) {
	fprintf(stderr, "__pmFindPDUBuf(%d) -> " PRINTF_P_PFX "%p\n",
		need, pcp->bc_buf);
	pdubufdump();
    }
#endif

    return (__pmPDU *)pcp->bc_buf;
}
Esempio n. 20
0
int
pmWhichContext(void)
{
    /*
     * return curcontext, provided it is defined
     */
    int		sts;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (PM_TPD(curcontext) > PM_CONTEXT_UNDEF)
	sts = PM_TPD(curcontext);
    else
	sts = PM_ERR_NOCONTEXT;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT)
	fprintf(stderr, "pmWhichContext() -> %d, cur=%d\n",
	    sts, PM_TPD(curcontext));
#endif
    PM_UNLOCK(__pmLock_libpcp);
    return sts;
}
Esempio n. 21
0
void
__pmSecureServerShutdown(void)
{
    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);
    if (secure_server.certificate) {
	CERT_DestroyCertificate(secure_server.certificate);
	secure_server.certificate = NULL;
    }
    if (secure_server.private_key) {
	SECKEY_DestroyPrivateKey(secure_server.private_key);
	secure_server.private_key = NULL;
    }
    if (secure_server.ssl_session_cache_setup) {
	SSL_ShutdownServerSessionIDCache();
	secure_server.ssl_session_cache_setup = 0;
    }    
    if (secure_server.initialized) {
	NSS_Shutdown();
	secure_server.initialized = 0;
    }
    PM_UNLOCK(secureserver_lock);
}
Esempio n. 22
0
int
__pmSecureServerSetup(const char *db, const char *passwd)
{
    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);

    /* Configure optional (cmdline) password file in case DB locked */
    secure_server.password_file = passwd;

    /*
     * Configure location of the NSS database with a sane default.
     * For servers, we default to the shared (sql) system-wide database.
     * If command line db specified, pass it directly through - allowing
     * any old database format, at the users discretion.
     */
    if (db) {
	/* shortened-buffer-size (-2) guarantees null-termination */
	strncpy(secure_server.database_path, db, MAXPATHLEN-2);
    }

    PM_UNLOCK(__pmLock_libpcp);
    return 0;
}
Esempio n. 23
0
static char *
certificate_database_password(PK11SlotInfo *info, PRBool retry, void *arg)
{
    size_t length = MAX_NSSDB_PASSWORD_LENGTH;
    char *password = NULL;
    char passfile[MAXPATHLEN];
    int sts;

    (void)arg;
    (void)info;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    passfile[0] = '\0';
    if (secure_server.password_file)
	strncpy(passfile, secure_server.password_file, MAXPATHLEN-1);
    passfile[MAXPATHLEN-1] = '\0';
    PM_UNLOCK(__pmLock_libpcp);

    if (passfile[0] == '\0') {
	__pmNotifyErr(LOG_ERR, "Password sought but no password file given");
	return NULL;
    }
    if (retry) {
	__pmNotifyErr(LOG_ERR, "Retry attempted during password extraction");
	return NULL;	/* no soup^Wretries for you */
    }

    sts = secure_file_contents(passfile, &password, &length);
    if (sts < 0) {
	__pmNotifyErr(LOG_ERR, "Cannot read password file \"%s\": %s",
			passfile, pmErrStr(sts));
	return NULL;
    }
    return password;
}
Esempio n. 24
0
int
__pmSecureServerInit(void)
{
    const PRUint16 *cipher;
    SECStatus secsts;
    int pathSpecified;
    int sts = 0;

    PM_INIT_LOCKS();
    PM_LOCK(secureserver_lock);

    /* Only attempt this once. */
    if (secure_server.initialized)
	goto done;
    secure_server.initialized = 1;

    if (PR_Initialized() != PR_TRUE)
	PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);

    /* Configure optional (cmdline) password file in case DB locked */
    PK11_SetPasswordFunc(certificate_database_password);

    /*
     * Configure location of the NSS database with a sane default.
     * For servers, we default to the shared (sql) system-wide database.
     * If command line db specified, pass it directly through - allowing
     * any old database format, at the users discretion.
     */
    if (!secure_server.database_path[0]) {
	const char *path;
	pathSpecified = 0;
	path = serverdb(secure_server.database_path, MAXPATHLEN, "sql:");

	/* this is the default case on some platforms, so no log spam */
	if (access(path, R_OK|X_OK) < 0) {
	    if (pmDebugOptions.context)
		pmNotifyErr(LOG_INFO,
			      "Cannot access system security database: %s",
			      secure_server.database_path);
	    sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	    secure_server.init_failed = 1;
	    goto done;
	}
    }
    else
	pathSpecified = 1;

    /*
     * pmproxy acts as both a client and server. Since the
     * server init path happens first, the db previously
     * got opened readonly.  Instead try to open RW.
     * Fallback if there is an error.
     */

    secsts = NSS_InitReadWrite(secure_server.database_path);

    if( secsts != SECSuccess )
    	secsts = NSS_Init(secure_server.database_path);

    if (secsts != SECSuccess && !pathSpecified) {
	/* fallback, older versions of NSS do not support sql: */
	serverdb(secure_server.database_path, MAXPATHLEN, "");
	secsts = NSS_Init(secure_server.database_path);
    }

    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Cannot setup certificate DB (%s): %s",
			secure_server.database_path,
			pmErrStr(__pmSecureSocketsError(PR_GetError())));
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    }

    /* Some NSS versions don't do this correctly in NSS_SetDomesticPolicy. */
    for (cipher = SSL_GetImplementedCiphers(); *cipher != 0; ++cipher)
	SSL_CipherPolicySet(*cipher, SSL_ALLOWED);

    /* Configure SSL session cache for multi-process server, using defaults */
    secsts = SSL_ConfigMPServerSIDCache(1, 0, 0, NULL);
    if (secsts != SECSuccess) {
	pmNotifyErr(LOG_ERR, "Unable to configure SSL session ID cache: %s",
		pmErrStr(__pmSecureSocketsError(PR_GetError())));
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    } else {
	secure_server.ssl_session_cache_setup = 1;
    }

    /*
     * Iterate over any/all PCP Collector nickname certificates,
     * seeking one valid certificate.  No-such-nickname is not an
     * error (not configured by admin at all) but anything else is.
     */
    CERTCertList *certlist;
    CERTCertDBHandle *nssdb = CERT_GetDefaultCertDB();
    CERTCertificate *dbcert = PK11_FindCertFromNickname(secure_server.cert_nickname, NULL);

    if (dbcert) {
	PRTime now = PR_Now();
	SECItem *name = &dbcert->derSubject;
	CERTCertListNode *node;

	certlist = CERT_CreateSubjectCertList(NULL, nssdb, name, now, PR_FALSE);
	if (certlist) {
	    for (node = CERT_LIST_HEAD(certlist);
		 !CERT_LIST_END(node, certlist);
		 node = CERT_LIST_NEXT (node)) {
		if (pmDebugOptions.context)
		    __pmDumpCertificate(stderr, secure_server.cert_nickname, node->cert);
		if (!__pmValidCertificate(nssdb, node->cert, now))
		    continue;
		secure_server.certificate_verified = 1;
		break;
	    }
	    CERT_DestroyCertList(certlist);
	}

	if (secure_server.certificate_verified) {
	    secure_server.certificate_KEA = NSS_FindCertKEAType(dbcert);
	    secure_server.private_key = PK11_FindKeyByAnyCert(dbcert, NULL);
	    if (!secure_server.private_key) {
		pmNotifyErr(LOG_ERR, "Unable to extract %s private key",
				secure_server.cert_nickname);
		CERT_DestroyCertificate(dbcert);
		secure_server.certificate_verified = 0;
		sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
		secure_server.init_failed = 1;
		goto done;
	    }
	} else {
	    pmNotifyErr(LOG_ERR, "Unable to find a valid %s", secure_server.cert_nickname);
	    CERT_DestroyCertificate(dbcert);
	    sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	    secure_server.init_failed = 1;
	    goto done;
	}
    }

    if (! secure_server.certificate_verified) {
	if (pmDebugOptions.context) {
	    pmNotifyErr(LOG_INFO, "No valid %s in security database: %s",
			  secure_server.cert_nickname, secure_server.database_path);
	}
	sts = -EOPNOTSUPP;	/* not fatal - just no secure connections */
	secure_server.init_failed = 1;
	goto done;
    }

    secure_server.certificate = dbcert;
    secure_server.init_failed = 0;
    sts = 0;

done:
    PM_UNLOCK(secureserver_lock);
    return sts;
}
Esempio n. 25
0
int
__pmConnectLocal(__pmHashCtl *attrs)
{
    int			i;
    __pmDSO		*dp;
    char		pathbuf[MAXPATHLEN];
    const char		*path;
#if defined(HAVE_DLOPEN)
    unsigned int	challenge;
    void		(*initp)(pmdaInterface *);
#ifdef HAVE_ATEXIT
    static int		atexit_installed = 0;
#endif
#endif

    if (numdso == -1) {
	int	sts;
	sts = build_dsotab();
	if (sts < 0) return sts;
    }

    for (i = 0; i < numdso; i++) {
	dp = &dsotab[i];
	if (dp->domain == -1 || dp->handle != NULL)
	    continue;
	/*
	 * __pmLocalPMDA() means the path to the DSO may be something
	 * other than relative to $PCP_PMDAS_DIR ... need to try both
	 * options and also with and without DSO_SUFFIX (so, dll, etc)
	 */
	snprintf(pathbuf, sizeof(pathbuf), "%s%c%s",
		 pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name);
	if ((path = __pmFindPMDA(pathbuf)) == NULL) {
	    snprintf(pathbuf, sizeof(pathbuf), "%s%c%s.%s",
		 pmGetConfig("PCP_PMDAS_DIR"), __pmPathSeparator(), dp->name, DSO_SUFFIX);
	    if ((path = __pmFindPMDA(pathbuf)) == NULL) {
		if ((path = __pmFindPMDA(dp->name)) == NULL) {
		    snprintf(pathbuf, sizeof(pathbuf), "%s.%s", dp->name, DSO_SUFFIX);
		    if ((path = __pmFindPMDA(pathbuf)) == NULL) {
			pmprintf("__pmConnectLocal: Warning: cannot find DSO at \"%s\" or \"%s\"\n", 
			     pathbuf, dp->name);
			pmflush();
			dp->domain = -1;
			dp->handle = NULL;
			continue;
		    }
		}
	    }
	}
#if defined(HAVE_DLOPEN)
	dp->handle = dlopen(path, RTLD_NOW);
	if (dp->handle == NULL) {
	    pmprintf("__pmConnectLocal: Warning: error attaching DSO "
		     "\"%s\"\n%s\n\n", path, dlerror());
	    pmflush();
	    dp->domain = -1;
	}
#else	/* ! HAVE_DLOPEN */
	dp->handle = NULL;
	pmprintf("__pmConnectLocal: Warning: error attaching DSO \"%s\"\n",
		 path);
	pmprintf("No dynamic DSO/DLL support on this platform\n\n");
	pmflush();
	dp->domain = -1;
#endif

	if (dp->handle == NULL)
	    continue;

#if defined(HAVE_DLOPEN)
	/*
	 * rest of this only makes sense if the dlopen() worked
	 */
	if (dp->init == NULL)
	    initp = NULL;
	else
	    initp = (void (*)(pmdaInterface *))dlsym(dp->handle, dp->init);
	if (initp == NULL) {
	    pmprintf("__pmConnectLocal: Warning: couldn't find init function "
		     "\"%s\" in DSO \"%s\"\n", dp->init, path);
	    pmflush();
	    dlclose(dp->handle);
	    dp->domain = -1;
	    continue;
	}

	/*
	 * Pass in the expected domain id.
	 * The PMDA initialization routine can (a) ignore it, (b) check it
	 * is the expected value, or (c) self-adapt.
	 */
	dp->dispatch.domain = dp->domain;

	/*
	 * the PMDA interface / PMAPI version discovery as a "challenge" ...
	 * for pmda_interface it is all the bits being set,
	 * for pmapi_version it is the complement of the one you are using now
	 */
	challenge = 0xff;
	dp->dispatch.comm.pmda_interface = challenge;
	dp->dispatch.comm.pmapi_version = ~PMAPI_VERSION;
	dp->dispatch.comm.flags = 0;
	dp->dispatch.status = 0;

	(*initp)(&dp->dispatch);

	if (dp->dispatch.status != 0) {
	    /* initialization failed for some reason */
	    char	errmsg[PM_MAXERRMSGLEN];
	    pmprintf("__pmConnectLocal: Warning: initialization "
		     "routine \"%s\" failed in DSO \"%s\": %s\n", 
		     dp->init, path, pmErrStr_r(dp->dispatch.status, errmsg, sizeof(errmsg)));
	    pmflush();
	    dlclose(dp->handle);
	    dp->domain = -1;
	}
	else {
	    if (dp->dispatch.comm.pmda_interface < PMDA_INTERFACE_2 ||
		dp->dispatch.comm.pmda_interface > PMDA_INTERFACE_LATEST) {
		pmprintf("__pmConnectLocal: Error: Unknown PMDA interface "
			 "version %d in \"%s\" DSO\n", 
			 dp->dispatch.comm.pmda_interface, path);
		pmflush();
		dlclose(dp->handle);
		dp->domain = -1;
	    }
	    else if (dp->dispatch.comm.pmapi_version != PMAPI_VERSION_2) {
		pmprintf("__pmConnectLocal: Error: Unknown PMAPI version %d "
			 "in \"%s\" DSO\n",
			 dp->dispatch.comm.pmapi_version, path);
		pmflush();
		dlclose(dp->handle);
		dp->domain = -1;
	    }
	    else if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_6 &&
		    (dp->dispatch.comm.flags & PDU_FLAG_AUTH) != 0) {
		/* Agent wants to know about connection attributes */
		build_dsoattrs(&dp->dispatch, attrs);
	    }
	}
#ifdef HAVE_ATEXIT
	PM_INIT_LOCKS();
	PM_LOCK(__pmLock_libpcp);
	if (dp->dispatch.comm.pmda_interface >= PMDA_INTERFACE_5 &&
	    atexit_installed == 0) {
	    /* install end of local context handler */
	    atexit(EndLocalContext);
	    atexit_installed = 1;
	}
	PM_UNLOCK(__pmLock_libpcp);
#endif
#endif	/* HAVE_DLOPEN */
    }

    return 0;
}
Esempio n. 26
0
File: pdu.c Progetto: rwongone/pcp
/* result is pinned on successful return */
int
__pmGetPDU(int fd, int mode, int timeout, __pmPDU **result)
{
    int			need;
    int			len;
    static int		maxsize = PDU_CHUNK;
    char		*handle;
    __pmPDU		*pdubuf;
    __pmPDU		*pdubuf_prev;
    __pmPDUHdr		*php;

    if ((pdubuf = __pmFindPDUBuf(maxsize)) == NULL)
	return -oserror();

    /* First read - try to read the header */
    len = pduread(fd, (void *)pdubuf, sizeof(__pmPDUHdr), HEADER, timeout);
    php = (__pmPDUHdr *)pdubuf;

    if (len < (int)sizeof(__pmPDUHdr)) {
	if (len == -1) {
	    if (__pmSocketClosed()) {
		len = 0;
	    } else {
		char	errmsg[PM_MAXERRMSGLEN];
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: len=%d: %s", fd, len, pmErrStr_r(-oserror(), errmsg, sizeof(errmsg)));
	    }
	}
	else if (len >= (int)sizeof(php->len)) {
	    /*
	     * Have part of a PDU header.  Enough for the "len"
	     * field to be valid, but not yet all of it - save
	     * what we have received and try to read some more.
	     * Note this can only happen once per PDU, so the
	     * ntohl() below will _only_ be done once per PDU.
	     */
	    goto check_read_len;	/* continue, do not return */
	}
	else if (len == PM_ERR_TIMEOUT) {
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_TIMEOUT;
	}
	else if (len < 0) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    __pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: len=%d: %s", fd, len, pmErrStr_r(len, errmsg, sizeof(errmsg)));
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}
	else if (len > 0) {
	    __pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d hdr read: bad len=%d", fd, len);
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}

	/*
	 * end-of-file with no data
	 */
	__pmUnpinPDUBuf(pdubuf);
	return 0;
    }

check_read_len:
    php->len = ntohl(php->len);
    if (php->len < (int)sizeof(__pmPDUHdr)) {
	/*
	 * PDU length indicates insufficient bytes for a PDU header
	 * ... looks like DOS attack like PV 935490
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d illegal PDU len=%d in hdr", fd, php->len);
	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_IPC;
    }
    else if (mode == LIMIT_SIZE && php->len > ceiling) {
	/*
	 * Guard against denial of service attack ... don't accept PDUs
	 * from clients that are larger than 64 Kbytes (ceiling)
	 * (note, pmcd and pmdas have to be able to _send_ large PDUs,
	 * e.g. for a pmResult or instance domain enquiry)
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d bad PDU len=%d in hdr exceeds maximum client PDU size (%d)",
		      fd, php->len, ceiling);

	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_TOOBIG;
    }

    if (len < php->len) {
	/*
	 * need to read more ...
	 */
	int		tmpsize;
	int		have = len;

	PM_INIT_LOCKS();
	PM_LOCK(__pmLock_libpcp);
	if (php->len > maxsize) {
	    tmpsize = PDU_CHUNK * ( 1 + php->len / PDU_CHUNK);
	    maxsize = tmpsize;
	}
	else
	    tmpsize = maxsize;
	PM_UNLOCK(__pmLock_libpcp);

	pdubuf_prev = pdubuf;
	if ((pdubuf = __pmFindPDUBuf(tmpsize)) == NULL) {
	    __pmUnpinPDUBuf(pdubuf_prev);
	    return -oserror();
	}

	memmove((void *)pdubuf, (void *)php, len);
	__pmUnpinPDUBuf(pdubuf_prev);

	php = (__pmPDUHdr *)pdubuf;
	need = php->len - have;
	handle = (char *)pdubuf;
	/* block until all of the PDU is received this time */
	len = pduread(fd, (void *)&handle[len], need, BODY, timeout);
	if (len != need) {
	    if (len == PM_ERR_TIMEOUT) {
		__pmUnpinPDUBuf(pdubuf);
		return PM_ERR_TIMEOUT;
	    }
	    else if (len < 0) {
		char	errmsg[PM_MAXERRMSGLEN];
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d data read: len=%d: %s", fd, len, pmErrStr_r(-oserror(), errmsg, sizeof(errmsg)));
	    }
	    else
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d data read: have %d, want %d, got %d", fd, have, need, len);
	    /*
	     * only report header fields if you've read enough bytes
	     */
	    if (len > 0)
		have += len;
	    if (have >= (int)(sizeof(php->len)+sizeof(php->type)+sizeof(php->from)))
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: PDU hdr: len=0x%x type=0x%x from=0x%x", php->len, (unsigned)ntohl(php->type), (unsigned)ntohl(php->from));
	    else if (have >= (int)(sizeof(php->len)+sizeof(php->type)))
		__pmNotifyErr(LOG_ERR, "__pmGetPDU: PDU hdr: len=0x%x type=0x%x", php->len, (unsigned)ntohl(php->type));
	    __pmUnpinPDUBuf(pdubuf);
	    return PM_ERR_IPC;
	}
    }

    *result = (__pmPDU *)php;
    php->type = ntohl((unsigned int)php->type);
    if (php->type < 0) {
	/*
	 * PDU type is bad ... could be a possible mem leak attack like
	 * https://bugzilla.redhat.com/show_bug.cgi?id=841319
	 */
	__pmNotifyErr(LOG_ERR, "__pmGetPDU: fd=%d illegal PDU type=%d in hdr", fd, php->type);
	__pmUnpinPDUBuf(pdubuf);
	return PM_ERR_IPC;
    }
    php->from = ntohl((unsigned int)php->from);
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_PDU) {
	int	j;
	char	*p;
	int	jend = PM_PDU_SIZE(php->len);
	char	strbuf[20];

        /* clear the padding bytes, lest they contain garbage */
	p = (char *)*result + php->len;
	while (p < (char *)*result + jend*sizeof(__pmPDU))
	    *p++ = '~';	/* buffer end */

	if (mypid == -1)
	    mypid = (int)getpid();
	fprintf(stderr, "[%d]pmGetPDU: %s fd=%d len=%d from=%d",
		mypid, __pmPDUTypeStr_r(php->type, strbuf, sizeof(strbuf)), fd, php->len, php->from);
	for (j = 0; j < jend; j++) {
	    if ((j % 8) == 0)
		fprintf(stderr, "\n%03d: ", j);
	    fprintf(stderr, "%8x ", (*result)[j]);
	}
	putc('\n', stderr);
    }
#endif
    if (php->type >= PDU_START && php->type <= PDU_FINISH)
	__pmPDUCntIn[php->type-PDU_START]++;

    /*
     * Note php points into the PDU buffer pdubuf that remains pinned
     * and php is returned via the result parameter ... see the
     * thread-safe comments above
     */
    return php->type;
}
Esempio n. 27
0
File: fetch.c Progetto: Aconex/pcp
int
pmFetch(int numpmid, pmID pmidlist[], pmResult **result)
{
    int		n;

    if (numpmid < 1) {
	n = PM_ERR_TOOSMALL;
	goto done;
    }

    if ((n = pmWhichContext()) >= 0) {
	__pmContext	*ctxp = __pmHandleToPtr(n);
	int		newcnt;
	pmID		*newlist = NULL;
	int		have_dm;

	if (ctxp == NULL) {
	    n = PM_ERR_NOCONTEXT;
	    goto done;
	}
	if (ctxp->c_type == PM_CONTEXT_LOCAL && PM_MULTIPLE_THREADS(PM_SCOPE_DSO_PMDA)) {
	    /* Local context requires single-threaded applications */
	    n = PM_ERR_THREAD;
	    PM_UNLOCK(ctxp->c_lock);
	    goto done;
	}

	/* for derived metrics, may need to rewrite the pmidlist */
	have_dm = newcnt = __pmPrepareFetch(ctxp, numpmid, pmidlist, &newlist);
	if (newcnt > numpmid) {
	    /* replace args passed into pmFetch */
	    numpmid = newcnt;
	    pmidlist = newlist;
	}

	if (ctxp->c_type == PM_CONTEXT_HOST) {
	    /*
	     * Thread-safe note
	     *
	     * Need to be careful here, because the PMCD changed protocol
	     * may mean several PDUs are returned, but __pmDecodeResult()
	     * may request more info from PMCD if pmDebug is set.
	     *
	     * So unlock ctxp->c_pmcd->pc_lock as soon as possible.
	     */
	    PM_LOCK(ctxp->c_pmcd->pc_lock);
	    if ((n = request_fetch(n, ctxp, numpmid, pmidlist)) >= 0) {
		int changed = 0;
		do {
		    __pmPDU	*pb;
		    int		pinpdu;

		    pinpdu = n = __pmGetPDU(ctxp->c_pmcd->pc_fd, ANY_SIZE,
					    ctxp->c_pmcd->pc_tout_sec, &pb);
		    if (n == PDU_RESULT) {
			PM_UNLOCK(ctxp->c_pmcd->pc_lock);
			n = __pmDecodeResult(pb, result);
		    }
		    else if (n == PDU_ERROR) {
			__pmDecodeError(pb, &n);
			if (n > 0)
			    /* PMCD state change protocol */
			    changed = n;
			else
			    PM_UNLOCK(ctxp->c_pmcd->pc_lock);
		    }
		    else {
			PM_UNLOCK(ctxp->c_pmcd->pc_lock);
			if (n != PM_ERR_TIMEOUT)
			    n = PM_ERR_IPC;
		    }
		    if (pinpdu > 0)
			__pmUnpinPDUBuf(pb);
		} while (n > 0);

		if (n == 0)
		    n |= changed;
	    }
	    else
		PM_UNLOCK(ctxp->c_pmcd->pc_lock);
	}
	else if (ctxp->c_type == PM_CONTEXT_LOCAL) {
	    n = __pmFetchLocal(ctxp, numpmid, pmidlist, result);
	}
	else {
	    /* assume PM_CONTEXT_ARCHIVE */
	    n = __pmLogFetch(ctxp, numpmid, pmidlist, result);
	    if (n >= 0 && (ctxp->c_mode & __PM_MODE_MASK) != PM_MODE_INTERP) {
		ctxp->c_origin.tv_sec = (__int32_t)(*result)->timestamp.tv_sec;
		ctxp->c_origin.tv_usec = (__int32_t)(*result)->timestamp.tv_usec;
	    }
	}

	/* process derived metrics, if any */
	if (have_dm) {
	    __pmFinishResult(ctxp, n, result);
	    if (newlist != NULL)
		free(newlist);
	}
	PM_UNLOCK(ctxp->c_lock);
    }

done:
#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_FETCH) {
	fprintf(stderr, "pmFetch returns ...\n");
	if (n > 0) {
	    fprintf(stderr, "PMCD state changes: agent(s)");
	    if (n & PMCD_ADD_AGENT) fprintf(stderr, " added");
	    if (n & PMCD_RESTART_AGENT) fprintf(stderr, " restarted");
	    if (n & PMCD_DROP_AGENT) fprintf(stderr, " dropped");
	    fputc('\n', stderr);
	}
	if (n >= 0)
	    __pmDumpResult(stderr, *result);
	else {
	    char	errmsg[PM_MAXERRMSGLEN];
	    fprintf(stderr, "Error: %s\n", pmErrStr_r(n, errmsg, sizeof(errmsg)));
	}
    }
#endif

    return n;
}
Esempio n. 28
0
File: err.c Progetto: scotte/pcp
char *
pmErrStr_r(int code, char *buf, int buflen)
{
    int		i;
#ifndef IS_MINGW
    static int	first = 1;
    static char	*unknown = NULL;
#else
    static char	unknown[] = "Unknown error";
#endif

    if (code == 0) {
	strncpy(buf, "No error", buflen);
	buf[buflen-1] = '\0';
	return buf;
    }

    /*
     * Is the code from a library wrapped by libpcp?  (e.g. NSS/SSL/SASL)
     * By good fortune, these libraries are using error codes that do not
     * overlap - by design for NSS/SSL/NSPR, and by sheer luck with SASL.
     */
    if (code < PM_ERR_NYI) {
#ifdef HAVE_SECURE_SOCKETS
#define DECODE_SECURE_SOCKETS_ERROR(c)	((c) - PM_ERR_NYI)	/* negative */
#define DECODE_SASL_SPECIFIC_ERROR(c)	((c) < -1000 ? 0 : (c))

	int error = DECODE_SECURE_SOCKETS_ERROR(code);
	if (DECODE_SASL_SPECIFIC_ERROR(error)) {
	    PM_LOCK(__pmLock_extcall);
	    pmsprintf(buf, buflen, "Authentication - %s", sasl_errstring(error, NULL, NULL));	/* THREADSAFE */
	    PM_UNLOCK(__pmLock_extcall);
	}
	else
	    strncpy(buf, PR_ErrorToString(error, PR_LANGUAGE_EN), buflen);
	buf[buflen-1] = '\0';
	return buf;
#endif
    }

#ifndef IS_MINGW
    PM_LOCK(err_lock);
    if (first) {
	/*
	 * reference message for an unrecognized error code.
	 * For IRIX, strerror() returns NULL in this case.
	 */
	strerror_x(-1, buf, buflen);
	if (buf[0] != '\0') {
	    /*
	     * For Linux et al, strip the last word, expected to be the
	     * error number as in ...
	     *    Unknown error -1
	     * or
	     *    Unknown error 4294967295
	     */
	    char *sp = strrchr(buf, ' ');
	    char *p;

	    if (sp != NULL) {
		sp++;
		if (*sp == '-') sp++;
		for (p = sp; *p != '\0'; p++) {
		    if (!isdigit((int)*p)) break;
		}

		if (*p == '\0') {
PM_FAULT_POINT("libpcp/" __FILE__ ":1", PM_FAULT_ALLOC);
		    *sp = '\0';
		    if ((unknown = strdup(buf)) != NULL)
			unknown[sp - buf] = '\0';
		}
	    }
	}
	first = 0;
    }
    PM_UNLOCK(err_lock);
    if (code < 0 && code > -PM_ERR_BASE) {
	/* intro(2) / errno(3) errors, maybe */
	strerror_x(-code, buf, buflen);
	if (unknown == NULL) {
	    if (buf[0] != '\0')
		return buf;
	}
	else {
	    /* The intention here is to catch variants of "Unknown
	     * error XXX" - in this case we're going to fail the
	     * stncmp() below, fall through and return a pcp error
	     * message, otherwise return the system error message
	     */
	    if (strncmp(buf, unknown, strlen(unknown)) != 0)
		return buf;
	}
    }
#else	/* WIN32 */
    if (code > -PM_ERR_BASE || code < -PM_ERR_NYI) {
	const char	*bp;
	if ((bp = wsastrerror(-code)) != NULL) {
	    strncpy(buf, bp, buflen);
	    buf[buflen-1] = '\0';
	}
	else {
	    /* No strerror_r in MinGW, so need to lock */
	    char	*tbp;
	    PM_LOCK(__pmLock_extcall);
	    tbp = strerror(-code);		/* THREADSAFE */
	    strncpy(buf, tbp, buflen);
	    buf[buflen-1] = '\0';
	    PM_UNLOCK(__pmLock_extcall);
	}

	if (strncmp(buf, unknown, strlen(unknown)) != 0)
	    return buf;
    }
#endif

    for (i = 0; errtab[i].err; i++) {
	if (errtab[i].err == code) {
	    strncpy(buf, errtab[i].errmess, buflen);
	    buf[buflen-1] = '\0';
	    return buf;
	}
    }

    /* failure */
    pmsprintf(buf, buflen, BADCODE,  code);
    return buf;
}
Esempio n. 29
0
static void
foo(FILE *f, char *fn, int i, void *closure)
{
    int		sts;
    int		numnames;
    int		j;
    int		leaf;
    pmID	pmids[NMETRIC];
    char	**names;
    char	*name;
    int		*stsset;
    char	strbuf[20];

    if ((sts = pmLookupName(NMETRIC-i, &namelist[i], pmids)) < 0) {
	if (sts != PM_ERR_NONLEAF) {
	    fprintf(f, "%s: %s ...: pmLookupName Error: %s\n", fn, namelist[i], pmErrStr(sts));
	    pthread_exit("botch");
	}
    }
    for (j = i; j < NMETRIC; j++) {
	if (pmids[j-i] != pmidlist[j]) {
	    fprintf(f, "%s: %s: Botch: expecting %s", fn, namelist[j], pmIDStr_r(pmidlist[j], strbuf, sizeof(strbuf)));
	    fprintf(f, ", got %s\n", pmIDStr_r(pmids[j-i], strbuf, sizeof(strbuf)));
	    pthread_exit("botch");
	}
    }
    fprintf(f, "%s: %s ... pmLookupName OK\n", fn, namelist[i]);

    fprintf(f, "%s: %s", fn, namelist[i]);
    if (pmidlist[i] != PM_ID_NULL) {
	/* leaf node in PMNS */
	if ((numnames = pmNameAll(pmidlist[i], &names)) < 0) {
	    fprintf(f, "\n%s: %s ...: pmNameAll Error: %s\n", fn, namelist[i], pmErrStr(numnames));
	    pthread_exit("botch");
	}
	for (j = 0; j < numnames; j++) {
	    if (strcmp(names[j], namelist[i]) == 0)
		break;
	}
	if (j == numnames) {
	    fprintf(f, "\n%s: %s: Botch: expecting %s, got {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)), namelist[i]);
	    __pmPrintMetricNames(f, numnames, names, ",");
	    fprintf(f, "}\n");
	    pthread_exit("botch");
	}
	fprintf(f, " pmNameAll OK");
	if ((sts = pmNameID(pmidlist[i], &name)) < 0) {
	    fprintf(f, "\n%s: %s ...: pmNameID Error: %s\n", fn, namelist[i], pmErrStr(sts));
	    pthread_exit("botch");
	}
	for (j = 0; j < numnames; j++) {
	    if (strcmp(name, names[j]) == 0)
		break;
	}
	if (j == numnames) {
	    fprintf(f, "\n%s: %s: Botch: expecting one of {", fn, pmIDStr_r(pmidlist[i], strbuf, sizeof(strbuf)));
	    __pmPrintMetricNames(f, numnames, names, ",");
	    fprintf(f, "}, got %s\n", name);
	    pthread_exit("botch");
	}
	free(names);
	free(name);
	fprintf(f, " pmNameID OK");
    }
    else {
	/* non-leaf node in PMNS */
	int	keep = 0;
	if ((sts = pmGetChildrenStatus(namelist[i], &names, &stsset)) < 0) {
	    fprintf(f, "\n%s: %s ...: pmGetChildrenStatus Error: %s\n", fn, namelist[i], pmErrStr(sts));
	    pthread_exit("botch");
	}
	leaf = 0;
	for (j = 0; j < sts; j++) {
	    if (stsset[j] == PMNS_LEAF_STATUS) leaf++;
	}
	PM_LOCK(chn_lock);
	if (leaf_chn[i] == -1) {
	    leaf_chn[i] = leaf;
	    nonleaf_chn[i] = sts - leaf;
	    chn[i] = names;
	    keep = 1;
	}
	else {
	    if (leaf != leaf_chn[i] || sts - leaf != nonleaf_chn[i]) {
		fprintf(f, "\n%s: %s: Botch: expecting %d leaf & %d non-leaf, got %d leaf & %d non-leaf\n", fn, namelist[i], leaf_chn[i], nonleaf_chn[i], leaf, sts - leaf);
		pthread_exit("botch");
	    }
	    for (j = 0; j < sts; j++) {
		if (strcmp(chn[i][j], names[j]) != 0) {
		    fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]);
		    PM_UNLOCK(chn_lock);
		    pthread_exit("botch");
		}
	    }
	}
	if (keep == 0) {
	    free(names);
	    names = NULL; /* silence coverity */
	}
	free(stsset);
	fprintf(f, " pmGetChildrenStatus OK");
	if ((sts = pmGetChildren(namelist[i], &names)) < 0) {
	    fprintf(f, "\n%s: %s ...: pmGetChildren Error: %s\n", fn, namelist[i], pmErrStr(sts));
	    PM_UNLOCK(chn_lock);
	    pthread_exit("botch");
	}
	if (sts != leaf_chn[i] + nonleaf_chn[i]) {
	    fprintf(f, "\n%s: %s: Botch: expecting %d children, got %d\n", fn, namelist[i], leaf_chn[i] + nonleaf_chn[i], sts);
	    PM_UNLOCK(chn_lock);
	    pthread_exit("botch");
	}
	for (j = 0; j < sts; j++) {
	    if (strcmp(chn[i][j], names[j]) != 0) {
		fprintf(f, "\n%s: %s: Botch: child[%d] expecting %s, got %s\n", fn, namelist[i], j, chn[i][j], names[j]);
		PM_UNLOCK(chn_lock);
		pthread_exit("botch");
	    }
	}
	PM_UNLOCK(chn_lock);
	free(names);
	fprintf(f, " pmGetChildren OK");
	*((int *)closure) = 0;
	if ((sts = pmTraversePMNS_r(namelist[i], dometric, closure)) < 0) {
	    fprintf(f, "\n%s: %s ...: pmTraversePMNS_r Error: %s\n", fn, namelist[i], pmErrStr(sts));
	    pthread_exit("botch");
	}
	if (sum_traverse[i] != *((int *)closure)) {
	    fprintf(f, "\n%s: %s: Botch: sum strlen(descendent names) expecting %d, got %d\n", fn, namelist[i], sum_traverse[i], *((int *)closure));
	    pthread_exit("botch");
	}
	fprintf(f, " pmTraversePMNS_r OK");
    }
    fputc('\n', f);

}
Esempio n. 30
0
File: connect.c Progetto: tongfw/pcp
int
__pmConnectPMCD(pmHostSpec *hosts, int nhosts, int ctxflags, __pmHashCtl *attrs)
{
    int		sts = -1;
    int		fd = -1;	/* Fd for socket connection to pmcd */
    int		*ports;
    int		nports;
    int		portIx;
    int		version = -1;
    int		proxyport;
    pmHostSpec	*proxyhost;

    static int first_time = 1;
    static pmHostSpec proxy;

    PM_INIT_LOCKS();
    PM_LOCK(__pmLock_libpcp);
    if (first_time) {
	/*
	 * One-trip check for use of pmproxy(1) in lieu of pmcd(1),
	 * and to extract the optional environment variables ...
	 * PMCD_PORT, PMPROXY_HOST and PMPROXY_PORT.
	 * We also check for the presense of a certificate database
	 * and load it up if either a user or system (global) DB is
	 * found.
	 */
	first_time = 0;
	load_pmcd_ports();
	load_proxy_hostspec(&proxy);
    }

    if (hosts[0].nports == 0) {
	nports = global_nports;
	ports = global_portlist;
    }
    else {
	nports = hosts[0].nports;
	ports = hosts[0].ports;
    }

    if (proxy.name == NULL && nhosts == 1) {
	const char *name = (const char *)hosts[0].name;

	/*
	 * no proxy, connecting directly to pmcd
	 */
	PM_UNLOCK(__pmLock_libpcp);

	sts = -1;
	/* Try connecting via the local unix domain socket, if requested and supported. */
	if (nports == PM_HOST_SPEC_NPORTS_LOCAL || nports == PM_HOST_SPEC_NPORTS_UNIX) {
#if defined(HAVE_STRUCT_SOCKADDR_UN)
	    if ((fd = __pmAuxConnectPMCDUnixSocket(name)) >= 0) {
		if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) {
		    __pmCloseSocket(fd);
		}
		else
		    sts = fd;
		portIx = -1; /* no port */
	    }
#endif
	    /*
	     * If the connection failed, or is not supported, and the protocol was 'local:',
	     * then try connecting to localhost via the default port(s).
	     */
	    if (sts < 0) {
		if (nports == PM_HOST_SPEC_NPORTS_LOCAL) {
		    name = "localhost";
		    nports = global_nports;
		    ports = global_portlist;
		    sts = -1; /* keep trying */
		}
		else
		    sts = -2; /* no more connection attempts. */
	    }
	}

	/* If still not connected, try via the given host name and ports, if requested. */
	if (sts == -1) {
	    for (portIx = 0; portIx < nports; portIx++) {
		if ((fd = __pmAuxConnectPMCDPort(name, ports[portIx])) >= 0) {
		    if ((sts = __pmConnectHandshake(fd, name, ctxflags, attrs)) < 0) {
			__pmCloseSocket(fd);
		    }
		    else
			/* success */
			break;
		}
		else
		    sts = fd;
	    }
	}

	if (sts < 0) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_CONTEXT) {
		char	errmsg[PM_MAXERRMSGLEN];
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=",
		   hosts[0].name);
		for (portIx = 0; portIx < nports; portIx++) {
		    if (portIx == 0) fprintf(stderr, "%d", ports[portIx]);
		    else fprintf(stderr, ",%d", ports[portIx]);
		}
		fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	    }
#endif
	    return sts;
	}

#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_CONTEXT) {
	    if (portIx >= 0) {
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection port=%d fd=%d PDU version=%u\n",
			hosts[0].name, ports[portIx], fd, __pmVersionIPC(fd));
	    }
	    else {
		fprintf(stderr, "__pmConnectPMCD(%s): pmcd connection path=%s fd=%d PDU version=%u\n",
			hosts[0].name, name, fd, __pmVersionIPC(fd));
	    }
	    __pmPrintIPC();
	}
#endif

	return fd;
    }

    /*
     * connecting to pmproxy, and then to pmcd ... not a direct
     * connection to pmcd
     */
    proxyhost = (nhosts > 1) ? &hosts[1] : &proxy;
    proxyport = (proxyhost->nports > 0) ? proxyhost->ports[0] : PROXY_PORT;

    for (portIx = 0; portIx < nports; portIx++) {
	fd = __pmAuxConnectPMCDPort(proxyhost->name, proxyport);
	if (fd < 0) {
#ifdef PCP_DEBUG
	    if (pmDebug & DBG_TRACE_CONTEXT) {
		char	errmsg[PM_MAXERRMSGLEN];
		fprintf(stderr, "__pmConnectPMCD(%s): proxy to %s port=%d failed: %s \n",
			hosts[0].name, proxyhost->name, proxyport, pmErrStr_r(-neterror(), errmsg, sizeof(errmsg)));
	    }
#endif
	    PM_UNLOCK(__pmLock_libpcp);
	    return fd;
	}
	if ((sts = version = negotiate_proxy(fd, hosts[0].name, ports[portIx])) < 0)
	    __pmCloseSocket(fd);
	else if ((sts = __pmConnectHandshake(fd, proxyhost->name, ctxflags, attrs)) < 0)
	    __pmCloseSocket(fd);
	else
	    /* success */
	    break;
    }

    if (sts < 0) {
#ifdef PCP_DEBUG
	if (pmDebug & DBG_TRACE_CONTEXT) {
	    char	errmsg[PM_MAXERRMSGLEN];
	    fprintf(stderr, "__pmConnectPMCD(%s): proxy connection to %s port=",
			hosts[0].name, proxyhost->name);
	    for (portIx = 0; portIx < nports; portIx++) {
		if (portIx == 0) fprintf(stderr, "%d", ports[portIx]);
		else fprintf(stderr, ",%d", ports[portIx]);
	    }
	    fprintf(stderr, " failed: %s\n", pmErrStr_r(sts, errmsg, sizeof(errmsg)));
	}
#endif
	PM_UNLOCK(__pmLock_libpcp);
	return sts;
    }

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_CONTEXT) {
	fprintf(stderr, "__pmConnectPMCD(%s): proxy connection host=%s port=%d fd=%d version=%d\n",
	    hosts[0].name, proxyhost->name, ports[portIx], fd, version);
    }
#endif

    PM_UNLOCK(__pmLock_libpcp);
    return fd;
}