/** 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; }
/** 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; }
/* * 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; }