summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/conf.c30
-rw-r--r--lib/conn.c61
-rw-r--r--lib/err.c11
-rw-r--r--lib/include/radsec/radsec-impl.h26
-rw-r--r--lib/include/radsec/radsec.h4
-rw-r--r--lib/packet.c166
-rw-r--r--lib/radsec.c89
8 files changed, 252 insertions, 137 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index a76de88..d43198b 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -31,4 +31,4 @@ libradsec_la_SOURCES += \
endif
libradsec_la_LDFLAGS = -version-info 0:0:0
-libradsec_la_CFLAGS = $(AM_CFLAGS) #-DDEBUG -DDEBUG_LEVENT
+libradsec_la_CFLAGS = $(AM_CFLAGS) #-DDEBUG -DDEBUG_LEVENT -Werror
diff --git a/lib/conf.c b/lib/conf.c
index 8519922..5c1c51b 100644
--- a/lib/conf.c
+++ b/lib/conf.c
@@ -8,11 +8,14 @@
#include <string.h>
#include <radsec/radsec.h>
#include <radsec/radsec-impl.h>
+#include "debug.h"
#if 0
- # example of client config
+ # client config options
config NAME {
type = "UDP"|"TCP"|"TLS"|"DTLS"
+ timeout = INT
+ retries = INT
cacertfile = STRING
#cacertpath = STRING
certfile = STRING
@@ -21,8 +24,6 @@
hostname = STRING
service = STRING
secret = STRING
- timeout = INT /* optional */
- tries = INT /* optional */
}
}
#endif
@@ -30,19 +31,21 @@
int
rs_context_read_config(struct rs_context *ctx, const char *config_file)
{
-#warning "Missing some error handling in rs_context_read_config()"
+
+ /* FIXME: Missing some error handling in rs_context_read_config(). */
+
cfg_opt_t server_opts[] =
{
CFG_STR ("hostname", NULL, CFGF_NONE),
CFG_STR ("service", "radius", CFGF_NONE),
CFG_STR ("secret", NULL, CFGF_NONE),
- CFG_INT ("timeout", 3, CFGF_NONE),
- CFG_INT ("tries", 1, CFGF_NONE),
CFG_END ()
};
cfg_opt_t config_opts[] =
{
CFG_STR ("type", "UDP", CFGF_NONE),
+ CFG_INT ("timeout", 2, CFGF_NONE),
+ CFG_INT ("retries", 2, CFGF_NONE),
CFG_STR ("cacertfile", NULL, CFGF_NONE),
/*CFG_STR ("cacertpath", NULL, CFGF_NONE),*/
CFG_STR ("certfile", NULL, CFGF_NONE),
@@ -70,8 +73,13 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
if (!r)
return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
memset (r, 0, sizeof(*r));
- r->next = ctx->realms->next;
- ctx->realms->next = r;
+ if (ctx->realms)
+ {
+ r->next = ctx->realms->next;
+ ctx->realms->next = r;
+ }
+ else
+ ctx->realms = r;
cfg_config = cfg_getnsec (cfg, "config", i);
r->name = strdup (cfg_title (cfg_config));
@@ -87,6 +95,8 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
else
return rs_err_ctx_push_fl (ctx, RSE_CONFIG, __FILE__, __LINE__,
"invalid connection type: %s", typestr);
+ r->timeout = cfg_getint (cfg_config, "timeout");
+ r->retries = cfg_getint (cfg_config, "retries");
r->cacertfile = cfg_getstr (cfg_config, "cacertfile");
/*r->cacertpath = cfg_getstr (cfg_config, "cacertpath");*/
@@ -106,8 +116,6 @@ rs_context_read_config(struct rs_context *ctx, const char *config_file)
_rs_resolv (&p->addr, r->type, cfg_getstr (cfg_server, "hostname"),
cfg_getstr (cfg_server, "service"));
p->secret = strdup (cfg_getstr (cfg_server, "secret"));
- p->timeout = cfg_getint (cfg_server, "timeout");
- p->tries = cfg_getint (cfg_server, "tries");
}
}
return RSE_OK;
@@ -118,7 +126,7 @@ rs_conf_find_realm(struct rs_context *ctx, const char *name)
{
struct rs_realm *r;
- for (r = ctx->realms->next; r != ctx->realms; r = r->next)
+ for (r = ctx->realms; r; r = r->next)
if (!strcmp (r->name, name))
return r;
return NULL;
diff --git a/lib/conn.c b/lib/conn.c
index 717eba6..784c316 100644
--- a/lib/conn.c
+++ b/lib/conn.c
@@ -18,37 +18,50 @@ rs_conn_create (struct rs_context *ctx, struct rs_connection **conn,
struct rs_connection *c;
c = (struct rs_connection *) malloc (sizeof(struct rs_connection));
- if (c)
+ if (!c)
+ return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
+
+ memset (c, 0, sizeof(struct rs_connection));
+ c->ctx = ctx;
+ c->fd = -1;
+ if (config)
{
- memset (c, 0, sizeof(struct rs_connection));
- c->ctx = ctx;
- if (config)
+ struct rs_realm *r = rs_conf_find_realm (ctx, config);
+ if (r)
+ {
+ struct rs_peer *p;
+
+ c->realm = r;
+ c->peers = r->peers; /* FIXME: Copy instead? */
+ for (p = c->peers; p; p = p->next)
+ p->conn = c;
+ c->tryagain = r->retries;
+ }
+ else
{
- struct rs_realm *r = rs_conf_find_realm (ctx, config);
- if (r)
- {
- struct rs_peer *p;
-
- c->type = r->type;
- c->peers = r->peers; /* FIXME: Copy instead? */
- for (p = c->peers; p; p = p->next)
- p->conn = c;
- }
+ c->realm = rs_malloc (ctx, sizeof (struct rs_realm));
+ if (!c->realm)
+ return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__,
+ NULL);
+ memset (c->realm, 0, sizeof (struct rs_realm));
}
}
+
if (conn)
*conn = c;
- return c ? RSE_OK : rs_err_ctx_push (ctx, RSE_NOMEM, NULL);
+ return RSE_OK;
}
void
rs_conn_set_type (struct rs_connection *conn, rs_conn_type_t type)
{
- conn->type = type;
+ assert (conn);
+ assert (conn->realm);
+ conn->realm->type = type;
}
-struct rs_error *
+struct rs_error * /* FIXME: Return int as all the others? */
_rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type,
const char *hostname, const char *service)
{
@@ -74,6 +87,8 @@ _rs_resolv (struct evutil_addrinfo **addr, rs_conn_type_t type,
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
break;
+ default:
+ return _rs_err_create (RSE_INVALID_CONN, __FILE__, __LINE__, NULL, NULL);
}
err = evutil_getaddrinfo (hostname, service, &hints, &res);
if (err)
@@ -100,8 +115,8 @@ rs_conn_disconnect (struct rs_connection *conn)
assert (conn);
- err = evutil_closesocket (conn->active_peer->fd);
- conn->active_peer->fd = -1;
+ err = evutil_closesocket (conn->fd);
+ conn->fd = -1;
return err;
}
@@ -113,13 +128,15 @@ rs_conn_destroy (struct rs_connection *conn)
assert (conn);
- if (conn->active_peer->is_connected)
+ if (conn->is_connected)
{
err = rs_conn_disconnect (conn);
if (err)
return err;
}
+ /* NOTE: conn->realm is owned by context. */
+
for (p = conn->peers; p; p = p->next)
{
if (p->addr)
@@ -128,6 +145,8 @@ rs_conn_destroy (struct rs_connection *conn)
rs_free (conn->ctx, p->secret);
}
+ if (conn->tev)
+ event_free (conn->tev);
if (conn->evb)
event_base_free (conn->evb);
@@ -183,5 +202,5 @@ int rs_conn_fd (struct rs_connection *conn)
{
assert (conn);
assert (conn->active_peer);
- return conn->active_peer->fd;
+ return conn->fd;
}
diff --git a/lib/err.c b/lib/err.c
index a7ddeb9..1ad76a6 100644
--- a/lib/err.c
+++ b/lib/err.c
@@ -27,7 +27,7 @@ static const char *_errtxt[] = {
"internal error", /* 13 RSE_INTERNAL */
"SSL error", /* 14 RSE_SSLERR */
"invalid packet", /* 15 RSE_INVALID_PKT */
- "ERR 16", /* RSE_ */
+ "I/O timeout", /* 16 RSE_IOTIMEOUT */
"ERR 17", /* RSE_ */
"ERR 18", /* RSE_ */
"ERR 19", /* RSE_ */
@@ -177,6 +177,15 @@ rs_err_conn_pop (struct rs_connection *conn)
return err;
}
+int
+rs_err_conn_peek_code (struct rs_connection *conn)
+{
+ if (conn && conn->err)
+ return conn->err->code;
+ else
+ return RSE_OK;
+}
+
void
rs_err_free (struct rs_error *err)
{
diff --git a/lib/include/radsec/radsec-impl.h b/lib/include/radsec/radsec-impl.h
index 14801ab..b5dafef 100644
--- a/lib/include/radsec/radsec-impl.h
+++ b/lib/include/radsec/radsec-impl.h
@@ -23,8 +23,6 @@ typedef unsigned int rs_cred_type_t;
extern "C" {
#endif
-struct rs_packet;
-
struct rs_credentials {
enum rs_cred_type type;
char *identity;
@@ -37,22 +35,19 @@ struct rs_error {
char buf[1024];
};
-struct rs_peer {
+struct rs_peer { /* Config object for a connection. */
struct rs_connection *conn;
struct rs_realm *realm;
struct evutil_addrinfo *addr;
- int fd; /* Socket. */
- char is_connecting; /* FIXME: replace with a single state member */
- char is_connected; /* FIXME: replace with a single state member */
char *secret;
- int timeout; /* client only */
- int tries; /* client only */
struct rs_peer *next;
};
-struct rs_realm {
+struct rs_realm { /* Config object for a RADIUS realm. */
char *name;
enum rs_conn_type type;
+ int timeout;
+ int retries;
char *cacertfile;
char *cacertpath;
char *certfile;
@@ -70,15 +65,20 @@ struct rs_context {
struct rs_connection {
struct rs_context *ctx;
- struct event_base *evb;
- struct bufferevent *bev;
- enum rs_conn_type type;
+ struct rs_realm *realm; /* Owned by ctx. */
+ struct event_base *evb; /* Event base. */
+ struct bufferevent *bev; /* Buffer event. */
+ struct event *tev; /* Timeout event. */
struct rs_credentials transport_credentials;
struct rs_conn_callbacks callbacks;
void *user_data;
struct rs_peer *peers;
struct rs_peer *active_peer;
struct rs_error *err;
+ char is_connecting; /* FIXME: replace with a single state member */
+ char is_connected; /* FIXME: replace with a single state member */
+ int fd; /* Socket. */
+ int tryagain;
int nextid;
int user_dispatch_flag : 1; /* User does the dispatching. */
#if defined(RS_ENABLE_TLS)
@@ -125,6 +125,8 @@ int _rs_err_conn_push_err(struct rs_connection *conn,
(h->alloc_scheme.free ? h->alloc_scheme.free : free)(ptr)
#define rs_realloc(h, realloc, ptr, size) \
(h->alloc_scheme.realloc ? h->alloc_scheme.realloc : realloc)(ptr, size)
+#define min(a, b) ((a) < (b) ? (a) : (b))
+#define max(a, b) ((a) > (b) ? (a) : (b))
/* Local Variables: */
/* c-file-style: "stroustrup" */
diff --git a/lib/include/radsec/radsec.h b/lib/include/radsec/radsec.h
index d609118..c929111 100644
--- a/lib/include/radsec/radsec.h
+++ b/lib/include/radsec/radsec.h
@@ -21,6 +21,7 @@ enum rs_err_code {
RSE_INTERNAL = 13,
RSE_SSLERR = 14, /* OpenSSL error. */
RSE_INVALID_PKT = 15,
+ RSE_IOTIMEOUT = 16,
RSE_SOME_ERROR = 21, /* Unspecified error. Shouldn't happen. */
};
@@ -115,7 +116,7 @@ int rs_server_set_address(struct rs_peer *server, const char *hostname,
const char *service);
int rs_server_set_secret(struct rs_peer *server, const char *secret);
void rs_server_set_timeout(struct rs_peer *server, int timeout);
-void rs_server_set_tries(struct rs_peer *server, int tries);
+void rs_server_set_retries(struct rs_peer *server, int retries);
/* Packet. */
int rs_packet_create(struct rs_connection *conn, struct rs_packet **pkt_out);
@@ -149,6 +150,7 @@ int rs_err_conn_push(struct rs_connection *conn, int code, const char *fmt,
int rs_err_conn_push_fl(struct rs_connection *conn, int code,
const char *file, int line, const char *fmt, ...);
struct rs_error *rs_err_conn_pop(struct rs_connection *conn);
+int rs_err_conn_peek_code (struct rs_connection *conn);
void rs_err_free(struct rs_error *err);
char *rs_err_msg(struct rs_error *err, int dofree_flag);
int rs_err_code(struct rs_error *err, int dofree_flag);
diff --git a/lib/packet.c b/lib/packet.c
index 9c6edf2..c8f4af1 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -6,6 +6,8 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
+#include <sys/time.h>
#include <assert.h>
#include <freeradius/libradius.h>
#include <event2/event.h>
@@ -63,14 +65,14 @@ _do_send (struct rs_packet *pkt)
if (err < 0)
return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_write: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
return RSE_OK;
}
static void
_on_connect (struct rs_connection *conn)
{
- conn->active_peer->is_connected = 1;
+ conn->is_connected = 1;
rs_debug (("%s: %p connected\n", __func__, conn->active_peer));
if (conn->callbacks.connected_cb)
conn->callbacks.connected_cb (conn->user_data);
@@ -79,7 +81,8 @@ _on_connect (struct rs_connection *conn)
static void
_on_disconnect (struct rs_connection *conn)
{
- conn->active_peer->is_connected = 0;
+ conn->is_connecting = 0;
+ conn->is_connected = 0;
rs_debug (("%s: %p disconnected\n", __func__, conn->active_peer));
if (conn->callbacks.disconnected_cb)
conn->callbacks.disconnected_cb (conn->user_data);
@@ -89,11 +92,11 @@ static void
_event_cb (struct bufferevent *bev, short events, void *ctx)
{
struct rs_packet *pkt = (struct rs_packet *)ctx;
- struct rs_connection *conn;
- struct rs_peer *p;
- int sockerr;
+ struct rs_connection *conn = NULL;
+ struct rs_peer *p = NULL;
+ int sockerr = 0;
#if defined (RS_ENABLE_TLS)
- unsigned long tlserr;
+ unsigned long tlserr = 0;
#endif
assert (pkt);
@@ -102,7 +105,7 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
conn = pkt->conn;
p = conn->active_peer;
- p->is_connecting = 0;
+ conn->is_connecting = 0;
if (events & BEV_EVENT_CONNECTED)
{
_on_connect (conn);
@@ -113,6 +116,12 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
{
_on_disconnect (conn);
}
+ else if (events & BEV_EVENT_TIMEOUT)
+ {
+ rs_debug (("%s: %p times out on %s\n", __func__, p,
+ (events & BEV_EVENT_READING) ? "read" : "write"));
+ rs_err_conn_push_fl (pkt->conn, RSE_IOTIMEOUT, __FILE__, __LINE__, NULL);
+ }
else if (events & BEV_EVENT_ERROR)
{
sockerr = evutil_socket_geterror (conn->active_peer->fd);
@@ -124,11 +133,12 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
{
rs_err_conn_push_fl (pkt->conn, RSE_SOCKERR, __FILE__, __LINE__,
"%d: socket error %d (%s)",
- conn->active_peer->fd,
+ conn->fd,
sockerr,
evutil_socket_error_to_string (sockerr));
- rs_debug (("%s: socket error on fd %d: %d\n", __func__,
- conn->active_peer->fd,
+ rs_debug (("%s: socket error on fd %d: %s (%d)\n", __func__,
+ conn->fd,
+ evutil_socket_error_to_string (sockerr),
sockerr));
}
#if defined (RS_ENABLE_TLS)
@@ -146,6 +156,11 @@ _event_cb (struct bufferevent *bev, short events, void *ctx)
}
#endif /* RS_ENABLE_TLS */
}
+
+#if defined (DEBUG)
+ if (events & BEV_EVENT_ERROR && events != BEV_EVENT_ERROR)
+ rs_debug (("%s: BEV_EVENT_ERROR and more: 0x%x\n", __func__, events));
+#endif
}
static void
@@ -308,7 +323,7 @@ _read_cb (struct bufferevent *bev, void *ctx)
assert (pkt->conn);
assert (pkt->rpkt);
- pkt->rpkt->sockfd = pkt->conn->active_peer->fd;
+ pkt->rpkt->sockfd = pkt->conn->fd;
pkt->rpkt->vps = NULL;
if (!pkt->hdr_read_flag)
@@ -348,35 +363,37 @@ _evlog_cb (int severity, const char *msg)
static int
_init_evb (struct rs_connection *conn)
{
- if (!conn->evb)
- {
+ if (conn->evb)
+ return RSE_OK;
+
#if defined (DEBUG)
- event_enable_debug_mode ();
+ event_enable_debug_mode ();
#endif
- event_set_log_callback (_evlog_cb);
- conn->evb = event_base_new ();
- if (!conn->evb)
- return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
- "event_base_new");
- }
+ event_set_log_callback (_evlog_cb);
+ conn->evb = event_base_new ();
+ if (!conn->evb)
+ return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "event_base_new");
+
return RSE_OK;
}
static int
_init_socket (struct rs_connection *conn, struct rs_peer *p)
{
- if (p->fd != -1)
+ if (conn->fd != -1)
return RSE_OK;
assert (p->addr);
- p->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
- p->addr->ai_protocol);
- if (p->fd < 0)
+ conn->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
+ p->addr->ai_protocol);
+ if (conn->fd < 0)
return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
strerror (errno));
- if (evutil_make_socket_nonblocking (p->fd) < 0)
+ if (evutil_make_socket_nonblocking (conn->fd) < 0)
{
- evutil_closesocket (p->fd);
+ evutil_closesocket (conn->fd);
+ conn->fd = -1;
return rs_err_conn_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
strerror (errno));
}
@@ -386,8 +403,13 @@ _init_socket (struct rs_connection *conn, struct rs_peer *p)
static struct rs_peer *
_pick_peer (struct rs_connection *conn)
{
+ assert (conn);
+
+ if (conn->active_peer)
+ conn->active_peer = conn->active_peer->next; /* Next. */
if (!conn->active_peer)
- conn->active_peer = conn->peers;
+ conn->active_peer = conn->peers; /* From the top. */
+
return conn->active_peer;
}
@@ -397,15 +419,20 @@ _init_bev (struct rs_connection *conn, struct rs_peer *peer)
if (conn->bev)
return RSE_OK;
- switch (conn->type)
+ switch (conn->realm->type)
{
case RS_CONN_TYPE_UDP:
+ /* Fall through. */
+ /* NOTE: We know this is wrong for several reasons, most notably
+ because libevent doesn't work as expected with UDP. The
+ timeout handling is wrong too. */
case RS_CONN_TYPE_TCP:
- conn->bev = bufferevent_socket_new (conn->evb, peer->fd, 0);
+ conn->bev = bufferevent_socket_new (conn->evb, conn->fd, 0);
if (!conn->bev)
return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_socket_new");
break;
+
#if defined (RS_ENABLE_TLS)
case RS_CONN_TYPE_TLS:
if (rs_tls_init (conn))
@@ -414,62 +441,79 @@ _init_bev (struct rs_connection *conn, struct rs_peer *peer)
seem to break when be_openssl_ctrl() (in libevent) calls
SSL_set_bio() after BIO_new_socket() with flag=1. */
conn->bev =
- bufferevent_openssl_socket_new (conn->evb, peer->fd, conn->tls_ssl,
+ bufferevent_openssl_socket_new (conn->evb, conn->fd, conn->tls_ssl,
BUFFEREVENT_SSL_CONNECTING, 0);
if (!conn->bev)
return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_openssl_socket_new");
-
break;
+
case RS_CONN_TYPE_DTLS:
return rs_err_conn_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
"%s: NYI", __func__);
#endif /* RS_ENABLE_TLS */
+
default:
return rs_err_conn_push_fl (conn, RSE_INTERNAL, __FILE__, __LINE__,
"%s: unknown connection type: %d", __func__,
- conn->type);
+ conn->realm->type);
}
return RSE_OK;
}
static void
-_do_connect (struct rs_peer *p)
+_do_connect (struct rs_connection *conn)
{
+ struct rs_peer *p;
int err;
+ assert (conn);
+ assert (conn->active_peer);
+ p = conn->active_peer;
+
+#if defined (DEBUG)
+ {
+ char host[80], serv[80];
+
+ getnameinfo (p->addr->ai_addr,
+ p->addr->ai_addrlen,
+ host, sizeof(host), serv, sizeof(serv),
+ 0 /* NI_NUMERICHOST|NI_NUMERICSERV*/);
+ rs_debug (("%s: connecting to %s:%s\n", __func__, host, serv));
+ }
+#endif
+
err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
p->addr->ai_addrlen);
if (err < 0)
rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_socket_connect: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
else
- p->is_connecting = 1;
+ p->conn->is_connecting = 1;
}
static int
_conn_open(struct rs_connection *conn, struct rs_packet *pkt)
{
- struct rs_peer *p;
-
if (_init_evb (conn))
return -1;
- p = _pick_peer (conn);
- if (!p)
+ if (!conn->active_peer)
+ _pick_peer (conn);
+ if (!conn->active_peer)
return rs_err_conn_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
- if (_init_socket (conn, p))
+ if (_init_socket (conn, conn->active_peer))
return -1;
- if (_init_bev (conn, p))
+ if (_init_bev (conn, conn->active_peer))
return -1;
- if (!p->is_connected)
- if (!p->is_connecting)
- _do_connect (p);
+ if (!conn->is_connected)
+ if (!conn->is_connecting)
+ _do_connect (conn);
return RSE_OK;
}
@@ -477,7 +521,7 @@ _conn_open(struct rs_connection *conn, struct rs_packet *pkt)
static int
_conn_is_open_p (struct rs_connection *conn)
{
- return conn->active_peer && conn->active_peer->is_connected;
+ return conn->active_peer && conn->is_connected;
}
/* Public functions. */
@@ -553,14 +597,14 @@ _wcb (void *user_data)
if (err < 0)
rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
"event_base_loopbreak: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
}
int
rs_packet_send (struct rs_packet *pkt, void *user_data)
{
struct rs_connection *conn = NULL;
- int err = RSE_OK;
+ int err = 0;
assert (pkt);
assert (pkt->conn);
@@ -575,7 +619,7 @@ rs_packet_send (struct rs_packet *pkt, void *user_data)
assert (conn->evb);
assert (conn->bev);
assert (conn->active_peer);
- assert (conn->active_peer->fd >= 0);
+ assert (conn->fd >= 0);
conn->user_data = user_data;
bufferevent_setcb (conn->bev, NULL, _write_cb, _event_cb, pkt);
@@ -590,7 +634,7 @@ rs_packet_send (struct rs_packet *pkt, void *user_data)
if (err < 0)
return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
"event_base_dispatch: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
rs_debug (("%s: event loop done\n", __func__));
conn->callbacks.sent_cb = NULL;
conn->user_data = NULL;
@@ -613,7 +657,7 @@ _rcb (struct rs_packet *packet, void *user_data)
if (err < 0)
rs_err_conn_push_fl (packet->conn, RSE_EVENT, __FILE__, __LINE__,
"event_base_loopbreak: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
}
/* Special function used in libradsec blocking dispatching mode,
@@ -636,10 +680,11 @@ rs_conn_receive_packet (struct rs_connection *conn,
struct rs_packet *request,
struct rs_packet **pkt_out)
{
- int err = RSE_OK;
+ int err = 0;
struct rs_packet *pkt = NULL;
assert (conn);
+ assert (conn->realm);
assert (!conn->user_dispatch_flag); /* Dispatching mode only. */
if (rs_packet_create (conn, pkt_out))
@@ -648,36 +693,35 @@ rs_conn_receive_packet (struct rs_connection *conn,
pkt->conn = conn;
pkt->original = request;
- if (_conn_open (conn, pkt))
- return -1;
assert (conn->evb);
assert (conn->bev);
assert (conn->active_peer);
- assert (conn->active_peer->fd >= 0);
+ assert (conn->fd >= 0);
- /* Install read and event callbacks with libevent. */
+ /* Install callbacks with libevent. */
bufferevent_setwatermark (conn->bev, EV_READ, RS_HEADER_LEN, 0);
bufferevent_enable (conn->bev, EV_READ);
bufferevent_setcb (conn->bev, _read_cb, NULL, _event_cb, pkt);
- /* Install read callback with ourselves, for signaling successful
- reception of message. */
+ /* Install read callback with ourselves, for breaking event
+ loop upon reception of a valid packet. */
conn->callbacks.received_cb = _rcb;
/* Dispatch. */
rs_debug (("%s: entering event loop\n", __func__));
err = event_base_dispatch (conn->evb);
+ conn->callbacks.received_cb = NULL;
if (err < 0)
return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
"event_base_dispatch: %s",
- evutil_gai_strerror(err));
+ evutil_gai_strerror (err));
rs_debug (("%s: event loop done\n", __func__));
- conn->callbacks.received_cb = NULL;
+
if (!event_base_got_break (conn->evb))
return -1;
#if defined (DEBUG)
- rs_dump_packet (pkt);
+ rs_dump_packet (pkt);
#endif
pkt->original = NULL; /* FIXME: Why? */
diff --git a/lib/radsec.c b/lib/radsec.c
index 16a554f..c821566 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -18,6 +18,7 @@
#include <radsec/radsec-impl.h>
#if defined (RS_ENABLE_TLS)
#include <regex.h>
+#include "debug.h"
#include "rsp_list.h"
#include "../radsecproxy.h"
#endif
@@ -69,14 +70,6 @@ rs_context_create(struct rs_context **ctx, const char *dict)
debug_init ("libradsec"); /* radsecproxy compat, FIXME: remove */
memset (h, 0, sizeof(struct rs_context));
- h->realms = malloc (sizeof (struct rs_realm));
- if (!h->realms)
- {
- err = RSE_NOMEM;
- goto err_out;
- }
- memset (h->realms, 0, sizeof (struct rs_realm));
- h->realms->next = h->realms;
fr_randinit (&h->fr_randctx, 0);
fr_rand_seed (NULL, 0);
@@ -95,19 +88,6 @@ rs_context_create(struct rs_context **ctx, const char *dict)
return err;
}
-void rs_context_destroy(struct rs_context *ctx)
-{
- free (ctx);
-}
-
-int rs_context_set_alloc_scheme(struct rs_context *ctx,
- struct rs_alloc_scheme *scheme)
-{
- return rs_err_ctx_push_fl (ctx, RSE_NOSYS, __FILE__, __LINE__,
- "%s: NYI", __func__);
-}
-
-
struct rs_peer *
_rs_peer_create (struct rs_context *ctx, struct rs_peer **rootp)
{
@@ -117,15 +97,59 @@ _rs_peer_create (struct rs_context *ctx, struct rs_peer **rootp)
if (p)
{
memset (p, 0, sizeof(struct rs_peer));
- p->fd = -1;
if (*rootp)
- (*rootp)->next = p;
+ {
+ p->next = (*rootp)->next;
+ (*rootp)->next = p;
+ }
else
*rootp = p;
}
return p;
}
+static void
+_rs_peer_destroy (struct rs_peer *p)
+{
+ assert (p);
+ assert (p->conn);
+ assert (p->conn->ctx);
+ /* NOTE: The peer object doesn't own its connection (conn). */
+ if (p->addr)
+ {
+ evutil_freeaddrinfo (p->addr);
+ p->addr = NULL;
+ }
+ rs_free (p->conn->ctx, p);
+}
+
+void rs_context_destroy(struct rs_context *ctx)
+{
+ struct rs_realm *r = NULL;
+ struct rs_peer *p = NULL;
+
+ for (r = ctx->realms; r; )
+ {
+ struct rs_realm *tmp = r;
+ for (p = r->peers; p; )
+ {
+ struct rs_peer *tmp = p;
+ p = p->next;
+ _rs_peer_destroy (tmp);
+ }
+ r = r->next;
+ rs_free (ctx, tmp);
+ }
+ rs_free (ctx, ctx);
+}
+
+int rs_context_set_alloc_scheme(struct rs_context *ctx,
+ struct rs_alloc_scheme *scheme)
+{
+ return rs_err_ctx_push_fl (ctx, RSE_NOSYS, __FILE__, __LINE__,
+ "%s: NYI", __func__);
+}
+
int
rs_server_create (struct rs_connection *conn, struct rs_peer **server)
{
@@ -135,8 +159,8 @@ rs_server_create (struct rs_connection *conn, struct rs_peer **server)
if (srv)
{
srv->conn = conn;
- srv->timeout = 1;
- srv->tries = 3;
+ srv->realm->timeout = 2;
+ srv->realm->retries = 2;
}
else
return rs_err_conn_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
@@ -151,7 +175,10 @@ rs_server_set_address (struct rs_peer *server, const char *hostname,
{
struct rs_error *err;
- err = _rs_resolv (&server->addr, server->conn->type, hostname, service);
+ assert (server);
+ assert (server->realm);
+
+ err = _rs_resolv (&server->addr, server->realm->type, hostname, service);
if (err)
return _rs_err_conn_push_err (server->conn, err);
return RSE_OK;
@@ -160,12 +187,16 @@ rs_server_set_address (struct rs_peer *server, const char *hostname,
void
rs_server_set_timeout (struct rs_peer *server, int timeout)
{
- server->timeout = timeout;
+ assert (server);
+ assert (server->realm);
+ server->realm->timeout = timeout;
}
void
-rs_server_set_tries (struct rs_peer *server, int tries)
+rs_server_set_retries (struct rs_peer *server, int retries)
{
- server->tries = tries;
+ assert (server);
+ assert (server->realm);
+ server->realm->retries = retries;
}
int