2 * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no>
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
10 #include <sys/socket.h>
11 #include <netinet/in.h>
20 #include <sys/types.h>
21 #include <sys/select.h>
24 #include <arpa/inet.h>
27 #include <openssl/ssl.h>
31 #include "radsecproxy.h"
34 /* exactly one of client and server must be non-NULL */
35 /* return who we received from in *client or *server */
36 /* return from in sa if not NULL */
37 unsigned char *radudpget(int s, struct client **client, struct server **server, struct sockaddr_storage *sa) {
39 unsigned char buf[4], *rad = NULL;
40 struct sockaddr_storage from;
41 socklen_t fromlen = sizeof(from);
43 struct list_node *node;
53 if (select(s + 1, &readfds, NULL, NULL, NULL) < 1)
55 cnt = recvfrom(s, buf, 4, MSG_PEEK | MSG_TRUNC, (struct sockaddr *)&from, &fromlen);
57 debug(DBG_WARN, "radudpget: recv failed");
61 debug(DBG_WARN, "radudpget: length too small");
67 ? find_clconf(RAD_UDP, (struct sockaddr *)&from, NULL)
68 : find_srvconf(RAD_UDP, (struct sockaddr *)&from, NULL);
70 debug(DBG_WARN, "radudpget: got packet from wrong or unknown UDP peer %s, ignoring", addr2string((struct sockaddr *)&from, fromlen));
77 debug(DBG_WARN, "radudpget: length too small");
84 debug(DBG_ERR, "radudpget: malloc failed");
89 cnt = recv(s, rad, len, MSG_TRUNC);
90 debug(DBG_DBG, "radudpget: got %d bytes from %s", cnt, addr2string((struct sockaddr *)&from, fromlen));
93 debug(DBG_WARN, "radudpget: packet smaller than length field in radius header");
97 debug(DBG_DBG, "radudpget: packet was padded with %d bytes", cnt - len);
100 node = list_first(p->clients);
101 *client = node ? (struct client *)node->data : addclient(p);
105 *server = p->servers;
113 int clientradputudp(struct server *server, unsigned char *rad) {
115 struct sockaddr_storage sa;
116 struct sockaddr *sap;
117 struct clsrvconf *conf = server->conf;
118 in_port_t *port = NULL;
122 if (*rad == RAD_Accounting_Request) {
123 sap = (struct sockaddr *)&sa;
124 memcpy(sap, conf->addrinfo->ai_addr, conf->addrinfo->ai_addrlen);
126 sap = conf->addrinfo->ai_addr;
128 switch (sap->sa_family) {
130 port = &((struct sockaddr_in *)sap)->sin_port;
133 port = &((struct sockaddr_in6 *)sap)->sin6_port;
139 if (*rad == RAD_Accounting_Request)
140 *port = htons(ntohs(*port) + 1);
142 if (sendto(server->sock, rad, len, 0, sap, conf->addrinfo->ai_addrlen) >= 0) {
143 debug(DBG_DBG, "clienradputudp: sent UDP of length %d to %s port %d", len, conf->host, ntohs(*port));
147 debug(DBG_WARN, "clientradputudp: send failed");
151 void *udpclientrd(void *arg) {
152 struct server *server;
158 buf = radudpget(*s, NULL, &server, NULL);
159 if (!replyh(server, buf))
164 void *udpserverrd(void *arg) {
166 int *sp = (int *)arg;
169 memset(&rq, 0, sizeof(struct request));
170 rq.buf = radudpget(*sp, &rq.from, NULL, &rq.fromsa);
171 rq.fromudpsock = *sp;
177 void *udpserverwr(void *arg) {
178 struct queue *replyq = (struct queue *)arg;
182 pthread_mutex_lock(&replyq->mutex);
183 while (!(reply = (struct reply *)list_shift(replyq->entries))) {
184 debug(DBG_DBG, "udp server writer, waiting for signal");
185 pthread_cond_wait(&replyq->cond, &replyq->mutex);
186 debug(DBG_DBG, "udp server writer, got signal");
188 pthread_mutex_unlock(&replyq->mutex);
190 if (sendto(reply->toudpsock, reply->buf, RADLEN(reply->buf), 0,
191 (struct sockaddr *)&reply->tosa, SOCKADDR_SIZE(reply->tosa)) < 0)
192 debug(DBG_WARN, "sendudp: send failed");