diff options
Diffstat (limited to 'plugins/fmhttp/fmhttp.c')
-rw-r--r-- | plugins/fmhttp/fmhttp.c | 188 |
1 files changed, 188 insertions, 0 deletions
diff --git a/plugins/fmhttp/fmhttp.c b/plugins/fmhttp/fmhttp.c new file mode 100644 index 0000000..c465b23 --- /dev/null +++ b/plugins/fmhttp/fmhttp.c @@ -0,0 +1,188 @@ +/* fmhttp.c + * This is a function module for http functions. + * + * File begun on 2018-03-16 by JGerhards + * + * Copyright 2010-2018 Rainer Gerhards, Jan Gerhards and Adiscon GmbH. + * + * This file is part of rsyslog. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * -or- + * see COPYING.ASL20 in the source distribution + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include "config.h" +#include "rsyslog.h" +#include <stdlib.h> +#include <string.h> +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <curl/curl.h> +#include "errmsg.h" +#include "conf.h" +#include "syslogd-types.h" +#include "template.h" +#include "msg.h" +#include "parserif.h" +#include "module-template.h" +#include "rainerscript.h" +#include "unicode-helper.h" + +MODULE_TYPE_FUNCTION +MODULE_TYPE_NOKEEP +DEF_FMOD_STATIC_DATA + +struct curl_funcData { + const char *reply; + size_t replyLen; +}; + +/* curl callback for doFunc_http_request */ +static size_t +curlResult(void *ptr, size_t size, size_t nmemb, void *userdata) +{ + char *buf; + size_t newlen; + struct cnffunc *const func = (struct cnffunc *) userdata; + assert(func != NULL); + struct curl_funcData *const curlData = (struct curl_funcData*) func->funcdata; + assert(curlData != NULL); + + if(ptr == NULL) { + LogError(0, RS_RET_ERR, "internal error: libcurl provided ptr=NULL"); + return 0; + } + + newlen = curlData->replyLen + size*nmemb; + if((buf = realloc((void*)curlData->reply, newlen + 1)) == NULL) { + LogError(errno, RS_RET_ERR, "rainerscript: realloc failed in curlResult"); + return 0; /* abort due to failure */ + } + memcpy(buf+curlData->replyLen, (char*)ptr, size*nmemb); + curlData->replyLen = newlen; + curlData->reply = buf; + return size*nmemb; +} + +static void ATTR_NONNULL() +doFunc_http_request(struct cnffunc *__restrict__ const func, + struct svar *__restrict__ const ret, + void *__restrict__ const usrptr, + wti_t *__restrict__ const pWti) +{ + struct svar srcVal; + int bMustFree; + cnfexprEval(func->expr[0], &srcVal, usrptr, pWti); + char *url = (char*) var2CString(&srcVal, &bMustFree); + + int resultSet = 0; + CURL *handle = NULL; + CURLcode res; + assert(func != NULL); + struct curl_funcData *const curlData = (struct curl_funcData*) func->funcdata; + assert(curlData != NULL); + rsRetVal iRet __attribute__((unused)) = RS_RET_OK; + + CHKmalloc(handle = curl_easy_init()); + curl_easy_setopt(handle, CURLOPT_NOSIGNAL, TRUE); + curl_easy_setopt(handle, CURLOPT_WRITEFUNCTION, curlResult); + curl_easy_setopt(handle, CURLOPT_WRITEDATA, func); + + curl_easy_setopt(handle, CURLOPT_URL, url); + res = curl_easy_perform(handle); + if(res != CURLE_OK) { + LogError(0, RS_RET_IO_ERROR, + "rainerscript: http_request to failed, URL: '%s', error %s", + url, curl_easy_strerror(res)); + ABORT_FINALIZE(RS_RET_OK); + } + + + CHKmalloc(ret->d.estr = es_newStrFromCStr(curlData->reply, curlData->replyLen)); + ret->datatype = 'S'; + resultSet = 1; + +finalize_it: + free((void*)curlData->reply); + curlData->reply = NULL; + curlData->replyLen = 0; + + if(handle != NULL) { + curl_easy_cleanup(handle); + } + if(!resultSet) { + /* provide dummy value */ + ret->d.n = 0; + ret->datatype = 'N'; + } + if(bMustFree) { + free(url); + } + varFreeMembers(&srcVal); +} + +static rsRetVal ATTR_NONNULL(1) +initFunc_http_request(struct cnffunc *const func) +{ + DEFiRet; + + func->destructable_funcdata = 1; + CHKmalloc(func->funcdata = calloc(1, sizeof(struct curl_funcData))); + if(func->nParams != 1) { + parser_errmsg("rsyslog logic error in line %d of file %s\n", + __LINE__, __FILE__); + FINALIZE; + } + +finalize_it: + RETiRet; +} + +static void ATTR_NONNULL(1) +destructFunc_http_request(struct cnffunc *const func) +{ + if(func->funcdata != NULL) { + free((void*) ((struct curl_funcData*)func->funcdata)->reply); + } +} + +static struct scriptFunct functions[] = { + {"http_request", 1, 1, doFunc_http_request, initFunc_http_request, destructFunc_http_request}, + {NULL, 0, 0, NULL, NULL, NULL} //last element to check end of array +}; + +BEGINgetFunctArray +CODESTARTgetFunctArray + *version = 1; + *functArray = functions; +ENDgetFunctArray + + +BEGINmodExit +CODESTARTmodExit +ENDmodExit + + +BEGINqueryEtryPt +CODESTARTqueryEtryPt +CODEqueryEtryPt_STD_FMOD_QUERIES +ENDqueryEtryPt + + +BEGINmodInit() +CODESTARTmodInit + *ipIFVersProvided = CURR_MOD_IF_VERSION; /* we only support the current interface specification */ +CODEmodInit_QueryRegCFSLineHdlr + dbgprintf("rsyslog fmhttp init called, compiled with version %s\n", VERSION); +ENDmodInit |