Commit 67902f98 authored by venaas's avatar venaas Committed by venaas

rewriting code for hosts,ports,resolving,currently does not build

git-svn-id: https://svn.testnett.uninett.no/radsecproxy/trunk@461 e88ac4ed-0b26-0410-9574-a7f39faa03bf
parent c8f99534
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
......
......@@ -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);
This diff is collapsed.
/*
* 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;
......
/*
* 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;
}
/*
* 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;
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment