mirror of
https://github.com/sonertari/SSLproxy
synced 2024-11-18 03:25:31 +00:00
Add conf file support, with -f command line option, supports a subset of all possible options
This commit is contained in:
parent
1a6eab50a5
commit
7748e3ec1b
414
main.c
414
main.c
@ -279,6 +279,307 @@ oom_die(const char *argv0)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_cacrt(opts_t *opts, const char *argv0, char *optarg)
|
||||||
|
{
|
||||||
|
if (opts->cacrt)
|
||||||
|
X509_free(opts->cacrt);
|
||||||
|
opts->cacrt = ssl_x509_load(optarg);
|
||||||
|
if (!opts->cacrt) {
|
||||||
|
fprintf(stderr, "%s: error loading CA "
|
||||||
|
"cert from '%s':\n",
|
||||||
|
argv0, optarg);
|
||||||
|
if (errno) {
|
||||||
|
fprintf(stderr, "%s\n",
|
||||||
|
strerror(errno));
|
||||||
|
} else {
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
ssl_x509_refcount_inc(opts->cacrt);
|
||||||
|
sk_X509_insert(opts->chain, opts->cacrt, 0);
|
||||||
|
if (!opts->cakey) {
|
||||||
|
opts->cakey = ssl_key_load(optarg);
|
||||||
|
}
|
||||||
|
#ifndef OPENSSL_NO_DH
|
||||||
|
if (!opts->dh) {
|
||||||
|
opts->dh = ssl_dh_load(optarg);
|
||||||
|
}
|
||||||
|
#endif /* !OPENSSL_NO_DH */
|
||||||
|
fprintf(stderr, "cacrt: %s\n", optarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_cakey(opts_t *opts, const char *argv0, char *optarg)
|
||||||
|
{
|
||||||
|
if (opts->cakey)
|
||||||
|
EVP_PKEY_free(opts->cakey);
|
||||||
|
opts->cakey = ssl_key_load(optarg);
|
||||||
|
if (!opts->cakey) {
|
||||||
|
fprintf(stderr, "%s: error loading CA "
|
||||||
|
"key from '%s':\n",
|
||||||
|
argv0, optarg);
|
||||||
|
if (errno) {
|
||||||
|
fprintf(stderr, "%s\n",
|
||||||
|
strerror(errno));
|
||||||
|
} else {
|
||||||
|
ERR_print_errors_fp(stderr);
|
||||||
|
}
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (!opts->cacrt) {
|
||||||
|
opts->cacrt = ssl_x509_load(optarg);
|
||||||
|
if (opts->cacrt) {
|
||||||
|
ssl_x509_refcount_inc(
|
||||||
|
opts->cacrt);
|
||||||
|
sk_X509_insert(opts->chain,
|
||||||
|
opts->cacrt, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef OPENSSL_NO_DH
|
||||||
|
if (!opts->dh) {
|
||||||
|
opts->dh = ssl_dh_load(optarg);
|
||||||
|
}
|
||||||
|
#endif /* !OPENSSL_NO_DH */
|
||||||
|
fprintf(stderr, "cakey: %s\n", optarg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_user(opts_t *opts, const char *argv0, char *optarg)
|
||||||
|
{
|
||||||
|
if (!sys_isuser(optarg)) {
|
||||||
|
fprintf(stderr, "%s: '%s' is not an "
|
||||||
|
"existing user\n",
|
||||||
|
argv0, optarg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (opts->dropuser)
|
||||||
|
free(opts->dropuser);
|
||||||
|
opts->dropuser = strdup(optarg);
|
||||||
|
if (!opts->dropuser)
|
||||||
|
oom_die(argv0);
|
||||||
|
fprintf(stderr, "dropuser: %s\n", opts->dropuser);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_group(opts_t *opts, const char *argv0, char *optarg)
|
||||||
|
{
|
||||||
|
if (!sys_isgroup(optarg)) {
|
||||||
|
fprintf(stderr, "%s: '%s' is not an "
|
||||||
|
"existing group\n",
|
||||||
|
argv0, optarg);
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
if (opts->dropgroup)
|
||||||
|
free(opts->dropgroup);
|
||||||
|
opts->dropgroup = strdup(optarg);
|
||||||
|
if (!opts->dropgroup)
|
||||||
|
oom_die(argv0);
|
||||||
|
fprintf(stderr, "dropgroup: %s\n", opts->dropgroup);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
set_pidfile(opts_t *opts, const char *argv0, char *optarg)
|
||||||
|
{
|
||||||
|
if (opts->pidfile)
|
||||||
|
free(opts->pidfile);
|
||||||
|
opts->pidfile = strdup(optarg);
|
||||||
|
if (!opts->pidfile)
|
||||||
|
oom_die(argv0);
|
||||||
|
fprintf(stderr, "pidfile: %s\n", opts->pidfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
load_conffile(opts_t *opts, const char *argv0, const char *natengine)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
int rv, line_num, found;
|
||||||
|
size_t line_len;
|
||||||
|
char *n, *value, *v, *value_end;
|
||||||
|
char *line, *name;
|
||||||
|
|
||||||
|
f = fopen(opts->conffile, "r");
|
||||||
|
if (!f) {
|
||||||
|
fprintf(stderr, "Error opening conf file %s: %s\n", opts->conffile, strerror(errno));
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
line = NULL;
|
||||||
|
line_num = 0;
|
||||||
|
while (!feof(f)) {
|
||||||
|
rv = getline(&line, &line_len, f);
|
||||||
|
if (rv == -1) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (line == NULL) {
|
||||||
|
fprintf(stderr, "getline() buf=NULL");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
line_num++;
|
||||||
|
|
||||||
|
// skip white space
|
||||||
|
for (name = line; *name == ' ' || *name == '\t'; name++);
|
||||||
|
|
||||||
|
// skip comments and empty lines
|
||||||
|
if ((name[0] == '\0') || (name[0] == '#') || (name[0] == ';') ||
|
||||||
|
(name[0] == '\r') || (name[0] == '\n')) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip to the end of option name and terminate it with '\0'
|
||||||
|
for (n = name;; n++) {
|
||||||
|
if (*n == ' ' || *n == '\t') {
|
||||||
|
*n = '\0';
|
||||||
|
n++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*n == '\0') {
|
||||||
|
n = NULL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// no value
|
||||||
|
if (n == NULL) {
|
||||||
|
fprintf(stderr, "Conf error at line %d\n", line_num);
|
||||||
|
fclose(f);
|
||||||
|
if (line) {
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// skip white space before value
|
||||||
|
while (*n == ' ' || *n == '\t') {
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = n;
|
||||||
|
|
||||||
|
// find end of value and terminate it with '\0'
|
||||||
|
// find first occurrence of trailing white space
|
||||||
|
value_end = NULL;
|
||||||
|
for (v = value;; v++) {
|
||||||
|
if (*v == '\0') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*v == '\r' || *v == '\n') {
|
||||||
|
*v = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (*v == ' ' || *v == '\t') {
|
||||||
|
if (!value_end) {
|
||||||
|
value_end = v;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
value_end = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value_end) {
|
||||||
|
*value_end = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
if (!strncasecmp(name, "CACert", 6)) {
|
||||||
|
set_cacrt(opts, argv0, value);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "CAKey", 5)) {
|
||||||
|
set_cakey(opts, argv0, value);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "ProxySpec", 9)) {
|
||||||
|
char **argv = malloc(strlen(value) + 1);
|
||||||
|
char **save_argv = argv;
|
||||||
|
int argc = 0;
|
||||||
|
char *p, *last;
|
||||||
|
|
||||||
|
for ((p = strtok_r(value, " ", &last)); p; (p = strtok_r(NULL, " ", &last))) {
|
||||||
|
// Limit max # token
|
||||||
|
if (argc < 10) {
|
||||||
|
argv[argc++] = p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyspec_parse(&argc, &argv, natengine, opts);
|
||||||
|
free(save_argv);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "ConnIdleTimeout", 15)) {
|
||||||
|
unsigned int rv = atoi(value);
|
||||||
|
if (rv >= 10 && rv <= 3600) {
|
||||||
|
opts->conn_idle_timeout = rv;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid ConnIdleTimeout %s at line %d, use 10-3600\n", value, line_num);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "ConnIdleTimeout: %u\n", opts->conn_idle_timeout);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "ExpiredConnCheckPeriod", 22)) {
|
||||||
|
unsigned int rv = atoi(value);
|
||||||
|
if (rv >= 10 && rv <= 60) {
|
||||||
|
opts->expired_conn_check_period = rv;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid ExpiredConnCheckPeriod %s at line %d, use 10-60\n", value, line_num);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "ExpiredConnCheckPeriod: %u\n", opts->expired_conn_check_period);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "SSLShutdownRetryDelay", 21)) {
|
||||||
|
unsigned int rv = atoi(value);
|
||||||
|
if (rv >= 100 && rv <= 10000) {
|
||||||
|
opts->ssl_shutdown_retry_delay = rv;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid SSLShutdownRetryDelay %s at line %d, use 100-10000\n", value, line_num);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "SSLShutdownRetryDelay: %u\n", opts->ssl_shutdown_retry_delay);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "PidFile", 7)) {
|
||||||
|
set_pidfile(opts, argv0, value);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "LogStats", 8)) {
|
||||||
|
if (!strncasecmp(value, "yes", 3)) {
|
||||||
|
opts->statslog = 1;
|
||||||
|
} else if (!strncasecmp(value, "no", 3)) {
|
||||||
|
opts->statslog = 0;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid LogStats %s at line %d, use yes|no\n", value, line_num);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "LogStats: %u\n", opts->statslog);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "StatsPeriod", 11)) {
|
||||||
|
unsigned int rv = atoi(value);
|
||||||
|
if (rv >= 1 && rv <= 10) {
|
||||||
|
opts->stats_period = rv;
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "Invalid StatsPeriod %s at line %d, use 1-10\n", value, line_num);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "StatsPeriod: %u\n", opts->stats_period);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "User", 4)) {
|
||||||
|
set_user(opts, argv0, value);
|
||||||
|
found = 1;
|
||||||
|
} else if (!strncasecmp(name, "Group", 5)) {
|
||||||
|
set_group(opts, argv0, value);
|
||||||
|
found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stderr, "Unknown option '%s' at %s line %d\n", name, opts->conffile, line_num);
|
||||||
|
fclose(f);
|
||||||
|
if (line) {
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
fclose(f);
|
||||||
|
if (line) {
|
||||||
|
free(line);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Main entry point.
|
* Main entry point.
|
||||||
*/
|
*/
|
||||||
@ -302,66 +603,29 @@ main(int argc, char *argv[])
|
|||||||
natengine = NULL;
|
natengine = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set defaults
|
||||||
|
opts->conn_idle_timeout = 120;
|
||||||
|
opts->expired_conn_check_period = 10;
|
||||||
|
opts->ssl_shutdown_retry_delay = 100;
|
||||||
|
opts->log_stats = 0;
|
||||||
|
opts->stats_period = 1;
|
||||||
|
|
||||||
while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z OPT_i "k:c:C:K:t:"
|
while ((ch = getopt(argc, argv, OPT_g OPT_G OPT_Z OPT_i "k:c:C:K:t:"
|
||||||
"OPs:r:R:e:Eu:m:j:p:l:L:S:F:dD::VhW:w:I")) != -1) {
|
"OPs:r:R:e:Eu:m:j:p:l:L:S:F:dD::VhW:w:If:")) != -1) {
|
||||||
switch (ch) {
|
switch (ch) {
|
||||||
|
case 'f':
|
||||||
|
if (opts->conffile)
|
||||||
|
free(opts->conffile);
|
||||||
|
opts->conffile = strdup(optarg);
|
||||||
|
if (!opts->conffile)
|
||||||
|
oom_die(argv0);
|
||||||
|
fprintf(stderr, "Conf file: %s\n", opts->conffile);
|
||||||
|
break;
|
||||||
case 'c':
|
case 'c':
|
||||||
if (opts->cacrt)
|
set_cacrt(opts, argv0, optarg);
|
||||||
X509_free(opts->cacrt);
|
|
||||||
opts->cacrt = ssl_x509_load(optarg);
|
|
||||||
if (!opts->cacrt) {
|
|
||||||
fprintf(stderr, "%s: error loading CA "
|
|
||||||
"cert from '%s':\n",
|
|
||||||
argv0, optarg);
|
|
||||||
if (errno) {
|
|
||||||
fprintf(stderr, "%s\n",
|
|
||||||
strerror(errno));
|
|
||||||
} else {
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
}
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
ssl_x509_refcount_inc(opts->cacrt);
|
|
||||||
sk_X509_insert(opts->chain, opts->cacrt, 0);
|
|
||||||
if (!opts->cakey) {
|
|
||||||
opts->cakey = ssl_key_load(optarg);
|
|
||||||
}
|
|
||||||
#ifndef OPENSSL_NO_DH
|
|
||||||
if (!opts->dh) {
|
|
||||||
opts->dh = ssl_dh_load(optarg);
|
|
||||||
}
|
|
||||||
#endif /* !OPENSSL_NO_DH */
|
|
||||||
break;
|
break;
|
||||||
case 'k':
|
case 'k':
|
||||||
if (opts->cakey)
|
set_cakey(opts, argv0, optarg);
|
||||||
EVP_PKEY_free(opts->cakey);
|
|
||||||
opts->cakey = ssl_key_load(optarg);
|
|
||||||
if (!opts->cakey) {
|
|
||||||
fprintf(stderr, "%s: error loading CA "
|
|
||||||
"key from '%s':\n",
|
|
||||||
argv0, optarg);
|
|
||||||
if (errno) {
|
|
||||||
fprintf(stderr, "%s\n",
|
|
||||||
strerror(errno));
|
|
||||||
} else {
|
|
||||||
ERR_print_errors_fp(stderr);
|
|
||||||
}
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (!opts->cacrt) {
|
|
||||||
opts->cacrt = ssl_x509_load(optarg);
|
|
||||||
if (opts->cacrt) {
|
|
||||||
ssl_x509_refcount_inc(
|
|
||||||
opts->cacrt);
|
|
||||||
sk_X509_insert(opts->chain,
|
|
||||||
opts->cacrt, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#ifndef OPENSSL_NO_DH
|
|
||||||
if (!opts->dh) {
|
|
||||||
opts->dh = ssl_dh_load(optarg);
|
|
||||||
}
|
|
||||||
#endif /* !OPENSSL_NO_DH */
|
|
||||||
break;
|
break;
|
||||||
case 'C':
|
case 'C':
|
||||||
if (ssl_x509chain_load(NULL, &opts->chain,
|
if (ssl_x509chain_load(NULL, &opts->chain,
|
||||||
@ -486,37 +750,13 @@ main(int argc, char *argv[])
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
if (!sys_isuser(optarg)) {
|
set_user(opts, argv0, optarg);
|
||||||
fprintf(stderr, "%s: '%s' is not an "
|
|
||||||
"existing user\n",
|
|
||||||
argv0, optarg);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (opts->dropuser)
|
|
||||||
free(opts->dropuser);
|
|
||||||
opts->dropuser = strdup(optarg);
|
|
||||||
if (!opts->dropuser)
|
|
||||||
oom_die(argv0);
|
|
||||||
break;
|
break;
|
||||||
case 'm':
|
case 'm':
|
||||||
if (!sys_isgroup(optarg)) {
|
set_group(opts, argv0, optarg);
|
||||||
fprintf(stderr, "%s: '%s' is not an "
|
|
||||||
"existing group\n",
|
|
||||||
argv0, optarg);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
if (opts->dropgroup)
|
|
||||||
free(opts->dropgroup);
|
|
||||||
opts->dropgroup = strdup(optarg);
|
|
||||||
if (!opts->dropgroup)
|
|
||||||
oom_die(argv0);
|
|
||||||
break;
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
if (opts->pidfile)
|
set_pidfile(opts, argv0, optarg);
|
||||||
free(opts->pidfile);
|
|
||||||
opts->pidfile = strdup(optarg);
|
|
||||||
if (!opts->pidfile)
|
|
||||||
oom_die(argv0);
|
|
||||||
break;
|
break;
|
||||||
case 'j':
|
case 'j':
|
||||||
if (!sys_isdir(optarg)) {
|
if (!sys_isdir(optarg)) {
|
||||||
@ -675,8 +915,6 @@ main(int argc, char *argv[])
|
|||||||
case 'D':
|
case 'D':
|
||||||
opts->debug = 1;
|
opts->debug = 1;
|
||||||
|
|
||||||
fprintf(stderr, "Debug optarg = %s.\n", optarg);
|
|
||||||
|
|
||||||
if (optarg && strncmp(optarg, "2", 1) == 0) {
|
if (optarg && strncmp(optarg, "2", 1) == 0) {
|
||||||
log_dbg_mode(LOG_DBG_MODE_FINE);
|
log_dbg_mode(LOG_DBG_MODE_FINE);
|
||||||
} else if (optarg && strncmp(optarg, "3", 1) == 0) {
|
} else if (optarg && strncmp(optarg, "3", 1) == 0) {
|
||||||
@ -702,7 +940,13 @@ main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
argc -= optind;
|
argc -= optind;
|
||||||
argv += optind;
|
argv += optind;
|
||||||
opts->spec = proxyspec_parse(&argc, &argv, natengine);
|
proxyspec_parse(&argc, &argv, natengine, opts);
|
||||||
|
|
||||||
|
if (opts->conffile) {
|
||||||
|
if (load_conffile(opts, argv0, natengine) == -1) {
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* usage checks before defaults */
|
/* usage checks before defaults */
|
||||||
if (opts->detach && OPTS_DEBUG(opts)) {
|
if (opts->detach && OPTS_DEBUG(opts)) {
|
||||||
|
86
opts.c
86
opts.c
@ -278,15 +278,13 @@ opts_proto_dbg_dump(opts_t *opts)
|
|||||||
"");
|
"");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parse proxyspecs using a simple state machine.
|
* Parse proxyspecs using a simple state machine.
|
||||||
* Returns NULL if parsing failed.
|
|
||||||
*/
|
*/
|
||||||
proxyspec_t *
|
void
|
||||||
proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
proxyspec_parse(int *argc, char **argv[], const char *natengine, opts_t *opts)
|
||||||
{
|
{
|
||||||
proxyspec_t *curspec, *spec = NULL;
|
proxyspec_t *curspec;
|
||||||
char *addr = NULL;
|
char *addr = NULL;
|
||||||
int af = AF_UNSPEC;
|
int af = AF_UNSPEC;
|
||||||
int state = 0;
|
int state = 0;
|
||||||
@ -298,35 +296,37 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
/* tcp | ssl | http | https | autossl | mail | mails */
|
/* tcp | ssl | http | https | autossl | mail | mails */
|
||||||
curspec = malloc(sizeof(proxyspec_t));
|
curspec = malloc(sizeof(proxyspec_t));
|
||||||
memset(curspec, 0, sizeof(proxyspec_t));
|
memset(curspec, 0, sizeof(proxyspec_t));
|
||||||
curspec->next = spec;
|
|
||||||
spec = curspec;
|
curspec->next = opts->spec;
|
||||||
|
opts->spec = curspec;
|
||||||
|
|
||||||
// Defaults
|
// Defaults
|
||||||
spec->ssl = 0;
|
curspec->ssl = 0;
|
||||||
spec->http = 0;
|
curspec->http = 0;
|
||||||
spec->upgrade = 0;
|
curspec->upgrade = 0;
|
||||||
spec->mail = 0;
|
curspec->mail = 0;
|
||||||
if (!strcmp(**argv, "tcp")) {
|
if (!strcmp(**argv, "tcp")) {
|
||||||
// use defaults
|
// use defaults
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "ssl")) {
|
if (!strcmp(**argv, "ssl")) {
|
||||||
spec->ssl = 1;
|
curspec->ssl = 1;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "http")) {
|
if (!strcmp(**argv, "http")) {
|
||||||
spec->http = 1;
|
curspec->http = 1;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "https")) {
|
if (!strcmp(**argv, "https")) {
|
||||||
spec->ssl = 1;
|
curspec->ssl = 1;
|
||||||
spec->http = 1;
|
curspec->http = 1;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "autossl")) {
|
if (!strcmp(**argv, "autossl")) {
|
||||||
spec->upgrade = 1;
|
curspec->upgrade = 1;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "mail")) {
|
if (!strcmp(**argv, "mail")) {
|
||||||
spec->mail = 1;
|
curspec->mail = 1;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "mails")) {
|
if (!strcmp(**argv, "mails")) {
|
||||||
spec->ssl = 1;
|
curspec->ssl = 1;
|
||||||
spec->mail = 1;
|
curspec->mail = 1;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unknown connection "
|
fprintf(stderr, "Unknown connection "
|
||||||
"type '%s'\n", **argv);
|
"type '%s'\n", **argv);
|
||||||
@ -349,23 +349,23 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
af = AF_INET;
|
af = AF_INET;
|
||||||
else
|
else
|
||||||
af = AF_UNSPEC;
|
af = AF_UNSPEC;
|
||||||
af = sys_sockaddr_parse(&spec->listen_addr,
|
af = sys_sockaddr_parse(&curspec->listen_addr,
|
||||||
&spec->listen_addrlen,
|
&curspec->listen_addrlen,
|
||||||
addr, **argv, af,
|
addr, **argv, af,
|
||||||
EVUTIL_AI_PASSIVE);
|
EVUTIL_AI_PASSIVE);
|
||||||
if (af == -1) {
|
if (af == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
if (natengine) {
|
if (natengine) {
|
||||||
spec->natengine = strdup(natengine);
|
curspec->natengine = strdup(natengine);
|
||||||
if (!spec->natengine) {
|
if (!curspec->natengine) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Out of memory"
|
"Out of memory"
|
||||||
"\n");
|
"\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spec->natengine = NULL;
|
curspec->natengine = NULL;
|
||||||
}
|
}
|
||||||
state++;
|
state++;
|
||||||
break;
|
break;
|
||||||
@ -375,14 +375,14 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
// @todo Make this a conf file option?
|
// @todo Make this a conf file option?
|
||||||
// @todo Need IPv6?
|
// @todo Need IPv6?
|
||||||
if (strstr(**argv, "up:")) {
|
if (strstr(**argv, "up:")) {
|
||||||
af = sys_sockaddr_parse(&spec->parent_dst_addr,
|
af = sys_sockaddr_parse(&curspec->parent_dst_addr,
|
||||||
&spec->parent_dst_addrlen,
|
&curspec->parent_dst_addrlen,
|
||||||
"127.0.0.1", **argv+3, AF_INET, EVUTIL_AI_PASSIVE);
|
"127.0.0.1", **argv + 3, AF_INET, EVUTIL_AI_PASSIVE);
|
||||||
if (af == -1) {
|
if (af == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
af = sys_sockaddr_parse(&spec->child_src_addr,
|
af = sys_sockaddr_parse(&curspec->child_src_addr,
|
||||||
&spec->child_src_addrlen,
|
&curspec->child_src_addrlen,
|
||||||
"127.0.0.1", "0", AF_INET, EVUTIL_AI_PASSIVE);
|
"127.0.0.1", "0", AF_INET, EVUTIL_AI_PASSIVE);
|
||||||
if (af == -1) {
|
if (af == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -404,9 +404,9 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
state = 0;
|
state = 0;
|
||||||
} else
|
} else
|
||||||
if (!strcmp(**argv, "sni")) {
|
if (!strcmp(**argv, "sni")) {
|
||||||
free(spec->natengine);
|
free(curspec->natengine);
|
||||||
spec->natengine = NULL;
|
curspec->natengine = NULL;
|
||||||
if (!spec->ssl) {
|
if (!curspec->ssl) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"SNI hostname lookup "
|
"SNI hostname lookup "
|
||||||
"only works for ssl "
|
"only works for ssl "
|
||||||
@ -418,9 +418,9 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
} else
|
} else
|
||||||
if (nat_exist(**argv)) {
|
if (nat_exist(**argv)) {
|
||||||
/* natengine */
|
/* natengine */
|
||||||
free(spec->natengine);
|
free(curspec->natengine);
|
||||||
spec->natengine = strdup(**argv);
|
curspec->natengine = strdup(**argv);
|
||||||
if (!spec->natengine) {
|
if (!curspec->natengine) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"Out of memory"
|
"Out of memory"
|
||||||
"\n");
|
"\n");
|
||||||
@ -429,16 +429,16 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
state = 0;
|
state = 0;
|
||||||
} else {
|
} else {
|
||||||
/* explicit target address */
|
/* explicit target address */
|
||||||
free(spec->natengine);
|
free(curspec->natengine);
|
||||||
spec->natengine = NULL;
|
curspec->natengine = NULL;
|
||||||
addr = **argv;
|
addr = **argv;
|
||||||
state++;
|
state++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
/* dstport */
|
/* dstport */
|
||||||
af = sys_sockaddr_parse(&spec->connect_addr,
|
af = sys_sockaddr_parse(&curspec->connect_addr,
|
||||||
&spec->connect_addrlen,
|
&curspec->connect_addrlen,
|
||||||
addr, **argv, af, 0);
|
addr, **argv, af, 0);
|
||||||
if (af == -1) {
|
if (af == -1) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
@ -447,13 +447,13 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
break;
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
/* SNI dstport */
|
/* SNI dstport */
|
||||||
spec->sni_port = atoi(**argv);
|
curspec->sni_port = atoi(**argv);
|
||||||
if (!spec->sni_port) {
|
if (!curspec->sni_port) {
|
||||||
fprintf(stderr, "Invalid port '%s'\n",
|
fprintf(stderr, "Invalid port '%s'\n",
|
||||||
**argv);
|
**argv);
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
spec->dns = 1;
|
curspec->dns = 1;
|
||||||
state = 0;
|
state = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -463,8 +463,6 @@ proxyspec_parse(int *argc, char **argv[], const char *natengine)
|
|||||||
fprintf(stderr, "Incomplete proxyspec!\n");
|
fprintf(stderr, "Incomplete proxyspec!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
return spec;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
9
opts.h
9
opts.h
@ -97,6 +97,7 @@ typedef struct opts {
|
|||||||
char *dropgroup;
|
char *dropgroup;
|
||||||
char *jaildir;
|
char *jaildir;
|
||||||
char *pidfile;
|
char *pidfile;
|
||||||
|
char *conffile;
|
||||||
char *connectlog;
|
char *connectlog;
|
||||||
int statslog;
|
int statslog;
|
||||||
char *contentlog;
|
char *contentlog;
|
||||||
@ -113,6 +114,11 @@ typedef struct opts {
|
|||||||
char *ecdhcurve;
|
char *ecdhcurve;
|
||||||
#endif /* !OPENSSL_NO_ECDH */
|
#endif /* !OPENSSL_NO_ECDH */
|
||||||
proxyspec_t *spec;
|
proxyspec_t *spec;
|
||||||
|
unsigned int conn_idle_timeout;
|
||||||
|
unsigned int expired_conn_check_period;
|
||||||
|
unsigned int ssl_shutdown_retry_delay;
|
||||||
|
int log_stats;
|
||||||
|
unsigned int stats_period;
|
||||||
} opts_t;
|
} opts_t;
|
||||||
|
|
||||||
opts_t *opts_new(void) MALLOC;
|
opts_t *opts_new(void) MALLOC;
|
||||||
@ -124,7 +130,8 @@ void opts_proto_disable(opts_t *, const char *, const char *) NONNULL(1,2,3);
|
|||||||
void opts_proto_dbg_dump(opts_t *) NONNULL(1);
|
void opts_proto_dbg_dump(opts_t *) NONNULL(1);
|
||||||
#define OPTS_DEBUG(opts) unlikely((opts)->debug)
|
#define OPTS_DEBUG(opts) unlikely((opts)->debug)
|
||||||
|
|
||||||
proxyspec_t * proxyspec_parse(int *, char **[], const char *) MALLOC;
|
void proxyspec_parse(int *, char **[], const char *, opts_t *);
|
||||||
|
|
||||||
void proxyspec_free(proxyspec_t *) NONNULL(1);
|
void proxyspec_free(proxyspec_t *) NONNULL(1);
|
||||||
char * proxyspec_str(proxyspec_t *) NONNULL(1) MALLOC;
|
char * proxyspec_str(proxyspec_t *) NONNULL(1) MALLOC;
|
||||||
|
|
||||||
|
13
pxythrmgr.c
13
pxythrmgr.c
@ -46,10 +46,6 @@
|
|||||||
* The attach and detach functions are thread-safe.
|
* The attach and detach functions are thread-safe.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define THR_TIMER_TIMEOUT 10
|
|
||||||
#define THR_TIMER_PRINT_INFO_TIMEOUT 1*THR_TIMER_TIMEOUT
|
|
||||||
#define CONN_EXPIRE_TIME 120
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pxy_thrmgr_get_thr_expired_conns(pxy_thr_ctx_t *tctx, pxy_conn_ctx_t **expired_conns)
|
pxy_thrmgr_get_thr_expired_conns(pxy_thr_ctx_t *tctx, pxy_conn_ctx_t **expired_conns)
|
||||||
{
|
{
|
||||||
@ -61,11 +57,10 @@ pxy_thrmgr_get_thr_expired_conns(pxy_thr_ctx_t *tctx, pxy_conn_ctx_t **expired_c
|
|||||||
pxy_conn_ctx_t *ctx = tctx->conns;
|
pxy_conn_ctx_t *ctx = tctx->conns;
|
||||||
while (ctx) {
|
while (ctx) {
|
||||||
unsigned long elapsed_time = now - ctx->atime;
|
unsigned long elapsed_time = now - ctx->atime;
|
||||||
if (elapsed_time > CONN_EXPIRE_TIME) {
|
if (elapsed_time > tctx->thrmgr->opts->conn_idle_timeout) {
|
||||||
ctx->next_expired = *expired_conns;
|
ctx->next_expired = *expired_conns;
|
||||||
*expired_conns = ctx;
|
*expired_conns = ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx = ctx->next;
|
ctx = ctx->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -307,10 +302,10 @@ pxy_thrmgr_timer_cb(UNUSED evutil_socket_t fd, UNUSED short what,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @todo Print thread info only if stats logging is enabled, if disabled debug logs are not printed either
|
// @attention Print thread info only if stats logging is enabled, if disabled debug logs are not printed either
|
||||||
if (ctx->thrmgr->opts->statslog) {
|
if (ctx->thrmgr->opts->statslog) {
|
||||||
ctx->timeout_count++;
|
ctx->timeout_count++;
|
||||||
if (ctx->timeout_count * THR_TIMER_TIMEOUT > THR_TIMER_PRINT_INFO_TIMEOUT) {
|
if (ctx->timeout_count * ctx->thrmgr->opts->expired_conn_check_period >= ctx->thrmgr->opts->stats_period * ctx->thrmgr->opts->expired_conn_check_period) {
|
||||||
ctx->timeout_count = 0;
|
ctx->timeout_count = 0;
|
||||||
pxy_thrmgr_print_thr_info(ctx);
|
pxy_thrmgr_print_thr_info(ctx);
|
||||||
}
|
}
|
||||||
@ -325,7 +320,7 @@ static void *
|
|||||||
pxy_thrmgr_thr(void *arg)
|
pxy_thrmgr_thr(void *arg)
|
||||||
{
|
{
|
||||||
pxy_thr_ctx_t *ctx = arg;
|
pxy_thr_ctx_t *ctx = arg;
|
||||||
struct timeval timer_delay = {THR_TIMER_TIMEOUT, 0};
|
struct timeval timer_delay = {ctx->thrmgr->opts->expired_conn_check_period, 0};
|
||||||
struct event *ev;
|
struct event *ev;
|
||||||
|
|
||||||
ev = event_new(ctx->evbase, -1, EV_PERSIST, pxy_thrmgr_timer_cb, ctx);
|
ev = event_new(ctx->evbase, -1, EV_PERSIST, pxy_thrmgr_timer_cb, ctx);
|
||||||
|
Loading…
Reference in New Issue
Block a user