+#if defined HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <assert.h>
+#include <radius/client.h>
+#include <event2/bufferevent.h>
+#include <radsec/radsec.h>
+#include <radsec/radsec-impl.h>
+#include "conn.h"
+#include "debug.h"
+#include "packet.h"
+
+#if defined (DEBUG)
+#include <netdb.h>
+#include <sys/socket.h>
+#include <event2/buffer.h>
+#endif
+
+int
+packet_verify_response (struct rs_connection *conn,
+ struct rs_packet *response,
+ struct rs_packet *request)
+{
+ int err;
+
+ assert (conn);
+ assert (conn->active_peer);
+ assert (conn->active_peer->secret);
+ assert (response);
+ assert (response->rpkt);
+ assert (request);
+ assert (request->rpkt);
+
+ response->rpkt->secret = conn->active_peer->secret;
+ response->rpkt->sizeof_secret = strlen (conn->active_peer->secret);
+
+ /* Verify header and message authenticator. */
+ err = nr_packet_verify (response->rpkt, request->rpkt);
+ if (err)
+ {
+ if (conn->is_connected)
+ rs_conn_disconnect(conn);
+ return rs_err_conn_push_fl (conn, -err, __FILE__, __LINE__,
+ "nr_packet_verify");
+ }
+
+ /* Decode and decrypt. */
+ err = nr_packet_decode (response->rpkt, request->rpkt);
+ if (err)
+ {
+ if (conn->is_connected)
+ rs_conn_disconnect(conn);
+ return rs_err_conn_push_fl (conn, -err, __FILE__, __LINE__,
+ "nr_packet_decode");
+ }
+
+ return RSE_OK;
+}
+
+
+/* Badly named function for preparing a RADIUS message and queue it.
+ FIXME: Rename. */
+int
+packet_do_send (struct rs_packet *pkt)
+{
+ int err;
+
+ assert (pkt);
+ assert (pkt->conn);
+ assert (pkt->conn->active_peer);
+ assert (pkt->conn->active_peer->secret);
+ assert (pkt->rpkt);
+
+ pkt->rpkt->secret = pkt->conn->active_peer->secret;
+ pkt->rpkt->sizeof_secret = strlen (pkt->rpkt->secret);
+
+ /* Encode message. */
+ err = nr_packet_encode (pkt->rpkt, NULL);
+ if (err < 0)
+ return rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__,
+ "nr_packet_encode");
+ /* Sign message. */
+ err = nr_packet_sign (pkt->rpkt, NULL);
+ if (err < 0)
+ return rs_err_conn_push_fl (pkt->conn, -err, __FILE__, __LINE__,
+ "nr_packet_sign");
+#if defined (DEBUG)
+ {
+ char host[80], serv[80];
+
+ getnameinfo (pkt->conn->active_peer->addr_cache->ai_addr,
+ pkt->conn->active_peer->addr_cache->ai_addrlen,
+ host, sizeof(host), serv, sizeof(serv),
+ 0 /* NI_NUMERICHOST|NI_NUMERICSERV*/);
+ rs_debug (("%s: about to send this to %s:%s:\n", __func__, host, serv));
+ rs_dump_packet (pkt);
+ }
+#endif
+
+ /* Put message in output buffer. */
+ if (pkt->conn->bev) /* TCP. */
+ {
+ int err = bufferevent_write (pkt->conn->bev, pkt->rpkt->data,
+ pkt->rpkt->length);
+ if (err < 0)
+ return rs_err_conn_push_fl (pkt->conn, RSE_EVENT, __FILE__, __LINE__,
+ "bufferevent_write: %s",
+ evutil_gai_strerror (err));
+ }
+ else /* UDP. */
+ {
+ struct rs_packet **pp = &pkt->conn->out_queue;
+
+ while (*pp && (*pp)->next)
+ *pp = (*pp)->next;
+ *pp = pkt;
+ }
+
+ return RSE_OK;
+}