Example #1
0
/** Instantiate thread data for the submodule.
 *
 */
static int mod_thread_instantiate(UNUSED CONF_SECTION const *cs, void *instance, UNUSED fr_event_list_t *el, void *thread)
{
	rlm_stats_t *inst = talloc_get_type_abort(instance, rlm_stats_t);
	rlm_stats_thread_t *t = thread;

	(void) talloc_set_type(t, rlm_stats_thread_t);

	t->inst = inst;

	t->src = rbtree_talloc_create(t, data_cmp, rlm_stats_data_t, NULL, RBTREE_FLAG_LOCK);
	t->dst = rbtree_talloc_create(t, data_cmp, rlm_stats_data_t, NULL, RBTREE_FLAG_LOCK);

	pthread_mutex_lock(&inst->mutex);
	fr_dlist_insert_head(&inst->list, t);
	pthread_mutex_unlock(&inst->mutex);

	return 0;
}
static int mod_instantiate(void *instance, UNUSED CONF_SECTION *conf)
{
	rlm_securid_t *inst = instance;

	/*
	 *	Lookup sessions in the tree.  We don't free them in
	 *	the tree, as that's taken care of elsewhere...
	 */
	inst->session_tree = rbtree_talloc_create(NULL, securid_session_cmp, SECURID_SESSION NULL, 0);
	if (!inst->session_tree) {
		ERROR("Cannot initialize session tree");
		return -1;
	}

	pthread_mutex_init(&(inst->session_mutex), NULL);
	return 0;
}
Example #3
0
/** Create a network
 *
 * @param[in] ctx the talloc ctx
 * @param[in] el the event list
 * @param[in] logger the destination for all logging messages
 * @param[in] lvl log level
 * @return
 *	- NULL on error
 *	- fr_network_t on success
 */
fr_network_t *fr_network_create(TALLOC_CTX *ctx, fr_event_list_t *el, fr_log_t const *logger, fr_log_lvl_t lvl)
{
	fr_network_t *nr;

	nr = talloc_zero(ctx, fr_network_t);
	if (!nr) {
		fr_strerror_printf("Failed allocating memory");
		return NULL;
	}

	nr->el = el;
	nr->log = logger;
	nr->lvl = lvl;
	nr->max_workers = MAX_WORKERS;
	nr->num_workers = 0;

	nr->kq = fr_event_list_kq(nr->el);
	rad_assert(nr->kq >= 0);

	nr->aq_control = fr_atomic_queue_create(nr, 1024);
	if (!nr->aq_control) {
		talloc_free(nr);
		return NULL;
	}

	nr->aq_ident = fr_event_user_insert(nr->el, fr_network_evfilt_user, nr);
	if (!nr->aq_ident) {
		fr_strerror_printf_push("Failed updating event list");
		talloc_free(nr);
		return NULL;
	}

	nr->control = fr_control_create(nr, nr->kq, nr->aq_control, nr->aq_ident);
	if (!nr->control) {
		fr_strerror_printf_push("Failed creating control queue");
	fail:
		(void) fr_event_user_delete(nr->el, fr_network_evfilt_user, nr);
		talloc_free(nr);
		return NULL;
	}

	/*
	 *	@todo - rely on thread-local variables.  And then the
	 *	various users of this can check if (rb == nr->rb), and
	 *	if so, skip the whole control plane / kevent /
	 *	whatever roundabout thing.
	 */
	nr->rb = fr_ring_buffer_create(nr, FR_CONTROL_MAX_MESSAGES * FR_CONTROL_MAX_SIZE);
	if (!nr->rb) {
		fr_strerror_printf_push("Failed creating ring buffer");
	fail2:
		fr_control_free(nr->control);
		goto fail;
	}

	if (fr_control_callback_add(nr->control, FR_CONTROL_ID_CHANNEL, nr, fr_network_channel_callback) < 0) {
		fr_strerror_printf_push("Failed adding channel callback");
		goto fail2;
	}

	if (fr_control_callback_add(nr->control, FR_CONTROL_ID_SOCKET, nr, fr_network_socket_callback) < 0) {
		fr_strerror_printf_push("Failed adding socket callback");
		goto fail2;
	}

	if (fr_control_callback_add(nr->control, FR_CONTROL_ID_DIRECTORY, nr, fr_network_directory_callback) < 0) {
		fr_strerror_printf_push("Failed adding socket callback");
		goto fail2;
	}

	if (fr_control_callback_add(nr->control, FR_CONTROL_ID_WORKER, nr, fr_network_worker_callback) < 0) {
		fr_strerror_printf_push("Failed adding worker callback");
		goto fail2;
	}

	if (fr_control_callback_add(nr->control, FR_CONTROL_ID_INJECT, nr, fr_network_inject_callback) < 0) {
		fr_strerror_printf_push("Failed adding packet injection callback");
		goto fail2;
	}

	/*
	 *	Create the various heaps.
	 */
	nr->sockets = rbtree_talloc_create(nr, socket_listen_cmp, fr_network_socket_t, NULL, RBTREE_FLAG_NONE);
	if (!nr->sockets) {
		fr_strerror_printf_push("Failed creating listen tree for sockets");
		goto fail2;
	}

	nr->sockets_by_num = rbtree_talloc_create(nr, socket_num_cmp, fr_network_socket_t, NULL, RBTREE_FLAG_NONE);
	if (!nr->sockets_by_num) {
		fr_strerror_printf_push("Failed creating number tree for sockets");
		goto fail2;
	}

	nr->replies = fr_heap_create(nr, reply_cmp, fr_channel_data_t, channel.heap_id);
	if (!nr->replies) {
		fr_strerror_printf_push("Failed creating heap for replies");
		goto fail2;
	}

	if (fr_event_post_insert(nr->el, fr_network_post_event, nr) < 0) {
		fr_strerror_printf("Failed inserting post-processing event");
		goto fail2;
	}

	return nr;
}
Example #4
0
/*
 *	Do any per-module initialization that is separate to each
 *	configured instance of the module.  e.g. set up connections
 *	to external databases, read configuration files, set up
 *	dictionary entries, etc.
 *
 *	If configuration information is given in the config section
 *	that must be referenced in later calls, store a handle to it
 *	in *instance otherwise put a null pointer there.
 */
