[svn-commits] oej: branch oej/deluxepine-1.4 r237089 - /team/oej/deluxepine-1.4/main/nacl.c

SVN commits to the Digium repositories svn-commits at lists.digium.com
Wed Dec 30 17:23:21 CST 2009


Author: oej
Date: Wed Dec 30 17:23:19 2009
New Revision: 237089

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=237089
Log:
Adding CLI commands for manipulating NACLs. Next up is manager...


Modified:
    team/oej/deluxepine-1.4/main/nacl.c

Modified: team/oej/deluxepine-1.4/main/nacl.c
URL: http://svnview.digium.com/svn/asterisk/team/oej/deluxepine-1.4/main/nacl.c?view=diff&rev=237089&r1=237088&r2=237089
==============================================================================
--- team/oej/deluxepine-1.4/main/nacl.c (original)
+++ team/oej/deluxepine-1.4/main/nacl.c Wed Dec 30 17:23:19 2009
@@ -61,6 +61,7 @@
 	char tag[MAXHOSTNAMELEN];		/*!< Name of this ACL */
 	struct ast_ha *acl;			/*!< The actual ACL */
 	int rules;				/*!< Number of ACL rules */
+	int manipulated;			/*!< Manipulated by CLI or manager */
 	char owner[20];				/*!< Owner (module) */
 	char desc[80];				/*!< Description */
 };
@@ -196,58 +197,219 @@
 	ASTOBJ_UNREF(nacl, nacl_destroy);
 }
 
+/*! \brief Update a HA list by inserting or deleting a row at a specific position 
+	if inser is false, it means delete
+*/
+static struct ast_ha *ha_update(struct ast_ha *ha, int line, int insert, struct ast_ha *new)
+{
+	struct ast_ha *next = ha;
+	struct ast_ha *temp = NULL;
+	int rule = 0;
+
+	/* IF we have nothing to insert, just give up */
+	if (insert && !new) {
+		return ha;
+	}
+
+	/* If there's no existing ha we have nothing to delete */
+	if (!insert && !ha) {
+		return NULL;
+	}
+	ast_log(LOG_DEBUG, "--- Operation %s requested line %d\n", insert?"insert":"delete", line);
+
+	/* Insert or delete at top */
+	if (line <= 1) {
+		if (insert) {
+			if (next == NULL) {
+				return new;
+			}
+			ast_log(LOG_DEBUG, "---  inserting at start\n");
+			new->next = next;
+			return new;
+		} else {	/* Delete first rule */
+			temp = next->next;
+			ast_log(LOG_DEBUG, "---  deleting first line\n");
+			free(next);
+			return temp;
+		}
+	}
+
+	for (rule=1; (rule <= line && next != NULL); rule++) {
+		ast_log(LOG_DEBUG, "\n---  Rule %d ", rule);
+		if (rule == line) {
+			/* Ok, we are here */
+			if (insert) {
+				ast_log(LOG_DEBUG, "---  inserting\n");
+				/* Insert */
+				new->next = temp->next;
+				temp->next = new;
+			} else {
+				ast_log(LOG_DEBUG, "---  deleting\n");
+				/* Delete */
+				temp->next = next->next;	/* The one to delete */
+				free(next);
+			}
+			return ha;
+		}
+		temp = next;	/* The previous NACL */
+		next = next->next;
+	}
+	/* If we are here, the line number was greater than the number of lines available */
+	if (insert) {
+		ast_log(LOG_DEBUG, "---  inserting\n");
+		temp->next = new;
+	}
+	return ha;
+	
+}
+
+/*! \brief Print ha list to CLI */
+static void ha_list(int fd, struct ast_ha *ha, const int rules)
+{
+	char iabuf[INET_ADDRSTRLEN];
+	char iabuf2[INET_ADDRSTRLEN];
+	int rulesfound = 0;
+
+	while (ha) {
+		rulesfound++;
+		ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
+		ast_copy_string(iabuf, ast_inet_ntoa(ha->netmask), sizeof(iabuf));
+		ast_cli(fd,"     %-3.3d: %s: %s mask %s\n", rulesfound, (ha->sense == AST_SENSE_ALLOW) ? "permit" : "deny  ", iabuf2, iabuf);
+		ha = ha->next;
+	}
+	/* Rules is only used for configuration based nacls */
+	if (rules != 0 && rulesfound != rules) {
+		ast_cli(fd, "     NOTE: Number of rules doesn't match configuration. Please check.\n");
+	}
+}
+
+/*! \brief CLI command to list named ACLs */
+static int cli_show_nacls(int fd, int argc, char *argv[])
+{
+#define FORMAT "%-40.40s %-20.20s %5d %5d %7s\n"
+#define FORMAT2 "%-40.40s %-20.20s %-5.5s %-5.5s %7s\n"
+
+	ast_cli(fd, FORMAT2, "ACL name:", "Set by", "#rules", "Usage", "Flags");
+	ASTOBJ_CONTAINER_TRAVERSE(&nacl_list, 1, {
+                ASTOBJ_RDLOCK(iterator);
+		ast_cli(fd, FORMAT, iterator->name, 
+			S_OR(iterator->owner, "-"),
+			iterator->rules,
+			iterator->refcount,
+			iterator->manipulated ? "M" : "");
+		ha_list(fd, iterator->acl, iterator->rules);
+                ASTOBJ_UNLOCK(iterator);
+	} );
+	ast_cli(fd, "\nFlag M = Modified by AMI or CLI\n");
+	return RESULT_SUCCESS;
+}
+#undef FORMAT
+#undef FORMAT2
+
+/*! \brief Update NACL (or create it if it doesn't exist) */
+static int nacl_update(int fd, const char *command, const char *name, int rule, char *operation, const char *target, const char *owner)
+{
+	struct named_acl *nacl;
+	struct ast_ha *newha = NULL;
+	int insert = !strcasecmp(command, "add");
+
+	nacl = ast_nacl_find(name);
+	if (!nacl) {
+		if (insert) {
+			nacl = ast_nacl_add(name, owner);
+			/* Add a ref so that both existing and new NACLs has an extra ref after nacl_find or nacl_add */
+			ast_cli(fd, "Successfully added new NACL %s\n", name);
+			ASTOBJ_REF(nacl);
+		} else {
+			ast_cli(fd, "No such NACL: %s\n", name);
+			return RESULT_SUCCESS;
+		}
+	}
+	ASTOBJ_WRLOCK(nacl);
+	if (insert) {
+		newha = ast_append_ha(operation, target, NULL);
+	}
+	nacl->acl = ha_update(nacl->acl, rule, insert, newha);
+	if (insert) {
+		nacl->rules++;
+	} else {
+		nacl->rules--;
+	}
+	nacl->manipulated = TRUE;
+	ASTOBJ_UNLOCK(nacl);
+	ASTOBJ_UNREF(nacl, nacl_destroy);
+	return RESULT_SUCCESS;
+}
+
 static char show_nacls_usage[] = 
 "Usage: nacl show\n"
 "       Lists all configured named ACLs.\n"
 "       Named ACLs can be used in many configuration files as well as internally\n"
 "       by Asterisk.\n";
 
-/*! \brief Print ha list to CLI */
-static void ha_list(int fd, struct ast_ha *ha, const int rules)
-{
-	char iabuf[INET_ADDRSTRLEN];
-	char iabuf2[INET_ADDRSTRLEN];
-	int rulesfound = 0;
-
-	while (ha) {
-		rulesfound++;
-		ast_copy_string(iabuf2, ast_inet_ntoa(ha->netaddr), sizeof(iabuf2));
-		ast_copy_string(iabuf, ast_inet_ntoa(ha->netmask), sizeof(iabuf));
-		ast_cli(fd,"     %s: %s mask %s\n", (ha->sense == AST_SENSE_ALLOW) ? "permit" : "deny  ", iabuf2, iabuf);
-		ha = ha->next;
-	}
-	/* Rules is only used for configuration based nacls */
-	if (rules != 0 && rulesfound != rules) {
-		ast_cli(fd, "     NOTE: Number of rules doesn't match configuration. Please check.\n");
-	}
-}
-
-/*! \brief CLI command to list named ACLs */
-static int cli_show_nacls(int fd, int argc, char *argv[])
-{
-#define FORMAT "%-40.40s %-20.20s %5d %5d \n"
-#define FORMAT2 "%-40.40s %-20.20s %-5.5s %-5.5s\n"
-
-	ast_cli(fd, FORMAT2, "ACL name:", "Set by", "#rules", "Usage");
-	ASTOBJ_CONTAINER_TRAVERSE(&nacl_list, 1, {
-                ASTOBJ_RDLOCK(iterator);
-		ast_cli(fd, FORMAT, iterator->name, 
-			S_OR(iterator->owner, "-"),
-			iterator->rules,
-			iterator->refcount);
-		ha_list(fd, iterator->acl, iterator->rules);
-                ASTOBJ_UNLOCK(iterator);
-	} );
-	ast_cli(fd, "\n");
-	return RESULT_SUCCESS;
-}
-#undef FORMAT
-#undef FORMAT2
-
 static struct ast_cli_entry cli_nacl = { 
 	{ "nacl", "show", NULL },
 	cli_show_nacls, "List configured named ACLs.",
 	show_nacls_usage };
