fixed memory leaks in restconf evhtp module
This commit is contained in:
parent
6be4b18391
commit
2e23856676
4 changed files with 83 additions and 45 deletions
|
|
@ -1,13 +1,37 @@
|
|||
# Clixon Restconf
|
||||
|
||||
* [Installation](#installation)
|
||||
* [Evhtp](#evhtp)
|
||||
* [Nginx](#nginx)
|
||||
* [Streams](#streams)
|
||||
* [Nchan Streams](#nchan)
|
||||
* [Debugging](#debugging)
|
||||
|
||||
## Installation
|
||||
There are two installation instructions: for libevhtp and nginx.
|
||||
|
||||
The examples are based on Nginx. Other reverse proxies should work but are not verified.
|
||||
## Evhtp
|
||||
|
||||
Download, build and install libevhtp from source. Prereqs: libevent and cmake.
|
||||
```
|
||||
git clone https://github.com/criticalstack/libevhtp.git
|
||||
cd libevhtp/build
|
||||
cmake -DEVHTP_DISABLE_REGEX=ON -DEVHTP_DISABLE_EVTHR=ON ..
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
|
||||
Configure clixon with evhtp:
|
||||
```
|
||||
./configure --with-restconf=evhtp
|
||||
```
|
||||
|
||||
Ensure www-data is member of the CLICON_SOCK_GROUP (default clicon). If not, add it:
|
||||
```
|
||||
sudo usermod -a -G clicon www-data
|
||||
```
|
||||
|
||||
## Nginx
|
||||
|
||||
Installation instruction for Nginx. Other reverse proxies should work but are not verified.
|
||||
|
||||
Ensure www-data is member of the CLICON_SOCK_GROUP (default clicon). If not, add it:
|
||||
```
|
||||
|
|
@ -49,6 +73,8 @@ Or on FreeBSD:
|
|||
sudo service nginx start
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
Start clixon backend daemon (if not already started)
|
||||
```
|
||||
sudo clixon_backend -s init -f /usr/local/etc/example.xml
|
||||
|
|
|
|||
|
|
@ -118,7 +118,6 @@ restconf_reply_header(void *req0,
|
|||
clicon_err(OE_CFG, errno, "evhttp_header_new");
|
||||
goto done;
|
||||
}
|
||||
value = NULL; /* freed by evhtp */
|
||||
evhtp_headers_add_header(req->headers_out, evhdr);
|
||||
retval = 0;
|
||||
done:
|
||||
|
|
|
|||
|
|
@ -38,11 +38,12 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "clixon_config.h" /* generated by config & autoconf */
|
||||
#endif
|
||||
/* compilation withotu threading support
|
||||
* XXX: could be disabled already in configure?
|
||||
|
||||
/* The clixon evhtp code can be compiled with or without threading support
|
||||
* The choice is set at libevhtp compile time by cmake. Eg:
|
||||
* cmake -DEVHTP_DISABLE_EVTHR=ON # Disable threads.
|
||||
* Default in testing is disabled threads.
|
||||
*/
|
||||
//#define EVHTP_DISABLE_EVTHR
|
||||
#define EVHTP_DISABLE_REGEX
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -87,7 +88,24 @@
|
|||
/* Need global variable to for signal handler XXX */
|
||||
static clicon_handle _CLICON_HANDLE = NULL;
|
||||
|
||||
static struct evhtp_handle{
|
||||
evhtp_t *eh_htp;
|
||||
struct event_base *eh_evbase;
|
||||
evhtp_ssl_cfg_t *eh_ssl_config;
|
||||
} _EVHTP_HANDLE = {0,};
|
||||
|
||||
static void
|
||||
evhtp_terminate(struct evhtp_handle *eh)
|
||||
{
|
||||
if (eh->eh_htp){
|
||||
evhtp_unbind_socket(eh->eh_htp);
|
||||
evhtp_free(eh->eh_htp);
|
||||
}
|
||||
if (eh->eh_evbase)
|
||||
event_base_free(eh->eh_evbase);
|
||||
if (eh->eh_ssl_config)
|
||||
free(eh->eh_ssl_config);
|
||||
}
|
||||
|
||||
/*! Signall terminates process
|
||||
*/
|
||||
|
|
@ -101,6 +119,7 @@ restconf_sig_term(int arg)
|
|||
__PROGRAM__, __FUNCTION__, getpid(), arg);
|
||||
else
|
||||
exit(-1);
|
||||
evhtp_terminate(&_EVHTP_HANDLE);
|
||||
if (_CLICON_HANDLE){
|
||||
// stream_child_freeall(_CLICON_HANDLE);
|
||||
restconf_terminate(_CLICON_HANDLE);
|
||||
|
|
@ -457,6 +476,8 @@ cx_path_restconf(evhtp_request_t *req,
|
|||
if (restconf_param_del_all(h) < 0)
|
||||
goto done;
|
||||
done:
|
||||
if (qvec)
|
||||
cvec_free(qvec);
|
||||
return; /* void */
|
||||
}
|
||||
|
||||
|
|
@ -601,15 +622,13 @@ main(int argc,
|
|||
size_t cligen_bufthreshold;
|
||||
uint16_t defaultport;
|
||||
uint16_t port = 0;
|
||||
evhtp_t *htp = NULL;
|
||||
struct event_base *evbase = NULL;
|
||||
evhtp_ssl_cfg_t *ssl_config = NULL;
|
||||
int dbg = 0;
|
||||
int use_ssl = 0;
|
||||
int ssl_verify_clients = 0;
|
||||
char *restconf_ipv4_addr = NULL;
|
||||
char *restconf_ipv6_addr = NULL;
|
||||
int i;
|
||||
struct evhtp_handle *eh = &_EVHTP_HANDLE;
|
||||
|
||||
/* In the startup, logs to stderr & debug flag set later */
|
||||
clicon_log_init(__PROGRAM__, LOG_INFO, logdst);
|
||||
|
|
@ -747,20 +766,20 @@ main(int argc,
|
|||
/* Check server ssl certs */
|
||||
if (use_ssl){
|
||||
/* Init evhtp ssl config struct */
|
||||
if ((ssl_config = malloc(sizeof(evhtp_ssl_cfg_t))) == NULL){
|
||||
if ((eh->eh_ssl_config = malloc(sizeof(evhtp_ssl_cfg_t))) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(ssl_config, 0, sizeof(evhtp_ssl_cfg_t));
|
||||
ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
|
||||
memset(eh->eh_ssl_config, 0, sizeof(evhtp_ssl_cfg_t));
|
||||
eh->eh_ssl_config->ssl_opts = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1;
|
||||
|
||||
if (cx_get_certs(h, ssl_verify_clients, ssl_config) < 0)
|
||||
if (cx_get_certs(h, ssl_verify_clients, eh->eh_ssl_config) < 0)
|
||||
goto done;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs; /* Is extra verification necessary? */
|
||||
if (ssl_verify_clients){
|
||||
ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
ssl_config->verify_depth = 2;
|
||||
eh->eh_ssl_config->verify_peer = SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
|
||||
eh->eh_ssl_config->x509_verify_cb = cx_verify_certs;
|
||||
eh->eh_ssl_config->verify_depth = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -770,44 +789,44 @@ main(int argc,
|
|||
clicon_argv_set(h, argv0, argc, argv);
|
||||
|
||||
/* Init evhtp */
|
||||
if ((evbase = event_base_new()) == NULL){
|
||||
if ((eh->eh_evbase = event_base_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "event_base_new");
|
||||
goto done;
|
||||
}
|
||||
/* create a new evhtp_t instance */
|
||||
if ((htp = evhtp_new(evbase, NULL)) == NULL){
|
||||
if ((eh->eh_htp = evhtp_new(eh->eh_evbase, NULL)) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
/* Here the daemon either uses SSL or not, ie you cant seem to mix http and https :-( */
|
||||
if (use_ssl){
|
||||
if (evhtp_ssl_init(htp, ssl_config) < 0){
|
||||
if (evhtp_ssl_init(eh->eh_htp, eh->eh_ssl_config) < 0){
|
||||
clicon_err(OE_UNIX, errno, "evhtp_new");
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
#ifndef EVHTP_DISABLE_EVTHR
|
||||
evhtp_use_threads_wexit(htp, NULL, NULL, 4, NULL);
|
||||
evhtp_use_threads_wexit(eh->eh_htp, NULL, NULL, 4, NULL);
|
||||
#endif
|
||||
|
||||
/* Callback before the connection is accepted. */
|
||||
evhtp_set_pre_accept_cb(htp, cx_pre_accept, h);
|
||||
evhtp_set_pre_accept_cb(eh->eh_htp, cx_pre_accept, h);
|
||||
|
||||
/* Callback right after a connection is accepted. */
|
||||
evhtp_set_post_accept_cb(htp, cx_post_accept, h);
|
||||
evhtp_set_post_accept_cb(eh->eh_htp, cx_post_accept, h);
|
||||
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, "/" RESTCONF_API, cx_path_restconf, h) == NULL){
|
||||
if (evhtp_set_cb(eh->eh_htp, "/" RESTCONF_API, cx_path_restconf, h) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
/* Callback to be executed for all /restconf api calls */
|
||||
if (evhtp_set_cb(htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, h) == NULL){
|
||||
if (evhtp_set_cb(eh->eh_htp, RESTCONF_WELL_KNOWN, cx_path_wellknown, h) == NULL){
|
||||
clicon_err(OE_EVENTS, errno, "evhtp_set_cb");
|
||||
goto done;
|
||||
}
|
||||
/* Generic callback called if no other callbacks are matched */
|
||||
evhtp_set_gencb(htp, cx_gencb, h);
|
||||
evhtp_set_gencb(eh->eh_htp, cx_gencb, h);
|
||||
|
||||
/* bind to a socket, optionally with specific protocol support formatting
|
||||
*/
|
||||
|
|
@ -825,7 +844,7 @@ main(int argc,
|
|||
goto done;
|
||||
}
|
||||
cprintf(cb, "ipv4:%s", restconf_ipv4_addr);
|
||||
if (evhtp_bind_socket(htp, /* evhtp handle */
|
||||
if (evhtp_bind_socket(eh->eh_htp, /* evhtp handle */
|
||||
cbuf_get(cb), /* string address, eg ipv4:<ipv4addr> */
|
||||
port, /* port */
|
||||
SOCKET_LISTEN_BACKLOG /* backlog flag, see listen(5) */
|
||||
|
|
@ -836,14 +855,15 @@ main(int argc,
|
|||
if (cb)
|
||||
cbuf_free(cb);
|
||||
}
|
||||
if (restconf_ipv6_addr != NULL && strlen(restconf_ipv6_addr)){
|
||||
/* Eeh can only bind one */
|
||||
if (0 && restconf_ipv6_addr != NULL && strlen(restconf_ipv6_addr)){
|
||||
cbuf *cb;
|
||||
if ((cb = cbuf_new()) == NULL){
|
||||
clicon_err(OE_UNIX, errno, "cbuf_new");
|
||||
goto done;
|
||||
}
|
||||
cprintf(cb, "ipv6:%s", restconf_ipv6_addr);
|
||||
if (evhtp_bind_socket(htp, /* evhtp handle */
|
||||
if (evhtp_bind_socket(eh->eh_htp, /* evhtp handle */
|
||||
cbuf_get(cb), /* string address, eg ipv6:<ipv6addr> */
|
||||
port, /* port */
|
||||
SOCKET_LISTEN_BACKLOG /* backlog flag, see listen(5) */
|
||||
|
|
@ -855,7 +875,7 @@ main(int argc,
|
|||
cbuf_free(cb);
|
||||
}
|
||||
/* Drop privileges to WWWUSER if started as root */
|
||||
if (restconf_drop_privileges(h, WWWUSER) < 0)
|
||||
if (0 && restconf_drop_privileges(h, WWWUSER) < 0)
|
||||
goto done;
|
||||
|
||||
/* Init cligen buffers */
|
||||
|
|
@ -944,20 +964,13 @@ main(int argc,
|
|||
if (clixon_plugin_start_all(h) < 0)
|
||||
goto done;
|
||||
|
||||
/* Find and read configfile */
|
||||
if (clicon_options_main(h) < 0)
|
||||
goto done;
|
||||
|
||||
event_base_loop(evbase, 0);
|
||||
|
||||
evhtp_unbind_socket(htp);
|
||||
|
||||
// evhtp_safe_free(htp, evhtp_free);
|
||||
// evhtp_safe_free(evbase, event_base_free);
|
||||
event_base_loop(eh->eh_evbase, 0);
|
||||
|
||||
retval = 0;
|
||||
done:
|
||||
clicon_debug(1, "restconf_main_evhtp done");
|
||||
// stream_child_freeall(h);
|
||||
evhtp_terminate(&_EVHTP_HANDLE);
|
||||
restconf_terminate(h);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -554,8 +554,8 @@ yang_parse_file(int fd,
|
|||
|
||||
len = BUFLEN; /* any number is fine */
|
||||
if ((buf = malloc(len)) == NULL){
|
||||
perror("pt_file malloc");
|
||||
return NULL;
|
||||
clicon_err(OE_XML, errno, "malloc");
|
||||
goto done;
|
||||
}
|
||||
memset(buf, 0, len);
|
||||
i = 0; /* position in buf */
|
||||
|
|
@ -579,7 +579,7 @@ yang_parse_file(int fd,
|
|||
if ((ymod = yang_parse_str(buf, name, yspec)) < 0)
|
||||
goto done;
|
||||
done:
|
||||
if (buf)
|
||||
if (buf != NULL)
|
||||
free(buf);
|
||||
return ymod; /* top-level (sub)module */
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue