X-Git-Url: http://www.project-moonshot.org/gitweb/?a=blobdiff_plain;f=hostport.c;h=54c1d7465cd5a247a0ae970e3d3a7840fda54680;hb=a21be6733bfe23998f3aaec00d87d35fe0f1aefa;hp=b392346a36b2adfde292af203d50231161768158;hpb=9f542fc2c8905be58015a428f0240ebff20658ef;p=radsecproxy.git diff --git a/hostport.c b/hostport.c index b392346..54c1d74 100644 --- a/hostport.c +++ b/hostport.c @@ -6,15 +6,22 @@ * copyright notice and this permission notice appear in all copies. */ +/* Code contributions from: + * + * Simon Leinen + */ + #include +#include #include #include +#include #include "debug.h" #include "util.h" #include "list.h" #include "hostport.h" -static void freehostport(struct hostportres *hp) { +void freehostport(struct hostportres *hp) { if (hp) { free(hp->host); free(hp->port); @@ -45,7 +52,7 @@ static int parsehostport(struct hostportres *hp, char *hostport, char *default_p ipv6 = 1; } else { field = p; - for (; *p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n'; p++); + for (; *p && *p != ':' && *p != '/' && *p != ' ' && *p != '\t' && *p != '\n'; p++); } if (field == p) { debug(DBG_ERR, "missing host/address"); @@ -55,30 +62,30 @@ static int parsehostport(struct hostportres *hp, char *hostport, char *default_p hp->host = stringcopy(field, p - field); if (ipv6) { p++; - if (*p && *p != ':' && *p != ' ' && *p != '\t' && *p != '\n') { + if (*p && *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); + /* 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; } - -static struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok) { + +struct hostportres *newhostport(char *hostport, char *default_port, uint8_t prefixok) { struct hostportres *hp; char *slash, *s; int plen; - + hp = malloc(sizeof(struct hostportres)); if (!hp) { debug(DBG_ERR, "resolve_newhostport: malloc failed"); @@ -94,7 +101,7 @@ static struct hostportres *newhostport(char *hostport, char *default_port, uint8 hp->host = NULL; } - slash = hp->host ? strchr(hp->host, '/') : NULL; + slash = hostport ? strchr(hostport, '/') : NULL; if (slash) { if (!prefixok) { debug(DBG_WARN, "newhostport: prefix not allowed here", hp->host); @@ -116,17 +123,16 @@ static struct hostportres *newhostport(char *hostport, char *default_port, uint8 goto errexit; } hp->prefixlen = plen; - *slash = '\0'; } else hp->prefixlen = 255; return hp; - errexit: +errexit: freehostport(hp); return NULL; } -static int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) { +int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive) { struct addrinfo hints, *res; memset(&hints, 0, sizeof(hints)); @@ -134,7 +140,7 @@ static int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive 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, "1812" /* can be anything */, &hints, &hp->addrinfo)) { @@ -168,24 +174,33 @@ static int resolvehostport(struct hostportres *hp, int socktype, uint8_t passive } return 1; - errexit: +errexit: if (hp->addrinfo) freeaddrinfo(hp->addrinfo); return 0; -} +} -int addhostport(struct list **hostports, char *hostport, char *portdefault, uint8_t prefixok) { +int addhostport(struct list **hostports, char **hostport, char *portdefault, uint8_t prefixok) { struct hostportres *hp; + int i; - hp = newhostport(hostport, portdefault, prefixok); - if (!hp) - return 0; - if (!*hostports) + if (!*hostports) { *hostports = list_create(); - if (!*hostports || !list_push(*hostports, hp)) { - freehostport(hp); - debug(DBG_ERR, "addhostport: malloc failed"); - return 0; + if (!*hostports) { + debug(DBG_ERR, "addhostport: malloc failed"); + return 0; + } + } + + for (i = 0; hostport[i]; i++) { + hp = newhostport(hostport[i], portdefault, prefixok); + if (!hp) + return 0; + if (!list_push(*hostports, hp)) { + freehostport(hp); + debug(DBG_ERR, "addhostport: malloc failed"); + return 0; + } } return 1; } @@ -201,7 +216,7 @@ void freehostports(struct list *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 && !resolvehostport(hp, socktype, 0)) @@ -233,13 +248,13 @@ static int prefixmatch(void *a1, void *a2, uint8_t len) { return (((uint8_t *)a1)[l] & mask[r]) == (((uint8_t *)a2)[l] & mask[r]); } -int addressmatches(struct list *hostports, struct sockaddr *addr) { +int addressmatches(struct list *hostports, struct sockaddr *addr, uint8_t checkport) { 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)) { @@ -254,9 +269,14 @@ int addressmatches(struct list *hostports, struct sockaddr *addr) { 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)) || + !memcmp(a4, &((struct sockaddr_in *)res->ai_addr)->sin_addr, 4) && + (!checkport || ((struct sockaddr_in *)res->ai_addr)->sin_port == + ((struct sockaddr_in *)addr)->sin_port)) || (sa6 && res->ai_family == AF_INET6 && - !memcmp(&sa6->sin6_addr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16))) + !memcmp(&sa6->sin6_addr, + &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, 16) && + (!checkport || ((struct sockaddr_in6 *)res->ai_addr)->sin6_port == + ((struct sockaddr_in6 *)addr)->sin6_port))) return 1; } else { if ((a4 && res->ai_family == AF_INET && @@ -277,7 +297,7 @@ int connecttcphostlist(struct list *hostports, struct addrinfo *src) { for (entry = list_first(hostports); entry; entry = list_next(entry)) { hp = (struct hostportres *)entry->data; debug(DBG_WARN, "connecttcphostlist: trying to open TCP connection to %s port %s", hp->host, hp->port); - if ((s = connecttcp(hp->addrinfo, src)) >= 0) { + if ((s = connecttcp(hp->addrinfo, src, list_count(hostports) > 1 ? 5 : 30)) >= 0) { debug(DBG_WARN, "connecttcphostlist: TCP connection to %s port %s up", hp->host, hp->port); return s; } @@ -285,3 +305,7 @@ int connecttcphostlist(struct list *hostports, struct addrinfo *src) { debug(DBG_ERR, "connecttcphostlist: failed"); return -1; } + +/* Local Variables: */ +/* c-file-style: "stroustrup" */ +/* End: */