From 39692c605e2f1c37efd38f675abdd22ac503b382 Mon Sep 17 00:00:00 2001 From: venaas Date: Thu, 21 Aug 2008 07:45:34 +0000 Subject: separated tcp git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@348 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- radsecproxy.c | 291 +--------------------------------------------------------- 1 file changed, 4 insertions(+), 287 deletions(-) (limited to 'radsecproxy.c') diff --git a/radsecproxy.c b/radsecproxy.c index 14a28bd..17d3685 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -235,6 +235,10 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) { return ok; } +struct addrinfo *getsrcprotores(uint8_t type) { + return srcprotores[type]; +} + int resolvepeer(struct clsrvconf *conf, int ai_flags) { struct addrinfo hints, *addrinfo, *res; char *slash, *s; @@ -1066,55 +1070,6 @@ int tlsconnect(struct server *server, struct timeval *when, int timeout, char *t return 1; } -int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text) { - struct timeval now; - time_t elapsed; - - debug(DBG_DBG, "tcpconnect: called from %s", text); - pthread_mutex_lock(&server->lock); - if (when && memcmp(&server->lastconnecttry, when, sizeof(struct timeval))) { - /* already reconnected, nothing to do */ - debug(DBG_DBG, "tcpconnect(%s): seems already reconnected", text); - pthread_mutex_unlock(&server->lock); - return 1; - } - - for (;;) { - gettimeofday(&now, NULL); - elapsed = now.tv_sec - server->lastconnecttry.tv_sec; - if (timeout && server->lastconnecttry.tv_sec && elapsed > timeout) { - debug(DBG_DBG, "tcpconnect: timeout"); - if (server->sock >= 0) - close(server->sock); - pthread_mutex_unlock(&server->lock); - return 0; - } - if (server->connectionok) { - server->connectionok = 0; - sleep(2); - } else if (elapsed < 1) - sleep(2); - else if (elapsed < 60) { - debug(DBG_INFO, "tcpconnect: sleeping %lds", elapsed); - sleep(elapsed); - } else if (elapsed < 100000) { - debug(DBG_INFO, "tcpconnect: sleeping %ds", 60); - sleep(60); - } else - server->lastconnecttry.tv_sec = now.tv_sec; /* no sleep at startup */ - debug(DBG_WARN, "tcpconnect: trying to open TCP connection to %s port %s", server->conf->host, server->conf->port); - if (server->sock >= 0) - close(server->sock); - if ((server->sock = connecttcp(server->conf->addrinfo, srcprotores[RAD_TCP])) >= 0) - break; - debug(DBG_ERR, "tcpconnect: connecttcp failed"); - } - debug(DBG_WARN, "tcpconnect: TCP connection to %s port %s up", server->conf->host, server->conf->port); - gettimeofday(&server->lastconnecttry, NULL); - pthread_mutex_unlock(&server->lock); - return 1; -} - /* timeout in seconds, 0 means no timeout (blocking), returns when num bytes have been read, or timeout */ /* returns 0 on timeout, -1 on error and num if ok */ int sslreadtimeout(SSL *ssl, unsigned char *buf, int num, int timeout) { @@ -1194,73 +1149,6 @@ unsigned char *radtlsget(SSL *ssl, int timeout) { return rad; } -/* timeout in seconds, 0 means no timeout (blocking), returns when num bytes have been read, or timeout */ -/* returns 0 on timeout, -1 on error and num if ok */ -int tcpreadtimeout(int s, unsigned char *buf, int num, int timeout) { - int ndesc, cnt, len; - fd_set readfds, writefds; - struct timeval timer; - - if (s < 0) - return -1; - /* make socket non-blocking? */ - for (len = 0; len < num; len += cnt) { - FD_ZERO(&readfds); - FD_SET(s, &readfds); - writefds = readfds; - if (timeout) { - timer.tv_sec = timeout; - timer.tv_usec = 0; - } - ndesc = select(s + 1, &readfds, &writefds, NULL, timeout ? &timer : NULL); - if (ndesc < 1) - return ndesc; - - cnt = read(s, buf + len, num - len); - if (cnt <= 0) - return -1; - } - return num; -} - -/* timeout in seconds, 0 means no timeout (blocking) */ -unsigned char *radtcpget(int s, int timeout) { - int cnt, len; - unsigned char buf[4], *rad; - - for (;;) { - cnt = tcpreadtimeout(s, buf, 4, timeout); - if (cnt < 1) { - debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout"); - return NULL; - } - - len = RADLEN(buf); - rad = malloc(len); - if (!rad) { - debug(DBG_ERR, "radtcpget: malloc failed"); - continue; - } - memcpy(rad, buf, 4); - - cnt = tcpreadtimeout(s, rad + 4, len - 4, timeout); - if (cnt < 1) { - debug(DBG_DBG, cnt ? "radtcpget: connection lost" : "radtcpget: timeout"); - free(rad); - return NULL; - } - - if (len >= 20) - break; - - free(rad); - debug(DBG_WARN, "radtcpget: packet smaller than minimum radius size"); - } - - debug(DBG_DBG, "radtcpget: got %d bytes", len); - return rad; -} - int clientradputudp(struct server *server, unsigned char *rad) { size_t len; struct sockaddr_storage sa; @@ -1322,25 +1210,6 @@ int clientradputtls(struct server *server, unsigned char *rad) { return 1; } -int clientradputtcp(struct server *server, unsigned char *rad) { - int cnt; - size_t len; - struct timeval lastconnecttry; - struct clsrvconf *conf = server->conf; - - len = RADLEN(rad); - lastconnecttry = server->lastconnecttry; - while ((cnt = write(server->sock, rad, len)) <= 0) { - debug(DBG_ERR, "clientradputtcp: write error"); - tcpconnect(server, &lastconnecttry, 0, "clientradputtcp"); - lastconnecttry = server->lastconnecttry; - } - - server->connectionok = 1; - debug(DBG_DBG, "clientradputtcp: Sent %d bytes, Radius packet of length %d to TCP peer %s", cnt, len, conf->host); - return 1; -} - int radsign(unsigned char *rad, unsigned char *sec) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static unsigned char first = 1; @@ -2598,27 +2467,6 @@ void *tlsclientrd(void *arg) { return NULL; } -void *tcpclientrd(void *arg) { - struct server *server = (struct server *)arg; - unsigned char *buf; - struct timeval lastconnecttry; - - for (;;) { - /* yes, lastconnecttry is really necessary */ - lastconnecttry = server->lastconnecttry; - buf = radtcpget(server->sock, 0); - if (!buf) { - tcpconnect(server, &lastconnecttry, 0, "tcpclientrd"); - continue; - } - - if (!replyh(server, buf)) - free(buf); - } - server->clientrdgone = 1; - return NULL; -} - /* code for removing state not finished */ void *clientwr(void *arg) { struct server *server = (struct server *)arg; @@ -2987,137 +2835,6 @@ void *tlslistener(void *arg) { return NULL; } -void *tcpserverwr(void *arg) { - int cnt; - struct client *client = (struct client *)arg; - struct queue *replyq; - struct reply *reply; - - debug(DBG_DBG, "tcpserverwr: starting for %s", client->conf->host); - replyq = client->replyq; - for (;;) { - pthread_mutex_lock(&replyq->mutex); - while (!list_first(replyq->entries)) { - if (client->sock >= 0) { - debug(DBG_DBG, "tcpserverwr: waiting for signal"); - pthread_cond_wait(&replyq->cond, &replyq->mutex); - debug(DBG_DBG, "tcpserverwr: got signal"); - } - if (client->sock < 0) { - /* s might have changed while waiting */ - pthread_mutex_unlock(&replyq->mutex); - debug(DBG_DBG, "tcpserverwr: exiting as requested"); - pthread_exit(NULL); - } - } - reply = (struct reply *)list_shift(replyq->entries); - pthread_mutex_unlock(&replyq->mutex); - cnt = write(client->sock, reply->buf, RADLEN(reply->buf)); - if (cnt > 0) - debug(DBG_DBG, "tcpserverwr: sent %d bytes, Radius packet of length %d", - cnt, RADLEN(reply->buf)); - else - debug(DBG_ERR, "tcpserverwr: write error for %s", client->conf->host); - free(reply->buf); - free(reply); - } -} - -void tcpserverrd(struct client *client) { - struct request rq; - pthread_t tcpserverwrth; - - debug(DBG_DBG, "tcpserverrd: starting for %s", client->conf->host); - - if (pthread_create(&tcpserverwrth, NULL, tcpserverwr, (void *)client)) { - debug(DBG_ERR, "tcpserverrd: pthread_create failed"); - return; - } - - for (;;) { - memset(&rq, 0, sizeof(struct request)); - rq.buf = radtcpget(client->sock, 0); - if (!rq.buf) { - debug(DBG_ERR, "tcpserverrd: connection from %s lost", client->conf->host); - break; - } - debug(DBG_DBG, "tcpserverrd: got Radius message from %s", client->conf->host); - rq.from = client; - if (!radsrv(&rq)) { - debug(DBG_ERR, "tcpserverrd: message authentication/validation failed, closing connection from %s", client->conf->host); - break; - } - } - - /* stop writer by setting s to -1 and give signal in case waiting for data */ - client->sock = -1; - pthread_mutex_lock(&client->replyq->mutex); - pthread_cond_signal(&client->replyq->cond); - pthread_mutex_unlock(&client->replyq->mutex); - debug(DBG_DBG, "tcpserverrd: waiting for writer to end"); - pthread_join(tcpserverwrth, NULL); - removeclientrqs(client); - debug(DBG_DBG, "tcpserverrd: reader for %s exiting", client->conf->host); -} - -void *tcpservernew(void *arg) { - int s; - struct sockaddr_storage from; - size_t fromlen = sizeof(from); - struct clsrvconf *conf; - struct client *client; - - s = *(int *)arg; - if (getpeername(s, (struct sockaddr *)&from, &fromlen)) { - debug(DBG_DBG, "tcpservernew: getpeername failed, exiting"); - goto exit; - } - debug(DBG_WARN, "tcpservernew: incoming TCP connection from %s", addr2string((struct sockaddr *)&from, fromlen)); - - conf = find_conf(RAD_TCP, (struct sockaddr *)&from, clconfs, NULL); - if (conf) { - client = addclient(conf); - if (client) { - client->sock = s; - tcpserverrd(client); - removeclient(client); - } else - debug(DBG_WARN, "tcpservernew: failed to create new client instance"); - } else - debug(DBG_WARN, "tcpservernew: ignoring request, no matching TCP client"); - - exit: - shutdown(s, SHUT_RDWR); - close(s); - pthread_exit(NULL); -} - -void *tcplistener(void *arg) { - pthread_t tcpserverth; - int s, *sp = (int *)arg; - struct sockaddr_storage from; - size_t fromlen = sizeof(from); - - listen(*sp, 0); - - for (;;) { - s = accept(*sp, (struct sockaddr *)&from, &fromlen); - if (s < 0) { - debug(DBG_WARN, "accept failed"); - continue; - } - if (pthread_create(&tcpserverth, NULL, tcpservernew, (void *)&s)) { - debug(DBG_ERR, "tcplistener: pthread_create failed"); - shutdown(s, SHUT_RDWR); - close(s); - continue; - } - pthread_detach(tcpserverth); - } - free(sp); - return NULL; -} - void createlistener(uint8_t type, char *arg) { pthread_t th; struct clsrvconf *listenres; -- cgit v1.1