Example #1
0
int
__pmSendLabelReq(int fd, int from, int ident, int type)
{
    label_req_t	*pp;
    int		sts;
    int		nid;

    if (type & PM_LABEL_CONTEXT)
	nid = htonl(PM_ID_NULL);
    else if (type & PM_LABEL_DOMAIN)
	nid = htonl(ident);
    else if (type & PM_LABEL_INDOM)
	nid = __htonpmInDom((pmInDom)ident);
    else if (type & (PM_LABEL_CLUSTER|PM_LABEL_ITEM|PM_LABEL_INSTANCES))
	nid = __htonpmID((pmID)ident);
    else
	return -EINVAL;

    if ((pp = (label_req_t *)__pmFindPDUBuf(sizeof(label_req_t))) == NULL)
	return -oserror();
    pp->hdr.len = sizeof(label_req_t);
    pp->hdr.type = PDU_LABEL_REQ;
    pp->hdr.from = from;
    pp->ident = nid;
    pp->type = htonl(type);

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #2
0
int
__pmSendCreds(int fd, int from, int credcount, const __pmCred *credlist)
{
    size_t	need;
    creds_t	*pp;
    int		i;
    int		sts;

    if (credcount <= 0 || credcount > LIMIT_CREDS || credlist == NULL)
	return PM_ERR_IPC;

    need = sizeof(creds_t) + ((credcount-1) * sizeof(__pmCred));
    if ((pp = (creds_t *)__pmFindPDUBuf((int)need)) == NULL)
	return -oserror();
    pp->hdr.len = (int)need;
    pp->hdr.type = PDU_CREDS;
    pp->hdr.from = from;
    pp->numcreds = htonl(credcount);
    if (pmDebugOptions.context)
	for (i = 0; i < credcount; i++)
	    fprintf(stderr, "__pmSendCreds: #%d = %x\n", i, *(unsigned int*)&(credlist[i]));
    /* swab and fix bitfield order */
    for (i = 0; i < credcount; i++)
	pp->credlist[i] = __htonpmCred(credlist[i]);

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #3
0
int
__pmSendInstanceReq(int fd, int from, const __pmTimeval *when, pmInDom indom, 
		    int inst, const char *name)
{
    instance_req_t	*pp;
    int			need;
    int			sts;

    need = sizeof(instance_req_t) - sizeof(int);
    if (name != NULL)
	need += PM_PDU_SIZE_BYTES(strlen(name));
    if ((pp = (instance_req_t *)__pmFindPDUBuf(need)) == NULL)
	return -oserror();
    pp->hdr.len = need;
    pp->hdr.type = PDU_INSTANCE_REQ;
    pp->hdr.from = from;
    pp->when.tv_sec = htonl((__int32_t)when->tv_sec);
    pp->when.tv_usec = htonl((__int32_t)when->tv_usec);
    pp->indom = __htonpmInDom(indom);
    pp->inst = htonl(inst);
    if (name == NULL)
	pp->namelen = 0;
    else {
	pp->namelen = (int)strlen(name);
	memcpy((void *)pp->name, (void *)name, pp->namelen);
	if ((pp->namelen % sizeof(__pmPDU)) != 0) {
            /* clear the padding bytes, lest they contain garbage */
	    int	pad;
	    char	*padp = pp->name + pp->namelen;

	    for (pad = sizeof(__pmPDU) - 1; pad >= (pp->namelen % sizeof(__pmPDU)); pad--)
		*padp++ = '~';	/* buffer end */
	}
	pp->namelen = htonl(pp->namelen);
    }

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #4
0
int
__pmSendDesc(int fd, int ctx, pmDesc *desc)
{
    desc_t	*pp;
    int		sts;

    if ((pp = (desc_t *)__pmFindPDUBuf(sizeof(desc_t))) == NULL)
	return -oserror();

    pp->hdr.len = sizeof(desc_t);
    pp->hdr.type = PDU_DESC;
    pp->hdr.from = ctx;
    pp->desc.type = htonl(desc->type);
    pp->desc.sem = htonl(desc->sem);
    pp->desc.indom = __htonpmInDom(desc->indom);
    pp->desc.units = __htonpmUnits(desc->units);
    pp->desc.pmid = __htonpmID(desc->pmid);

    sts =__pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #5
0
int
__pmSendAttr(int fd, int from, int attr, const char *value, int length)
{
    size_t	need;
    attr_t	*pp;
    int		i;
    int		sts;

    if (length < 0 || length >= LIMIT_ATTR_PDU)
	return PM_ERR_IPC;

    need = (sizeof(*pp) - sizeof(pp->value)) + length;
    if ((pp = (attr_t *)__pmFindPDUBuf((int)need)) == NULL)
	return -oserror();
    pp->hdr.len = (int)need;
    pp->hdr.type = PDU_ATTR;
    pp->hdr.from = from;
    pp->attr = htonl(attr);
    memcpy(&pp->value, value, length);

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_ATTR) {
	char buffer[LIMIT_ATTR_PDU];
	for (i = 0; i < length; i++)
	    buffer[i] = isprint((int)value[i]) ? value[i] : '.';
	buffer[length] = buffer[LIMIT_ATTR_PDU-1] = '\0';
	if (attr)
	    fprintf(stderr, "__pmSendAttr [len=%d]: attr=0x%x value=\"%s\"\n",
			    length, attr, buffer);
	else
	    fprintf(stderr, "__pmSendAttr [len=%d]: payload=\"%s\"\n",
			    length, buffer);
    }
#endif

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #6
0
int
__pmSendText(int fd, int ctx, int ident, const char *buffer)
{
    text_t	*pp;
    size_t	need;
    size_t	len = strlen(buffer);
    int		sts;

    need = sizeof(text_t) - sizeof(pp->buffer) + PM_PDU_SIZE_BYTES(len);
    if ((pp = (text_t *)__pmFindPDUBuf((int)need)) == NULL)
	return -oserror();
    pp->hdr.len = (int)need;
    pp->hdr.type = PDU_TEXT;
    pp->hdr.from = ctx;
    /*
     * Note: ident argument must already be in network byte order.
     * The caller has to do this because the type of ident is not
     * part of the transmitted PDU_TEXT pdu; ident may be either
     * a pmID or pmInDom, and so the caller must use either
     * __htonpmID or __htonpmInDom (respectively).
     */
    pp->ident = ident;
    pp->buflen = htonl(len);
    memcpy((void *)pp->buffer, (void *)buffer, len);
    if (len % sizeof(__pmPDU) != 0) {
	/* clear the padding bytes, lest they contain garbage */
	int	pad;
	char	*padp = pp->buffer + len;
	for (pad = sizeof(__pmPDU) - 1; pad >= (len % sizeof(__pmPDU)); pad--)
	    *padp++ = '~';	/* buffer end */
    }

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #7
0
int
__pmSendTextReq(int fd, int from, int ident, int type)
{
    text_req_t	*pp;
    int		sts;

    if ((pp = (text_req_t *)__pmFindPDUBuf(sizeof(text_req_t))) == NULL)
	return -oserror();
    pp->hdr.len = sizeof(text_req_t);
    pp->hdr.type = PDU_TEXT_REQ;
    pp->hdr.from = from;

    if (type & PM_TEXT_PMID)
	pp->ident = __htonpmID((pmID)ident);
    else /* (type & PM_TEXT_INDOM) */
	pp->ident = __htonpmInDom((pmInDom)ident);

    type &= ~PM_TEXT_DIRECT;
    pp->type = htonl(type);

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #8
0
int
__pmSendDescReq(int fd, int from, pmID pmid)
{
    desc_req_t	*pp;
    int		sts;

    if ((pp = (desc_req_t *)__pmFindPDUBuf(sizeof(desc_req_t))) == NULL)
	return -oserror();
    pp->hdr.len = sizeof(desc_req_t);
    pp->hdr.type = PDU_DESC_REQ;
    pp->hdr.from = from;
    pp->pmid = __htonpmID(pmid);

#ifdef DESPERATE
    {
	char	strbuf[20];
	fprintf(stderr, "__pmSendDescReq: converted 0x%08x (%s) to 0x%08x\n", pmid, pmIDStr_r(pmid, strbuf, sizeof(strbuf)), pp->pmid);
    }
#endif

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #9
0
File: pdu.c Project: 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;
}
Example #10
0
int
__pmSendLabel(int fd, int from, int ident, int type, pmLabelSet *sets, int nsets)
{
    size_t	labels_offset;
    size_t	labels_need;
    size_t	json_offset;
    size_t	json_need;
    labelset_t	*lsp;
    labels_t	*pp;
    pmLabel	*lp;
    int		sts;
    int		i, j;

    if (nsets < 0)
	return -EINVAL;
    labels_need = sizeof(labels_t) + (sizeof(labelset_t) * (nsets - 1));
    json_need = 0;
    for (i = 0; i < nsets; i++) {
	json_need += sets[i].jsonlen;
	if (sets[i].nlabels > 0)
	    labels_need += sets[i].nlabels * sizeof(pmLabel);
    }

    if ((pp = (labels_t *)__pmFindPDUBuf((int)labels_need + json_need)) == NULL)
	return -oserror();

    pp->hdr.len = (int)(labels_need + json_need);
    pp->hdr.type = PDU_LABEL;
    pp->hdr.from = from;

    if (type & PM_LABEL_DOMAIN)
	pp->ident = htonl(ident);
    else if (type & (PM_LABEL_CLUSTER | PM_LABEL_ITEM | PM_LABEL_INSTANCES))
	pp->ident = __htonpmID((pmID)ident);
    else if (type & PM_LABEL_INDOM)
	pp->ident = __htonpmInDom((pmInDom)ident);
    else
	pp->ident = htonl(PM_ID_NULL);

    pp->type = htonl(type);
    pp->padding = 0;
    pp->nsets = htonl(nsets);

    labels_offset = (char *)&pp->sets[0] - (char *)pp;
    json_offset = labels_need;	/* JSONB immediately follows labelsets */

    for (i = 0; i < nsets; i++) {
	lsp = (labelset_t *)((char *)pp + labels_offset);
	lsp->inst = htonl(sets[i].inst);
	lsp->nlabels = htonl(sets[i].nlabels);
	lsp->json = htonl(json_offset);
	lsp->jsonlen = htonl(sets[i].jsonlen);

	if (sets[i].nlabels > 0) {
	    for (j = 0; j < sets[i].nlabels; j++) {
		lp = &lsp->labels[j];
		lp->name = htons(sets[i].labels[j].name);
		lp->namelen = sets[i].labels[j].namelen;	/* byte copy */
		lp->flags = sets[i].labels[j].flags;		/* byte copy */
		lp->value = htons(sets[i].labels[j].value);
		lp->valuelen = htons(sets[i].labels[j].valuelen);
	    }
	    labels_offset += sets[i].nlabels * sizeof(pmLabel);
	}
	labels_offset += sizeof(labelset_t);

	if (sets[i].jsonlen) {
	    memcpy((char *)pp + json_offset, sets[i].json, sets[i].jsonlen);
	    json_offset += sets[i].jsonlen;
	}
    }

    if (pmDebugOptions.labels)
	DumpLabelSets("__pmSendLabel", ident, type, sets, nsets);

    sts = __pmXmitPDU(fd, (__pmPDU *)pp);
    __pmUnpinPDUBuf(pp);
    return sts;
}
Example #11
0
int
__pmSendProfile(int fd, int from, int ctxnum, __pmProfile *instprof)
{
    __pmInDomProfile	*prof, *p_end;
    profile_t		*pduProfile;
    instprof_t		*pduInstProf;
    __pmPDU		*p;
    size_t		need;
    __pmPDU		*pdubuf;
    int			sts;

    /* work out how much space we need and then alloc a pdu buf */
    need = sizeof(profile_t) + instprof->profile_len * sizeof(instprof_t);
    for (prof = instprof->profile, p_end = prof + instprof->profile_len;
	 prof < p_end;
	 prof++)
	need += prof->instances_len * sizeof(int);

    if ((pdubuf = __pmFindPDUBuf((int)need)) == NULL)
	return -oserror();

    p = (__pmPDU *)pdubuf;

    /* First the profile itself */
    pduProfile = (profile_t *)p;
    pduProfile->hdr.len = (int)need;
    pduProfile->hdr.type = PDU_PROFILE;
    /* 
     * note: context id may be sent twice due to protocol evolution and
     * backwards compatibility issues
     */
    pduProfile->hdr.from = from;
    pduProfile->ctxnum = htonl(ctxnum);
    pduProfile->g_state = htonl(instprof->state);
    pduProfile->numprof = htonl(instprof->profile_len);
    pduProfile->pad = 0;

    p += sizeof(profile_t) / sizeof(__pmPDU);

    if (instprof->profile_len) {
	/* Next all the profile entries (if any) in one block */
	for (prof = instprof->profile, p_end = prof + instprof->profile_len;
	     prof < p_end;
	     prof++) {
	    pduInstProf = (instprof_t *)p;
	    pduInstProf->indom = __htonpmInDom(prof->indom);
	    pduInstProf->state = htonl(prof->state);
	    pduInstProf->numinst = htonl(prof->instances_len);
	    pduInstProf->pad = 0;
	    p += sizeof(instprof_t) / sizeof(__pmPDU);
	}

	/* and then all the instances */
	for (prof = instprof->profile, p_end = prof+instprof->profile_len;
	     prof < p_end;
	     prof++) {
	    int j;

	    /* and then the instances themselves (if any) */
	    for (j = 0; j < prof->instances_len; j++, p++)
		*p = htonl(prof->instances[j]);
	}
    }
    sts = __pmXmitPDU(fd, pdubuf);
    __pmUnpinPDUBuf(pdubuf);
    return sts;
}
Example #12
0
int
__pmSendInstance(int fd, int from, __pmInResult *result)
{
    instance_t	*rp;
    instlist_t		*ip;
    int			need;
    int			i;
    int			j;
    int			sts;

#ifdef PCP_DEBUG
    if (pmDebug & DBG_TRACE_INDOM)
	__pmDumpInResult(stderr, result);
#endif

    need = sizeof(*rp) - sizeof(rp->rest);
    /* instlist_t + name rounded up to a __pmPDU boundary */
    for (i = 0; i < result->numinst; i++) {
	need += sizeof(*ip) - sizeof(ip->name);
	if (result->namelist != NULL)
	    need += PM_PDU_SIZE_BYTES(strlen(result->namelist[i]));
    }

    if ((rp = (instance_t *)__pmFindPDUBuf(need)) == NULL)
	return -oserror();
    rp->hdr.len = need;
    rp->hdr.type = PDU_INSTANCE;
    rp->hdr.from = from;
    rp->indom = __htonpmInDom(result->indom);
    rp->numinst = htonl(result->numinst);

    for (i = j = 0; i < result->numinst; i++) {
	ip = (instlist_t *)&rp->rest[j/sizeof(__pmPDU)];
	if (result->instlist != NULL)
	    ip->inst = htonl(result->instlist[i]);
	else
	    /* weird, but this is going to be ignored at the other end */
	    ip->inst = htonl(PM_IN_NULL);
	if (result->namelist != NULL) {
	    ip->namelen = (int)strlen(result->namelist[i]);
	    memcpy((void *)ip->name, (void *)result->namelist[i], ip->namelen);
	    if ((ip->namelen % sizeof(__pmPDU)) != 0) {
                /* clear the padding bytes, lest they contain garbage */
		int	pad;
		char	*padp = ip->name + ip->namelen;
		for (pad = sizeof(__pmPDU) - 1; pad >= (ip->namelen % sizeof(__pmPDU)); pad--)
		    *padp++ = '~';	/* buffer end */
	    }
	    j += sizeof(*ip) - sizeof(ip->name) + PM_PDU_SIZE_BYTES(ip->namelen);
	    ip->namelen = htonl(ip->namelen);
	}
	else {
	    ip->namelen = 0;
	    j += sizeof(*ip) - sizeof(ip->name);
	}
    }

    sts = __pmXmitPDU(fd, (__pmPDU *)rp);
    __pmUnpinPDUBuf(rp);
    return sts;
}