From 883992d876f34a0486e675160a60701dc0a1b66a Mon Sep 17 00:00:00 2001 From: Linus Nordberg Date: Fri, 13 Apr 2012 13:33:44 +0200 Subject: [PATCH] Add client and server config options IPv4Only and IPv6Only. Related to RADSECPROXY-37. TODO: Add documentation. --- dtls.c | 4 +++- hostport.c | 13 +++++++------ hostport.h | 6 +++--- radsecproxy.c | 36 ++++++++++++++++++++++++++++++++---- radsecproxy.h | 1 + tcp.c | 4 +++- tls.c | 4 +++- udp.c | 4 +++- 8 files changed, 55 insertions(+), 17 deletions(-) diff --git a/dtls.c b/dtls.c index 19386c4..bbebfef 100644 --- 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) { diff --git a/hostport.c b/hostport.c index 54c1d74..4214c55 100644 --- a/hostport.c +++ b/hostport.c @@ -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; } diff --git a/hostport.h b/hostport.h index 425bb8f..207e2ba 100644 --- a/hostport.h +++ b/hostport.h @@ -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); diff --git a/radsecproxy.c b/radsecproxy.c index 5e9b5ca..fa72fb2 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -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) diff --git a/radsecproxy.h b/radsecproxy.h index dc09b1e..eb30afd 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -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 --- 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 --- 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 --- 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) { -- 2.1.4