int __pmDecodeLabelReq(__pmPDU *pdubuf, int *ident, int *otype) { label_req_t *pp; char *pduend; int type; pp = (label_req_t *)pdubuf; pduend = (char *)pdubuf + pp->hdr.len; if (pduend - (char*)pp < sizeof(label_req_t)) return PM_ERR_IPC; type = *otype = ntohl(pp->type); if (type & PM_LABEL_DOMAIN) *ident = ntohl(pp->ident); else if (type & (PM_LABEL_CLUSTER|PM_LABEL_ITEM|PM_LABEL_INSTANCES)) *ident = __ntohpmID(pp->ident); else if (type & PM_LABEL_INDOM) *ident = __ntohpmInDom(pp->ident); else *ident = PM_ID_NULL; return 0; }
int __pmDecodeInstanceReq(__pmPDU *pdubuf, __pmTimeval *when, pmInDom *indom, int *inst, char **name) { instance_req_t *pp; char *pdu_end; int namelen; pp = (instance_req_t *)pdubuf; pdu_end = (char *)pdubuf + pp->hdr.len; if (pdu_end - (char *)pp < sizeof(instance_req_t) - sizeof(pp->name)) return PM_ERR_IPC; when->tv_sec = ntohl(pp->when.tv_sec); when->tv_usec = ntohl(pp->when.tv_usec); *indom = __ntohpmInDom(pp->indom); *inst = ntohl(pp->inst); namelen = ntohl(pp->namelen); if (namelen > 0) { if (namelen >= INT_MAX - 1 || namelen > pp->hdr.len) return PM_ERR_IPC; if (pdu_end - (char *)pp < sizeof(instance_req_t) - sizeof(pp->name) + namelen) return PM_ERR_IPC; if ((*name = (char *)malloc(namelen+1)) == NULL) return -oserror(); strncpy(*name, pp->name, namelen); (*name)[namelen] = '\0'; } else if (namelen < 0) { return PM_ERR_IPC; } else { *name = NULL; } return 0; }
int __pmDecodeDesc(__pmPDU *pdubuf, pmDesc *desc) { desc_t *pp; char *pduend; pp = (desc_t *)pdubuf; pduend = (char *)pdubuf + pp->hdr.len; if (pduend - (char*)pp != sizeof(desc_t)) return PM_ERR_IPC; desc->type = ntohl(pp->desc.type); desc->sem = ntohl(pp->desc.sem); desc->indom = __ntohpmInDom(pp->desc.indom); desc->units = __ntohpmUnits(pp->desc.units); desc->pmid = __ntohpmID(pp->desc.pmid); return 0; }
int __pmDecodeTextReq(__pmPDU *pdubuf, int *ident, int *type) { text_req_t *pp; char *pduend; pp = (text_req_t *)pdubuf; pduend = (char *)pdubuf + pp->hdr.len; if (pduend - (char*)pp < sizeof(text_req_t)) return PM_ERR_IPC; *type = ntohl(pp->type); if ((*type) & PM_TEXT_PMID) *ident = __ntohpmID(pp->ident); else if ((*type) & PM_TEXT_INDOM) *ident = __ntohpmInDom(pp->ident); else *ident = PM_INDOM_NULL; return 0; }
/* * load _all_ of the hashed pmDesc and __pmLogInDom structures from the metadata * log file -- used at the initialization (NewContext) of an archive * If version 2 then * load all the names from the meta data and create l_pmns. */ int __pmLogLoadMeta(__pmLogCtl *lcp) { int rlen; int check; pmDesc *dp; int sts = 0; __pmLogHdr h; FILE *f = lcp->l_mdfp; int version2 = ((lcp->l_label.ill_magic & 0xff) == PM_LOG_VERS02); int numpmid = 0; int n; if (version2) { if ((sts = __pmNewPMNS(&(lcp->l_pmns))) < 0) { goto end; } } fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); for ( ; ; ) { n = (int)fread(&h, 1, sizeof(__pmLogHdr), f); /* swab hdr */ h.len = ntohl(h.len); h.type = ntohl(h.type); if (n != sizeof(__pmLogHdr) || h.len <= 0) { if (feof(f)) { clearerr(f); sts = 0; goto end; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: header read -> %d: expected: %d\n", n, (int)sizeof(__pmLogHdr)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: record len=%d, type=%d @ offset=%d\n", h.len, h.type, (int)(ftell(f) - sizeof(__pmLogHdr))); } #endif rlen = h.len - (int)sizeof(__pmLogHdr) - (int)sizeof(int); if (h.type == TYPE_DESC) { numpmid++; if ((dp = (pmDesc *)malloc(sizeof(pmDesc))) == NULL) { sts = -errno; goto end; } if ((n = (int)fread(dp, 1, sizeof(pmDesc), f)) != sizeof(pmDesc)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: pmDesc read -> %d: expected: %d\n", n, (int)sizeof(pmDesc)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab desc */ dp->type = ntohl(dp->type); dp->sem = ntohl(dp->sem); dp->indom = __ntohpmInDom(dp->indom); dp->units = __ntohpmUnits(dp->units); dp->pmid = __ntohpmID(dp->pmid); } if ((sts = __pmHashAdd((int)dp->pmid, (void *)dp, &lcp->l_hashpmid)) < 0) goto end; if (version2) { char name[MAXPATHLEN]; int numnames; int i; int len; /* read in the names & store in PMNS tree ... */ if ((n = (int)fread(&numnames, 1, sizeof(numnames), f)) != sizeof(numnames)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: numnames read -> %d: expected: %d\n", n, (int)sizeof(numnames)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab numnames */ numnames = ntohl(numnames); } for (i = 0; i < numnames; i++) { if ((n = (int)fread(&len, 1, sizeof(len), f)) != sizeof(len)) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: len name[%d] read -> %d: expected: %d\n", i, n, (int)sizeof(len)); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } else { /* swab len */ len = ntohl(len); } if ((n = (int)fread(name, 1, len, f)) != len) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: name[%d] read -> %d: expected: %d\n", i, n, len); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } name[len] = '\0'; #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: PMID: %s name: %s\n", pmIDStr(dp->pmid), name); } #endif if ((sts = __pmAddPMNSNode(lcp->l_pmns, dp->pmid, name)) < 0) { /* * If we see a duplicate PMID, its a recoverable error. * We wont be able to see all of the data in the log, but * its better to provide access to some rather than none, * esp. when only one or two metric IDs may be corrupted * in this way (which we may not be interested in anyway). */ if (sts != PM_ERR_PMID) goto end; sts = 0; } }/*for*/ }/*version2*/ } else if (h.type == TYPE_INDOM) { int *tbuf; pmInDom indom; __pmTimeval *when; int numinst; int *instlist; char **namelist; char *namebase; int *stridx; int i; int k; int allinbuf; if ((tbuf = (int *)malloc(rlen)) == NULL) { sts = -errno; goto end; } if ((n = (int)fread(tbuf, 1, rlen, f)) != rlen) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: indom read -> %d: expected: %d\n", n, rlen); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } k = 0; when = (__pmTimeval *)&tbuf[k]; when->tv_sec = ntohl(when->tv_sec); when->tv_usec = ntohl(when->tv_usec); k += sizeof(*when)/sizeof(int); indom = __ntohpmInDom((unsigned int)tbuf[k++]); numinst = ntohl(tbuf[k++]); if (numinst > 0) { instlist = &tbuf[k]; k += numinst; stridx = &tbuf[k]; #if defined(HAVE_32BIT_PTR) namelist = (char **)stridx; allinbuf = 1; /* allocation is all in tbuf */ #else allinbuf = 0; /* allocation for namelist + tbuf */ /* need to allocate to hold the pointers */ namelist = (char **)malloc(numinst*sizeof(char*)); if (namelist == NULL) { sts = -errno; goto end; } #endif k += numinst; namebase = (char *)&tbuf[k]; for (i = 0; i < numinst; i++) { instlist[i] = ntohl(instlist[i]); namelist[i] = &namebase[ntohl(stridx[i])]; } } else { /* no instances, or an error */ instlist = NULL; namelist = NULL; } if ((sts = addindom(lcp, indom, when, numinst, instlist, namelist, tbuf, allinbuf)) < 0) goto end; } else fseek(f, (long)rlen, SEEK_CUR); n = (int)fread(&check, 1, sizeof(check), f); check = ntohl(check); if (n != sizeof(check) || h.len != check) { #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_LOGMETA) { fprintf(stderr, "__pmLogLoadMeta: trailer read -> %d or len=%d: expected %d @ offset=%d\n", n, check, h.len, (int)(ftell(f) - sizeof(check))); } #endif if (ferror(f)) { clearerr(f); sts = -errno; } else sts = PM_ERR_LOGREC; goto end; } }/*for*/ end: fseek(f, (long)(sizeof(__pmLogLabel) + 2*sizeof(int)), SEEK_SET); if (version2 && sts == 0) { __pmFixPMNSHashTab(lcp->l_pmns, numpmid, 1); } return sts; }
int __pmDecodeProfile(__pmPDU *pdubuf, int *ctxnump, __pmProfile **resultp) { __pmProfile *instprof; __pmInDomProfile *prof, *p_end; profile_t *pduProfile; instprof_t *pduInstProf; __pmPDU *p = (__pmPDU *)pdubuf; char *pdu_end; int ctxnum; int sts = 0; /* First the profile */ pduProfile = (profile_t *)pdubuf; pdu_end = (char*)pdubuf + pduProfile->hdr.len; if (pdu_end - (char*)pdubuf < sizeof(profile_t)) return PM_ERR_IPC; ctxnum = ntohl(pduProfile->ctxnum); if (ctxnum < 0 || ctxnum > LIMIT_CTXNUM) return PM_ERR_IPC; if ((instprof = (__pmProfile *)malloc(sizeof(__pmProfile))) == NULL) return -oserror(); instprof->state = ntohl(pduProfile->g_state); instprof->profile = NULL; instprof->profile_len = ntohl(pduProfile->numprof); if (instprof->profile_len < 0) { sts = PM_ERR_IPC; goto fail; } p += sizeof(profile_t) / sizeof(__pmPDU); if (instprof->profile_len > 0) { if (instprof->profile_len >= INT_MAX / sizeof(__pmInDomProfile) || instprof->profile_len >= pduProfile->hdr.len) { sts = PM_ERR_IPC; goto fail; } if ((instprof->profile = (__pmInDomProfile *)calloc( instprof->profile_len, sizeof(__pmInDomProfile))) == NULL) { sts = -oserror(); goto fail; } /* Next the profiles (if any) all together */ for (prof = instprof->profile, p_end = prof + instprof->profile_len; prof < p_end; prof++) { if ((char *)p >= pdu_end) { sts = PM_ERR_IPC; goto fail; } pduInstProf = (instprof_t *)p; prof->indom = __ntohpmInDom(pduInstProf->indom); prof->state = ntohl(pduInstProf->state); prof->instances = NULL; prof->instances_len = ntohl(pduInstProf->numinst); p += sizeof(instprof_t) / sizeof(__pmPDU); } /* Finally, all the instances for all profiles (if any) together */ for (prof = instprof->profile, p_end = prof+instprof->profile_len; prof < p_end; prof++) { int j; if (prof->instances_len > 0) { if (prof->instances_len >= INT_MAX / sizeof(int) || prof->instances_len >= pduProfile->hdr.len) { sts = PM_ERR_IPC; goto fail; } prof->instances = (int *)calloc(prof->instances_len, sizeof(int)); if (prof->instances == NULL) { sts = -oserror(); goto fail; } for (j = 0; j < prof->instances_len; j++, p++) { if ((char *)p >= pdu_end) { sts = PM_ERR_IPC; goto fail; } prof->instances[j] = ntohl(*p); } } else if (prof->instances_len < 0) { sts = PM_ERR_IPC; goto fail; } else { prof->instances = NULL; } } } else { instprof->profile = NULL; } *resultp = instprof; *ctxnump = ctxnum; return 0; fail: if (instprof != NULL) { if (instprof->profile != NULL) { for (prof = instprof->profile, p_end = prof+instprof->profile_len; prof < p_end; prof++) { if (prof->instances != NULL) free(prof->instances); } free(instprof->profile); } free(instprof); } return sts; }
int __pmDecodeInstance(__pmPDU *pdubuf, __pmInResult **result) { int i; int j; instance_t *rp; instlist_t *ip; __pmInResult *res; int sts; char *p; char *pdu_end; int keep_instlist; int keep_namelist; rp = (instance_t *)pdubuf; pdu_end = (char *)pdubuf + rp->hdr.len; if (pdu_end - (char *)pdubuf < sizeof(instance_t) - sizeof(__pmPDU)) return PM_ERR_IPC; if ((res = (__pmInResult *)malloc(sizeof(*res))) == NULL) return -oserror(); res->instlist = NULL; res->namelist = NULL; res->indom = __ntohpmInDom(rp->indom); res->numinst = ntohl(rp->numinst); if (res->numinst >= (INT_MAX / sizeof(res->instlist[0])) || res->numinst >= (INT_MAX / sizeof(res->namelist[0])) || res->numinst >= rp->hdr.len) { sts = PM_ERR_IPC; goto badsts; } if ((res->instlist = (int *)malloc(res->numinst * sizeof(res->instlist[0]))) == NULL) { sts = -oserror(); goto badsts; } if ((res->namelist = (char **)malloc(res->numinst * sizeof(res->namelist[0]))) == NULL) { sts = -oserror(); goto badsts; } /* required for __pmFreeInResult() in the event of a later error */ memset(res->namelist, 0, res->numinst * sizeof(res->namelist[0])); if (res->numinst == 1) keep_instlist = keep_namelist = 0; else keep_instlist = keep_namelist = 1; for (i = j = 0; i < res->numinst; i++) { ip = (instlist_t *)&rp->rest[j/sizeof(__pmPDU)]; if (sizeof(instlist_t) - sizeof(ip->name) > (size_t)(pdu_end - (char *)ip)) { sts = PM_ERR_IPC; goto badsts; } res->instlist[i] = ntohl(ip->inst); if (res->instlist[i] != PM_IN_NULL) keep_instlist = 1; ip->namelen = ntohl(ip->namelen); if (ip->namelen > 0) keep_namelist = 1; if (ip->namelen < 0) { sts = PM_ERR_IPC; goto badsts; } if (sizeof(instlist_t) - sizeof(int) + ip->namelen > (size_t)(pdu_end - (char *)ip)) { sts = PM_ERR_IPC; goto badsts; } if ((p = (char *)malloc(ip->namelen + 1)) == NULL) { sts = -oserror(); goto badsts; } memcpy((void *)p, (void *)ip->name, ip->namelen); p[ip->namelen] = '\0'; res->namelist[i] = p; j += sizeof(*ip) - sizeof(ip->name) + PM_PDU_SIZE_BYTES(ip->namelen); } if (keep_instlist == 0) { free(res->instlist); res->instlist = NULL; } if (keep_namelist == 0) { free(res->namelist[0]); free(res->namelist); res->namelist = NULL; } #ifdef PCP_DEBUG if (pmDebug & DBG_TRACE_INDOM) __pmDumpInResult(stderr, res); #endif *result = res; return 0; badsts: __pmFreeInResult(res); return sts; }