summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--radsecproxy.c95
-rw-r--r--radsecproxy.conf-example8
-rw-r--r--radsecproxy.h2
-rw-r--r--util.c27
4 files changed, 85 insertions, 47 deletions
diff --git a/radsecproxy.c b/radsecproxy.c
index 59d207a..3956da0 100644
--- a/radsecproxy.c
+++ b/radsecproxy.c
@@ -61,6 +61,8 @@ static int server_udp_count = 0;
static int server_tls_count = 0;
static int server_count = 0;
+static struct peer *tcp_server_listen;
+static struct peer *udp_server_listen;
static struct replyq udp_server_replyq;
static int udp_server_sock = -1;
static pthread_mutex_t *ssl_locks;
@@ -190,12 +192,13 @@ void printauth(char *s, unsigned char *t) {
printf("\n");
}
-int resolvepeer(struct peer *peer) {
+int resolvepeer(struct peer *peer, int ai_flags) {
struct addrinfo hints, *addrinfo;
memset(&hints, 0, sizeof(hints));
hints.ai_socktype = (peer->type == 'T' ? SOCK_STREAM : SOCK_DGRAM);
hints.ai_family = AF_UNSPEC;
+ hints.ai_flags = ai_flags;
if (getaddrinfo(peer->host, peer->port, &hints, &addrinfo)) {
err("resolvepeer: can't resolve %s port %s", peer->host, peer->port);
return 0;
@@ -226,6 +229,25 @@ int connecttoserver(struct addrinfo *addrinfo) {
return s;
}
+int bindtoaddr(struct addrinfo *addrinfo) {
+ int s, on = 1;
+ struct addrinfo *res;
+
+ for (res = addrinfo; res; res = res->ai_next) {
+ s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (s < 0) {
+ err("bindtoaddr: socket failed");
+ continue;
+ }
+ setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ if (!bind(s, res->ai_addr, res->ai_addrlen))
+ return s;
+ err("bindtoaddr: bind failed");
+ close(s);
+ }
+ return -1;
+}
+
/* returns the client with matching address, or NULL */
/* if client argument is not NULL, we only check that one client */
struct client *find_client(char type, struct sockaddr *addr, struct client *client) {
@@ -1378,12 +1400,12 @@ void *udpserverrd(void *arg) {
struct server *to;
struct client *fr;
pthread_t udpserverwrth;
-
- if ((udp_server_sock = bindport(SOCK_DGRAM, options.udpserverport)) < 0) {
+
+ if ((udp_server_sock = bindtoaddr(udp_server_listen->addrinfo)) < 0) {
printf("udpserverrd: socket/bind failed\n");
exit(1);
}
- printf("udpserverrd: listening on UDP port %s\n", options.udpserverport);
+ printf("udpserverrd: listening for UDP on host %s port %s\n", udp_server_listen->host, udp_server_listen->port);
if (pthread_create(&udpserverwrth, NULL, udpserverwr, NULL))
errx("pthread_create failed");
@@ -1500,18 +1522,20 @@ int tlslistener() {
size_t fromlen = sizeof(from);
struct client *client;
- if ((s = bindport(SOCK_STREAM, DEFAULT_TLS_PORT)) < 0) {
+ if ((s = bindtoaddr(tcp_server_listen->addrinfo)) < 0) {
printf("tlslistener: socket/bind failed\n");
exit(1);
}
listen(s, 0);
- printf("listening for incoming TLS on port %s\n", DEFAULT_TLS_PORT);
+ printf("listening for incoming TCP on address %s port %s\n", tcp_server_listen->host, tcp_server_listen->port);
for (;;) {
snew = accept(s, (struct sockaddr *)&from, &fromlen);
- if (snew < 0)
- errx("accept failed");
+ if (snew < 0) {
+ err("accept failed");
+ continue;
+ }
printf("incoming TLS connection from %s\n", addr2string((struct sockaddr *)&from, fromlen));
client = find_client('T', (struct sockaddr *)&from, NULL);
@@ -1730,8 +1754,8 @@ void getconfig(const char *serverfile, const char *clientfile) {
}
}
- if ((serverfile && !resolvepeer(&server->peer)) ||
- (clientfile && !resolvepeer(&client->peer))) {
+ if ((serverfile && !resolvepeer(&server->peer, 0)) ||
+ (clientfile && !resolvepeer(&client->peer, 0))) {
printf("failed to resolve host %s port %s, exiting\n", peer->host, peer->port);
exit(1);
}
@@ -1773,6 +1797,33 @@ void getconfig(const char *serverfile, const char *clientfile) {
fclose(f);
}
+struct peer *server_create(char type) {
+ struct peer *server;
+ char *conf;
+
+ server = malloc(sizeof(struct peer));
+ if (!server)
+ errx("malloc failed");
+ memset(server, 0, sizeof(struct peer));
+ server->type = type;
+ conf = (type == 'T' ? options.listentcp : options.listenudp);
+ if (conf) {
+ parsehostport(conf, server);
+ if (!strcmp(server->host, "*")) {
+ free(server->host);
+ server->host = NULL;
+ }
+ } else if (type == 'T')
+ server->port = stringcopy(DEFAULT_TLS_PORT, 0);
+ else
+ server->port = stringcopy(options.udpserverport ? options.udpserverport : DEFAULT_UDP_PORT, 0);
+ if (!resolvepeer(server, AI_PASSIVE)) {
+ printf("failed to resolve host %s port %s, exiting\n", server->host, server->port);
+ exit(1);
+ }
+ return server;
+}
+
void getmainconfig(const char *configfile) {
FILE *f;
char line[1024];
@@ -1826,14 +1877,18 @@ void getmainconfig(const char *configfile) {
options.udpserverport = stringcopy(val, 0);
continue;
}
-
+ if (!strcasecmp(opt, "ListenUDP")) {
+ options.listenudp = stringcopy(val, 0);
+ continue;
+ }
+ if (!strcasecmp(opt, "ListenTCP")) {
+ options.listentcp = stringcopy(val, 0);
+ continue;
+ }
printf("error in %s, unknown option %s\n", configfile, opt);
exit(1);
}
fclose(f);
-
- if (!options.udpserverport)
- options.udpserverport = stringcopy(DEFAULT_UDP_PORT, 0);
}
#if 0
@@ -1871,10 +1926,12 @@ int main(int argc, char **argv) {
/* pthread_attr_init(&joinable); */
/* pthread_attr_setdetachstate(&joinable, PTHREAD_CREATE_JOINABLE); */
- if (client_udp_count)
+ if (client_udp_count) {
+ udp_server_listen = server_create('U');
if (pthread_create(&udpserverth, NULL /*&joinable*/, udpserverrd, NULL))
errx("pthread_create failed");
-
+ }
+
if (client_tls_count || server_tls_count)
ssl_ctx = ssl_init();
@@ -1882,9 +1939,11 @@ int main(int argc, char **argv) {
if (pthread_create(&servers[i].clientth, NULL, clientwr, (void *)&servers[i]))
errx("pthread_create failed");
- if (client_tls_count)
+ if (client_tls_count) {
+ tcp_server_listen = server_create('T');
return tlslistener();
-
+ }
+
/* just hang around doing nothing, anything to do here? */
for (;;)
sleep(1000);
diff --git a/radsecproxy.conf-example b/radsecproxy.conf-example
index 94321c0..2648e78 100644
--- a/radsecproxy.conf-example
+++ b/radsecproxy.conf-example
@@ -12,5 +12,9 @@ TLSCertificateKeyFile /etc/hostcertkey/host.example.com.key.pem
# Optionally specify password if key is encrypted (not very secure)
TLSCertificateKeyPassword follow the white rabbit
-# You can optionally specify a non-standard UDP port to listen
-#UDPServerPort 1814
+# You can optionally specify addresses and ports to listen on
+# Max one of each, below are just multiple examples
+#ListenUDP *:1814
+#listenUDP localhost
+#listenTCP 10.10.10.10:2084
+#ListenTCP [2001:700:1:7:215:f2ff:fe35:307d]:2084
diff --git a/radsecproxy.h b/radsecproxy.h
index 9a71de3..e1ffb53 100644
--- a/radsecproxy.h
+++ b/radsecproxy.h
@@ -54,6 +54,8 @@ struct options {
char *tlscertificatekeyfile;
char *tlscertificatekeypassword;
char *udpserverport;
+ char *listenudp;
+ char *listentcp;
};
/* requests that our client will send */
diff --git a/util.c b/util.c
index 3c48e71..ae733eb 100644
--- a/util.c
+++ b/util.c
@@ -83,33 +83,6 @@ char *addr2string(struct sockaddr *addr, socklen_t len) {
return addr_buf[i];
}
-int bindport(int type, char *port) {
- struct addrinfo hints, *res0, *res;
- int s, one = 1;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_socktype = type;
- hints.ai_family = AF_UNSPEC;
- hints.ai_flags = AI_PASSIVE;
-
- if (getaddrinfo(NULL, port, &hints, &res0) != 0) {
- err("bindport: can't resolve port %s", port);
- return -1;
- }
- for (res = res0; res; res = res->ai_next) {
- s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s >= 0) {
- setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
- if (bind(s, res->ai_addr, res->ai_addrlen) == 0)
- break;
- close(s);
- s = -1;
- }
- }
- freeaddrinfo(res0);
- return s;
-}
-
int connectport(int type, char *host, char *port) {
struct addrinfo hints, *res0, *res;
int s;