#endif
}
+#ifdef WITH_COA_TUNNEL
+ /*
+ * Originate CoA requests to a NAS.
+ */
+ if (this->send_coa) {
+ home_server_t *home;
+
+ rad_assert(this->type != RAD_LISTEN_PROXY);
+
+ this->proxy_send = dual_tls_send_coa_request;
+ this->proxy_encode = master_listen[RAD_LISTEN_PROXY].encode;
+ this->proxy_decode = master_listen[RAD_LISTEN_PROXY].decode;
+
+ // @todo - save this listener as being outbound to the NAS IP
+
+ /*
+ * Automatically create a home server for this
+ * client. There MAY be one already one for that
+ * IP in the configuration files, but it will not
+ * have this particular port.
+ */
+ sock->home = home = talloc_zero(this, home_server_t);
+ home->ipaddr = sock->other_ipaddr;
+ home->port = sock->other_port;
+ home->proto = sock->proto;
+ home->secret = sock->client->secret;
+
+ home->coa_irt = this->coa_irt;
+ home->coa_mrt = this->coa_mrt;
+ home->coa_mrc = this->coa_mrc;
+ home->coa_mrd = this->coa_mrd;
+ home->coa_server = this->server;
+ }
+#endif
+
/*
* FIXME: set O_NONBLOCK on the accept'd fd.
* See djb's portability rants for details.
listen_socket_t *sock = listener->data;
RADCLIENT *client = sock->client;
BIO *rbio;
+#ifdef WITH_COA_TUNNEL
+ bool is_reply = false;
+#endif
if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;
FR_STATS_INC(dsc, total_requests);
fun = rad_coa_recv;
break;
+
+#ifdef WITH_COA_TUNNEL
+ case PW_CODE_COA_ACK:
+ case PW_CODE_COA_NAK:
+ if (!listener->send_coa) goto bad_packet;
+ is_reply = true;
+ break;
+#endif
#endif
case PW_CODE_STATUS_SERVER:
return 0;
} /* switch over packet types */
+#ifdef WITH_COA_TUNNEL
+ if (is_reply) {
+ if (!request_proxy_reply(packet)) {
+ rad_free(&packet);
+ return 0;
+ }
+ } else
+#endif
+
if (!request_receive(NULL, listener, packet, client, fun)) {
FR_STATS_INC(auth, total_packets_dropped);
rad_free(&packet);
return 0;
}
+#ifdef WITH_COA_TUNNEL
+/*
+ * Send a CoA request to a NAS, as a proxied packet.
+ *
+ * The proxied packet MUST already have been encoded.
+ */
+int dual_tls_send_coa_request(rad_listen_t *listener, REQUEST *request)
+{
+ listen_socket_t *sock = listener->data;
+
+ VERIFY_REQUEST(request);
+
+ rad_assert(listener->proxy_send == dual_tls_send_coa_request);
+
+ if (listener->status != RAD_LISTEN_STATUS_KNOWN) return 0;
+
+ rad_assert(request->proxy->data);
+
+ if (request->proxy->data_len > (MAX_PACKET_LEN - 100)) {
+ RWARN("Packet is large, and possibly truncated - %zd vs max %d",
+ request->proxy->data_len, MAX_PACKET_LEN);
+ }
+
+ PTHREAD_MUTEX_LOCK(&sock->mutex);
+
+ /*
+ * Write the packet to the SSL buffers.
+ */
+ sock->ssn->record_plus(&sock->ssn->clean_in,
+ request->proxy->data, request->proxy->data_len);
+
+ dump_hex("TUNNELED DATA < ", sock->ssn->clean_in.data, sock->ssn->clean_in.used);
+
+ /*
+ * Do SSL magic to get encrypted data.
+ */
+ tls_handshake_send(request, sock->ssn);
+
+ /*
+ * And finally write the data to the socket.
+ */
+ if (sock->ssn->dirty_out.used > 0) {
+ dump_hex("WRITE TO SSL", sock->ssn->dirty_out.data, sock->ssn->dirty_out.used);
+
+// tls_socket_write(listener, request);
+ }
+ PTHREAD_MUTEX_UNLOCK(&sock->mutex);
+
+ return 0;
+}
+#endif
+
static int try_connect(tls_session_t *ssn)
{
int ret;