+
+/*! \brief CLI command to add named ACLs */
+static int cli_nacl_add(int fd, int argc, char *argv[])
+{
+
+	if (argc != 6) {
+		return RESULT_SHOWUSAGE;
+	}
+	if (option_debug >= 2) {
+		ast_cli(fd, "--- Command: %s %s\n", argv[0], argv[1]);
+		ast_cli(fd, "--- NACL Name: %s Operation %s\n", argv[2], argv[4]);
+		ast_cli(fd, "--- NACL line: %s Address %s\n", argv[3], argv[5]);
+	}
+	if (strcasecmp(argv[4], "permit") && strcasecmp(argv[4], "deny")) {
+		ast_cli(fd, "Error: Illegal operand %s\n", argv[4]);
+		return RESULT_SHOWUSAGE;
+	}
+	return nacl_update(fd, argv[1], argv[2], atoi(argv[3]), argv[4], argv[5], "cli");
+}
+
+/*! \brief CLI command to delete rules in named ACLs */
+static int cli_nacl_delete(int fd, int argc, char *argv[])
+{
+	if (argc != 4) {
+		return RESULT_SHOWUSAGE;
+	}
+	ast_cli(fd, "--- Command: %s %s\n", argv[0], argv[1]);
+	ast_cli(fd, "--- NACL Name: %s Line %s\n", argv[2], argv[3]);
+	return nacl_update(fd, argv[1], argv[2], atoi(argv[3]), NULL, NULL, "cli");
+}
+
+static char nacl_delete_usage[] = 
+"Usage: nacl delete <name> <number>\n"
+"       Delete a rule from a NACL.\n"
+"	The NACL will still remain in memory, even if there are no active rules\n"
+"	Please note that changes to ACLs are not stored in configuration, thuse are not\n"
+"	persistant between Asterisk restarts.\n"
+"\n";
+
+static char nacl_add_usage[] = 
+"Usage: nacl add <name> <number> [permit|deny] <address>\n"
+"       Add a rule to a specific NACL.\n"
+"	If the NACL doesn't exist, it's created. If there is an existing rule with the given\n"
+"       number, the new rule is inserted before.\n"
+"       Address is given as <ipaddress>/<netmask> or <ipaddress>/<maskbytes> (CIDR notation)\n"
+"	Please note that changes to ACLs are not stored in configuration, thuse are not\n"
+"	persistant between Asterisk restarts.\n"
+"\n";
+
+static struct ast_cli_entry clidef_nacl_add = { 
+	{ "nacl", "add", NULL },
+	cli_nacl_add, "Add a new rule to a NACL.",
+	nacl_add_usage };
+
+static struct ast_cli_entry clidef_nacl_delete = { 
+	{ "nacl", "delete", NULL },
+	cli_nacl_delete, "Delete a rule from an NACL.",
+	nacl_delete_usage };
+
 
 /* Initialize named ACLs 
 	This function is used both at load and reload time.
@@ -301,6 +463,8 @@
 
 	if (reload_reason == NACL_LOAD) {
 		ast_cli_register(&cli_nacl);
+		ast_cli_register(&clidef_nacl_add);
+		ast_cli_register(&clidef_nacl_delete);
 	}
 	return 0;
 }
@@ -316,26 +480,3 @@
 {
 	return nacl_init(NACL_RELOAD);
 }
-
-#ifdef ERROR
-nacl.c: In function 'ast_nacl_add':
-nacl.c:95: warning: assignment from incompatible pointer type
-nacl.c: In function 'ast_nacl_find_all':
-nacl.c:114: warning: assignment from incompatible pointer type
-nacl.c:114: warning: implicit declaration of function 'ASTOBJ_RDUNLOCK'
-nacl.c: At top level:
-nacl.c:156: warning: no previous prototype for 'ast_nacl_mark_all_owned'
-nacl.c: In function 'ast_nacl_mark_all_owned':
-nacl.c:161: warning: assignment from incompatible pointer type
-nacl.c:157: warning: unused variable 'nacl'
-nacl.c:326:1: error: unterminated argument list invoking macro "ASTOBJ_CONTAINER_TRAVERSE"
-nacl.c: In function 'cli_show_nacls':
-nacl.c:239: error: 'ASTOBJ_CONTAINER_TRAVERSE' undeclared (first use in this function)
-nacl.c:239: error: (Each undeclared identifier is reported only once
-nacl.c:239: error: for each function it appears in.)
-nacl.c:239: error: expected ';' at end of input
-nacl.c:239: error: expected declaration or statement at end of input
-nacl.c:229: warning: unused variable 'nacl'
-nacl.c:239: warning: no return statement in function returning non-void
-#endif
-




More information about the svn-commits mailing list