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; }
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; }
static int VerifyClient(ClientInfo *cp, __pmPDU *pb) { int i, sts, flags = 0, sender = 0, credcount = 0; __pmPDUHdr *header = (__pmPDUHdr *)pb; __pmHashCtl attrs = { 0 }; /* TODO */ __pmCred *credlist; /* first check that this is a credentials PDU */ if (header->type != PDU_CREDS) return PM_ERR_IPC; /* now decode it and if secure connection requested, set it up */ if ((sts = __pmDecodeCreds(pb, &sender, &credcount, &credlist)) < 0) return sts; for (i = 0; i < credcount; i++) { if (credlist[i].c_type == CVERSION) { __pmVersionCred *vcp = (__pmVersionCred *)&credlist[i]; flags = vcp->c_flags; break; } } if (credlist != NULL) free(credlist); /* need to ensure both the pmcd and client channel use flags */ if (sts >= 0 && flags) sts = __pmSecureServerHandshake(cp->fd, flags, &attrs); /* send credentials PDU through to pmcd now (order maintained) */ if (sts >= 0) sts = __pmXmitPDU(cp->pmcd_fd, pb); /* * finally perform any additional handshaking needed with pmcd. * Do not initialize NSS again. */ if (sts >= 0 && flags) sts = __pmSecureClientHandshake(cp->pmcd_fd, flags | PDU_FLAG_NO_NSS_INIT, hostname, &attrs); return sts; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/* Determine which clients (if any) have sent data to the server and handle it * as required. */ void HandleInput(__pmFdSet *fdsPtr) { int i, sts; __pmPDU *pb; ClientInfo *cp; /* input from clients */ for (i = 0; i < nClients; i++) { if (!client[i].status.connected || !__pmFD_ISSET(client[i].fd, fdsPtr)) continue; cp = &client[i]; sts = __pmGetPDU(cp->fd, LIMIT_SIZE, 0, &pb); if (sts <= 0) { CleanupClient(cp, sts); continue; } /* We *must* see a credentials PDU as the first PDU */ if (!cp->status.allowed) { sts = VerifyClient(cp, pb); __pmUnpinPDUBuf(pb); if (sts < 0) { CleanupClient(cp, sts); continue; } cp->status.allowed = 1; continue; } sts = __pmXmitPDU(cp->pmcd_fd, pb); __pmUnpinPDUBuf(pb); if (sts <= 0) { CleanupClient(cp, sts); continue; } } /* input from pmcds */ for (i = 0; i < nClients; i++) { if (!client[i].status.connected || !__pmFD_ISSET(client[i].pmcd_fd, fdsPtr)) continue; cp = &client[i]; sts = __pmGetPDU(cp->pmcd_fd, ANY_SIZE, 0, &pb); if (sts <= 0) { CleanupClient(cp, sts); continue; } sts = __pmXmitPDU(cp->fd, pb); __pmUnpinPDUBuf(pb); if (sts <= 0) { CleanupClient(cp, sts); continue; } } }
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; }
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; }