usr/src/cmd/rad/mod/xport_tcp/mod_tcp.c
changeset 862 f20f2afa6263
parent 852 bcfb754700ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/rad/mod/xport_tcp/mod_tcp.c	Fri May 18 11:08:12 2012 -0400
@@ -0,0 +1,168 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2010, 2012, Oracle and/or its affiliates. All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <bsm/adt_event.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <unistd.h>
+
+#include <rad/adr_stream.h>
+#include "rad_object.h"
+#include "rad_modapi.h"
+#include "rad_modapi_xport.h"
+#include "rad_connection.h"
+#include "rad_xport.h"
+#include "../rad_listen.h"
+
+#include "api_tcp.h"
+
+static char *pam_service = "rad-tcp";
+
+static void
+tcp_run(void *arg)
+{
+	radmod_connection_t *conn = arg;
+	rad_proto_handle(conn);
+	rad_conn_free(conn);
+}
+
+static rad_moderr_t
+tcp_listen(rad_thread_t *arg)
+{
+	int fd;
+	data_t *d, *data = rad_thread_arg(arg);
+
+	int port = data_to_integer(struct_get(data, "port"));
+	d = struct_get(data, "proto");
+	const char *protostr = d != NULL ? data_to_string(d) : "rad";
+	d = struct_get(data, "localonly");
+	boolean_t local = d != NULL ? data_to_boolean(d) : B_TRUE;
+	d = struct_get(data, "noauth");
+	boolean_t noauth = d != NULL ? data_to_boolean(d) : B_FALSE;
+	d = struct_get(data, "pam_service");
+	if (d != NULL) {
+		pam_service = (char *)data_to_string(d);
+	}
+
+	rad_subject_t *subject = NULL;
+
+	rad_protocol_t *proto = rad_proto_find(protostr);
+	if (proto == NULL) {
+		rad_log(RL_ERROR, "unable to find protocol '%s'", protostr);
+		return (rm_config);
+	}
+
+	if (noauth) {
+		ucred_t *uc = ucred_get(P_MYID);
+		if (uc == NULL ||
+		    (subject = rad_subject_create_ucred(uc, B_FALSE,
+		    pam_service)) == NULL) {
+			rad_log(RL_ERROR, "failed to allocate subject");
+			return (rm_system);
+		}
+		rad_log(RL_WARN, "AUTHORIZING ANONYMOUS TCP CONNECTIONS");
+	}
+
+	if ((fd = listen_on_port(port, local)) < 0) {
+		rad_log(RL_ERROR, "error starting server on port %d", port);
+		return (rm_system);
+	}
+
+	rad_thread_ack(arg, rm_ok);
+	for (;;) {
+		int afd;
+
+		rad_log(RL_DEBUG, "Waiting for connection");
+		if ((afd = accept(fd, 0, 0)) == -1) {
+			rad_log(RL_ERROR, "error in accept(): %s\n",
+			    strerror(errno));
+			continue;
+		}
+		rad_log(RL_DEBUG, "Connection accepted");
+
+		adr_stream_t *stream = adr_stream_create_fd(afd);
+		if (stream == NULL)
+			continue;
+
+		radmod_connection_t *conn = rad_conn_create_fd(afd, B_TRUE);
+		if (conn == NULL) {
+			adr_stream_close(stream);
+			adr_stream_free(stream);
+			rad_log(RL_WARN, "failed to allocate connection");
+			continue;
+		}
+		conn->rm_conn_xport = stream;
+		conn->rm_conn_proto_ops = proto;
+		conn->rm_conn_pam_service = pam_service;
+
+		if (noauth) {
+			assert(subject != NULL);
+			rad_subject_ref(subject);
+			if (!rad_conn_setsubject(conn, subject)) {
+				rad_log(RL_WARN,
+				    "failed to set connection subject");
+				rad_conn_close(conn);
+				rad_conn_free(conn);
+				continue;
+			}
+		}
+
+		if (rad_thread_create_async(tcp_run, conn) != rm_ok) {
+			rad_conn_close(conn);
+			rad_conn_free(conn);
+		}
+	}
+}
+
+static rad_moderr_t
+starter(data_t *data)
+{
+	/*
+	 * Validate parameters
+	 */
+	data_t *port = struct_get(data, "port");
+	if (port == NULL) {
+		rad_log(RL_ERROR, "Port required\n");
+		return (rm_config);
+	}
+
+	return (rad_thread_create(tcp_listen, data));
+}
+
+static rad_modinfo_t modinfo = { "xport_tcp", "TCP transport module" };
+
+int
+_rad_init(void *handle)
+{
+	if (rad_module_register(handle, RAD_MODVERSION, &modinfo) == -1)
+		return (-1);
+
+	rad_xport_register("tcp", &t__tcp, starter);
+	return (0);
+}