added tcp and udp listen directives
authorvenaas <venaas>
Fri, 16 Feb 2007 08:53:15 +0000 (08:53 +0000)
committervenaas <venaas@e88ac4ed-0b26-0410-9574-a7f39faa03bf>
Fri, 16 Feb 2007 08:53:15 +0000 (08:53 +0000)
git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@60 e88ac4ed-0b26-0410-9574-a7f39faa03bf

radsecproxy.c
radsecproxy.conf-example
radsecproxy.h
util.c

index 59d207a..3956da0 100644 (file)
@@ -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);
index 94321c0..2648e78 100644 (file)
@@ -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
index 9a71de3..e1ffb53 100644 (file)
@@ -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 (file)
--- 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;