added -i option for pid file, HUP for reopening log file
[libradsec.git] / radsecproxy.c
index 8df4e1d..97bd560 100644 (file)
@@ -53,7 +53,6 @@
 #endif
 #include <sys/time.h>
 #include <sys/types.h>
-#include <sys/select.h>
 #include <ctype.h>
 #include <sys/wait.h>
 #include <arpa/inet.h>
@@ -1738,7 +1737,7 @@ void *clientwr(void *arg) {
     }
     
     if (!resolvehostports(conf->hostports, conf->pdef->socktype)) {
-       debug(DBG_WARN, "failed to resolve host %s port %s", conf->hostsrc ? conf->hostsrc : "(null)", conf->portsrc ? conf->portsrc : "(null)");
+       debug(DBG_WARN, "clientwr: resolve failed");
        server->dynstartup = 0;
        sleep(900);
        goto errexit;
@@ -1752,7 +1751,7 @@ void *clientwr(void *arg) {
     }
 
     if (conf->pdef->connecter) {
-       if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 6 : 0, "clientwr")) {
+       if (!conf->pdef->connecter(server, NULL, server->dynamiclookuparg ? 5 : 0, "clientwr")) {
            if (server->dynamiclookuparg) {
                server->dynstartup = 0;
                sleep(900);
@@ -2470,7 +2469,8 @@ int setttlattr(struct options *opts, char *defaultattr) {
 
 void freeclsrvconf(struct clsrvconf *conf) {
     free(conf->name);
-    free(conf->hostsrc);
+    if (conf->hostsrc)
+       freegconfmstr(conf->hostsrc);
     free(conf->portsrc);
     free(conf->secret);
     free(conf->tls);
@@ -2519,10 +2519,51 @@ int mergeconfstring(char **dst, char **src) {
     return 1;
 }
 
+char **mstringcopy(char **in) {
+    char **out;
+    int n;
+    
+    if (!in)
+       return NULL;
+
+    for (n = 0; in[n]; n++);
+    out = malloc((n + 1) * sizeof(char *));
+    if (!out)
+       return NULL;
+    for (n = 0; in[n]; n++) {
+       out[n] = stringcopy(in[n], 0);
+       if (!out[n]) {
+           freegconfmstr(out);
+           return NULL;
+       }
+    }
+    out[n] = NULL;
+    return out;
+}
+
+int mergeconfmstring(char ***dst, char ***src) {
+    char **t;
+    
+    if (*src) {
+       *dst = *src;
+       *src = NULL;
+       return 1;
+    }
+    if (*dst) {
+       t = mstringcopy(*dst);
+       if (!t) {
+           debug(DBG_ERR, "malloc failed");
+           return 0;
+       }
+       *dst = t;
+    }
+    return 1;
+}
+
 /* assumes dst is a shallow copy */
 int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
     if (!mergeconfstring(&dst->name, &src->name) ||
-       !mergeconfstring(&dst->hostsrc, &src->hostsrc) ||
+       !mergeconfmstring(&dst->hostsrc, &src->hostsrc) ||
        !mergeconfstring(&dst->portsrc, &src->portsrc) ||
        !mergeconfstring(&dst->secret, &src->secret) ||
        !mergeconfstring(&dst->tls, &src->tls) ||
@@ -2557,7 +2598,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     
     if (!getgenericconfig(cf, block,
                          "type", CONF_STR, &conftype,
-                         "host", CONF_STR, &conf->hostsrc,
+                         "host", CONF_MSTR, &conf->hostsrc,
                          "secret", CONF_STR, &conf->secret,
 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)    
                          "tls", CONF_STR, &conf->tls,
@@ -2575,9 +2616,14 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
        debugx(1, DBG_ERR, "configuration error");
     
     conf->name = stringcopy(val, 0);
-    if (!conf->hostsrc)
-       conf->hostsrc = stringcopy(val, 0);
-    if (!conf->name || !conf->hostsrc)
+    if (conf->name && !conf->hostsrc) {
+       conf->hostsrc = malloc(2 * sizeof(char *));
+       if (conf->hostsrc) {
+           conf->hostsrc[0] = stringcopy(val, 0);
+           conf->hostsrc[1] = NULL;
+       }
+    }
+    if (!conf->name || !conf->hostsrc || !conf->hostsrc[0])
        debugx(1, DBG_ERR, "malloc failed");
        
     if (!conftype)
@@ -2627,7 +2673,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
 
     if (!addhostport(&conf->hostports, conf->hostsrc, conf->pdef->portdefault, 1) ||
        !resolvehostports(conf->hostports, conf->pdef->socktype))
-       debugx(1, DBG_ERR, "failed to resolve %s, exiting", conf->hostsrc ? conf->hostsrc : "(null)");
+       debugx(1, DBG_ERR, "resolve failed, exiting");
     
     if (!conf->secret) {
        if (!conf->pdef->secretdefault)
@@ -2685,7 +2731,7 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) {
     }
 
     if (!conf->dynamiclookupcommand && !resolvehostports(conf->hostports, conf->pdef->socktype)) {
-       debug(DBG_ERR, "resolve host %s port %s, exiting", conf->hostsrc ? conf->hostsrc : "(null)", conf->portsrc ? conf->portsrc : "(null)");
+       debug(DBG_ERR, "resolve failed, exiting");
        return 0;
     }
     return 1;
@@ -2713,7 +2759,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
 
     if (!getgenericconfig(cf, block,
                          "type", CONF_STR, &conftype,
-                         "host", CONF_STR, &conf->hostsrc,
+                         "host", CONF_MSTR, &conf->hostsrc,
                          "port", CONF_STR, &conf->portsrc,
                          "secret", CONF_STR, &conf->secret,
 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)    
@@ -2736,17 +2782,17 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     }
     
     conf->name = stringcopy(val, 0);
-    if (!conf->name) {
+    if (conf->name && !conf->hostsrc) {
+       conf->hostsrc = malloc(2 * sizeof(char *));
+       if (conf->hostsrc) {
+           conf->hostsrc[0] = stringcopy(val, 0);
+           conf->hostsrc[1] = NULL;
+       }
+    }
+    if (!conf->name || !conf->hostsrc || !conf->hostsrc[0]) {
         debug(DBG_ERR, "malloc failed");
        goto errexit;
     }
-    if (!conf->hostsrc) {
-       conf->hostsrc = stringcopy(val, 0);
-       if (!conf->hostsrc) {
-            debug(DBG_ERR, "malloc failed");
-           goto errexit;
-        }
-    }
 
     if (!conftype) {
        debug(DBG_ERR, "error in block %s, option type missing", block);
@@ -2966,10 +3012,10 @@ void getmainconfig(const char *configfile) {
            setprotoopts(i, listenargs[i], sourcearg[i]);
 }
 
-void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile) {
+void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8_t *loglevel, char **configfile, char **pidfile) {
     int c;
 
-    while ((c = getopt(argc, argv, "c:d:fpv")) != -1) {
+    while ((c = getopt(argc, argv, "c:d:i:fpv")) != -1) {
        switch (c) {
        case 'c':
            *configfile = optarg;
@@ -2982,6 +3028,9 @@ void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8
        case 'f':
            *foreground = 1;
            break;
+       case 'i':
+           *pidfile = optarg;
+           break;
        case 'p':
            *pretend = 1;
            break;
@@ -3009,7 +3058,7 @@ void getargs(int argc, char **argv, uint8_t *foreground, uint8_t *pretend, uint8
        return;
 
  usage:
-    debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -p ] [ -v ]", argv[0]);
+    debugx(1, DBG_ERR, "Usage:\n%s [ -c configfile ] [ -d debuglevel ] [ -f ] [ -i pidfile ] [ -p ] [ -v ]", argv[0]);
 }
 
 #ifdef SYS_SOLARIS9
@@ -3035,13 +3084,17 @@ void *sighandler(void *arg) {
 
     for(;;) {
        sigemptyset(&sigset);
+       sigaddset(&sigset, SIGHUP);
        sigaddset(&sigset, SIGPIPE);
        sigwait(&sigset, &sig);
-       /* only get SIGPIPE right now, so could simplify below code */
         switch (sig) {
         case 0:
             /* completely ignoring this */
             break;
+        case SIGHUP:
+            debug(DBG_INFO, "sighandler: got SIGHUP");
+           debug_reopen_log();
+            break;
         case SIGPIPE:
             debug(DBG_WARN, "sighandler: got SIGPIPE, TLS write error?");
             break;
@@ -3051,12 +3104,20 @@ void *sighandler(void *arg) {
     }
 }
 
+int createpidfile(const char *pidfile) {
+    int r;
+    FILE *f = fopen(pidfile, "w");
+    if (f)
+       r = fprintf(f, "%d\n", getpid());
+    return f && !fclose(f) && r >= 0;
+}
+
 int main(int argc, char **argv) {
     pthread_t sigth;
     sigset_t sigset;
     struct list_node *entry;
     uint8_t foreground = 0, pretend = 0, loglevel = 0;
-    char *configfile = NULL;
+    char *configfile = NULL, *pidfile = NULL;
     struct clsrvconf *srvconf;
     int i;
     
@@ -3069,7 +3130,7 @@ int main(int argc, char **argv) {
     /* needed even if no TLS/DTLS transport */
     sslinit();
     
-    getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile);
+    getargs(argc, argv, &foreground, &pretend, &loglevel, &configfile, &pidfile);
     if (loglevel)
        debug_set_level(loglevel);
     getmainconfig(configfile ? configfile : CONFIG_MAIN);
@@ -3094,9 +3155,12 @@ int main(int argc, char **argv) {
     
     debug_timestamp_on();
     debug(DBG_INFO, "radsecproxy revision $Rev$ starting");
-
+    if (pidfile && !createpidfile(pidfile))
+       debugx(1, DBG_ERR, "failed to create pidfile %s: %s", pidfile, strerror(errno));
+    
     sigemptyset(&sigset);
-    /* exit on all but SIGPIPE, ignore more? */
+    /* exit on all but SIGHUP|SIGPIPE, ignore more? */
+    sigaddset(&sigset, SIGHUP);
     sigaddset(&sigset, SIGPIPE);
     pthread_sigmask(SIG_BLOCK, &sigset, NULL);
     pthread_create(&sigth, NULL, sighandler, NULL);