diff options
| -rw-r--r-- | lib/Makefile.am | 2 | ||||
| -rw-r--r-- | lib/conf.c | 30 | ||||
| -rw-r--r-- | lib/conn.c | 61 | ||||
| -rw-r--r-- | lib/err.c | 11 | ||||
| -rw-r--r-- | lib/include/radsec/radsec-impl.h | 26 | ||||
| -rw-r--r-- | lib/include/radsec/radsec.h | 4 | ||||
| -rw-r--r-- | lib/packet.c | 166 | ||||
| -rw-r--r-- | lib/radsec.c | 89 | 
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 @@ -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; @@ -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;  } @@ -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 | 
