summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/err.c14
-rw-r--r--lib/examples/client.c20
-rw-r--r--lib/libradsec-impl.h6
-rw-r--r--lib/packet.c130
-rw-r--r--lib/radsec.c93
5 files changed, 171 insertions, 92 deletions
diff --git a/lib/err.c b/lib/err.c
index 74edeb0..4c88ce1 100644
--- a/lib/err.c
+++ b/lib/err.c
@@ -1,4 +1,5 @@
#include <stdio.h>
+#include <string.h>
#include <assert.h>
#include "libradsec.h"
#include "libradsec-impl.h"
@@ -27,6 +28,7 @@ const char *_errtxt[] = {
"ERR " /* RSE_ */
"some error" /* 21 RSE_SOME_ERROR */
};
+#define ERRTXT_SIZE (sizeof(_errtxt) / sizeof(*_errtxt))
static struct rs_error *
_err_new (unsigned int code, const char *file, int line, const char *fmt, va_list args)
@@ -39,8 +41,16 @@ _err_new (unsigned int code, const char *file, int line, const char *fmt, va_lis
int n;
memset (err, 0, sizeof(struct rs_error));
err->code = code;
- n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
- if (n > 0)
+ if (fmt)
+ n = vsnprintf (err->buf, sizeof(err->buf), fmt, args);
+ else
+ {
+ strncpy (err->buf,
+ err->code < ERRTXT_SIZE ? _errtxt[err->code] : "",
+ sizeof(err->buf));
+ n = strlen (err->buf);
+ }
+ if (n >= 0)
{
char *sep = strrchr (file, '/');
if (sep)
diff --git a/lib/examples/client.c b/lib/examples/client.c
index 14555c7..d7e7270 100644
--- a/lib/examples/client.c
+++ b/lib/examples/client.c
@@ -38,9 +38,17 @@ rsx_client (const char *srvname, int srvport)
return rs_conn_err_pop (conn);
req = NULL;
+#if 0
+ if (rs_packet_recv (conn, &resp))
+ return rs_conn_err_pop (conn);
+#if defined (DEBUG)
+ rs_dump_packet (resp);
+#endif
+#endif
+
rs_conn_destroy (conn);
rs_context_destroy (h);
- return 0;
+ return NULL;
}
int
@@ -53,8 +61,10 @@ main (int argc, char *argv[])
host = strsep (argv + 1, ":");
port = atoi (argv[1]);
err = rsx_client (host, port);
- if (!err)
- return -1;
- fprintf (stderr, "%s\n", rs_err_msg (err, 0));
- return rs_err_code (err, 1);
+ if (err)
+ {
+ fprintf (stderr, "%s\n", rs_err_msg (err, 0));
+ return rs_err_code (err, 1);
+ }
+ return 0;
}
diff --git a/lib/libradsec-impl.h b/lib/libradsec-impl.h
index e51c54c..a4ce7c2 100644
--- a/lib/libradsec-impl.h
+++ b/lib/libradsec-impl.h
@@ -71,6 +71,8 @@ struct rs_peer {
struct rs_connection *conn;
struct evutil_addrinfo *addr;
int s; /* Socket. */
+ char is_connecting;
+ char is_connected;
char *secret;
int timeout; /* client only */
int tries; /* client only */
@@ -80,6 +82,7 @@ struct rs_peer {
struct rs_connection {
struct rs_handle *ctx;
struct event_base *evb;
+ struct bufferevent *bev;
enum rs_conn_type type;
struct rs_credentials transport_credentials;
struct rs_conn_callbacks callbacks;
@@ -98,9 +101,6 @@ struct rs_attr {
VALUE_PAIR *vp;
};
-/* Internal functions. */
-int rs_conn_open(struct rs_connection *conn);
-
/* Convenience macros. */
#define rs_calloc(h, nmemb, size) \
(h->alloc_scheme.calloc ? h->alloc_scheme.calloc : calloc)(nmemb, size)
diff --git a/lib/packet.c b/lib/packet.c
index 652c495..90c8c31 100644
--- a/lib/packet.c
+++ b/lib/packet.c
@@ -66,11 +66,19 @@ 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;
assert (pkt);
assert (pkt->conn);
+ assert (pkt->conn->active_peer);
+ conn = pkt->conn;
+ p = conn->active_peer;
+
+ p->is_connecting = 0;
if (events & BEV_EVENT_CONNECTED)
{
+ p->is_connected = 1;
#if defined (DEBUG)
fprintf (stderr, "%s: connected\n", __func__);
#endif
@@ -110,32 +118,107 @@ _write_cb (struct bufferevent *bev, void *ctx)
rs_packet_destroy (pkt);
}
-int
-rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
+static int
+_init_evb (struct rs_connection *conn)
{
- struct bufferevent *bev;
- struct rs_peer *p;
+ if (!conn->evb)
+ {
+#if defined (DEBUG)
+ event_enable_debug_mode ();
+#endif
+ conn->evb = event_base_new ();
+ if (!conn->evb)
+ return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "event_base_new");
+ }
+ return RSE_OK;
+}
- assert (pkt->rpkt);
+static int
+_init_socket (struct rs_connection *conn, struct rs_peer *p)
+{
+ if (p->s < 0)
+ {
+ assert (p->addr);
+ p->s = socket (p->addr->ai_family, p->addr->ai_socktype,
+ p->addr->ai_protocol);
+ if (p->s < 0)
+ return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
+ strerror (errno));
+ }
+ return RSE_OK;
+}
- if (rs_conn_open (conn))
- return -1;
- p = conn->active_peer;
- assert (p);
+static struct rs_peer *
+_pick_peer (struct rs_connection *conn)
+{
+ if (!conn->active_peer)
+ conn->active_peer = conn->peers;
+ return conn->active_peer;
+}
- assert (conn->active_peer->s >= 0);
- bev = bufferevent_socket_new (conn->evb, conn->active_peer->s, 0);
- if (!bev)
- return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
- "bufferevent_socket_new");
- if (bufferevent_socket_connect (bev, p->addr->ai_addr, p->addr->ai_addrlen) < 0)
+static int
+_init_bev (struct rs_connection *conn, struct rs_peer *peer,
+ struct rs_packet *pkt)
+{
+ if (!conn->bev)
{
- bufferevent_free (bev);
- return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
- "bufferevent_socket_connect");
+ conn->bev = bufferevent_socket_new (conn->evb, peer->s, 0);
+ if (!conn->bev)
+ return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_socket_new");
+ bufferevent_setcb (conn->bev, NULL, _write_cb, _event_cb, pkt);
}
+ return RSE_OK;
+}
+
+static void
+_do_connect (struct rs_peer *p)
+{
+ if (bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
+ p->addr->ai_addrlen) < 0)
+ rs_conn_err_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_socket_connect");
+ else
+ p->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)
+ return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
+
+ if (_init_socket (conn, p))
+ return -1;
+
+ if (_init_bev (conn, p, pkt))
+ return -1;
- bufferevent_setcb (bev, NULL, _write_cb, _event_cb, pkt);
+ if (!p->is_connected)
+ if (!p->is_connecting)
+ _do_connect (p);
+
+ return RSE_OK;
+}
+
+int
+rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
+{
+ assert (conn);
+ assert (pkt->rpkt);
+ if (_conn_open (conn, pkt))
+ return -1;
+ assert (conn->evb);
+ assert (conn->bev);
+ assert (conn->active_peer);
+ assert (conn->active_peer->s >= 0);
event_base_dispatch (conn->evb);
#if defined (DEBUG)
fprintf (stderr, "%s: event loop done\n", __func__);
@@ -147,13 +230,18 @@ rs_packet_send (struct rs_connection *conn, struct rs_packet *pkt, void *data)
int rs_packet_receive(struct rs_connection *conn, struct rs_packet **pkt)
{
- return rs_conn_err_push_fl (conn, RSE_NOSYS, __FILE__, __LINE__,
- "%s: NYI", __func__);
+ //struct bufferevent *bev;
+
+ //skalleper;
+ //bufferevent_enable(bev, EV_READ);
+ return 0; /* FIXME */
}
+
void
rs_packet_add_attr(struct rs_packet *pkt, struct rs_attr *attr)
{
pairadd (&pkt->rpkt->vps, attr->vp);
attr->pkt = pkt;
}
+
diff --git a/lib/radsec.c b/lib/radsec.c
index 82576e1..72d7f5f 100644
--- a/lib/radsec.c
+++ b/lib/radsec.c
@@ -128,35 +128,53 @@ _resolv (struct rs_connection *conn, const char *hostname, int port)
return res; /* Simply use first result. */
}
+static struct rs_peer *
+_peer_new (struct rs_connection *conn, const char *hostname, int port)
+{
+ struct rs_peer *p;
+ struct evutil_addrinfo *addr;
+
+ addr = _resolv (conn, hostname, port);
+ if (!addr)
+ return NULL;
+
+ p = (struct rs_peer *) malloc (sizeof(*p));
+ if (p)
+ {
+ memset (p, 0, sizeof(struct rs_peer));
+ p->conn = conn;
+ p->s = -1;
+ p->addr = addr;
+ p->next = conn->peers;
+ if (conn->peers)
+ conn->peers->next = p;
+ else
+ conn->peers = p;
+ }
+ else
+ {
+ evutil_freeaddrinfo (addr);
+ rs_conn_err_push_fl (conn, RSE_NOMEM, __FILE__, __LINE__, NULL);
+ }
+ return p;
+}
+
int
rs_conn_add_server(struct rs_connection *conn, struct rs_peer **server,
rs_conn_type_t type, const char *hostname, int port)
{
struct rs_peer *srv;
- struct evutil_addrinfo *addr;
if (conn->type == RS_CONN_TYPE_NONE)
conn->type = type;
else if (conn->type != type)
return rs_conn_err_push (conn, RSE_CONN_TYPE_MISMATCH, NULL);
- addr = _resolv (conn, hostname, port);
- if (!addr)
- return -1;
-
- srv = (struct rs_peer *) malloc (sizeof(struct rs_peer));
+ srv = _peer_new (conn, hostname, port);
if (srv)
{
- memset (srv, 0, sizeof(struct rs_peer));
- srv->conn = conn;
- srv->addr = addr;
srv->timeout = 10;
srv->tries = 3;
- srv->next = conn->peers;
- if (conn->peers)
- conn->peers->next = srv;
- else
- conn->peers = srv;
}
if (*server)
*server = srv;
@@ -188,7 +206,6 @@ int rs_conn_add_listener(struct rs_connection *conn, rs_conn_type_t type, const
"%s: NYI", __func__);
}
-
void
rs_conn_destroy(struct rs_connection *conn)
{
@@ -232,49 +249,3 @@ int rs_conn_get_current_server(struct rs_connection *conn, const char *name, siz
"%s: NYI", __func__);
}
-/* Non-public. */
-int
-rs_conn_open(struct rs_connection *conn)
-{
- int s;
- struct rs_peer *p;
-
- if (conn->active_peer)
- return RSE_OK;
- p = conn->peers;
- if (!p)
- return rs_conn_err_push_fl (conn, RSE_NOPEER, __FILE__, __LINE__, NULL);
-
- s = socket (p->addr->ai_family, p->addr->ai_socktype, p->addr->ai_protocol);
- if (s < 0)
- return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
- strerror (errno));
-#if 0 /* let librevent do this in rs_packet_send() */
- if (connect (s, p->addr->ai_addr, p->addr->ai_addrlen))
- {
- /* TODO: handle nonblocking sockets (EINTR, EAGAIN). */
- EVUTIL_CLOSESOCKET (s);
- return rs_conn_err_push_fl (conn, RSE_SOME_ERROR, __FILE__, __LINE__,
- strerror (errno));
- }
-#endif
-
- if (!conn->evb)
- {
-#if defined (DEBUG)
- event_enable_debug_mode ();
-#endif
- conn->evb = event_base_new ();
- }
-
- if (!conn->evb)
- {
- EVUTIL_CLOSESOCKET (s);
- return rs_conn_err_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
- "event_base_new");
- }
-
- p->s = s;
- conn->active_peer = p;
- return RSE_OK;
-}