From 1d8719f2e4b91c85e678a148924bb293d0162b2f Mon Sep 17 00:00:00 2001 From: Datong Sun Date: Mon, 14 Jul 2014 01:49:24 -0500 Subject: [PATCH 1/2] Added support for setrlimit(2) --- config.h.in | 3 +++ configure | 2 +- configure.ac | 2 +- src/jconf.c | 4 ++++ src/jconf.h | 1 + src/local.c | 18 ++++++++++++++++++ src/server.c | 18 ++++++++++++++++++ src/utils.c | 38 ++++++++++++++++++++++++++++++++++++++ src/utils.h | 3 +++ 9 files changed, 87 insertions(+), 2 deletions(-) diff --git a/config.h.in b/config.h.in index 5c377bf3..44721eeb 100644 --- a/config.h.in +++ b/config.h.in @@ -151,6 +151,9 @@ /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID +/* Define to 1 if you have the `setrlimit' function. */ +#undef HAVE_SETRLIMIT + /* Define to 1 if you have the `signalfd' function. */ #undef HAVE_SIGNALFD diff --git a/configure b/configure index 757df0fc..5e229c51 100755 --- a/configure +++ b/configure @@ -14272,7 +14272,7 @@ cat >>confdefs.h <<_ACEOF _ACEOF -for ac_func in memset select setresuid setreuid strerror getpwnam_r +for ac_func in memset select setresuid setreuid strerror getpwnam_r setrlimit do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" diff --git a/configure.ac b/configure.ac index 820f9a90..0f9aacce 100755 --- a/configure.ac +++ b/configure.ac @@ -153,7 +153,7 @@ dnl Checks for library functions. AC_FUNC_FORK AC_FUNC_SELECT_ARGTYPES AC_TYPE_SIGNAL -AC_CHECK_FUNCS([memset select setresuid setreuid strerror getpwnam_r]) +AC_CHECK_FUNCS([memset select setresuid setreuid strerror getpwnam_r setrlimit]) dnl Check for select() into ws2_32 for Msys/Mingw if test "$ac_cv_func_select" != "yes"; then diff --git a/src/jconf.c b/src/jconf.c index e94d9263..91f08a07 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -183,6 +183,10 @@ jconf_t *read_jconf(const char* file) { conf.fast_open = value->u.boolean; } + else if (strcmp(name, "nofile") == 0) + { + conf.nofile = value->u.integer; + } } } else diff --git a/src/jconf.h b/src/jconf.h index 9ba5796a..12ab62c1 100644 --- a/src/jconf.h +++ b/src/jconf.h @@ -44,6 +44,7 @@ typedef struct char *method; char *timeout; int fast_open; + int nofile; } jconf_t; jconf_t *read_jconf(const char* file); diff --git a/src/local.c b/src/local.c index ca484500..fbe83d05 100644 --- a/src/local.c +++ b/src/local.c @@ -74,6 +74,9 @@ int acl = 0; int verbose = 0; int udprelay = 0; static int fast_open = 0; +#ifdef HAVE_SETRLIMIT +static int nofile = 0; +#endif #ifndef __MINGW32__ static int setnonblocking(int fd) @@ -1025,6 +1028,21 @@ int main (int argc, char **argv) if (method == NULL) method = conf->method; if (timeout == NULL) timeout = conf->timeout; if (fast_open == 0) fast_open = conf->fast_open; +#ifdef HAVE_SETRLIMIT + if (nofile == 0) nofile = conf->nofile; + /* + * no need to check the return value here since we will show + * the user an error message if setrlimit(2) fails + */ + if (nofile) + { + if (verbose) + { + LOGD("setting NOFILE to %d", nofile); + } + set_nofile(nofile); + } +#endif } if (remote_num == 0 || remote_port == NULL || diff --git a/src/server.c b/src/server.c index ec1ebf52..d63b2d24 100644 --- a/src/server.c +++ b/src/server.c @@ -67,6 +67,9 @@ int udprelay = 0; #ifdef TCP_FASTOPEN static int fast_open = 0; #endif +#ifdef HAVE_SETRLIMIT +static int nofile = 0; +#endif static int remote_conn = 0; static int server_conn = 0; @@ -1048,6 +1051,21 @@ int main (int argc, char **argv) if (timeout == NULL) timeout = conf->timeout; #ifdef TCP_FASTOPEN if (fast_open == 0) fast_open = conf->fast_open; +#endif +#ifdef HAVE_SETRLIMIT + if (nofile == 0) nofile = conf->nofile; + /* + * no need to check the return value here since we will show + * the user an error message if setrlimit(2) fails + */ + if (nofile) + { + if (verbose) + { + LOGD("setting NOFILE to %d", nofile); + } + set_nofile(nofile); + } #endif } diff --git a/src/utils.c b/src/utils.c index 3289b4bd..b29ba466 100644 --- a/src/utils.c +++ b/src/utils.c @@ -37,6 +37,11 @@ #include "config.h" #endif +#ifdef HAVE_SETRLIMIT +#include +#include +#endif + #define INT_DIGITS 19 /* enough for 64 bit integer */ #ifdef HAS_SYSLOG @@ -275,3 +280,36 @@ void daemonize(const char* path) #endif } +#ifdef HAVE_SETRLIMIT +int set_nofile(int nofile) +{ + struct rlimit limit = {nofile, nofile}; /* set both soft and hard limit */ + + if (nofile <= 0) + { + FATAL("nofile must be greater than 0\n"); + } + + if (setrlimit(RLIMIT_NOFILE, &limit) < 0) + { + if (errno == EPERM) + { + LOGE("insufficient permission to change NOFILE, not starting as root?"); + return -1; + } + else if (errno == EINVAL) + { + LOGE("invalid fileno, decrease nofile and try again"); + return -1; + } + else + { + LOGE("setrlimit failed: %s", strerror(errno)); + return -1; + } + } + + return 0; +} +#endif + diff --git a/src/utils.h b/src/utils.h index 5ee98892..607b7956 100644 --- a/src/utils.h +++ b/src/utils.h @@ -124,5 +124,8 @@ void FATAL(const char *msg); void usage(void); void daemonize(const char* path); char *ss_strndup(const char *s, size_t n); +#ifdef HAVE_SETRLIMIT +int set_nofile(int nofile); +#endif #endif // _UTILS_H From c53fddd96a4e7771bbd852b7b9f53daad93a216d Mon Sep 17 00:00:00 2001 From: Datong Sun Date: Mon, 14 Jul 2014 01:53:32 -0500 Subject: [PATCH 2/2] Fixed a typo --- src/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils.c b/src/utils.c index b29ba466..41df1a43 100644 --- a/src/utils.c +++ b/src/utils.c @@ -299,7 +299,7 @@ int set_nofile(int nofile) } else if (errno == EINVAL) { - LOGE("invalid fileno, decrease nofile and try again"); + LOGE("invalid nofile, decrease nofile and try again"); return -1; } else