/* a helper function for rsCStr*Strf() */ static rsRetVal rsCStrConstructFromszStrv(cstr_t **ppThis, uchar *fmt, va_list ap) { DEFiRet; cstr_t *pThis; va_list ap2; int len; assert(ppThis != NULL); va_copy(ap2, ap); len = vsnprintf(NULL, 0, (char*)fmt, ap2); va_end(ap2); if(len < 0) ABORT_FINALIZE(RS_RET_ERR); CHKiRet(rsCStrConstruct(&pThis)); pThis->iBufSize = pThis->iStrLen = len; len++; /* account for the \0 written by vsnprintf */ if((pThis->pBuf = (uchar*) MALLOC(sizeof(uchar) * len)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } vsnprintf((char*)pThis->pBuf, len, (char*)fmt, ap); *ppThis = pThis; finalize_it: RETiRet; }
/* Parse a quoted string ("-some-data") from the given position. * Leading whitespace before the first quote is skipped. During * parsing, escape sequences are detected and converted: * \\ - backslash character * \" - quote character * any other value \<somechar> is reserved for future use. * * After return, the parse pointer is paced after the trailing * quote. * * Output: * ppCStr Pointer to the parsed string - must be freed by caller and * does NOT include the quotes. * rgerhards, 2005-09-19 */ rsRetVal parsQuotedCStr(rsParsObj *pThis, cstr_t **ppCStr) { register unsigned char *pC; cstr_t *pCStr; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); if((iRet = parsSkipAfterChar(pThis, '"')) != RS_RET_OK) FINALIZE; pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* OK, we most probably can obtain a value... */ CHKiRet(rsCStrConstruct(&pCStr)); while(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) { if(*pC == '"') { break; /* we are done! */ } else if(*pC == '\\') { ++pThis->iCurrPos; ++pC; if(pThis->iCurrPos < rsCStrLen(pThis->pCStr)) { /* in this case, we copy the escaped character * to the output buffer (but do not rely on this, * we might later introduce other things, like \007! */ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { rsCStrDestruct(&pCStr); FINALIZE; } } } else { /* regular character */ if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } } ++pThis->iCurrPos; ++pC; } if(*pC == '"') { ++pThis->iCurrPos; /* 'eat' trailing quote */ } else { /* error - improperly quoted string! */ rsCStrDestruct (&pCStr); ABORT_FINALIZE(RS_RET_MISSING_TRAIL_QUOTE); } /* We got the string, let's finish it... */ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } /* done! */ *ppCStr = pCStr; finalize_it: RETiRet; }
/* helper to ochAddLine. Parses a comma-delimited field * The field is delimited by SP or comma. Leading whitespace * is "eaten" and does not become part of the field content. * returns: 0 - ok, 1 - failure */ static int get_Field(uchar **pp, uchar **pField) { register uchar *p; cstr_t *pStrB; assert(pp != NULL); assert(*pp != NULL); assert(pField != NULL); skip_Comma((char**)pp); p = *pp; if(rsCStrConstruct(&pStrB) != RS_RET_OK) return 1; rsCStrSetAllocIncrement(pStrB, 32); /* copy the field */ while(*p && *p != ' ' && *p != ',') { rsCStrAppendChar(pStrB, *p++); } *pp = p; rsCStrFinish(pStrB); if(rsCStrConvSzStrAndDestruct(pStrB, pField, 0) != RS_RET_OK) return 1; return 0; }
/* parse a whitespace-delimited word from the provided string. This is a * helper function for a number of syntaxes. The parsed value is returned * in ppStrB (which must be provided by caller). * rgerhards, 2008-02-14 */ static rsRetVal getWord(uchar **pp, cstr_t **ppStrB) { DEFiRet; uchar *p; ASSERT(pp != NULL); ASSERT(*pp != NULL); ASSERT(ppStrB != NULL); CHKiRet(rsCStrConstruct(ppStrB)); /* parse out the word */ p = *pp; while(*p && !isspace((int) *p)) { CHKiRet(rsCStrAppendChar(*ppStrB, *p++)); } CHKiRet(rsCStrFinish(*ppStrB)); *pp = p; finalize_it: RETiRet; }
/* Parse string up to a delimiter. * * Input: * cDelim - the delimiter * The following two are for whitespace stripping, * 0 means "no", 1 "yes" * - bTrimLeading * - bTrimTrailing * * Output: * ppCStr Pointer to the parsed string - must be freed by caller! */ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing) { DEFiRet; register unsigned char *pC; cstr_t *pCStr; rsCHECKVALIDOBJECT(pThis, OIDrsPars); CHKiRet(rsCStrConstruct(&pCStr)); if(bTrimLeading) parsSkipWhitespace(pThis); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) { if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { rsCStrDestruct(&pCStr); FINALIZE; } ++pThis->iCurrPos; ++pC; } if(*pC == cDelim) { ++pThis->iCurrPos; /* eat delimiter */ } /* We got the string, now take it and see if we need to * remove anything at its end. */ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } if(bTrimTrailing) { if((iRet = rsCStrTrimTrailingWhiteSpace(pCStr)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } } /* done! */ *ppCStr = pCStr; finalize_it: RETiRet; }
/* Parse string up to a delimiter. * * Input: * cDelim - the delimiter. Note that SP within a value always is a delimiter, * so cDelim is actually an *additional* delimiter. * The following two are for whitespace stripping, * 0 means "no", 1 "yes" * - bTrimLeading * - bTrimTrailing * - bConvLower - convert string to lower case? * * Output: * ppCStr Pointer to the parsed string - must be freed by caller! */ rsRetVal parsDelimCStr(rsParsObj *pThis, cstr_t **ppCStr, char cDelim, int bTrimLeading, int bTrimTrailing, int bConvLower) { DEFiRet; register unsigned char *pC; cstr_t *pCStr = NULL; rsCHECKVALIDOBJECT(pThis, OIDrsPars); CHKiRet(rsCStrConstruct(&pCStr)); if(bTrimLeading) parsSkipWhitespace(pThis); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != cDelim) { CHKiRet(cstrAppendChar(pCStr, bConvLower ? tolower(*pC) : *pC)); ++pThis->iCurrPos; ++pC; } if(pThis->iCurrPos < cstrLen(pThis->pCStr)) { //BUGFIX!! ++pThis->iCurrPos; /* eat delimiter */ } /* We got the string, now take it and see if we need to * remove anything at its end. */ CHKiRet(cstrFinalize(pCStr)); if(bTrimTrailing) { CHKiRet(cstrTrimTrailingWhiteSpace(pCStr)); } /* done! */ *ppCStr = pCStr; finalize_it: if(iRet != RS_RET_OK) { if(pCStr != NULL) rsCStrDestruct(&pCStr); } RETiRet; }
/* construct from sz string * rgerhards 2005-09-15 */ rsRetVal rsCStrConstructFromszStr(cstr_t **ppThis, uchar *sz) { DEFiRet; cstr_t *pThis; assert(ppThis != NULL); CHKiRet(rsCStrConstruct(&pThis)); pThis->iBufSize = pThis->iStrLen = strlen((char *) sz); if((pThis->pBuf = (uchar*) MALLOC(sizeof(uchar) * pThis->iStrLen)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* we do NOT need to copy the \0! */ memcpy(pThis->pBuf, sz, pThis->iStrLen); *ppThis = pThis; finalize_it: RETiRet; }
/* construct from CStr object. only the counted string is * copied, not the szString. * rgerhards 2005-10-18 */ rsRetVal rsCStrConstructFromCStr(cstr_t **ppThis, cstr_t *pFrom) { DEFiRet; cstr_t *pThis; assert(ppThis != NULL); rsCHECKVALIDOBJECT(pFrom, OIDrsCStr); CHKiRet(rsCStrConstruct(&pThis)); pThis->iBufSize = pThis->iStrLen = pFrom->iStrLen; if((pThis->pBuf = (uchar*) MALLOC(sizeof(uchar) * pThis->iStrLen)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* copy properties */ memcpy(pThis->pBuf, pFrom->pBuf, pThis->iStrLen); *ppThis = pThis; finalize_it: RETiRet; }
/* construct from es_str_t string * rgerhards 2010-12-03 */ rsRetVal cstrConstructFromESStr(cstr_t **ppThis, es_str_t *str) { DEFiRet; cstr_t *pThis; CHKiRet(rsCStrConstruct(&pThis)); pThis->iStrLen = es_strlen(str); pThis->iBufSize = pThis->iStrLen + 1; if((pThis->pBuf = (uchar*) MALLOC(pThis->iBufSize)) == NULL) { RSFREEOBJ(pThis); ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); } /* we do NOT need to copy the \0! */ memcpy(pThis->pBuf, es_getBufAddr(str), pThis->iStrLen); *ppThis = pThis; finalize_it: RETiRet; }
rsRetVal parsAddrWithBits(rsParsObj *pThis, struct NetAddr **pIP, int *pBits) { register uchar *pC; uchar *pszIP; uchar *pszTmp; struct addrinfo hints, *res = NULL; cstr_t *pCStr; DEFiRet; rsCHECKVALIDOBJECT(pThis, OIDrsPars); assert(pIP != NULL); assert(pBits != NULL); CHKiRet(rsCStrConstruct(&pCStr)); parsSkipWhitespace(pThis); pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; /* we parse everything until either '/', ',' or * whitespace. Validity will be checked down below. */ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && *pC != '/' && *pC != ',' && !isspace((int)*pC)) { if((iRet = rsCStrAppendChar(pCStr, *pC)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } ++pThis->iCurrPos; ++pC; } /* We got the string, let's finish it... */ if((iRet = rsCStrFinish(pCStr)) != RS_RET_OK) { rsCStrDestruct (&pCStr); FINALIZE; } /* now we have the string and must check/convert it to * an NetAddr structure. */ CHKiRet(rsCStrConvSzStrAndDestruct(pCStr, &pszIP, 0)); *pIP = calloc(1, sizeof(struct NetAddr)); if (*((char*)pszIP) == '[') { pszTmp = (uchar*)strchr ((char*)pszIP, ']'); if (pszTmp == NULL) { free (pszIP); ABORT_FINALIZE(RS_RET_INVALID_IP); } *pszTmp = '\0'; memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_INET6; # ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; # else hints.ai_flags = AI_NUMERICHOST; # endif switch(getaddrinfo ((char*)pszIP+1, NULL, &hints, &res)) { case 0: (*pIP)->addr.NetAddr = malloc (res->ai_addrlen); memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo (res); break; case EAI_NONAME: F_SET((*pIP)->flags, ADDR_NAME|ADDR_PRI6); (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP+1); break; default: free (pszIP); free (*pIP); ABORT_FINALIZE(RS_RET_ERR); } if(*pC == '/') { /* mask bits follow, let's parse them! */ ++pThis->iCurrPos; /* eat slash */ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) { free (pszIP); free (*pIP); FINALIZE; } /* we need to refresh pointer (changed by parsInt()) */ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; } else { /* no slash, so we assume a single host (/128) */ *pBits = 128; } } else { /* now parse IPv4 */ memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_INET; # ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST; # else hints.ai_flags = AI_NUMERICHOST; # endif switch(getaddrinfo ((char*)pszIP, NULL, &hints, &res)) { case 0: (*pIP)->addr.NetAddr = malloc (res->ai_addrlen); memcpy ((*pIP)->addr.NetAddr, res->ai_addr, res->ai_addrlen); freeaddrinfo (res); break; case EAI_NONAME: F_SET((*pIP)->flags, ADDR_NAME); (*pIP)->addr.HostWildcard = strdup ((const char*)pszIP); break; default: free (pszIP); free (*pIP); ABORT_FINALIZE(RS_RET_ERR); } if(*pC == '/') { /* mask bits follow, let's parse them! */ ++pThis->iCurrPos; /* eat slash */ if((iRet = parsInt(pThis, pBits)) != RS_RET_OK) { free (pszIP); free (*pIP); FINALIZE; } /* we need to refresh pointer (changed by parsInt()) */ pC = rsCStrGetBufBeg(pThis->pCStr) + pThis->iCurrPos; } else { /* no slash, so we assume a single host (/32) */ *pBits = 32; } } free(pszIP); /* no longer needed */ /* skip to next processable character */ while(pThis->iCurrPos < rsCStrLen(pThis->pCStr) && (*pC == ',' || isspace((int)*pC))) { ++pThis->iCurrPos; ++pC; } iRet = RS_RET_OK; finalize_it: RETiRet; }