From: venaas Date: Thu, 21 Aug 2008 08:27:09 +0000 (+0000) Subject: separated udp X-Git-Tag: radsecproxy-1.4-beta1~185 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=radsecproxy.git;a=commitdiff_plain;h=193b6127860d8bd6ec638fb3d74ceff63698fb8d separated udp git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@350 e88ac4ed-0b26-0410-9574-a7f39faa03bf --- diff --git a/Makefile b/Makefile index 06a09d4..51d2b95 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ CFLAGS = -g -Wall -pedantic -pthread LDFLAGS = -lssl -OBJ = util.o debug.o list.o gconfig.o tcp.o tls.o dtls.o radsecproxy.o +OBJ = util.o debug.o list.o gconfig.o udp.o tcp.o tls.o dtls.o radsecproxy.o all: radsecproxy diff --git a/Makefile.am b/Makefile.am index 0bf27aa..505791b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -5,6 +5,7 @@ radsecproxy_SOURCES = radsecproxy.c \ util.c \ debug.c \ list.c \ + udp.c \ tcp.c \ tls.c \ dtls.c \ @@ -13,6 +14,7 @@ radsecproxy_SOURCES = radsecproxy.c \ debug.h \ util.h \ list.h \ + udp.h \ tcp.h \ tls.h \ dtls.h diff --git a/radsecproxy.c b/radsecproxy.c index 1a9fc54..63dba64 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -64,6 +64,7 @@ #include "util.h" #include "gconfig.h" #include "radsecproxy.h" +#include "udp.h" #include "tcp.h" #include "tls.h" #include "dtls.h" @@ -92,11 +93,6 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char void freerealm(struct realm *realm); void freeclsrvconf(struct clsrvconf *conf); void freerqdata(struct request *rq); -void *udpserverrd(void *arg); -void *udpclientrd(void *arg); -int clientradputudp(struct server *server, unsigned char *rad); -X509 *verifytlscert(SSL *ssl); -int radsrv(struct request *rq); static const struct protodefs protodefs[] = { { "udp", /* UDP, assuming RAD_UDP defined as 0 */ @@ -728,83 +724,6 @@ int addserver(struct clsrvconf *conf) { return 0; } -/* exactly one of client and server must be non-NULL */ -/* return who we received from in *client or *server */ -/* return from in sa if not NULL */ -unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) { - int cnt, len; - unsigned char buf[4], *rad = NULL; - struct sockaddr_storage from; - socklen_t fromlen = sizeof(from); - struct clsrvconf *p; - struct list_node *node; - fd_set readfds; - - for (;;) { - if (rad) { - free(rad); - rad = NULL; - } - FD_ZERO(&readfds); - FD_SET(s, &readfds); - if (select(s + 1, &readfds, NULL, NULL, NULL) < 1) - continue; - cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen); - if (cnt == -1) { - debug(DBG_WARN, "radudpget: recv failed"); - continue; - } - if (cnt < 20) { - debug(DBG_WARN, "radudpget: length too small"); - recv(s, buf, 4, 0); - continue; - } - - p = find_conf(RAD_UDP, (struct sockaddr *)&from, client ? clconfs : srvconfs, NULL); - if (!p) { - debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen)); - recv(s, buf, 4, 0); - continue; - } - - len = RADLEN(buf); - if (len < 20) { - debug(DBG_WARN, "radudpget: length too small"); - recv(s, buf, 4, 0); - continue; - } - - rad = malloc(len); - if (!rad) { - debug(DBG_ERR, "radudpget: malloc failed"); - recv(s, buf, 4, 0); - continue; - } - - cnt = recv(s, rad, len, MSG_TRUNC); - debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen)); - - if (cnt < len) { - debug(DBG_WARN, "radudpget: packet smaller than length field in radius header"); - continue; - } - if (cnt > len) - debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); - - if (client) { - node = list_first(p->clients); - *client = node ? (struct client *)node->data : addclient(p); - if (!*client) - continue; - } else if (server) - *server = p->servers; - break; - } - if (sa) - *sa = from; - return rad; -} - int subjectaltnameaddr(X509 *cert, int family, struct in6_addr *addr) { int loc, i, l, n, r = 0; char *v; @@ -993,44 +912,6 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) { return 1; } -int clientradputudp(struct server *server, unsigned char *rad) { - size_t len; - struct sockaddr_storage sa; - struct sockaddr *sap; - struct clsrvconf *conf = server->conf; - in_port_t *port = NULL; - - len = RADLEN(rad); - - if (*rad == RAD_Accounting_Request) { - sap = (struct sockaddr *)&sa; - memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen); - } else - sap = conf->addrinfo->ai_addr; - - switch (sap->sa_family) { - case AF_INET: - port = &((struct sockaddr_in *)sap)->sin_port; - break; - case AF_INET6: - port = &((struct sockaddr_in6 *)sap)->sin6_port; - break; - default: - return 0; - } - - if (*rad == RAD_Accounting_Request) - *port = htons(ntohs(*port) + 1); - - if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) { - debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port)); - return 1; - } - - debug(DBG_WARN, "clientradputudp: send failed"); - return 0; -} - int radsign(unsigned char *rad, unsigned char *sec) { static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; static unsigned char first = 1; @@ -2244,19 +2125,6 @@ int replyh(struct server *server, unsigned char *buf) { return 1; } -void *udpclientrd(void *arg) { - struct server *server; - unsigned char *buf; - int *s = (int *)arg; - - for (;;) { - server = NULL; - buf = radudpget(*s, NULL, &server, NULL); - if (!replyh(server, buf)) - free(buf); - } -} - /* code for removing state not finished */ void *clientwr(void *arg) { struct server *server = (struct server *)arg; @@ -2429,40 +2297,6 @@ void *clientwr(void *arg) { return NULL; } -void *udpserverwr(void *arg) { - struct queue *replyq = udp_server_replyq; - struct reply *reply; - - for (;;) { - pthread_mutex_lock(&replyq->mutex); - while (!(reply = (struct reply *)list_shift(replyq->entries))) { - debug(DBG_DBG, "udp server writer, waiting for signal"); - pthread_cond_wait(&replyq->cond, &replyq->mutex); - debug(DBG_DBG, "udp server writer, got signal"); - } - pthread_mutex_unlock(&replyq->mutex); - - if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0, - (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0) - debug(DBG_WARN, "sendudp: send failed"); - free(reply->buf); - free(reply); - } -} - -void *udpserverrd(void *arg) { - struct request rq; - int *sp = (int *)arg; - - for (;;) { - memset(&rq, 0, sizeof(struct request)); - rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa); - rq.fromudpsock = *sp; - radsrv(&rq); - } - free(sp); -} - void createlistener(uint8_t type, char *arg) { pthread_t th; struct clsrvconf *listenres; @@ -3755,7 +3589,7 @@ int main(int argc, char **argv) { if (find_conf_type(RAD_UDP, clconfs, NULL)) { udp_server_replyq = newqueue(); - if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL)) + if (pthread_create(&udpserverwrth, NULL, udpserverwr, (void *)udp_server_replyq)) debugx(1, DBG_ERR, "pthread_create failed"); createlisteners(RAD_UDP, options.listenudp); if (options.listenaccudp) diff --git a/tcp.c b/tcp.c index e33e4c7..6f6fec8 100644 --- a/tcp.c +++ b/tcp.c @@ -25,7 +25,6 @@ #include #include #include -#include #include "debug.h" #include "list.h" #include "util.h" diff --git a/udp.c b/udp.c new file mode 100644 index 0000000..470e6d8 --- /dev/null +++ b/udp.c @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2006-2008 Stig Venaas + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +#include +#include +#include +#include +#include +#include +#include +#ifdef SYS_SOLARIS9 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "debug.h" +#include "list.h" +#include "util.h" +#include "radsecproxy.h" +#include "tls.h" + +/* exactly one of client and server must be non-NULL */ +/* return who we received from in *client or *server */ +/* return from in sa if not NULL */ +unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) { + int cnt, len; + unsigned char buf[4], *rad = NULL; + struct sockaddr_storage from; + socklen_t fromlen = sizeof(from); + struct clsrvconf *p; + struct list_node *node; + fd_set readfds; + + for (;;) { + if (rad) { + free(rad); + rad = NULL; + } + FD_ZERO(&readfds); + FD_SET(s, &readfds); + if (select(s + 1, &readfds, NULL, NULL, NULL) < 1) + continue; + cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen); + if (cnt == -1) { + debug(DBG_WARN, "radudpget: recv failed"); + continue; + } + if (cnt < 20) { + debug(DBG_WARN, "radudpget: length too small"); + recv(s, buf, 4, 0); + continue; + } + + p = client + ? find_clconf(RAD_UDP, (struct sockaddr *)&from, NULL) + : find_srvconf(RAD_UDP, (struct sockaddr *)&from, NULL); + if (!p) { + debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen)); + recv(s, buf, 4, 0); + continue; + } + + len = RADLEN(buf); + if (len < 20) { + debug(DBG_WARN, "radudpget: length too small"); + recv(s, buf, 4, 0); + continue; + } + + rad = malloc(len); + if (!rad) { + debug(DBG_ERR, "radudpget: malloc failed"); + recv(s, buf, 4, 0); + continue; + } + + cnt = recv(s, rad, len, MSG_TRUNC); + debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen)); + + if (cnt < len) { + debug(DBG_WARN, "radudpget: packet smaller than length field in radius header"); + continue; + } + if (cnt > len) + debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len); + + if (client) { + node = list_first(p->clients); + *client = node ? (struct client *)node->data : addclient(p); + if (!*client) + continue; + } else if (server) + *server = p->servers; + break; + } + if (sa) + *sa = from; + return rad; +} + +int clientradputudp(struct server *server, unsigned char *rad) { + size_t len; + struct sockaddr_storage sa; + struct sockaddr *sap; + struct clsrvconf *conf = server->conf; + in_port_t *port = NULL; + + len = RADLEN(rad); + + if (*rad == RAD_Accounting_Request) { + sap = (struct sockaddr *)&sa; + memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen); + } else + sap = conf->addrinfo->ai_addr; + + switch (sap->sa_family) { + case AF_INET: + port = &((struct sockaddr_in *)sap)->sin_port; + break; + case AF_INET6: + port = &((struct sockaddr_in6 *)sap)->sin6_port; + break; + default: + return 0; + } + + if (*rad == RAD_Accounting_Request) + *port = htons(ntohs(*port) + 1); + + if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) { + debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port)); + return 1; + } + + debug(DBG_WARN, "clientradputudp: send failed"); + return 0; +} + +void *udpclientrd(void *arg) { + struct server *server; + unsigned char *buf; + int *s = (int *)arg; + + for (;;) { + server = NULL; + buf = radudpget(*s, NULL, &server, NULL); + if (!replyh(server, buf)) + free(buf); + } +} + +void *udpserverrd(void *arg) { + struct request rq; + int *sp = (int *)arg; + + for (;;) { + memset(&rq, 0, sizeof(struct request)); + rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa); + rq.fromudpsock = *sp; + radsrv(&rq); + } + free(sp); +} + +void *udpserverwr(void *arg) { + struct queue *replyq = (struct queue *)arg; + struct reply *reply; + + for (;;) { + pthread_mutex_lock(&replyq->mutex); + while (!(reply = (struct reply *)list_shift(replyq->entries))) { + debug(DBG_DBG, "udp server writer, waiting for signal"); + pthread_cond_wait(&replyq->cond, &replyq->mutex); + debug(DBG_DBG, "udp server writer, got signal"); + } + pthread_mutex_unlock(&replyq->mutex); + + if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0, + (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0) + debug(DBG_WARN, "sendudp: send failed"); + free(reply->buf); + free(reply); + } +} diff --git a/udp.h b/udp.h new file mode 100644 index 0000000..af375d6 --- /dev/null +++ b/udp.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2006-2008 Stig Venaas + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + */ + +int clientradputudp(struct server *server, unsigned char *rad); +void *udpclientrd(void *arg); +void *udpserverrd(void *arg); +void *udpserverwr(void *arg);