Merge branch 'libradsec' into libradsec-server-support
authorLinus Nordberg <linus@nordberg.se>
Wed, 15 May 2013 13:39:20 +0000 (15:39 +0200)
committerLinus Nordberg <linus@nordberg.se>
Wed, 15 May 2013 13:39:20 +0000 (15:39 +0200)
Conflicts:
lib/HACKING
lib/Makefile.am
lib/README
lib/compat.h
lib/conf.c
lib/configure.ac
lib/conn.c
lib/conn.h
lib/err.c
lib/err.h
lib/event.c
lib/event.h
lib/examples/Makefile.am
lib/examples/client-blocking.c
lib/examples/client.conf
lib/include/radsec/radsec-impl.h
lib/include/radsec/radsec.h
lib/include/radsec/request-impl.h
lib/include/radsec/request.h
lib/packet.c
lib/packet.h
lib/peer.c
lib/peer.h
lib/request.c
lib/send.c
lib/tcp.c
lib/tests/Makefile.am
lib/tls.c
lib/udp.c
lib/util.c

26 files changed:
1  2 
lib/HACKING
lib/Makefile.am
lib/README
lib/compat.h
lib/conf.c
lib/configure.ac
lib/conn.c
lib/debug.c
lib/debug.h
lib/event.c
lib/event.h
lib/examples/Makefile.am
lib/examples/client-blocking.c
lib/include/radsec/radsec-impl.h
lib/include/radsec/radsec.h
lib/include/radsec/request-impl.h
lib/include/radsec/request.h
lib/peer.c
lib/radsec.c
lib/request.c
lib/send.c
lib/tcp.c
lib/tests/Makefile.am
lib/tls.c
lib/udp.c
lib/udp.h

diff --cc lib/HACKING
@@@ -1,6 -1,6 +1,6 @@@
  HACKING file for libradsec (in Emacs -*- org -*- mode).
  
- Status as of libradsec-0.2.0.dev (2013-05-02).
 -Status as of libradsec-0.0.4.dev (2013-05-06).
++Status as of libradsec-0.2.0.dev (2013-05-06).
  
  * Build instructions
  sh autogen.sh
@@@ -19,7 -56,7 +19,7 @@@ Details (within parentheses) apply to D
  - OpenSSL (1.0.1c-4) -- optional, for TLS and DTLS support
    sudo apt-get install libssl-dev libssl1.0.0
    
--* Functionality and quality in 0.0.x
++* Functionality and quality in 0.2.x
  ** Not well tested
  - reading config file
  - [TCP] short read
diff --cc lib/Makefile.am
@@@ -4,23 -4,21 +4,24 @@@ ACLOCAL_AMFLAGS = -I m
  # Shared library interface version, i.e. -version-info to Libtool,
  # expressed as three integers CURRENT:REVISION:AGE.
  #
- # CURRENT is the version number of the current interface.
- # Increment CURRENT when the library interface changes.
+ # CURRENT is the version number of the current interface. Increment
+ # CURRENT when the library interface has changed or has been extended.
  #
  # REVISION is the version number of the _implementation_ of the
- # CURRENT interface.
- # Set REVISION to 0 when CURRENT changes, else increment.
+ # CURRENT interface. Set REVISION to 0 when CURRENT changes, else
+ # increment.
  #
  # AGE is the number of interfaces this library implements, i.e. how
- # many versions before CURRENT that are supported.
- # Increment AGE when the library interface is _extended_.
- # Set AGE to 0 when the library interface is _changed_.
+ # many versions before CURRENT that are supported. Increment AGE when
+ # the library interface is _extended_. Set AGE to 0 when the library
+ # interface is _changed_.
  
 +VER_CUR = 1
 +VER_REV = 0
 +VER_AGE = 0
  
- SUBDIRS = radius radsecproxy . include examples
+ SUBDIRS = radius radsecproxy include . examples
+ DIST_SUBDIRS = $(SUBDIRS) tests
  
  INCLUDES = -I$(srcdir)/include
  AM_CFLAGS = -Wall -Werror -g
@@@ -47,19 -43,29 +48,33 @@@ libradsec_la_SOURCES = 
        util.c
  
  if RS_ENABLE_TLS
 -libradsec_la_SOURCES += tls.c
 +  libradsec_la_SOURCES += tls.c
  else
 -libradsec_la_SOURCES += md5.c
 +  libradsec_la_SOURCES += md5.c
  endif
  
- EXTRA_DIST = HACKING LICENSE
+ libradsec_la_SOURCES += \
+       compat.h \
+       conn.h \
+       debug.h \
+       err.h \
+       event.h \
+       md5.h \
 -      packet.h \
+       peer.h \
+       radsec.h \
+       tcp.h \
+       tls.h \
+       udp.h \
+       util.h
 -EXTRA_DIST = HACKING LICENSE libradsec.spec radsec.sym
 -AM_DISTCHECK_CONFIGURE_FLAGS = --enable-tls --enable-tls-psk
