/** Initialise a new outbound connection
 *
 * @param[out] fd_out	Where to write the new file descriptor.
 * @param[in] uctx	A #rlm_logtee_thread_t.
 */
static fr_connection_state_t _logtee_conn_init(int *fd_out, void *uctx)
{
	rlm_logtee_thread_t	*t = talloc_get_type_abort(uctx, rlm_logtee_thread_t);
	rlm_logtee_t const	*inst = t->inst;
	int			fd = -1;

	switch (inst->log_dst) {
	case LOGTEE_DST_UNIX:
		DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path);
		fd = fr_socket_client_unix(inst->unix_sock.path, true);
		if (fd < 0) return FR_CONNECTION_STATE_FAILED;
		break;

	case LOGTEE_DST_TCP:
		DEBUG2("Opening TCP connection to %pV:%u",
		       fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port);
		fd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
		if (fd < 0) return FR_CONNECTION_STATE_FAILED;
		break;

	case LOGTEE_DST_UDP:
		DEBUG2("Opening UDP connection to %pV:%u",
		       fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port);
		fd = fr_socket_client_udp(NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
		if (fd < 0) return FR_CONNECTION_STATE_FAILED;
		break;

	/*
	 *	Are not connection oriented destinations
	 */
	case LOGTEE_DST_INVALID:
	case LOGTEE_DST_FILE:
		rad_assert(0);
		return FR_CONNECTION_STATE_FAILED;
	}

	*fd_out = fd;

	return FR_CONNECTION_STATE_CONNECTING;
}
Example #2
0
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout)
{
	int fd;
	rlm_smsotp_t *inst = instance;
	int *fdp;

	fd = fr_socket_client_unix(inst->socket, false);
	if (fd < 0) {
		ERROR("Failed opening SMSOTP file %s: %s", inst->socket, fr_syserror(errno));
		return NULL;
	}

	if (fr_socket_wait_for_connect(fd, timeout) < 0) {
		ERROR("Failed connecting to SMSOTP file %s: %s", inst->socket, fr_syserror(errno));
		return NULL;
	}

	fdp = talloc_zero(ctx, int);
	talloc_set_destructor(fdp, _mod_conn_free);
	*fdp = fd;

	return fdp;
}
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout)
{
	linelog_instance_t	*inst = instance;
	linelog_conn_t		*conn;
	int			sockfd = -1;

	switch (inst->log_dst) {
	case LINELOG_DST_UNIX:
		DEBUG2("rlm_linelog (%s): Opening UNIX socket at \"%s\"", inst->name, inst->unix.path);
		sockfd = fr_socket_client_unix(inst->unix.path, true);
		if (sockfd < 0) {
			ERROR("rlm_linelog (%s): Failed opening UNIX socket: %s", inst->name, fr_strerror());
			return NULL;
		}
		break;

	case LINELOG_DST_TCP:
		if (DEBUG_ENABLED2) {
			char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */

			fr_ntop(buff, sizeof(buff), &inst->tcp.dst_ipaddr);

			DEBUG2("rlm_linelog (%s): Opening TCP connection to %s:%u", inst->name, buff, inst->tcp.port);
		}

		sockfd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true);
		if (sockfd < 0) {
			ERROR("rlm_linelog (%s): Failed opening TCP socket: %s", inst->name, fr_strerror());
			return NULL;
		}
		break;

	case LINELOG_DST_UDP:
		if (DEBUG_ENABLED2) {
			char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */

			fr_ntop(buff, sizeof(buff), &inst->udp.dst_ipaddr);

			DEBUG2("rlm_linelog (%s): Opening UDP connection to %s:%u", inst->name, buff, inst->udp.port);
		}

		sockfd = fr_socket_client_udp(NULL, &inst->udp.dst_ipaddr, inst->udp.port, true);
		if (sockfd < 0) {
			ERROR("rlm_linelog (%s): Failed opening UDP socket: %s", inst->name, fr_strerror());
			return NULL;
		}
		break;

	/*
	 *	Are not connection oriented destinations
	 */
	case LINELOG_DST_INVALID:
	case LINELOG_DST_FILE:
	case LINELOG_DST_SYSLOG:
		rad_assert(0);
		return NULL;
	}

	if (errno == EINPROGRESS) {
		if (FR_TIMEVAL_TO_MS(timeout)) {
			DEBUG2("rlm_linelog (%s): Waiting for connection to complete...", inst->name);
		} else {
			DEBUG2("rlm_linelog (%s): Blocking until connection complete...", inst->name);
		}
		if (fr_socket_wait_for_connect(sockfd, timeout) < 0) {
			ERROR("rlm_linelog (%s): %s", inst->name, fr_strerror());
			close(sockfd);
			return NULL;
		}
	}
	DEBUG2("rlm_linelog (%s): Connection successful", inst->name);

	/*
	 *	Set blocking operation as we have no timeout set
	 */
	if (!FR_TIMEVAL_TO_MS(timeout) && (fr_blocking(sockfd) < 0)) {
		ERROR("rlm_linelog (%s): Failed setting nonblock flag on fd", inst->name);
		close(sockfd);
		return NULL;
	}

	conn = talloc_zero(ctx, linelog_conn_t);
	conn->sockfd = sockfd;
	talloc_set_destructor(conn, _mod_conn_free);

	return conn;
}
Example #4
0
static int do_connect(int *out, char const *file, char const *server)
{
	int sockfd;
	ssize_t r;
	fr_channel_type_t channel;
	char buffer[65536];

	uint32_t magic;

	/*
	 *	Close stale file descriptors
	 */
	if (*out != -1) {
		close(*out);
		*out = -1;
	}

	if (file) {
		/*
		 *	FIXME: Get destination from command line, if possible?
		 */
		sockfd = fr_socket_client_unix(file, false);
		if (sockfd < 0) {
			fr_perror("radmin");
			if (errno == ENOENT) {
					fprintf(stderr, "Perhaps you need to run the commands:");
					fprintf(stderr, "\tcd /etc/raddb\n");
					fprintf(stderr, "\tln -s sites-available/control-socket "
						"sites-enabled/control-socket\n");
					fprintf(stderr, "and then re-start the server?\n");
			}
			return -1;
		}
	} else {
		sockfd = client_socket(server);
	}

	/*
	 *	Only works for BSD, but Linux allows us
	 *	to mask SIGPIPE, so that's fine.
	 */
#ifdef SO_NOSIGPIPE
	{
		int set = 1;

		setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int));
	}
#endif

	/*
	 *	Set up the initial header data.
	 */
	magic = 0xf7eead16;
	magic = htonl(magic);
	memcpy(buffer, &magic, sizeof(magic));
	memset(buffer + sizeof(magic), 0, sizeof(magic));

	r = fr_channel_write(sockfd, FR_CHANNEL_INIT_ACK, buffer, 8);
	if (r <= 0) {
	do_close:
		fprintf(stderr, "%s: Error in socket: %s\n",
			progname, fr_syserror(errno));
		close(sockfd);
			return -1;
	}

	r = fr_channel_read(sockfd, &channel, buffer + 8, 8);
	if (r <= 0) goto do_close;

	if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) ||
	    (memcmp(buffer, buffer + 8, 8) != 0)) {
		fprintf(stderr, "%s: Incompatible versions\n", progname);
		close(sockfd);
		return -1;
	}

	if (server && secret) {
		r = do_challenge(sockfd);
		if (r <= 0) goto do_close;
	}

	*out = sockfd;

	return 0;
}