static int mod_bootstrap(void *instance, CONF_SECTION *conf)
{
	rlm_csv_t *inst = instance;
	int i;
	char const *p;
	char *q;
	char *header;
	FILE *fp;
	int lineno;
	char buffer[8192];

	inst->name = cf_section_name2(conf);
	if (!inst->name) inst->name = cf_section_name1(conf);

	if (inst->delimiter[1]) {
		cf_log_err(conf, "'delimiter' must be one character long");
		return -1;
	}

	for (p = inst->header; p != NULL; p = strchr(p + 1, *inst->delimiter)) {
		inst->num_fields++;
	}

	if (inst->num_fields < 2) {
		cf_log_err(conf, "Must have at least a key field and data field");
		return -1;
	}

	inst->field_names = talloc_array(inst, const char *, inst->num_fields);
	if (!inst->field_names) {
	oom:
		cf_log_err(conf, "Out of memory");
		return -1;
	}

	inst->field_offsets = talloc_array(inst, int, inst->num_fields);
	if (!inst->field_offsets) goto oom;

	for (i = 0; i < inst->num_fields; i++) {
		inst->field_offsets[i] = -1; /* unused */
	}

	/*
	 *	Get a writable copy of the header
	 */
	header = talloc_typed_strdup(inst, inst->header);
	if (!header) goto oom;

	/*
	 *	Mark up the field names.  Note that they can be empty,
	 *	in which case they don't map to anything.
	 */
	inst->key_field = -1;

	/*
	 *	FIXME: remove whitespace from field names, if we care.
	 */
	for (p = header, i = 0; p != NULL; p = q, i++) {
		q = strchr(p, *inst->delimiter);

		/*
		 *	Fields 0..N-1
		 */
		if (q) {
			*q = '\0';

			if (q > (p + 1)) {
					if (strcmp(p, inst->key) == 0) {
					inst->key_field = i;
				} else {
					inst->field_offsets[i] = inst->used_fields++;
				}
			}
			q++;

		} else {	/* field N */
			if (*p) {
				if (strcmp(p, inst->key) == 0) {
					inst->key_field = i;
				} else {
					inst->field_offsets[i] = inst->used_fields++;
				}
			}
		}

		/*
		 *	Save the field names, even when they're not used.
		 */
		inst->field_names[i] = p;
	}

	if (inst->key_field < 0) {
		cf_log_err(conf, "Key field '%s' does not appear in header", inst->key);
		return -1;
	}

	inst->tree = rbtree_talloc_create(inst, csv_entry_cmp, rlm_csv_entry_t, NULL, 0);
	if (!inst->tree) goto oom;

	/*
	 *	Read the file line by line.
	 */
	fp = fopen(inst->filename, "r");
	if (!fp) {
		cf_log_err(conf, "Error opening filename %s: %s", inst->filename, fr_syserror(errno));
		return -1;
	}

	lineno = 1;
	while (fgets(buffer, sizeof(buffer), fp)) {
		rlm_csv_entry_t *e;

		e = file2csv(conf, inst, lineno, buffer);
		if (!e) {
			fclose(fp);
			return -1;
		}

		lineno++;
	}

	fclose(fp);

	/*
	 *	And register the map function.
	 */
	map_proc_register(inst, inst->name, mod_map_proc, csv_map_verify, 0);

	return 0;
}