++EXTRA_DIST = HACKING LICENSE radsec.sym
 +EXTRA_libradsec_la_DEPENDENCIES = radsec.sym
  
 -libradsec_la_LIBADD = radsecproxy/libradsec-radsecproxy.la radius/libradsec-radius.la
 -libradsec_la_LDFLAGS = -version-info 0:0:0 -export-symbols $(srcdir)/radsec.sym
 -libradsec_la_CFLAGS = $(AM_CFLAGS) -DHAVE_CONFIG_H -Werror # -DDEBUG -DDEBUG_LEVENT 
 +libradsec_la_CFLAGS = \
-       $(AM_CFLAGS) -DHAVE_CONFIG_H -DDEBUG -DDEBUG_LEVENT
++      $(AM_CFLAGS) -DHAVE_CONFIG_H #-DDEBUG -DDEBUG_LEVENT
 +libradsec_la_LDFLAGS = \
 +      -version-info $(VER_CUR):$(VER_REV):$(VER_AGE) \
-       -export-symbols radsec.sym
++      -export-symbols $(srcdir)/radsec.sym
 +libradsec_la_LIBADD = \
 +      radsecproxy/libradsec-radsecproxy.la \
 +      radius/libradsec-radius.la
diff --cc lib/README
@@@ -16,24 -7,36 +16,39 @@@ The canonical pickup point i
  http://git.nordu.net/?p=radsecproxy.git;a=shortlog;h=refs/heads/libradsec
  
  
- The source code is licensed under a 3-clause BSD license. See LICENSE.
+ The source code is licensed under a 3-clause BSD license. See the
+ LICENSE file.
  
  
 -Libradsec depends on 
 +Libradsec depends on
  - libconfuse
  - libevent2
  - openssl (if configured with --enable-tls)
  
  
 +For changes between releases, see the CHANGES file.
 +
 +
  To compile the library and the examples, do something like
  
-  sh autogen.sh && ./configure && make
+   sh autogen.sh && ./configure && make
  
- If any of the libraries are not found, try setting environment
- variable LDFLAGS at configure time like so:
+ There are a couple of options that can be used when configuring. See
+   ./configure --help
+ for the full list. Worth mentioning here is --enable-tls and
+ --enable-tls-psk.
+ If the preprocessor has a hard time finding some of the header files
+ are, try setting environment variable CPPFLAGS at configure
+ time. Example:
+   CPPFLAGS="-I/usr/local/include" ./configure --enable-tls
+ If the link editor has trouble finding any of the libraries needed,
+ try setting environment variable LDFLAGS at configure time. Example:
  
    LDFLAGS="-L/usr/local/lib" ./configure --enable-tls
  
diff --cc lib/compat.h
@@@ -1,11 -1,5 +1,11 @@@
- /* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
-    See LICENSE for licensing information.  */
+ /* Copyright 2011 NORDUnet A/S. All rights reserved.
+    See LICENSE for licensing information. */
  
 +#ifdef _WIN32
 +#define INLINE __inline
 +#else
 +#define INLINE inline
 +#endif
 +
  ssize_t compat_send (int sockfd, const void *buf, size_t len, int flags);
  ssize_t compat_recv (int sockfd, void *buf, size_t len, int flags);
diff --cc lib/conf.c
Simple merge
@@@ -1,7 -1,7 +1,7 @@@
  # -*- Autoconf -*- script for libradsec.
  
- AC_PREREQ([2.65])
+ AC_PREREQ([2.63])
 -AC_INIT([libradsec], [0.0.4.dev], [linus+libradsec@nordu.net])
 +AC_INIT([libradsec], [0.2.0.dev], [linus+libradsec@nordu.net])
  AC_CONFIG_MACRO_DIR([m4])
  AC_CONFIG_SRCDIR([radsec.c])
  AC_CONFIG_AUX_DIR([build-aux])
diff --cc lib/conn.c
@@@ -34,16 -33,17 +34,18 @@@ conn_user_dispatch_p (const struct rs_c
  int
  conn_activate_timeout (struct rs_connection *conn)
  {
++  const struct rs_conn_base *connbase;
    assert (conn);
++  connbase = TO_BASE_CONN (conn);
++  assert (connbase->ctx);
++  assert (connbase->ctx->evb);
    assert (conn->tev);
-   assert (conn->base_.ctx->evb);
-   if (conn->base_.timeout.tv_sec || conn->base_.timeout.tv_usec)
 -  assert (conn->evb);
 -  if (conn->timeout.tv_sec || conn->timeout.tv_usec)
++  if (connbase->timeout.tv_sec || connbase->timeout.tv_usec)
      {
        rs_debug (("%s: activating timer: %d.%d\n", __func__,
-                conn->base_.timeout.tv_sec, conn->base_.timeout.tv_usec));
-       if (evtimer_add (conn->tev, &conn->base_.timeout))
 -               conn->timeout.tv_sec, conn->timeout.tv_usec));
 -      if (evtimer_add (conn->tev, &conn->timeout))
--      return rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
--                                  "evtimer_add: %d", errno);
++               connbase->timeout.tv_sec, connbase->timeout.tv_usec));
++      if (evtimer_add (conn->tev, &connbase->timeout))
++      return rs_err_conn_push (conn, RSE_EVENT, "evtimer_add: %d", errno);
      }
    return RSE_OK;
  }
