Add client and server config options IPv4Only and IPv6Only.
authorLinus Nordberg <linus@nordu.net>
Fri, 13 Apr 2012 11:33:44 +0000 (13:33 +0200)
committerLinus Nordberg <linus@nordu.net>
Tue, 17 Apr 2012 07:11:49 +0000 (09:11 +0200)
Related to RADSECPROXY-37.

TODO: Add documentation.

dtls.c
hostport.c
hostport.h
radsecproxy.c
radsecproxy.h
tcp.c
tls.c
udp.c

diff --git a/dtls.c b/dtls.c
index 19386c4..bbebfef 100644 (file)
--- a/dtls.c
+++ b/dtls.c
@@ -99,7 +99,9 @@ struct dtlsservernewparams {
 
 void dtlssetsrcres() {
     if (!srcres)
-       srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, NULL, protodefs.socktype);
+       srcres =
+            resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL,
+                                   AF_UNSPEC, NULL, protodefs.socktype);
 }
 
 int udp2bio(int s, struct gqueue *q, int cnt) {
index 54c1d74..4214c55 100644 (file)
@@ -132,12 +132,12 @@ errexit:
     return NULL;
 }
 
-int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) {
+int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passive) {
     struct addrinfo hints, *res;
 
     memset(&hints, 0, sizeof(hints));
     hints.ai_socktype = socktype;
-    hints.ai_family = AF_UNSPEC;
+    hints.ai_family = af;
     if (passive)
        hints.ai_flags = AI_PASSIVE;
 
@@ -172,6 +172,7 @@ int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) {
            }
        }
     }
+    debug(DBG_DBG, "%s: %s -> %s", __func__, hp->host, addr2string(hp->addrinfo->ai_addr));
     return 1;
 
 errexit:
@@ -213,22 +214,22 @@ void freehostports(struct list *hostports) {
     list_destroy(hostports);
 }
 
