diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | hostport.c | 103 | ||||
-rw-r--r-- | hostport.h | 8 | ||||
-rw-r--r-- | radsecproxy.c | 300 | ||||
-rw-r--r-- | radsecproxy.h | 9 | ||||
-rw-r--r-- | resolve.c | 155 | ||||
-rw-r--r-- | resolve.h | 14 |
8 files changed, 156 insertions, 436 deletions
@@ -1,6 +1,6 @@ CFLAGS = -g -Wall -pedantic -pthread -DRADPROT_UDP -DRADPROT_TCP -DRADPROT_TLS -DRADPROT_DTLS LDFLAGS = -lssl -OBJ = util.o debug.o list.o hash.o gconfig.o tlv11.o radmsg.o udp.o tcp.o tls.o dtls.o tlscommon.o radsecproxy.o +OBJ = util.o debug.o list.o hash.o gconfig.o tlv11.o hostport.o radmsg.o udp.o tcp.o tls.o dtls.o tlscommon.o radsecproxy.o all: radsecproxy diff --git a/Makefile.am b/Makefile.am index dd7d72b..47ff3f9 100644 --- a/Makefile.am +++ b/Makefile.am @@ -8,6 +8,7 @@ radsecproxy_SOURCES = radsecproxy.c \ list.c \ hash.c \ tlv11.c \ + hostport.c \ radmsg.c \ udp.c \ tcp.c \ @@ -11,9 +11,10 @@ #include <netdb.h> #include "debug.h" #include "util.h" -#include "resolve.h" +#include "list.h" +#include "hostport.h" -void resolve_freehostport(struct hostportres *hp) { +static void freehostport(struct hostportres *hp) { if (hp) { free(hp->host); free(hp->port); @@ -23,7 +24,7 @@ void resolve_freehostport(struct hostportres *hp) { } } -static int resolve_parsehostport(struct hostportres *hp, char *hostport, char *default_port) { +static int parsehostport(struct hostportres *hp, char *hostport, char *default_port) { char *p, *field; int ipv6 = 0; @@ -69,7 +70,7 @@ static int resolve_parsehostport(struct hostportres *hp, char *hostport, char *d return 1; } -struct hostportres *resolve_newhostport(char *hostport, char *default_port, uint8_t prefixok) { +static struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok) { struct hostportres *hp; char *slash, *s; int plen; @@ -81,7 +82,7 @@ struct hostportres *resolve_newhostport(char *hostport, char *default_port, uint } memset(hp, 0, sizeof(struct hostportres)); - if (!resolve_parsehostport(hp, hostport, default_port)) + if (!parsehostport(hp, hostport, default_port)) goto errexit; if (!strcmp(hp->host, "*")) { @@ -92,22 +93,22 @@ struct hostportres *resolve_newhostport(char *hostport, char *default_port, uint slash = hp->host ? strchr(hp->host, '/') : NULL; if (slash) { if (!prefixok) { - debug(DBG_WARN, "resolve_newhostport: prefix not allowed here", hp->host); + debug(DBG_WARN, "newhostport: prefix not allowed here", hp->host); goto errexit; } s = slash + 1; if (!*s) { - debug(DBG_WARN, "resolve_newhostport: prefix length must be specified after the / in %s", hp->host); + debug(DBG_WARN, "newhostport: prefix length must be specified after the / in %s", hp->host); goto errexit; } for (; *s; s++) if (*s < '0' || *s > '9') { - debug(DBG_WARN, "resolve_newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); + debug(DBG_WARN, "newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); goto errexit; } plen = atoi(slash + 1); if (plen < 0 || plen > 128) { - debug(DBG_WARN, "resolve_newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); + debug(DBG_WARN, "newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); goto errexit; } hp->prefixlen = plen; @@ -117,11 +118,11 @@ struct hostportres *resolve_newhostport(char *hostport, char *default_port, uint return hp; errexit: - resolve_freehostport(hp); + freehostport(hp); return NULL; } -static int resolve_resolve(struct hostportres *hp, int socktype, uint8_t passive) { +static int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) { struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); @@ -133,7 +134,7 @@ static int resolve_resolve(struct hostportres *hp, int socktype, uint8_t passive if (!hp->host && !hp->port) { /* getaddrinfo() doesn't like host and port to be NULL */ if (getaddrinfo(hp->host, "1812" /* can be anything */, &hints, &hp->addrinfo)) { - debug(DBG_WARN, "resolve_resolve: can't resolve (null) port (null)"); + debug(DBG_WARN, "resolvehostport: can't resolve (null) port (null)"); goto errexit; } for (res = hp->addrinfo; res; res = res->ai_next) @@ -142,21 +143,21 @@ static int resolve_resolve(struct hostportres *hp, int socktype, uint8_t passive if (hp->prefixlen != 255) hints.ai_flags |= AI_NUMERICHOST; if (getaddrinfo(hp->host, hp->port, &hints, &hp->addrinfo)) { - debug(DBG_WARN, "resolve_resolve: can't resolve %s port %s", hp->host ? hp->host : "(null)", hp->port ? hp->port : "(null)"); + debug(DBG_WARN, "resolvehostport: can't resolve %s port %s", hp->host ? hp->host : "(null)", hp->port ? hp->port : "(null)"); goto errexit; } if (hp->prefixlen != 255) { switch (hp->addrinfo->ai_family) { case AF_INET: if (hp->prefixlen > 32) { - debug(DBG_WARN, "resolve_resolve: prefix length must be <= 32 in %s", hp->host); + debug(DBG_WARN, "resolvehostport: prefix length must be <= 32 in %s", hp->host); goto errexit; } break; case AF_INET6: break; default: - debug(DBG_WARN, "resolve_resolve: prefix must be IPv4 or IPv6 in %s", hp->host); + debug(DBG_WARN, "resolvehostport: prefix must be IPv4 or IPv6 in %s", hp->host); goto errexit; } } @@ -169,26 +170,50 @@ static int resolve_resolve(struct hostportres *hp, int socktype, uint8_t passive return 0; } -int resolve_hostports(struct list *hostports, int socktype) { +int addhostport(struct list **hostports, char *hostport, char *portdefault, uint8_t prefixok) { + struct hostportres *hp; + + hp = newhostport(hostport, portdefault, prefixok); + if (!hp) + return 0; + if (!*hostports) + *hostports = list_create(); + if (!*hostports || !list_push(*hostports, hp)) { + freehostport(hp); + debug(DBG_ERR, "addhostport: malloc failed"); + return 0; + } + return 1; +} + +void freehostports(struct list *hostports) { + struct hostportres *hp; + + while ((hp = (struct hostportres *)list_shift(hostports))) + freehostport(hp); + list_destroy(hostports); +} + +int resolvehostports(struct list *hostports, 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 && !resolve_resolve(hp, socktype, 0)) + if (!hp->addrinfo && !resolvehostport(hp, socktype, 0)) return 0; } return 1; } -struct addrinfo *resolve_passiveaddrinfo(char *hostport, char *default_port, int socktype) { +struct addrinfo *resolvepassiveaddrinfo(char *hostport, char *default_port, int socktype) { struct addrinfo *ai = NULL; - struct hostportres *hp = resolve_newhostport(hostport, default_port, 0); - if (hp && resolve_resolve(hp, socktype, 1)) { + struct hostportres *hp = newhostport(hostport, default_port, 0); + if (hp && resolvehostport(hp, socktype, 1)) { ai = hp->addrinfo; hp->addrinfo = NULL; } - resolve_freehostport(hp); + freehostport(hp); return ai; } @@ -203,3 +228,39 @@ static int prefixmatch(void *a1, void *a2, uint8_t len) { return 1; return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]); } + +int addressmatches(struct list *hostports, struct sockaddr *addr) { + struct sockaddr_in6 *sa6 = NULL; + struct in_addr *a4 = NULL; + struct addrinfo *res; + struct list_node *entry; + struct hostportres *hp = NULL; + + if (addr->sa_family == AF_INET6) { + sa6 = (struct sockaddr_in6 *)addr; + if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { + a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12]; + sa6 = NULL; + } + } else + a4 = &((struct sockaddr_in *)addr)->sin_addr; + + for (entry = list_first(hostports); entry; entry = list_next(entry)) { + hp = (struct hostportres *)entry->data; + for (res = hp->addrinfo; res; res = res->ai_next) + if (hp->prefixlen == 255) { + if ((a4 && res->ai_family == AF_INET && + !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) || + (sa6 && res->ai_family == AF_INET6 && + !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16))) + return 1; + } else { + if ((a4 && res->ai_family == AF_INET && + prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, hp->prefixlen)) || + (sa6 && res->ai_family == AF_INET6 && + prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, hp->prefixlen))) + return 1; + } + } + return 0; +} @@ -13,6 +13,8 @@ struct hostportres { struct addrinfo *addrinfo; }; -void resolve_freehostport(struct hostportres *hp); -struct hostportres *resolve_newhostport(char *hostport, char *default_port, uint8_t prefixok); -int resolve_resolve(struct hostportres *hp, int socktype, uint8_t passive); +int addhostport(struct list **hostports, char *hostport, char *portdefault, uint8_t prefixok); +void freehostports(struct list *hostports); +int resolvehostports(struct list *hostports, int socktype); +struct addrinfo *resolvepassiveaddrinfo(char *hostport, char *default_port, int socktype); +int addressmatches(struct list *hostports, struct sockaddr *addr); diff --git a/radsecproxy.c b/radsecproxy.c index 3140c0b..7266597 100644 --- a/radsecproxy.c +++ b/radsecproxy.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -68,6 +68,7 @@ #include "list.h" #include "hash.h" #include "util.h" +#include "hostport.h" #include "radsecproxy.h" #include "udp.h" #include "tcp.h" @@ -119,155 +120,6 @@ void ssl_locking_callback(int mode, int type, const char *file, int line) { pthread_mutex_unlock(&ssl_locks[type]); } -int resolvepeer(struct clsrvconf *conf, int ai_flags) { - struct addrinfo hints, *addrinfo, *res; - char *slash, *s; - int plen = 0; - - slash = conf->host ? strchr(conf->host, '/') : NULL; - if (slash) { - s = slash + 1; - if (!*s) { - debug(DBG_WARN, "resolvepeer: prefix length must be specified after the / in %s", conf->host); - return 0; - } - for (; *s; s++) - if (*s < '0' || *s > '9') { - debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host); - return 0; - } - plen = atoi(slash + 1); - if (plen < 0 || plen > 128) { - debug(DBG_WARN, "resolvepeer: %s in %s is not a valid prefix length", slash + 1, conf->host); - return 0; - } - *slash = '\0'; - } - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = conf->pdef->socktype; - hints.ai_family = AF_UNSPEC; - hints.ai_flags = ai_flags; - if (!conf->host && !conf->port) { - /* getaddrinfo() doesn't like host and port to be NULL */ - if (getaddrinfo(conf->host, conf->pdef->portdefault, &hints, &addrinfo)) { - debug(DBG_WARN, "resolvepeer: can't resolve (null) port (null)"); - return 0; - } - for (res = addrinfo; res; res = res->ai_next) - port_set(res->ai_addr, 0); - } else { - if (slash) - hints.ai_flags |= AI_NUMERICHOST; - if (getaddrinfo(conf->host, conf->port, &hints, &addrinfo)) { - debug(DBG_WARN, "resolvepeer: can't resolve %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); - return 0; - } - if (slash) { - *slash = '/'; - switch (addrinfo->ai_family) { - case AF_INET: - if (plen > 32) { - debug(DBG_WARN, "resolvepeer: prefix length must be <= 32 in %s", conf->host); - freeaddrinfo(addrinfo); - return 0; - } - break; - case AF_INET6: - break; - default: - debug(DBG_WARN, "resolvepeer: prefix must be IPv4 or IPv6 in %s", conf->host); - freeaddrinfo(addrinfo); - return 0; - } - conf->prefixlen = (uint8_t)plen; - } else - conf->prefixlen = 255; - } - if (conf->addrinfo) - freeaddrinfo(conf->addrinfo); - conf->addrinfo = addrinfo; - return 1; -} - -char *parsehostport(char *s, struct clsrvconf *conf, char *default_port) { - char *p, *field; - int ipv6 = 0; - - p = s; - /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */ - if (*p == '[') { - p++; - field = p; - for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++); - if (*p != ']') - debugx(1, DBG_ERR, "no ] matching initial ["); - ipv6 = 1; - } else { - field = p; - for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++); - } - if (field == p) - debugx(1, DBG_ERR, "missing host/address"); - - conf->host = stringcopy(field, p - field); - if (ipv6) { - p++; - if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n') - debugx(1, DBG_ERR, "unexpected character after ]"); - } - if (*p == ':') { - /* port number or service name is specified */; - field = ++p; - for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++); - if (field == p) - debugx(1, DBG_ERR, "syntax error, : but no following port"); - conf->port = stringcopy(field, p - field); - } else - conf->port = default_port ? stringcopy(default_port, 0) : NULL; - return p; -} - -struct clsrvconf *resolve_hostport(uint8_t type, char *lconf, char *default_port) { - struct clsrvconf *conf; - - conf = malloc(sizeof(struct clsrvconf)); - if (!conf) - debugx(1, DBG_ERR, "malloc failed"); - memset(conf, 0, sizeof(struct clsrvconf)); - conf->type = type; - conf->pdef = protodefs[conf->type]; - if (lconf) { - parsehostport(lconf, conf, default_port); - if (!strcmp(conf->host, "*")) { - free(conf->host); - conf->host = NULL; - } - } else - conf->port = default_port ? stringcopy(default_port, 0) : NULL; - if (!resolvepeer(conf, AI_PASSIVE)) - debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); - return conf; -} - -void freeclsrvres(struct clsrvconf *res) { - free(res->host); - free(res->port); - if (res->addrinfo) - freeaddrinfo(res->addrinfo); - free(res); -} - -struct addrinfo *resolve_hostport_addrinfo(uint8_t type, char *hostport) { - struct addrinfo *ai; - struct clsrvconf *res; - - res = resolve_hostport(type, hostport, NULL); - ai = res->addrinfo; - res->addrinfo = NULL; - freeclsrvres(res); - return ai; -} - /* returns 1 if the len first bits are equal, else 0 */ int prefixmatch(void *a1, void *a2, uint8_t len) { static uint8_t mask[] = { 0, 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe }; @@ -282,46 +134,15 @@ int prefixmatch(void *a1, void *a2, uint8_t len) { /* returns next config with matching address, or NULL */ struct clsrvconf *find_conf(uint8_t type, struct sockaddr *addr, struct list *confs, struct list_node **cur) { - struct sockaddr_in6 *sa6 = NULL; - struct in_addr *a4 = NULL; - struct addrinfo *res; struct list_node *entry; struct clsrvconf *conf; - if (addr->sa_family == AF_INET6) { - sa6 = (struct sockaddr_in6 *)addr; - if (IN6_IS_ADDR_V4MAPPED(&sa6->sin6_addr)) { - a4 = (struct in_addr *)&sa6->sin6_addr.s6_addr[12]; - sa6 = NULL; - } - } else - a4 = &((struct sockaddr_in *)addr)->sin_addr; - for (entry = (cur && *cur ? list_next(*cur) : list_first(confs)); entry; entry = list_next(entry)) { conf = (struct clsrvconf *)entry->data; - if (conf->type == type) { - if (conf->prefixlen == 255) { - for (res = conf->addrinfo; res; res = res->ai_next) - if ((a4 && res->ai_family == AF_INET && - !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4)) || - (sa6 && res->ai_family == AF_INET6 && - !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16))) { - if (cur) - *cur = entry; - return conf; - } - } else { - res = conf->addrinfo; - if (res && - ((a4 && res->ai_family == AF_INET && - prefixmatch(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, conf->prefixlen)) || - (sa6 && res->ai_family == AF_INET6 && - prefixmatch(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, conf->prefixlen)))) { - if (cur) - *cur = entry; - return conf; - } - } + if (conf->type == type && addressmatches(conf->hostports, addr)) { + if (cur) + *cur = entry; + return conf; } } return NULL; @@ -681,7 +502,7 @@ void sendrq(struct request *rq) { goto errexit; } - debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->host); + debug(DBG_DBG, "sendrq: inserting packet with id %d in queue for %s", i, to->conf->name); to->requests[i].rq = rq; pthread_mutex_unlock(to->requests[i].lock); if (i >= start) /* i is not reserved for statusserver */ @@ -1434,18 +1255,19 @@ uint8_t *radattr2ascii(struct tlv *attr) { return a; } -void acclog(struct radmsg *msg, char *host) { +void acclog(struct radmsg *msg, struct client *from) { struct tlv *attr; uint8_t *username; - + attr = radmsg_gettype(msg, RAD_Attr_User_Name); if (!attr) { - debug(DBG_INFO, "acclog: accounting-request from %s without username attribute", host); + debug(DBG_INFO, "acclog: accounting-request from client %s (%s) without username attribute", from->conf->name, addr2string(from->addr)); return; } username = radattr2ascii(attr); if (username) { - debug(DBG_INFO, "acclog: accounting-request from %s with username: %s", host, username); + debug(DBG_INFO, "acclog: accounting-request from client %s (%s) with username: %s", from->conf->name, addr2string(from->addr), username); + free(username); } } @@ -1471,7 +1293,7 @@ void respond(struct request *rq, uint8_t code, char *message) { radmsg_free(rq->msg); rq->msg = msg; - debug(DBG_DBG, "respond: sending %s to %s", radmsgtype2string(msg->code), rq->from->conf->host); + debug(DBG_DBG, "respond: sending %s to %s (%s)", radmsgtype2string(msg->code), rq->from->conf->name, addr2string(rq->from->addr)); sendreply(newrqref(rq)); } @@ -1632,7 +1454,7 @@ int radsrv(struct request *rq) { attr = radmsg_gettype(msg, RAD_Attr_User_Name); if (!attr) { if (msg->code == RAD_Accounting_Request) { - acclog(msg, from->conf->host); + acclog(msg, from); respond(rq, RAD_Accounting_Response, NULL); } else debug(DBG_WARN, "radsrv: ignoring access request, no username attribute"); @@ -1658,10 +1480,10 @@ int radsrv(struct request *rq) { if (!to) { if (realm->message && msg->code == RAD_Access_Request) { - debug(DBG_INFO, "radsrv: sending reject to %s for %s", from->conf->host, userascii); + debug(DBG_INFO, "radsrv: sending reject to %s (%s) for %s", from->conf->name, addr2string(from->addr), userascii); respond(rq, RAD_Access_Reject, realm->message); } else if (realm->accresp && msg->code == RAD_Accounting_Request) { - acclog(msg, from->conf->host); + acclog(msg, from); respond(rq, RAD_Accounting_Response, NULL); } goto exit; @@ -1763,7 +1585,7 @@ void replyh(struct server *server, unsigned char *buf) { if (rqout->rq->msg->code == RAD_Status_Server) { freerqoutdata(rqout); - debug(DBG_DBG, "replyh: got status server response from %s", server->conf->host); + debug(DBG_DBG, "replyh: got status server response from %s", server->conf->name); goto errunlock; } @@ -1777,7 +1599,7 @@ void replyh(struct server *server, unsigned char *buf) { ttlres = checkttl(msg, options.ttlattrtype); if (!ttlres) { - debug(DBG_WARN, "replyh: ignoring reply from server %s, ttl exceeded", server->conf->host); + debug(DBG_WARN, "replyh: ignoring reply from server %s, ttl exceeded", server->conf->name); goto errunlock; } @@ -1813,20 +1635,20 @@ void replyh(struct server *server, unsigned char *buf) { if (stationid) { if (replymsg) { debug(DBG_INFO, "%s for user %s stationid %s from %s (%s)", - radmsgtype2string(msg->code), username, stationid, server->conf->host, replymsg); + radmsgtype2string(msg->code), username, stationid, server->conf->name, replymsg); free(replymsg); } else debug(DBG_INFO, "%s for user %s stationid %s from %s", - radmsgtype2string(msg->code), username, stationid, server->conf->host); + radmsgtype2string(msg->code), username, stationid, server->conf->name); free(stationid); } else { if (replymsg) { debug(DBG_INFO, "%s for user %s from %s (%s)", - radmsgtype2string(msg->code), username, server->conf->host, replymsg); + radmsgtype2string(msg->code), username, server->conf->name, replymsg); free(replymsg); } else debug(DBG_INFO, "%s for user %s from %s", - radmsgtype2string(msg->code), username, server->conf->host); + radmsgtype2string(msg->code), username, server->conf->name); } free(username); } @@ -1915,8 +1737,8 @@ void *clientwr(void *arg) { goto errexit; } - if (!conf->addrinfo && !resolvepeer(conf, 0)) { - debug(DBG_WARN, "failed to resolve host %s port %s", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); + if (!resolvehostports(conf->hostports, conf->pdef->socktype)) { + debug(DBG_WARN, "failed to resolve host %s port %s", conf->hostsrc ? conf->hostsrc : "(null)", conf->portsrc ? conf->portsrc : "(null)"); server->dynstartup = 0; sleep(900); goto errexit; @@ -2011,12 +1833,12 @@ void *clientwr(void *arg) { debug(DBG_DBG, "clientwr: removing expired packet from queue"); if (conf->statusserver) { if (*rqout->rq->buf == RAD_Status_Server) { - debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->host); + debug(DBG_WARN, "clientwr: no status server response, %s dead?", conf->name); if (server->lostrqs < 255) server->lostrqs++; } } else { - debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->host); + debug(DBG_WARN, "clientwr: no server response, %s dead?", conf->name); if (server->lostrqs < 255) server->lostrqs++; } @@ -2040,7 +1862,7 @@ void *clientwr(void *arg) { statsrvrq = createstatsrvrq(); if (statsrvrq) { statsrvrq->to = server; - debug(DBG_DBG, "clientwr: sending status server to %s", conf->host); + debug(DBG_DBG, "clientwr: sending status server to %s", conf->name); sendrq(statsrvrq); } } @@ -2062,15 +1884,14 @@ void *clientwr(void *arg) { void createlistener(uint8_t type, char *arg) { pthread_t th; - struct clsrvconf *listenres; - struct addrinfo *res; + struct addrinfo *listenres, *res; int s = -1, on = 1, *sp = NULL; - - listenres = resolve_hostport(type, arg, protodefs[type]->portdefault); + + listenres = resolvepassiveaddrinfo(arg, protodefs[type]->portdefault, protodefs[type]->socktype); if (!listenres) debugx(1, DBG_ERR, "createlistener: failed to resolve %s", arg); - for (res = listenres->addrinfo; res; res = res->ai_next) { + for (res = listenres; res; res = res->ai_next) { s = socket(res->ai_family, res->ai_socktype, res->ai_protocol); if (s < 0) { debug(DBG_WARN, "createlistener: socket failed"); @@ -2080,7 +1901,7 @@ void createlistener(uint8_t type, char *arg) { #ifdef IPV6_V6ONLY if (res->ai_family == AF_INET6) setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)); -#endif +#endif if (bind(s, res->ai_addr, res->ai_addrlen)) { debug(DBG_WARN, "createlistener: bind failed"); close(s); @@ -2099,9 +1920,8 @@ void createlistener(uint8_t type, char *arg) { if (!sp) debugx(1, DBG_ERR, "createlistener: socket/bind failed"); - debug(DBG_WARN, "createlistener: listening for %s on %s:%s", protodefs[type]->name, - listenres->host ? listenres->host : "*", listenres->port); - freeclsrvres(listenres); + debug(DBG_WARN, "createlistener: listening for %s on %s", protodefs[type]->name, arg); + freeaddrinfo(listenres); } void createlisteners(uint8_t type) { @@ -2650,8 +2470,8 @@ int setttlattr(struct options *opts, char *defaultattr) { void freeclsrvconf(struct clsrvconf *conf) { free(conf->name); - free(conf->host); - free(conf->port); + free(conf->hostsrc); + free(conf->portsrc); free(conf->secret); free(conf->tls); free(conf->matchcertattr); @@ -2670,8 +2490,8 @@ void freeclsrvconf(struct clsrvconf *conf) { free(conf->dynamiclookupcommand); free(conf->rewritein); free(conf->rewriteout); - if (conf->addrinfo) - freeaddrinfo(conf->addrinfo); + if (conf->hostports) + freehostports(conf->hostports); if (conf->lock) { pthread_mutex_destroy(conf->lock); free(conf->lock); @@ -2702,8 +2522,8 @@ int mergeconfstring(char **dst, char **src) { /* assumes dst is a shallow copy */ int mergesrvconf(struct clsrvconf *dst, struct clsrvconf *src) { if (!mergeconfstring(&dst->name, &src->name) || - !mergeconfstring(&dst->host, &src->host) || - !mergeconfstring(&dst->port, &src->port) || + !mergeconfstring(&dst->hostsrc, &src->hostsrc) || + !mergeconfstring(&dst->portsrc, &src->portsrc) || !mergeconfstring(&dst->secret, &src->secret) || !mergeconfstring(&dst->tls, &src->tls) || !mergeconfstring(&dst->matchcertattr, &src->matchcertattr) || @@ -2737,7 +2557,7 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char if (!getgenericconfig(cf, block, "type", CONF_STR, &conftype, - "host", CONF_STR, &conf->host, + "host", CONF_STR, &conf->hostsrc, "secret", CONF_STR, &conf->secret, #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) "tls", CONF_STR, &conf->tls, @@ -2755,9 +2575,9 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char debugx(1, DBG_ERR, "configuration error"); conf->name = stringcopy(val, 0); - if (!conf->host) - conf->host = stringcopy(val, 0); - if (!conf->name || !conf->host) + if (!conf->hostsrc) + conf->hostsrc = stringcopy(val, 0); + if (!conf->name || !conf->hostsrc) debugx(1, DBG_ERR, "malloc failed"); if (!conftype) @@ -2804,9 +2624,10 @@ int confclient_cb(struct gconffile **cf, void *arg, char *block, char *opt, char if (!conf->rewriteusername) debugx(1, DBG_ERR, "error in block %s, invalid RewriteAttributeValue", block); } - - if (!resolvepeer(conf, 0)) - debugx(1, DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); + + if (!addhostport(&conf->hostports, conf->hostsrc, conf->pdef->portdefault, 1) || + !resolvehostports(conf->hostports, conf->pdef->socktype)) + debugx(1, DBG_ERR, "failed to resolve %s, exiting", conf->hostsrc ? conf->hostsrc : "(null)"); if (!conf->secret) { if (!conf->pdef->secretdefault) @@ -2841,9 +2662,9 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { } #endif - if (!conf->port) { - conf->port = stringcopy(conf->pdef->portdefault, 0); - if (!conf->port) { + if (!conf->portsrc) { + conf->portsrc = stringcopy(conf->pdef->portdefault, 0); + if (!conf->portsrc) { debug(DBG_ERR, "malloc failed"); return 0; } @@ -2857,9 +2678,14 @@ int compileserverconfig(struct clsrvconf *conf, const char *block) { conf->rewritein = conf->confrewritein ? getrewrite(conf->confrewritein, NULL) : getrewrite("defaultserver", "default"); if (conf->confrewriteout) conf->rewriteout = getrewrite(conf->confrewriteout, NULL); + + if (!addhostport(&conf->hostports, conf->hostsrc, conf->portsrc, 0)) { + debug(DBG_ERR, "error in block %s, failed to parse %s", block, conf->hostsrc); + return 0; + } - if (!conf->dynamiclookupcommand && !resolvepeer(conf, 0)) { - debug(DBG_ERR, "failed to resolve host %s port %s, exiting", conf->host ? conf->host : "(null)", conf->port ? conf->port : "(null)"); + if (!conf->dynamiclookupcommand && !resolvehostports(conf->hostports, conf->pdef->socktype)) { + debug(DBG_ERR, "resolve host %s port %s, exiting", conf->hostsrc ? conf->hostsrc : "(null)", conf->portsrc ? conf->portsrc : "(null)"); return 0; } return 1; @@ -2887,8 +2713,8 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char if (!getgenericconfig(cf, block, "type", CONF_STR, &conftype, - "host", CONF_STR, &conf->host, - "port", CONF_STR, &conf->port, + "host", CONF_STR, &conf->hostsrc, + "port", CONF_STR, &conf->portsrc, "secret", CONF_STR, &conf->secret, #if defined(RADPROT_TLS) || defined(RADPROT_DTLS) "tls", CONF_STR, &conf->tls, @@ -2914,9 +2740,9 @@ int confserver_cb(struct gconffile **cf, void *arg, char *block, char *opt, char debug(DBG_ERR, "malloc failed"); goto errexit; } - if (!conf->host) { - conf->host = stringcopy(val, 0); - if (!conf->host) { + if (!conf->hostsrc) { + conf->hostsrc = stringcopy(val, 0); + if (!conf->hostsrc) { debug(DBG_ERR, "malloc failed"); goto errexit; } diff --git a/radsecproxy.h b/radsecproxy.h index 36c5317..3794272 100644 --- a/radsecproxy.h +++ b/radsecproxy.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2008 Stig Venaas <venaas@uninett.no> + * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -79,8 +79,9 @@ struct clsrvconf { char *name; uint8_t type; /* RAD_UDP/RAD_TLS/RAD_TCP */ const struct protodefs *pdef; - char *host; - char *port; + char *hostsrc; + char *portsrc; + struct list *hostports; char *secret; char *tls; char *matchcertattr; @@ -99,8 +100,6 @@ struct clsrvconf { uint8_t addttl; struct rewrite *rewritein; struct rewrite *rewriteout; - struct addrinfo *addrinfo; - uint8_t prefixlen; pthread_mutex_t *lock; /* only used for updating clients so far */ struct tls *tlsconf; struct list *clients; diff --git a/resolve.c b/resolve.c deleted file mode 100644 index 198181c..0000000 --- a/resolve.c +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - -void resolve_freehostport(struct hostportres *hp) { - if (hp) { - free(hp->host); - free(hp->port); - if (hp->addrinfo) - freeaddrinfo(hp->addrinfo); - free(hp); - } -} - -int resolve_parsehostport(struct hostportres *hp, char *hostport, char *default_port) { - char *p, *field; - int ipv6 = 0; - - p = hostport; - /* allow literal addresses and port, e.g. [2001:db8::1]:1812 */ - if (*p == '[') { - p++; - field = p; - for (; *p && *p != ']' && *p != ' ' && *p != '\t' && *p != '\n'; p++); - if (*p != ']') { - debug(DBG_ERR, "no ] matching initial ["); - return 0; - } - ipv6 = 1; - } else { - field = p; - for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++); - } - if (field == p) { - debug(DBG_ERR, "missing host/address"); - return 0; - } - - hp->host = stringcopy(field, p - field); - if (ipv6) { - p++; - if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n') { - debug(DBG_ERR, "unexpected character after ]"); - return 0; - } - } - if (*p == ':') { - /* port number or service name is specified */; - field = ++p; - for (; *p && *p != ' ' && *p != '\t' && *p != '\n'; p++); - if (field == p) { - debug(DBG_ERR, "syntax error, : but no following port"); - return 0; - } - hp->port = stringcopy(field, p - field); - } else - hp->port = default_port ? stringcopy(default_port, 0) : NULL; - return 1; -} - -struct hostportres *resolve_newhostport(char *hostport, char *default_port, int socktype, uint8_t passive, uint8_t prefixok) { - struct hostportres *hp; - struct addrinfo hints, *res; - char *slash, *s; - int plen = 0; - - hp = malloc(sizeof(struct hostportres)); - if (!hp) { - debug(DBG_ERR, "resolve_newhostport: malloc failed"); - goto errexit; - } - memset(hp, 0, sizeof(struct hostportres)); - - if (!resolve_parsehostport(hp, hostport, default_port)) - goto errexit; - - if (!strcmp(hp->host, "*")) { - free(hp->host); - hp->host = NULL; - } - - slash = hp->host ? strchr(hp->host, '/') : NULL; - if (slash) { - if (!prefixok) { - debug(DBG_WARN, "resolve_newhostport: prefix not allowed here", hp->host); - goto errexit; - } - s = slash + 1; - if (!*s) { - debug(DBG_WARN, "resolve_newhostport: prefix length must be specified after the / in %s", hp->host); - goto errexit; - } - for (; *s; s++) - if (*s < '0' || *s > '9') { - debug(DBG_WARN, "resolve_newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); - goto errexit; - } - plen = atoi(slash + 1); - if (plen < 0 || plen > 128) { - debug(DBG_WARN, "resolve_newhostport: %s in %s is not a valid prefix length", slash + 1, hp->host); - goto errexit; - } - *slash = '\0'; - } - - memset(&hints, 0, sizeof(hints)); - hints.ai_socktype = socktype; - hints.ai_family = AF_UNSPEC; - if (passive) - hints.ai_flags = AI_PASSIVE; - - if (!hp->host && !hp->port) { - /* getaddrinfo() doesn't like host and port to be NULL */ - if (getaddrinfo(hp->host, default_port, &hints, &hp->addrinfo)) { - debug(DBG_WARN, "resolve_newhostport: can't resolve (null) port (null)"); - goto errexit; - } - for (res = hp->addrinfo; res; res = res->ai_next) - port_set(res->ai_addr, 0); - } else { - if (slash) - hints.ai_flags |= AI_NUMERICHOST; - if (getaddrinfo(hp->host, hp->port, &hints, &hp->addrinfo)) { - debug(DBG_WARN, "resolve_newhostport: can't resolve %s port %s", hp->host ? hp->host : "(null)", hp->port ? hp->port : "(null)"); - goto errexit; - } - if (slash) { - *slash = '/'; - switch (hp->addrinfo->ai_family) { - case AF_INET: - if (plen > 32) { - debug(DBG_WARN, "resolve_newhostport: prefix length must be <= 32 in %s", hp->host); - goto errexit; - } - break; - case AF_INET6: - break; - default: - debug(DBG_WARN, "resolve_newhostport: prefix must be IPv4 or IPv6 in %s", hp->host); - goto errexit; - } - hp->prefixlen = (uint8_t)plen; - } else - hp->prefixlen = 255; - } - return hp; - - errexit: - resolve_freehostport(hostportres); - return NULL; -} diff --git a/resolve.h b/resolve.h deleted file mode 100644 index fdb83b9..0000000 --- a/resolve.h +++ /dev/null @@ -1,14 +0,0 @@ -/* - * Copyright (C) 2006-2009 Stig Venaas <venaas@uninett.no> - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - */ - -struct hostportres { - char *host; - char *port; - uint8_t prefixlen; - struct addrinfo *addrinfo; -}; |