radsecproxy-1.6.5.
[libradsec.git] / radsecproxy.c
index 8489a18..b7b2063 100644 (file)
@@ -52,6 +52,9 @@
 #include <string.h>
 #include <unistd.h>
 #include <limits.h>
+#if defined(HAVE_MALLOPT)
+#include <malloc.h>
+#endif
 #ifdef SYS_SOLARIS9
 #include <fcntl.h>
 #endif
@@ -1284,7 +1287,9 @@ void acclog(struct radmsg *msg, struct client *from) {
     }
 }
 
-void respond(struct request *rq, uint8_t code, char *message) {
+void respond(struct request *rq, uint8_t code, char *message,
+             int copy_proxystate_flag)
+{
     struct radmsg *msg;
     struct tlv *attr;
 
@@ -1302,6 +1307,12 @@ void respond(struct request *rq, uint8_t code, char *message) {
            return;
        }
     }
+    if (copy_proxystate_flag) {
+        if (radmsg_copy_attrs(msg, rq->msg, RAD_Proxy_State) < 0) {
+            debug(DBG_ERR, "%s: unable to copy all Proxy-State attributes",
+                  __func__);
+        }
+    }
 
     radmsg_free(rq->msg);
     rq->msg = msg;
@@ -1387,6 +1398,22 @@ struct request *newrequest() {
     return rq;
 }
 
+static void
+purgedupcache(struct client *client) {
+    struct request *r;
+    struct timeval now;
+    int i;
+
+    gettimeofday(&now, NULL);
+    for (i = 0; i < MAX_REQUESTS; i++) {
+       r = client->rqs[i];
+       if (r && now.tv_sec - r->created.tv_sec > r->from->conf->dupinterval) {
+           freerq(r);
+           client->rqs[i] = NULL;
+       }
+    }
+}
+
 int addclientrq(struct request *rq) {
     struct request *r;
     struct timeval now;
@@ -1450,11 +1477,12 @@ int radsrv(struct request *rq) {
        goto exit;
     }
 
+    purgedupcache(from);
     if (!addclientrq(rq))
        goto exit;
 
     if (msg->code == RAD_Status_Server) {
-       respond(rq, RAD_Access_Accept, NULL);
+       respond(rq, RAD_Access_Accept, NULL, 0);
        goto exit;
     }
 
@@ -1473,7 +1501,7 @@ int radsrv(struct request *rq) {
     if (!attr) {
        if (msg->code == RAD_Accounting_Request) {
            acclog(msg, from);
-           respond(rq, RAD_Accounting_Response, NULL);
+           respond(rq, RAD_Accounting_Response, NULL, 1);
        } else
            debug(DBG_INFO, "radsrv: ignoring access request, no username attribute");
        goto exit;
@@ -1499,10 +1527,10 @@ int radsrv(struct request *rq) {
     if (!to) {
        if (realm->message && msg->code == RAD_Access_Request) {
            debug(DBG_INFO, "radsrv: sending reject to %s (%s) for %s", from->conf->name, addr2string(from->addr), userascii);
-           respond(rq, RAD_Access_Reject, realm->message);
+           respond(rq, RAD_Access_Reject, realm->message, 1);
        } else if (realm->accresp && msg->code == RAD_Accounting_Request) {
            acclog(msg, from);
-           respond(rq, RAD_Accounting_Response, NULL);
+           respond(rq, RAD_Accounting_Response, NULL, 1);
        }
        goto exit;
     }
@@ -1777,8 +1805,8 @@ void *clientwr(void *arg) {
 #if defined ENABLE_EXPERIMENTAL_DYNDISC
        pthread_mutex_unlock(&server->lock);
 #endif
-       debug(DBG_WARN, "%s: dynamicconfig(%s) failed, sleeping %ds",
-              __func__, server->conf->name, ZZZ);
+       debug(DBG_WARN, "%s: dynamicconfig(%s: %s) failed, sleeping %ds",
+              __func__, server->conf->name, server->dynamiclookuparg, ZZZ);
        sleep(ZZZ);
        goto errexit;
     }
@@ -1816,7 +1844,7 @@ void *clientwr(void *arg) {
 #if defined ENABLE_EXPERIMENTAL_DYNDISC
        server->in_use = 1;
 #endif
-       if (pthread_create(&clientrdth, NULL, conf->pdef->clientconnreader, (void *)server)) {
+       if (pthread_create(&clientrdth, &pthread_attr, conf->pdef->clientconnreader, (void *)server)) {
            debugerrno(errno, DBG_ERR, "clientwr: pthread_create failed");
            goto errexit;
        }
@@ -1975,7 +2003,7 @@ void createlistener(uint8_t type, char *arg) {
         if (!sp)
             debugx(1, DBG_ERR, "malloc failed");
        *sp = s;
-       if (pthread_create(&th, NULL, protodefs[type]->listener, (void *)sp))
+       if (pthread_create(&th, &pthread_attr, protodefs[type]->listener, (void *)sp))
             debugerrnox(errno, DBG_ERR, "pthread_create failed");
        pthread_detach(th);
     }
@@ -2225,7 +2253,7 @@ struct list *createsubrealmservers(struct realm *realm, struct list *srvconfs) {
 #if defined ENABLE_EXPERIMENTAL_DYNDISC
                pthread_mutex_lock(&srvconf->servers->lock);
 #endif
-               if (pthread_create(&clientth, NULL, clientwr, (void *)(srvconf->servers))) {
+               if (pthread_create(&clientth, &pthread_attr, clientwr, (void *)(srvconf->servers))) {
 #if defined ENABLE_EXPERIMENTAL_DYNDISC
                     pthread_mutex_unlock(&srvconf->servers->lock);
 #endif
@@ -2445,7 +2473,9 @@ struct modattr *extractmodattr(char *nameval) {
     if (s[strlen(s) - 1] == '/')
        s[strlen(s) - 1] = '\0';
 
-    t = strchr(s, '/');
+    for (t = strchr(s, '/'); t; t = strchr(t+1, '/'))
+        if (t == s || t[-1] != '\\')
+            break;
     if (!t)
        return NULL;
     *t = '\0';
@@ -2624,8 +2654,8 @@ void freeclsrvconf(struct clsrvconf *conf) {
        free(conf->rewriteusername);
     }
     free(conf->dynamiclookupcommand);
-    free(conf->rewritein);
-    free(conf->rewriteout);
+    conf->rewritein=NULL;
+    conf->rewriteout=NULL;
     if (conf->hostports)
        freehostports(conf->hostports);
     if (conf->lock) {
@@ -3342,6 +3372,15 @@ int radsecproxy_main(int argc, char **argv) {
     debug_init("radsecproxy");
     debug_set_level(DEBUG_LEVEL);
 
+    if (pthread_attr_init(&pthread_attr))
+       debugx(1, DBG_ERR, "pthread_attr_init failed");
+    if (pthread_attr_setstacksize(&pthread_attr, PTHREAD_STACK_SIZE))
+       debugx(1, DBG_ERR, "pthread_attr_setstacksize failed");
+#if defined(HAVE_MALLOPT)
+    if (mallopt(M_TRIM_THRESHOLD, 4 * 1024) != 1)
+       debugx(1, DBG_ERR, "mallopt failed");
+#endif
+
     for (i = 0; i < RAD_PROTOCOUNT; i++)
        protodefs[i] = protoinits[i](i);
 
@@ -3393,7 +3432,7 @@ int radsecproxy_main(int argc, char **argv) {
     sigaddset(&sigset, SIGHUP);
     sigaddset(&sigset, SIGPIPE);
     pthread_sigmask(SIG_BLOCK, &sigset, NULL);
-    pthread_create(&sigth, NULL, sighandler, NULL);
+    pthread_create(&sigth, &pthread_attr, sighandler, NULL);
 
     for (entry = list_first(srvconfs); entry; entry = list_next(entry)) {
        srvconf = (struct clsrvconf *)entry->data;
@@ -3401,7 +3440,7 @@ int radsecproxy_main(int argc, char **argv) {
            continue;
        if (!addserver(srvconf))
            debugx(1, DBG_ERR, "failed to add server");
-       if (pthread_create(&srvconf->servers->clientth, NULL, clientwr,
+       if (pthread_create(&srvconf->servers->clientth, &pthread_attr, clientwr,
                           (void *)(srvconf->servers)))
            debugx(1, DBG_ERR, "pthread_create failed");
     }