-int resolvehostports(struct list *hostports, int socktype) {
+int resolvehostports(struct list *hostports, int af, int socktype) {
     struct list_node *entry;
     struct hostportres *hp;
 
     for (entry = list_first(hostports); entry; entry = list_next(entry)) {
        hp = (struct hostportres *)entry->data;
-       if (!hp->addrinfo && !resolvehostport(hp, socktype, 0))
+       if (!hp->addrinfo && !resolvehostport(hp, af, socktype, 0))
            return 0;
     }
     return 1;
 }
 
-struct addrinfo *resolvepassiveaddrinfo(char *hostport, char *default_port, int socktype) {
+struct addrinfo *resolvepassiveaddrinfo(char *hostport, int af, char *default_port, int socktype) {
     struct addrinfo *ai = NULL;
     struct hostportres *hp = newhostport(hostport, default_port, 0);
-    if (hp && resolvehostport(hp, socktype, 1)) {
+    if (hp && resolvehostport(hp, af, socktype, 1)) {
        ai = hp->addrinfo;
        hp->addrinfo = NULL;
     }
index 425bb8f..207e2ba 100644 (file)
@@ -17,9 +17,9 @@ struct hostportres *newhostport(char *hostport, char *default_port, uint8_t pref
 int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok);
 void freehostport(struct hostportres *hp);
 void freehostports(struct list *hostports);
-int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive);
-int resolvehostports(struct list *hostports, int socktype);
-struct addrinfo *resolvepassiveaddrinfo(char *hostport, char *default_port, int socktype);
+int resolvehostport(struct hostportres *hp, int af, int socktype, uint8_t passive);
+int resolvehostports(struct list *hostports, int af, int socktype);
+struct addrinfo *resolvepassiveaddrinfo(char *hostport, int af, char *default_port, int socktype);
 int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport);
 int connecttcphostlist(struct list *hostports,  struct addrinfo *src);
 
index 5e9b5ca..fa72fb2 100644 (file)
@@ -1773,7 +1773,7 @@ void *clientwr(void *arg) {
     /* FIXME: Is resolving not always done by compileserverconfig(),
      * either as part of static configuration setup or by
      * dynamicconfig() above?  */
-    if (!resolvehostports(conf->hostports, conf->pdef->socktype)) {
+    if (!resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype)) {
         debug(DBG_WARN, "%s: resolve failed, sleeping %ds", __func__, ZZZ);
         sleep(ZZZ);
         goto errexit;
@@ -1926,7 +1926,7 @@ void createlistener(uint8_t type, char *arg) {
     int s = -1, on = 1, *sp = NULL;
     struct hostportres *hp = newhostport(arg, protodefs[type]->portdefault, 0);
 
-    if (!hp || !resolvehostport(hp, protodefs[type]->socktype, 1))
+    if (!hp || !resolvehostport(hp, AF_UNSPEC, protodefs[type]->socktype, 1))
        debugx(1, DBG_ERR, "createlistener: failed to resolve %s", arg);
 
     for (res = hp->addrinfo; res; res = res->ai_next) {
@@ -2684,10 +2684,25 @@ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) {
     return 1;
 }
 
+int config_hostaf(const char *block, int ipv4only, int ipv6only, int *af) {
+    if (ipv4only && ipv6only) {
+       debug(DBG_ERR, "error in block %s, at most one of IPv4Only and "
+              "IPv6Only can be enabled", block);
+        return -1;
+    }
+    *af = AF_UNSPEC;
+    if (ipv4only)
+        *af = AF_INET;
+    if (ipv6only)
+        *af = AF_INET6;
+    return 0;
+}
+
 int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val) {
     struct clsrvconf *conf;
     char *conftype = NULL, *rewriteinalias = NULL;
     long int dupinterval = LONG_MIN, addttl = LONG_MIN;
+    uint8_t ipv4only, ipv6only;
 
     debug(DBG_DBG, "confclient_cb called for %s", block);
 
@@ -2701,6 +2716,8 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
            cf, block,
            "type", CONF_STR, &conftype,
            "host", CONF_MSTR, &conf->hostsrc,
+            "IPv4Only", CONF_BLN, &ipv4only,
+            "IPv6Only", CONF_BLN, &ipv6only,
            "secret", CONF_STR, &conf->secret,
 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
            "tls", CONF_STR, &conf->tls,
@@ -2752,6 +2769,9 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     }
 #endif
 
+    if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf))
+        debugx(1, DBG_ERR, "error in block %s: ^", block);
+
     if (dupinterval != LONG_MIN) {
        if (dupinterval < 0 || dupinterval > 255)
            debugx(1, DBG_ERR, "error in block %s, value of option DuplicateInterval is %d, must be 0-255", block, dupinterval);
@@ -2782,7 +2802,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     }
 
     if (!addhostport(&conf->hostports, conf->hostsrc, conf->pdef->portdefault, 1) ||
-       !resolvehostports(conf->hostports, conf->pdef->socktype))
+       !resolvehostports(conf->hostports, conf->hostaf, conf->pdef->socktype))
        debugx(1, DBG_ERR, "%s: resolve failed, exiting", __func__);
 
     if (!conf->secret) {
@@ -2844,7 +2864,9 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) {
        return 0;
     }
 
-    if (!conf->dynamiclookupcommand && !resolvehostports(conf->hostports, conf->pdef->socktype)) {
+    if (!conf->dynamiclookupcommand &&
+        !resolvehostports(conf->hostports, conf->hostaf,
+                          conf->pdef->socktype)) {
        debug(DBG_ERR, "%s: resolve failed", __func__);
        return 0;
     }
@@ -2855,6 +2877,7 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     struct clsrvconf *conf, *resconf;
     char *conftype = NULL, *rewriteinalias = NULL;
     long int retryinterval = LONG_MIN, retrycount = LONG_MIN, addttl = LONG_MIN;
+    uint8_t ipv4only, ipv6only;
 
     debug(DBG_DBG, "confserver_cb called for %s", block);
 
@@ -2875,6 +2898,8 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     if (!getgenericconfig(cf, block,
                          "type", CONF_STR, &conftype,
                          "host", CONF_MSTR, &conf->hostsrc,
+                          "IPv4Only", CONF_BLN, &ipv4only,
+                          "IPv6Only", CONF_BLN, &ipv6only,
                          "port", CONF_STR, &conf->portsrc,
                          "secret", CONF_STR, &conf->secret,
 #if defined(RADPROT_TLS) || defined(RADPROT_DTLS)
@@ -2922,6 +2947,9 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char
     free(conftype);
     conftype = NULL;
 
+    if (config_hostaf(block, ipv4only, ipv6only, &conf->hostaf))
+        goto errexit;
+
     conf->pdef = protodefs[conf->type];
 
     if (!conf->confrewritein)
index dc09b1e..eb30afd 100644 (file)
@@ -106,6 +106,7 @@ struct clsrvconf {
     uint8_t type; /* RAD_UDP/RAD_TLS/RAD_TCP */
     const struct protodefs *pdef;
     char **hostsrc;
+    int hostaf;
     char *portsrc;
     struct list *hostports;
     char *secret;
diff --git a/tcp.c b/tcp.c
index 797ec9e..86fa9b6 100644 (file)
--- a/tcp.c
+++ b/tcp.c
@@ -78,7 +78,9 @@ static char **getlistenerargs() {
 
 void tcpsetsrcres() {
     if (!srcres)
-       srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, NULL, protodefs.socktype);
+       srcres =
+            resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL,
+                                   AF_UNSPEC, NULL, protodefs.socktype);
 }
 
 int tcpconnect(struct server *server, struct timeval *when, int timeout, char *text) {
diff --git a/tls.c b/tls.c
index 0282d63..ba2c5a3 100644 (file)
--- a/tls.c
+++ b/tls.c
@@ -82,7 +82,9 @@ static char **getlistenerargs() {
 
 void tlssetsrcres() {
     if (!srcres)
-       srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, NULL, protodefs.socktype);
+       srcres =
+            resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL,
+                                   AF_UNSPEC, NULL, protodefs.socktype);
 }
 
 int tlsconnect(struct server *server, struct timeval *when, int timeout, char *text) {
diff --git a/udp.c b/udp.c
index 7614f2e..c804703 100644 (file)
--- a/udp.c
+++ b/udp.c
@@ -86,7 +86,9 @@ static char **getlistenerargs() {
 
 void udpsetsrcres() {
     if (!srcres)
-       srcres = resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL, NULL, protodefs.socktype);
+       srcres =
+            resolvepassiveaddrinfo(protoopts ? protoopts->sourcearg : NULL,
+                                   AF_UNSPEC, NULL, protodefs.socktype);
 }
 
 void removeudpclientfromreplyq(struct client *c) {