-/* Copyright 2011 NORDUnet A/S. All rights reserved.
- See the file COPYING for licensing information. */
+/* Copyright 2011-2013 NORDUnet A/S. All rights reserved.
+ See LICENSE for licensing information. */
#if defined HAVE_CONFIG_H
#include <config.h>
#endif
#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
#include <event2/event.h>
#include <event2/bufferevent.h>
#if defined (RS_ENABLE_TLS)
#if defined (RS_ENABLE_TLS)
#include "tls.h"
#endif
+#include "err.h"
+#include "radsec.h"
#include "event.h"
#include "packet.h"
#include "conn.h"
#include "debug.h"
+#if defined (DEBUG)
+extern int _event_debug_mode_on;
+#endif
+
static void
_evlog_cb (int severity, const char *msg)
{
rs_debug (("%s: retransmission timeout on %p (fd %d) sending to %p\n",
__func__, conn, conn->fd, conn->active_peer));
rs_err_conn_push_fl (conn, RSE_TIMEOUT_IO, __FILE__, __LINE__, NULL);
+
+ /* Disable/delete read and write events. Timing out on reading
+ might f.ex. trigger resending of a message. It'd be
+ surprising to end up reading without having enabled/created a
+ read event in that case. */
+ if (conn->bev) /* TCP. */
+ bufferevent_disable (conn->bev, EV_WRITE|EV_READ);
+ else /* UDP. */
+ {
+ if (conn->wev)
+ event_del (conn->wev);
+ if (conn->rev)
+ event_del (conn->rev);
+ }
+
event_loopbreak (conn);
}
}
if (conn->fd != -1)
return RSE_OK;
- assert (p->addr);
- conn->fd = socket (p->addr->ai_family, p->addr->ai_socktype,
- p->addr->ai_protocol);
+ if (p->addr_cache == NULL)
+ {
+ struct rs_error *err =
+ rs_resolve (&p->addr_cache, p->realm->type, p->hostname, p->service);
+ if (err != NULL)
+ return err_conn_push_err (conn, err);
+ }
+
+ conn->fd = socket (p->addr_cache->ai_family, p->addr_cache->ai_socktype,
+ p->addr_cache->ai_protocol);
if (conn->fd < 0)
return rs_err_conn_push_fl (conn, RSE_SOCKERR, __FILE__, __LINE__,
"socket: %d (%s)",
#if defined (RS_ENABLE_TLS)
else if (conn->realm->type == RS_CONN_TYPE_TLS)
{
- if (rs_tls_init (conn))
+ if (tls_init_conn (conn))
return -1;
/* Would be convenient to pass BEV_OPT_CLOSE_ON_FREE but things
seem to break when be_openssl_ctrl() (in libevent) calls
{
char host[80], serv[80];
- getnameinfo (p->addr->ai_addr,
- p->addr->ai_addrlen,
+ getnameinfo (p->addr_cache->ai_addr,
+ p->addr_cache->ai_addrlen,
host, sizeof(host), serv, sizeof(serv),
0 /* NI_NUMERICHOST|NI_NUMERICSERV*/);
rs_debug (("%s: connecting to %s:%s\n", __func__, host, serv));
if (p->conn->bev) /* TCP */
{
conn_activate_timeout (conn); /* Connect timeout. */
- err = bufferevent_socket_connect (p->conn->bev, p->addr->ai_addr,
- p->addr->ai_addrlen);
+ err = bufferevent_socket_connect (p->conn->bev, p->addr_cache->ai_addr,
+ p->addr_cache->ai_addrlen);
if (err < 0)
rs_err_conn_push_fl (p->conn, RSE_EVENT, __FILE__, __LINE__,
"bufferevent_socket_connect: %s",
}
else /* UDP */
{
- err = connect (p->conn->fd, p->addr->ai_addr, p->addr->ai_addrlen);
+ err = connect (p->conn->fd,
+ p->addr_cache->ai_addr,
+ p->addr_cache->ai_addrlen);
if (err < 0)
{
sockerr = evutil_socket_geterror (p->conn->fd);
{
int err = event_base_loopbreak (conn->evb);
if (err < 0)
- rs_err_conn_push_fl (conn, RSE_EVENT, __FILE__, __LINE__,
- "event_base_loopbreak: %s",
- evutil_gai_strerror (err));
+ rs_err_conn_push (conn, RSE_EVENT, "event_base_loopbreak");
return err;
}
conn->callbacks.disconnected_cb (conn->user_data);
}
-void
+/** Internal connect event returning 0 on success or -1 on error. */
+int
event_on_connect (struct rs_connection *conn, struct rs_packet *pkt)
{
assert (!conn->is_connecting);
+
+#if defined (RS_ENABLE_TLS)
+ if (conn_type_tls(conn) && !conn_cred_psk(conn))
+ if (tls_verify_cert (conn) != RSE_OK)
+ {
+ rs_debug (("%s: server cert verification failed\n", __func__));
+ return -1;
+ }
+#endif /* RS_ENABLE_TLS */
+
conn->is_connected = 1;
rs_debug (("%s: %p connected\n", __func__, conn->active_peer));
if (pkt)
packet_do_send (pkt);
+
+ return 0;
}
int
return RSE_OK;
#if defined (DEBUG)
- event_enable_debug_mode ();
+ if (!_event_debug_mode_on)
+ event_enable_debug_mode ();
#endif
event_set_log_callback (_evlog_cb);
conn->evb = event_base_new ();