[asterisk-commits] jrose: branch jrose/nacl_branch r368457 - /team/jrose/nacl_branch/main/nacl.c

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Jun 4 15:40:41 CDT 2012


Author: jrose
Date: Mon Jun  4 15:40:40 2012
New Revision: 368457

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=368457
Log:
Oops, forgot to add nacl.c

Added:
    team/jrose/nacl_branch/main/nacl.c   (with props)

Added: team/jrose/nacl_branch/main/nacl.c
URL: http://svnview.digium.com/svn/asterisk/team/jrose/nacl_branch/main/nacl.c?view=auto&rev=368457
==============================================================================
--- team/jrose/nacl_branch/main/nacl.c (added)
+++ team/jrose/nacl_branch/main/nacl.c Mon Jun  4 15:40:40 2012
@@ -1,0 +1,288 @@
+/*
+ * Asterisk -- A telephony toolkit for Linux.
+ *
+ * Copyright (C) 1999-2012, Digium, Inc.
+ *
+ * Jonathan Rose <jrose at digium.com> - Named ACL coder
+ * Olle E. Johanson <oej at something> - Named ACL concepts
+ * Mark Spencer <markster at digium.com>  - Asterisk Author
+ *
+ * v1.0   - (XX-XX-12)
+ */
+
+#include "asterisk.h"
+
+ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
+
+#include "asterisk/config.h"
+#include "asterisk/utils.h"
+#include "asterisk/module.h"
+#include "asterisk/cli.h"
+#include "asterisk/acl.h"
+#include "asterisk/astobj2.h"
+
+#define NACL_CONFIG "nacl.conf"
+
+#define NAME_LENGTH 80
+
+static struct ao2_container *nacl_list;
+
+struct nacl {
+	struct ast_ha *ha;
+	char name[NAME_LENGTH]; /* Same max length as a configuration category */
+};
+
+static void destroy_nacl(void *obj)
+{
+	struct nacl *nacl = obj;
+	ast_free_ha(nacl->ha);
+}
+
+static void add_nacl_from_config(char *name, struct ast_variable *input)
+{
+	struct nacl tmp;
+	struct nacl *nacl;
+	struct ast_variable *var = input;
+
+	ast_copy_string(tmp.name, name, sizeof(tmp.name));
+
+	nacl = ao2_find(nacl_list, &tmp, OBJ_POINTER);
+
+	if (nacl) {
+		ast_log(LOG_ERROR, "Multiple definitions present for nacl: %s\n", name);
+		ao2_ref(nacl, -1);
+		return;
+	}
+
+	nacl = ao2_alloc(sizeof(*nacl), destroy_nacl);
+
+	if (!nacl) {
+		ast_log(LOG_ERROR, "Failed to allocate ao2 object for nacl.\n");
+		return;
+	}
+
+	nacl->ha = NULL;
+	ast_copy_string(nacl->name, name, sizeof(nacl->name));
+
+	while(var) {
+		if (!strcasecmp(var->name, "permit") || !strcasecmp(var->name, "deny")) {
+			int ha_error = 0;
+			nacl->ha = ast_append_ha(var->name, var->value, nacl->ha, &ha_error);
+			if (ha_error) {
+				ast_log(LOG_ERROR, "Bad ACL entry in nacl configuration line %d : %s\n", var->lineno, var->value);
+			}
+		}
+		var = var->next;
+	}
+	ao2_link(nacl_list, nacl);
+	ao2_ref(nacl, -1);
+
+
+}
+
+static int nacl_hash_fn(const void *obj, const int flags)
+{
+	const struct nacl *entry = obj;
+	return ast_str_hash(entry->name);
+}
+
+static int nacl_cmp_fn(void *obj, void *arg, const int flags)
+{
+	struct nacl *entry1 = obj;
+	struct nacl *entry2 = arg;
+
+	return (!strcmp(entry1->name, entry2->name)) ? (CMP_MATCH | CMP_STOP) : 0;
+}
+
+static void nacl_list_scrub(void)
+{
+	struct ao2_iterator i;
+	void *o;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	while ((o = ao2_iterator_next(&i))) {
+		ao2_unlink(nacl_list, o);
+		ao2_ref(o, -1);
+	}
+
+	ao2_iterator_destroy(&i);
+}
+
+static int load_nacl_config(int reload)
+{
+	static char *cat = NULL;
+	struct ast_config *cfg = NULL;
+	struct ast_variable *var = NULL;
+	struct ast_flags config_flags = { reload ? CONFIG_FLAG_FILEUNCHANGED : 0 };
+
+	if ((cfg = ast_config_load(NACL_CONFIG, config_flags)) == CONFIG_STATUS_FILEUNCHANGED) {
+		return -1;
+	}
+
+	if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEINVALID) {
+		ast_log(LOG_WARNING, "No such configuration file %s\n", NACL_CONFIG);
+		return 0;
+	}
+
+	/* We need to lock the list since we'll be wiping it and repopulating it. */
+	ao2_lock(nacl_list);
+
+	/* If reloading, clean the list.  Otherwise, we need to create the list. */
+	if (reload) {
+		/* scrub the nacl entries */
+		nacl_list_scrub();
+	} else {
+		nacl_list = ao2_container_alloc(37, nacl_hash_fn, nacl_cmp_fn);
+	}
+
+
+	cat = ast_category_browse(cfg, NULL);
+	while (cat) {
+		if (strcasecmp(cat, "general")) {
+			var = ast_variable_browse(cfg, cat);
+			add_nacl_from_config(cat, var);
+		}
+		cat = ast_category_browse(cfg, cat);
+	}
+
+	/* It's safe to unlock the list now. */
+	ao2_unlock(nacl_list);
+
+	ast_config_destroy(cfg);
+	return 1;
+}
+
+struct ast_ha *ast_append_nacl(struct ast_ha *ha, const char *name)
+{
+	struct nacl tmp;
+	struct nacl *nacl;
+
+	ast_copy_string(tmp.name, name, sizeof(tmp.name));
+
+	nacl = ao2_find(nacl_list, &tmp, OBJ_POINTER);
+
+	if (!nacl) {
+		ast_log(LOG_ERROR, "nacl '%s' does not exist. Could not apply nacl.\n", name);
+		return ha;
+	}
+
+	/* Apply Staples! */
+	ha = ast_duplicate_and_append_ha(ha, nacl->ha);
+
+	ao2_ref(nacl, -1);
+
+	return ha;
+}
+
+static void reload_nacl(int fd)
+{
+	ast_cli(fd, "Reloading nacl configuration...\n");
+	if (load_nacl_config(1) == 1) {
+		ast_cli(fd, "Any modules using statically defined ACLs which were using existing nacls will need to be reloaded for changes to take effect.\n");
+	}
+}
+
+static void cli_display_nacl(int fd, const char *name)
+{
+	struct nacl tmp;
+	struct nacl *nacl;
+	struct ast_ha *ha;
+
+	ast_copy_string(tmp.name, name, sizeof(tmp.name));
+
+	nacl = ao2_find(nacl_list, &tmp, OBJ_POINTER);
+
+	if (!nacl) {
+		/* nacl not found message */
+		ast_cli(fd, "\nCould not find acl named '%s'\n", name);
+		return;
+	}
+
+	ast_cli(fd, "\n%s\n--------------------------------------------------\n", name);
+	for (ha = nacl->ha; ha; ha = ha->next) {
+		char *output = ast_sockaddr_stringify(&ha->addr);
+		ast_cli(fd, "%s - %s\n", ha->sense == AST_SENSE_ALLOW ? "allow" : " deny", output);
+	}
+
+	ao2_ref(nacl, -1);
+}
+
+static void cli_display_nacl_list(int fd)
+{
+	struct ao2_iterator i;
+	void *o;
+
+	i = ao2_iterator_init(nacl_list, 0);
+
+	ast_cli(fd, "\nnacl\n----\n");
+
+	while ((o = ao2_iterator_next(&i))) {
+		struct nacl *nacl = o;
+
+		ast_cli(fd, "%s\n", nacl->name);
+
+		ao2_ref(o, -1);
+	}
+
+	ao2_iterator_destroy(&i);
+}
+
+static char *handle_nacl_reload(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "nacl reload";
+		e->usage =
+			"Usage: nacl reload\n"
+			"       Reloads the nacl configuration.\n";
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc > 2) {
+		return CLI_SHOWUSAGE;
+	}
+
+	reload_nacl(a->fd);
+	return CLI_SUCCESS;
+}
+
+static char *handle_show_nacl_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
+{
+	switch (cmd) {
+	case CLI_INIT:
+		e->command = "nacl show";
+		e->usage =
+			"Usage: nacl show <name>\n"
+			"   Shows a list of named ACLs or lists all entries in a given named ACL.\n";
+		return NULL;
+	case CLI_GENERATE:
+		return NULL;
+	}
+
+	if (a->argc == 2) {
+		cli_display_nacl_list(a->fd);
+		return CLI_SUCCESS;
+	}
+
+	if (a->argc == 3) {
+		cli_display_nacl(a->fd, a->argv[2]);
+		return CLI_SUCCESS;
+	}
+
+
+	return CLI_SHOWUSAGE;
+}
+
+static struct ast_cli_entry cli_nacl[] = {
+	AST_CLI_DEFINE(handle_nacl_reload, "Reload nacl configurations"),
+	AST_CLI_DEFINE(handle_show_nacl_cmd, "Show a named ACL or list all named ACLs"),
+};
+
+int init_nacl()
+{
+	load_nacl_config(0);
+	ast_cli_register_multiple(cli_nacl, ARRAY_LEN(cli_nacl));
+	return 0;
+}

Propchange: team/jrose/nacl_branch/main/nacl.c
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: team/jrose/nacl_branch/main/nacl.c
------------------------------------------------------------------------------
    svn:keywords = "Author Date Id Rev URL"

Propchange: team/jrose/nacl_branch/main/nacl.c
------------------------------------------------------------------------------
    svn:mime-type = text/plain




More information about the asterisk-commits mailing list