@@@ -56,57 -56,28 +58,57 @@@ conn_type_tls_p (const struct rs_connec
  }
  
  int
 -conn_cred_psk (const struct rs_connection *conn)
 +baseconn_type_datagram_p (const struct rs_conn_base *connbase)
  {
 -  return conn->realm->transport_cred &&
 -    conn->realm->transport_cred->type == RS_CRED_TLS_PSK;
 +  return connbase->transport == RS_CONN_TYPE_UDP
 +    || connbase->transport == RS_CONN_TYPE_DTLS;
  }
  
 +int
 +baseconn_type_stream_p (const struct rs_conn_base *connbase)
 +{
 +  return connbase->transport == RS_CONN_TYPE_TCP
 +    || connbase->transport == RS_CONN_TYPE_TLS;
 +}
  
 -/* Public functions. */
  int
 -rs_conn_create (struct rs_context *ctx,
 -              struct rs_connection **conn,
 -              const char *config)
 +conn_cred_psk (const struct rs_connection *conn)
  {
 -  struct rs_connection *c;
 +  assert (conn);
-   assert (conn->active_peer);
-   return conn->active_peer->transport_cred &&
-     conn->active_peer->transport_cred->type == RS_CRED_TLS_PSK;
++  return conn->active_peer != NULL
++    && conn->active_peer->transport_cred
++    && conn->active_peer->transport_cred->type == RS_CRED_TLS_PSK;
 +}
  
 -  c = (struct rs_connection *) malloc (sizeof(struct rs_connection));
 -  if (!c)
 -    return rs_err_ctx_push_fl (ctx, RSE_NOMEM, __FILE__, __LINE__, NULL);
 +void
 +conn_init (struct rs_context *ctx, /* FIXME: rename connbase_init? */
 +           struct rs_conn_base *connbase,
 +           enum rs_conn_subtype type)
 +{
 +  switch (type)
 +    {
 +    case RS_CONN_OBJTYPE_BASE:
 +      connbase->magic = RS_CONN_MAGIC_BASE;
 +      break;
 +    case RS_CONN_OBJTYPE_GENERIC:
 +      connbase->magic = RS_CONN_MAGIC_GENERIC;
 +      break;
 +    case RS_CONN_OBJTYPE_LISTENER:
 +      connbase->magic = RS_CONN_MAGIC_LISTENER;
 +      break;
 +    default:
 +      assert ("invalid connection subtype" == NULL);
 +    }
  
 -  memset (c, 0, sizeof(struct rs_connection));
 -  c->ctx = ctx;
 -  c->fd = -1;
 +  connbase->ctx = ctx;
 +  connbase->fd = -1;
 +}
 +
 +int
 +conn_configure (struct rs_context *ctx, /* FIXME: rename conbbase_configure? */
 +                struct rs_conn_base *connbase,
 +                const char *config)
 +{
    if (config)
      {
        struct rs_realm *r = rs_conf_find_realm (ctx, config);
@@@ -249,8 -128,31 +251,31 @@@ rs_conn_add_listener (struct rs_connect
  int
  rs_conn_disconnect (struct rs_connection *conn)
  {
-   int err = baseconn_close (TO_BASE_CONN (conn));
-   conn->state = RS_CONN_STATE_UNDEFINED;
+   int err = 0;
+   assert (conn);
 -  if (conn->is_connected)
++  if (conn->state == RS_CONN_STATE_CONNECTED)
+     event_on_disconnect (conn);
 -  if (conn->bev)
++  if (TO_BASE_CONN (conn)->bev)
+     {
 -      bufferevent_free (conn->bev);
 -      conn->bev = NULL;
++      bufferevent_free (TO_BASE_CONN (conn)->bev);
++      TO_BASE_CONN (conn)->bev = NULL;
+     }
 -  if (conn->rev)
++  if (TO_BASE_CONN (conn)->rev)
+     {
 -      event_free (conn->rev);
 -      conn->rev = NULL;
++      event_free (TO_BASE_CONN (conn)->rev);
++      TO_BASE_CONN (conn)->rev = NULL;
+     }
 -  if (conn->wev)
++  if (TO_BASE_CONN (conn)->wev)
+     {
 -      event_free (conn->wev);
 -      conn->wev = NULL;
++      event_free (TO_BASE_CONN (conn)->wev);
++      TO_BASE_CONN (conn)->wev = NULL;
+     }
 -  err = evutil_closesocket (conn->fd);
 -  conn->fd = -1;
++  err = evutil_closesocket (TO_BASE_CONN (conn)->fd);
++  TO_BASE_CONN (conn)->fd = -1;
    return err;
  }
  
diff --cc lib/debug.c
Simple merge
diff --cc lib/debug.h
Simple merge
diff --cc lib/event.c
Simple merge
diff --cc lib/event.h
@@@ -1,4 -1,4 +1,4 @@@
- /* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
 -/* Copyright 2011-2012 NORDUnet A/S. All rights reserved.
++/* Copyright 2011-2013 NORDUnet A/S. All rights reserved.
     See LICENSE for licensing information. */
  
  void event_on_disconnect (struct rs_connection *conn);
@@@ -1,10 -1,8 +1,10 @@@
  AUTOMAKE_OPTIONS = foreign
- INCLUDES = -I$(top_srcdir)/include
- AM_CFLAGS = -Wall -Werror -g -DDEBUG -DDEBUG_LEVENT
+ INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)
 -AM_CFLAGS = -Wall -Werror -g
++AM_CFLAGS = -Wall -Werror -g #-DDEBUG -DDEBUG_LEVENT
  
 -noinst_PROGRAMS = client
 +LDADD = ../libradsec.la #-lefence
 +CFLAGS = $(AM_CFLAGS) -DUSE_CONFIG_FILE
 +
 +noinst_PROGRAMS = client client2 server
  client_SOURCES = client-blocking.c
 -client_LDADD = ../libradsec.la #-lefence
 -client_CFLAGS = $(AM_CFLAGS) -DUSE_CONFIG_FILE
 +client2_SOURCES = client-dispatch.c
Simple merge
@@@ -1,7 -1,7 +1,7 @@@
  /** @file libradsec-impl.h
 -    @brief Libraray internal header file for libradsec.  */
 +    @brief Libraray internal header file for libradsec. */
  
- /* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
+ /* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
     See LICENSE for licensing information. */
  
  #ifndef _RADSEC_RADSEC_IMPL_H_
@@@ -101,54 -81,36 +101,53 @@@ struct rs_config 
      cfg_t *cfg;
  };
  
 +/** Libradsec context. */
  struct rs_context {
      struct rs_config *config;
 +    struct rs_realm *realms;
      struct rs_alloc_scheme alloc_scheme;
      struct rs_error *err;
 +    struct event_base *evb;
  };
  
 -struct rs_connection {
 +/** Base class for a connection. */
 +struct rs_conn_base {
 +    uint32_t magic;             /* Must be one of RS_CONN_MAGIC_*. */
      struct rs_context *ctx;
 -    struct rs_realm *realm;   /* Owned by ctx.  */
 -    struct event_base *evb;   /* Event base.  */
 -    struct event *tev;                /* Timeout event.  */
 -    struct rs_conn_callbacks callbacks;
 -    void *user_data;
 +    struct rs_realm *realm;   /* Owned by ctx. */
 +    enum rs_conn_type transport;
 +    /** For a listener, allowed client addr/port pairs.
 +     For an outgoing connection, set of configured servers.
 +     For an incoming connection, the peer (as the only entry). */
      struct rs_peer *peers;
 -    struct rs_peer *active_peer;
 -    struct rs_error *err;
      struct timeval timeout;
 -    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;             /* For server failover.  */
 -    int nextid;                       /* Next RADIUS packet identifier.  */
 -    /* TCP transport specifics.  */
 -    struct bufferevent *bev;  /* Buffer event.  */
 -    /* UDP transport specifics.  */
 -    struct event *wev;                /* Write event (for UDP).  */
 -    struct event *rev;                /* Read event (for UDP).  */
 -    struct rs_packet *out_queue; /* Queue for outgoing UDP packets.  */
 +    int tryagain;             /* For server failover. */
 +    void *user_data;
 +    struct rs_error *err;
 +    int fd;                   /* Socket. */
 +    /* TCP transport specifics. */
 +    struct bufferevent *bev;  /* Buffer event. */
 +    /* UDP transport specifics. */
 +    struct event *wev;                /* Write event (for UDP). */
 +    struct event *rev;                /* Read event (for UDP). */
 +};
 +
 +enum rs_conn_state {
 +    RS_CONN_STATE_UNDEFINED = 0,
 +    RS_CONN_STATE_CONNECTING,
 +    RS_CONN_STATE_CONNECTED,
 +};
 +
 +/** A generic connection. */
 +struct rs_connection {
 +    struct rs_conn_base base_;
 +    struct event *tev;                /* Timeout event. */
 +    struct rs_conn_callbacks callbacks;
 +    enum rs_conn_state state;
 +    struct rs_peer *active_peer;
 +    struct rs_message *out_queue; /* Queue for outgoing UDP packets. */
  #if defined(RS_ENABLE_TLS)
 -    /* TLS specifics.  */
 +    /* TLS specifics. */
      SSL_CTX *tls_ctx;
      SSL *tls_ssl;
  #endif
@@@ -1,7 -1,7 +1,7 @@@
  /** \file radsec.h
 -    \brief Public interface for libradsec.  */
 +    \brief Public interface for libradsec. */
  
- /* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
+ /* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
     See LICENSE for licensing information. */
  
  #ifndef _RADSEC_RADSEC_H_
@@@ -359,58 -288,61 +358,67 @@@ void rs_peer_set_timeout(struct rs_pee
  void rs_peer_set_retries(struct rs_peer *peer, int retries);
  
  /************/
 -/* Packet.  */
 +/* Message. */
  /************/
 -/** Create a packet associated with connection \a conn.  */
 -int rs_packet_create(struct rs_connection *conn, struct rs_packet **pkt_out);
 -
 -/** Free all memory allocated for packet \a pkt.  */
 -void rs_packet_destroy(struct rs_packet *pkt);
 -
 -/** Send packet \a pkt on the connection associated with \a pkt.
 -    \a user_data is passed to the \a rs_conn_packet_received_cb callback
 -    registered with the connection. If no callback is registered with
 -    the connection, the event loop is run by \a rs_packet_send and it
 -    blocks until the full packet has been sent. Note that sending can
 -    fail in several ways, f.ex. if the transmission protocol in use
 -    is connection oriented (\a RS_CONN_TYPE_TCP and \a RS_CONN_TYPE_TLS)
 -    and the connection can not be established. Also note that no
 -    retransmission is done, something that is required for connectionless
 -    transport protocols (\a RS_CONN_TYPE_UDP and \a RS_CONN_TYPE_DTLS).
 -    The "request" API with \a rs_request_send can help with this.
 +/** Create a message associated with connection \a conn.  */
 +int rs_message_create(struct rs_connection *conn, struct rs_message **pkt_out);
 +
 +/** Free all memory allocated for message \a msg.  */
 +void rs_message_destroy(struct rs_message *msg);
 +
 +/** Send \a msg on the connection associated with \a msg.
 +    If no callback is registered with the connection
 +    (\a rs_conn_set_callbacks), the event loop is run by
 +    \a rs_message_send and it blocks until the message has been
 +    succesfully sent.
 +
++    Note that sending can fail in several ways, f.ex. if the
++    transmission protocol in use is connection oriented
++    (\a RS_CONN_TYPE_TCP and \a RS_CONN_TYPE_TLS) and the connection
++    can not be established.
++
++    Also note that no retransmission is being done. This is required
++    for connectionless transport protocols (\a RS_CONN_TYPE_UDP and
++    \a RS_CONN_TYPE_DTLS). The "request" API with \a rs_request_send can
++    help with this.
      \return On success, RSE_OK (0) is returned. On error, !0 is
      returned and a struct \a rs_error is pushed on the error stack for
-     the connection. The error can be accessed using \a
-     rs_err_conn_pop. */
+     the connection. The error can be accessed using \a rs_err_conn_pop. */
 -int rs_packet_send(struct rs_packet *pkt, void *user_data);
 -
 -/** Create a RADIUS authentication request packet associated with
 -    connection \a conn.  Optionally, User-Name and User-Password
 -    attributes are added to the packet using the data in \a user_name
 -    and \a user_pw.  */
 -int rs_packet_create_authn_request(struct rs_connection *conn,
 -                                 struct rs_packet **pkt,
 -                                 const char *user_name,
 -                                 const char *user_pw);
 -
 -/*** Append \a tail to packet \a pkt.  */
 +int rs_message_send(struct rs_message *msg);
 +
 +/** Create a RADIUS authentication request message associated with
 +    connection \a conn. Optionally, User-Name and User-Password
 +    attributes are added to the message using the data in \a user_name
 +    and \a user_pw.
 +    FIXME: describe what RADIUS shared secret is being used */
 +int rs_message_create_authn_request(struct rs_connection *conn,
 +                                    struct rs_message **msg,
 +                                    const char *user_name,
 +                                    const char *user_pw);
 +
 +/*** Append \a tail to message \a msg.  */
  int
 -rs_packet_append_avp(struct rs_packet *pkt,
 -                   unsigned int attribute, unsigned int vendor,
 -                   const void *data, size_t data_len);
 +rs_message_append_avp(struct rs_message *msg,
 +                      unsigned int attribute, unsigned int vendor,
 +                      const void *data, size_t data_len);
  
 -/*** Get pointer to \a pkt attribute value pairs. */
 +/*** Get pointer to \a msg attribute value pairs. */
  void
 -rs_packet_avps(struct rs_packet *pkt, rs_avp ***vps);
 +rs_message_avps(struct rs_message *msg, rs_avp ***vps);
  
 -/*** Get RADIUS packet type of \a pkt. */
 +/*** Get RADIUS message type of \a msg. */
  unsigned int
 -rs_packet_code(struct rs_packet *pkt);
 +rs_message_code(struct rs_message *msg);
  
 -/*** Get RADIUS AVP from \a pkt. */
 +/*** Get RADIUS AVP from \a msg. */
  rs_const_avp *
 -rs_packet_find_avp(struct rs_packet *pkt, unsigned int attr, unsigned int vendor);
 +rs_message_find_avp(struct rs_message *msg, unsigned int attr,
 +                    unsigned int vendor);
  
 -/*** Set packet identifier in \a pkt; returns old identifier */
 +/*** Set packet identifier in \a msg; returns old identifier */
  int
 -rs_packet_set_id (struct rs_packet *pkt, int id);
 +rs_message_set_id (struct rs_message *msg, int id);
  
  /************/
  /* Config.  */
Simple merge
@@@ -20,15 -16,14 +20,13 @@@ extern "C" 
  /** Create a request associated with connection \a conn.  */
  int rs_request_create(struct rs_connection *conn, struct rs_request **req_out);
  
 -/** Add RADIUS request message \a req_msg to request \a req.
 -    FIXME: Rename to rs_request_add_reqmsg?  */
 -void rs_request_add_reqpkt(struct rs_request *req, struct rs_packet *req_msg);
 +/** Add RADIUS request message \a req_msg to request \a req. */
 +void rs_request_add_reqmsg(struct rs_request *req, struct rs_message *req_msg);
  
  /** Create a request associated with connection \a conn containing a
-     newly created RADIUS authentication message, possibly with
-     \a user_name and \a user_pw attributes.  \a user_name and \a user_pw
-     are optional and can be NULL. If \a user_name and \a user_pw are provided,
-     \a secret must also be provided. \a secret is used for "hiding" the
-     password. */
+     newly created RADIUS authentication message, possibly with \a
+     user_name and \a user_pw attributes.  \a user_name and _user_pw
+     are optional and can be NULL.  */
  int rs_request_create_authn(struct rs_connection *conn,
                            struct rs_request **req_out,
                            const char *user_name,
diff --cc lib/peer.c
@@@ -1,4 -1,4 +1,4 @@@
- /* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
 -/* Copyright 2010-2012 NORDUnet A/S. All rights reserved.
++/* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
     See LICENSE for licensing information. */
  
  #if defined HAVE_CONFIG_H
diff --cc lib/radsec.c
Simple merge
diff --cc lib/request.c
@@@ -1,5 -1,5 +1,5 @@@
- /* Copyright 2010,2011,2013 NORDUnet A/S. All rights reserved.
-    See LICENSE for licensing information.  */
 -/* Copyright 2010-2011 NORDUnet A/S. All rights reserved.
++/* Copyright 2010-2013 NORDUnet A/S. All rights reserved.
+    See LICENSE for licensing information. */
  
  #if defined HAVE_CONFIG_H
  #include <config.h>
diff --cc lib/send.c
Simple merge
diff --cc lib/tcp.c
+++ b/lib/tcp.c
@@@ -31,27 -31,39 +31,37 @@@ _read_header (struct rs_message *msg
  {
    size_t n = 0;
  
 -  n = bufferevent_read (pkt->conn->bev, pkt->hdr, RS_HEADER_LEN);
 +  n = bufferevent_read (TO_BASE_CONN(msg->conn)->bev, msg->hdr, RS_HEADER_LEN);
    if (n == RS_HEADER_LEN)
      {
 -      pkt->flags |= RS_PACKET_HEADER_READ;
 -      pkt->rpkt->length = (pkt->hdr[2] << 8) + pkt->hdr[3];
 -      if (pkt->rpkt->length < 20 || pkt->rpkt->length > RS_MAX_PACKET_LEN)
 -      {
 -          rs_debug (("%s: invalid packet length: %d\n",
 -                     __func__, pkt->rpkt->length));
 -          rs_conn_disconnect (pkt->conn);
 -        return rs_err_conn_push (pkt->conn, RSE_INVALID_PKT,
 -                                 "invalid packet length: %d",
 -                                 pkt->rpkt->length);
 -      }
 -      memcpy (pkt->rpkt->data, pkt->hdr, RS_HEADER_LEN);
 -      bufferevent_setwatermark (pkt->conn->bev, EV_READ,
 -                              pkt->rpkt->length - RS_HEADER_LEN, 0);
 -      rs_debug (("%s: packet header read, total pkt len=%d\n",
 -               __func__, pkt->rpkt->length));
 +      msg->flags |= RS_MESSAGE_HEADER_READ;
 +      msg->rpkt->length = (msg->hdr[2] << 8) + msg->hdr[3];
 +      if (msg->rpkt->length < 20 || msg->rpkt->length > RS_MAX_PACKET_LEN)
-         return  rs_err_conn_push (msg->conn, RSE_INVALID_MSG,
-                                   "invalid message length: %d",
-                                   msg->rpkt->length);
++        {
++          rs_debug (("%s: invalid packet length: %d\n", __func__,
++                     msg->rpkt->length));
++          rs_conn_disconnect (msg->conn);
++          return  rs_err_conn_push (msg->conn, RSE_INVALID_MSG,
++                                    "invalid message length: %d",
++                                    msg->rpkt->length);
++        }
 +      memcpy (msg->rpkt->data, msg->hdr, RS_HEADER_LEN);
 +      bufferevent_setwatermark (TO_BASE_CONN(msg->conn)->bev, EV_READ,
 +                              msg->rpkt->length - RS_HEADER_LEN, 0);
 +      rs_debug (("%s: message header read, total msg len=%d\n",
 +               __func__, msg->rpkt->length));
      }
    else if (n < 0)
 -    {
 -      rs_debug (("%s: buffer frozen while reading header\n", __func__));
 -    }
 +    rs_debug (("%s: buffer frozen while reading header\n", __func__));
    else            /* Error: libevent gave us less than the low watermark. */
-     return rs_err_conn_push_fl (msg->conn, RSE_INTERNAL, __FILE__, __LINE__,
-                                 "got %d octets reading header", n);
+     {
+       rs_debug (("%s: got: %d octets reading header\n", __func__, n));
 -      rs_conn_disconnect (pkg->conn);
 -      return rs_err_conn_push_fl (pkt->conn, RSE_INTERNAL, __FILE__, __LINE__,
 -                                "got %d octets reading header", n);
++      rs_conn_disconnect (msg->conn);
++      return rs_err_conn_push (msg->conn, RSE_INTERNAL,
++                               "got %d octets reading header", n);
+     }
 -  return 0;
 +  return RSE_OK;
  }
  
  /** Read a message, check that it's valid RADIUS and hand it off to
@@@ -88,10 -100,14 +98,13 @@@ _read_message (struct rs_message *msg
         - invalid code field
         - attribute lengths >= 2
         - attribute sizes adding up correctly  */
 -      err = nr_packet_ok (pkt->rpkt);
 -      if (err != RSE_OK)
 +      err = nr_packet_ok (msg->rpkt);
 +      if (err)
-         return rs_err_conn_push_fl (msg->conn, err, __FILE__, __LINE__,
-                                     "invalid message");
+       {
+           rs_debug (("%s: %d: invalid packet\n", __func__, -err));
 -          rs_conn_disconnect (pkt->conn);
 -        return rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__,
 -                                    "invalid packet");
 -      }
++          rs_conn_disconnect (msg->conn);
++          return rs_err_conn_push (msg->conn, -err, "invalid message");
++        }
  
  #if defined (DEBUG)
        /* Find out what happens if there's data left in the buffer.  */
@@@ -144,11 -159,10 +157,10 @@@ tcp_read_cb (struct bufferevent *bev, v
  
       Room for improvement: Peek inside buffer (evbuffer_copyout()) to
       avoid the extra copying. */
 -  if ((pkt->flags & RS_PACKET_HEADER_READ) == 0)
 -    if (_read_header (pkt))
 -      return;                 /* Error.  */
 -  _read_packet (pkt);
 +  if ((msg->flags & RS_MESSAGE_HEADER_READ) == 0)
 +    if (_read_header (msg))
 +      return;                   /* Invalid header. */
-   if (_read_message (msg))
-     return;                     /* Invalid message. */
++  _read_message (msg);
  }
  
  void
@@@ -4,13 -4,9 +4,12 @@@ AM_CFLAGS = -Wall -Werror -
  
  TESTS = test-udp
  
 -check_PROGRAMS = test-udp udp-server
 +check_PROGRAMS = test-udp udp-server tls-server
  
- test_udp_SOURCES = test-udp.c udp.c
- test_udp_LDADD = ../libradsec.la -lcgreen -lm
+ test_udp_SOURCES = test-udp.c udp.c udp.h
+ test_udp_LDADD = ../libradsec.la -lcunit -lm
  
- udp_server_SOURCES = udp-server.c udp.c
+ udp_server_SOURCES = udp-server.c udp.c udp.h
 +
 +tls_server_SOURCES = server.c
 +tls_server_LDADD = ../libradsec.la
diff --cc lib/tls.c
Simple merge
diff --cc lib/udp.c
+++ b/lib/udp.c
@@@ -1,5 -1,5 +1,5 @@@
 -/* Copyright 2011 NORDUnet A/S. All rights reserved.
 +/* Copyright 2011,2013 NORDUnet A/S. All rights reserved.
-    See LICENSE for licensing information.  */
+    See LICENSE for licensing information. */
  
  #if defined HAVE_CONFIG_H
  #include <config.h>
@@@ -63,29 -65,28 +63,29 @@@ static voi
  _evcb (evutil_socket_t fd, short what, void *user_data)
  {
    int err;
 -  struct rs_packet *pkt = (struct rs_packet *) user_data;
 +  struct rs_message *msg = (struct rs_message *) user_data;
-   assert (msg);
-   assert (msg->conn);
  
    rs_debug (("%s: fd=%d what =", __func__, fd));
-   if (what & EV_TIMEOUT) rs_debug ((" TIMEOUT"));
+   if (what & EV_TIMEOUT) rs_debug ((" TIMEOUT -- shouldn't happen!"));
    if (what & EV_READ) rs_debug ((" READ"));
    if (what & EV_WRITE) rs_debug ((" WRITE"));
    rs_debug (("\n"));
  
 -  assert (pkt);
 -  assert (pkt->conn);
++  assert (msg);
++  assert (msg->conn);
    if (what & EV_READ)
      {
 -      /* Read a single UDP packet and stick it in USER_DATA.  */
 +      /* Read a single UDP packet and stick it in the struct
 +         rs_message passed in user_data. */
        /* TODO: Verify that unsolicited packets are dropped.  */
        ssize_t r = 0;
 +      assert (msg->rpkt);
 +      assert (msg->rpkt->data);
  
 -      assert (pkt->rpkt->data);
 -
 -      r = compat_recv (fd, pkt->rpkt->data, RS_MAX_PACKET_LEN, MSG_TRUNC);
 +      r = compat_recv (fd, msg->rpkt->data, RS_MAX_PACKET_LEN, MSG_TRUNC);
        if (r == -1)
        {
 -        int sockerr = evutil_socket_geterror (pkt->conn->fd);
 +        int sockerr = evutil_socket_geterror (msg->conn->fd);
          if (sockerr == EAGAIN)
            {
              /* FIXME: Really shouldn't happen since we've been told
            }
  
          /* Hard error.  */
 -        rs_err_conn_push_fl (pkt->conn, RSE_SOCKERR, __FILE__, __LINE__,
 -                             "%d: recv: %d (%s)", fd, sockerr,
 -                             evutil_socket_error_to_string (sockerr));
 -        event_del (pkt->conn->tev);
 +        rs_err_conn_push (msg->conn, RSE_SOCKERR,
 +                            "%d: recv: %d (%s)", fd, sockerr,
 +                            evutil_socket_error_to_string (sockerr));
 +        event_del (msg->conn->tev);
-         return;
+           goto err_out;
        }
 -      event_del (pkt->conn->tev);
 +      event_del (msg->conn->tev);
        if (r < 20 || r > RS_MAX_PACKET_LEN)    /* Short or long packet.  */
        {
 -        rs_err_conn_push (pkt->conn, RSE_INVALID_PKT,
 -                            "invalid packet length: %d", r);
 +        rs_err_conn_push (msg->conn, RSE_INVALID_MSG,
-                           "invalid message length: %d",
-                           msg->rpkt->length);
-         return;
++                          "invalid message length: %d", r);
+           goto err_out;
        }
 -      pkt->rpkt->length = (pkt->rpkt->data[2] << 8) + pkt->rpkt->data[3];
 -      err = nr_packet_ok (pkt->rpkt);
 +      msg->rpkt->length = (msg->rpkt->data[2] << 8) + msg->rpkt->data[3];
 +      err = nr_packet_ok (msg->rpkt);
        if (err)
        {
-         rs_err_conn_push_fl (msg->conn, err, __FILE__, __LINE__,
-                              "invalid message");
-         return;
 -        rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__,
 -                             "invalid packet");
++        rs_err_conn_push (msg->conn, -err, "invalid message");
+           goto err_out;
        }
 -      /* Hand over message to user.  This changes ownership of pkt.
 +      /* Hand over message to user.  This changes ownership of msg.
         Don't touch it afterwards -- it might have been freed.  */
 -      if (pkt->conn->callbacks.received_cb)
 -      pkt->conn->callbacks.received_cb (pkt, pkt->conn->user_data);
 +      if (msg->conn->callbacks.received_cb)
 +      msg->conn->callbacks.received_cb (msg, msg->conn->base_.user_data);
      }
    else if (what & EV_WRITE)
      {
 -      if (!pkt->conn->is_connected)
 -      event_on_connect (pkt->conn, pkt);
 -
 -      if (pkt->conn->out_queue)
 -      if (_send (pkt->conn, fd) == RSE_OK)
 -        if (pkt->conn->callbacks.sent_cb)
 -          pkt->conn->callbacks.sent_cb (pkt->conn->user_data);
 +      if (conn_originating_p (msg->conn))
 +        {
 +          /* We're a client. */
 +          if (msg->conn->state == RS_CONN_STATE_CONNECTING)
 +            event_on_connect_orig (msg->conn, msg);
 +        }
 +      else
 +        {
 +          /* We're a server. */
 +          rs_debug (("%s: write event on terminating conn %p\n",
 +                     __func__, msg->conn));
 +        }
 +
 +      if (msg->conn->out_queue)
 +      if (_send (msg->conn, fd) == RSE_OK)
 +        if (msg->conn->callbacks.sent_cb)
 +          msg->conn->callbacks.sent_cb (msg->conn->base_.user_data);
      }
+   return;
  
- #if defined (DEBUG)
-   if (what & EV_TIMEOUT)
-     rs_debug (("%s: timeout on UDP event, shouldn't happen\n", __func__));
- #endif
+  err_out:
 -  rs_conn_disconnect (pkt->conn);
++  rs_conn_disconnect (msg->conn);
  }
  
  int
diff --cc lib/udp.h
+++ b/lib/udp.h
@@@ -1,5 -1,5 +1,5 @@@
  /* Copyright 2011 NORDUnet A/S. All rights reserved.
-    See LICENSE for licensing information.  */
+    See LICENSE for licensing information. */
  
 -int udp_init (struct rs_connection *conn, struct rs_packet *pkt);
 +int udp_init (struct rs_connection *conn, struct rs_message *msg);
  int udp_init_retransmit_timer (struct rs_connection *conn);