示例#1
0
/** 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;
}
示例#2
0
int main(int argc, char **argv)
{
	int		c;
	char		filesecret[256];
	FILE		*fp;
	int		force_af = AF_UNSPEC;
	radsnmp_conf_t *conf;
	int		ret;
	int		sockfd;
	TALLOC_CTX	*autofree = talloc_autofree_context();

	fr_log_fp = stderr;

	conf = talloc_zero(autofree, radsnmp_conf_t);
	conf->proto = IPPROTO_UDP;
	conf->dict_dir = DICTDIR;
	conf->raddb_dir = RADDBDIR;
	conf->secret = talloc_strdup(conf, "testing123");
	conf->timeout.tv_sec = 3;
	conf->retries = 5;

#ifndef NDEBUG
	if (fr_fault_setup(autofree, getenv("PANIC_ACTION"), argv[0]) < 0) {
		fr_perror("radsnmp");
		exit(EXIT_FAILURE);
	}
#endif

	talloc_set_log_stderr();

	while ((c = getopt(argc, argv, "46c:d:D:f:Fhi:l:n:p:P:qr:sS:t:vx")) != -1) switch (c) {
		case '4':
			force_af = AF_INET;
			break;

		case '6':
			force_af = AF_INET6;
			break;

		case 'D':
			conf->dict_dir = optarg;
			break;

		case 'd':
			conf->raddb_dir = optarg;
			break;

		case 'l':
		{
			int log_fd;

			if (strcmp(optarg, "stderr") == 0) {
				fr_log_fp = stderr;	/* stdout goes to netsnmp */
				break;
			}

			log_fd = open(optarg, O_WRONLY | O_APPEND | O_CREAT, 0640);
			if (log_fd < 0) {
				fprintf(stderr, "radsnmp: Failed to open log file %s: %s\n",
					optarg, fr_syserror(errno));
				exit(EXIT_FAILURE);
			}
			fr_log_fp = fdopen(log_fd, "a");
		}
			break;

		case 'P':
			conf->proto_str = optarg;
			if (strcmp(conf->proto_str, "tcp") != 0) {
				if (strcmp(conf->proto_str, "udp") != 0) usage();
			} else {
				conf->proto = IPPROTO_TCP;
			}
			break;

		case 'r':
			if (!isdigit((int) *optarg)) usage();
			conf->retries = atoi(optarg);
			if ((conf->retries == 0) || (conf->retries > 1000)) usage();
			break;

		case 'S':
		{
			char *p;
			fp = fopen(optarg, "r");
			if (!fp) {
			       ERROR("Error opening %s: %s", optarg, fr_syserror(errno));
			       exit(EXIT_FAILURE);
			}
			if (fgets(filesecret, sizeof(filesecret), fp) == NULL) {
			       ERROR("Error reading %s: %s", optarg, fr_syserror(errno));
			       exit(EXIT_FAILURE);
			}
			fclose(fp);

			/* truncate newline */
			p = filesecret + strlen(filesecret) - 1;
			while ((p >= filesecret) &&
			      (*p < ' ')) {
			       *p = '\0';
			       --p;
			}

			if (strlen(filesecret) < 2) {
			       ERROR("Secret in %s is too short", optarg);
			       exit(EXIT_FAILURE);
			}
			talloc_free(conf->secret);
			conf->secret = talloc_strdup(conf, filesecret);
		}
		       break;

		case 't':
			if (fr_timeval_from_str(&conf->timeout, optarg) < 0) {
				ERROR("Failed parsing timeout value %s", fr_strerror());
				exit(EXIT_FAILURE);
			}
			break;

		case 'v':
			DEBUG("%s", radsnmp_version);
			exit(0);

		case 'x':
			fr_debug_lvl++;
			break;

		case 'h':
		default:
			usage();
	}
	argc -= (optind - 1);
	argv += (optind - 1);

	if ((argc < 2)  || ((conf->secret == NULL) && (argc < 3))) {
		ERROR("Insufficient arguments");
		usage();
	}
	/*
	 *	Mismatch between the binary and the libraries it depends on
	 */
	if (fr_check_lib_magic(RADIUSD_MAGIC_NUMBER) < 0) {
		fr_perror("radsnmp");
		return EXIT_FAILURE;
	}

	if (fr_dict_autoload(radsnmp_dict) < 0) {
		fr_perror("radsnmp");
		exit(EXIT_FAILURE);
	}

	if (fr_dict_attr_autoload(radsnmp_dict_attr) < 0) {
		fr_perror("radsnmp");
		exit(EXIT_FAILURE);
	}

	if (fr_dict_read(dict_freeradius, conf->raddb_dir, FR_DICTIONARY_FILE) == -1) {
		fr_perror("radsnmp");
		exit(EXIT_FAILURE);
	}
	fr_strerror();	/* Clear the error buffer */

	if (fr_log_fp) setvbuf(fr_log_fp, NULL, _IONBF, 0);

	/*
	 *	Get the request type
	 */
	if (!isdigit((int) argv[2][0])) {
		int code;

		code = fr_str2int(fr_request_types, argv[2], -1);
		if (code < 0) {
			ERROR("Unrecognised request type \"%s\"", argv[2]);
			usage();
		}
		conf->code = (unsigned int)code;
	} else {
		conf->code = atoi(argv[2]);
	}

	/*
	 *	Resolve hostname.
	 */
	if (fr_inet_pton_port(&conf->server_ipaddr, &conf->server_port, argv[1], -1, force_af, true, true) < 0) {
		ERROR("%s", fr_strerror());
		exit(EXIT_FAILURE);
	}

	/*
	 *	Add the secret
	 */
	if (argv[3]) {
		talloc_free(conf->secret);
		conf->secret = talloc_strdup(conf, argv[3]);
	}

	conf->snmp_root = fr_dict_attr_child_by_num(attr_vendor_specific, VENDORPEC_FREERADIUS);
	if (!conf->snmp_root) {
		ERROR("Incomplete dictionary: Missing definition for Extended-Attribute-1(%i)."
		      "Vendor-Specific(%i).FreeRADIUS(%i)",
		      attr_extended_attribute_1->attr,
		      attr_vendor_specific->attr,
		      VENDORPEC_FREERADIUS);
	dict_error:
		talloc_free(conf);
		exit(EXIT_FAILURE);
	}

	conf->snmp_oid_root = fr_dict_attr_child_by_num(conf->snmp_root, 1);
	if (!conf->snmp_oid_root) {
		ERROR("Incomplete dictionary: Missing definition for 1.Extended-Attribute-1(%i)."
		      "Vendor-Specific(%i).FreeRADIUS(%i).FreeRADIUS-Iso(%i)",
		      attr_extended_attribute_1->attr,
		      attr_vendor_specific->attr,
		      VENDORPEC_FREERADIUS, 1);
		goto dict_error;
	}

	switch (conf->proto) {
	case IPPROTO_TCP:
		sockfd = fr_socket_client_tcp(NULL, &conf->server_ipaddr, conf->server_port, true);
		break;

	default:
	case IPPROTO_UDP:
		sockfd = fr_socket_client_udp(NULL, NULL, &conf->server_ipaddr, conf->server_port, true);
		break;
	}
	if (sockfd < 0) {
		ERROR("Failed connecting to server %s:%hu", "foo", conf->server_port);
		ret = 1;
		goto finish;
	}

	fr_set_signal(SIGPIPE, rs_signal_stop);
	fr_set_signal(SIGINT, rs_signal_stop);
	fr_set_signal(SIGTERM, rs_signal_stop);
#ifdef SIGQUIT
	fr_set_signal(SIGQUIT, rs_signal_stop);
#endif

	DEBUG("%s - Starting pass_persist read loop", radsnmp_version);
	ret = radsnmp_send_recv(conf, sockfd);
	DEBUG("Read loop done");

finish:
	if (fr_log_fp) fflush(fr_log_fp);

	/*
	 *	Everything should be parented from conf
	 */
	talloc_free(conf);

	/*
	 *	...except the dictionaries
	 */
	fr_dict_autofree(radsnmp_dict);

	return ret;
}
示例#3
0
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;
}