svn commit: r316434 - in head: sbin/ipfw sys/netinet sys/netpfil/ipfw

Andrey V. Elsukov ae at FreeBSD.org
Mon Apr 3 02:44:41 UTC 2017


Author: ae
Date: Mon Apr  3 02:44:40 2017
New Revision: 316434
URL: https://svnweb.freebsd.org/changeset/base/316434

Log:
  Add O_EXTERNAL_DATA opcode support.
  
  This opcode can be used to attach some data to external action opcode.
  And unlike to O_EXTERNAL_INSTANCE opcode, this opcode does not require
  creating of named instance to pass configuration arguments to external
  action handler. The data is coming just next to O_EXTERNAL_ACTION opcode.
  
  The userlevel part currenly supports formatting for opcode with ipfw_insn
  size, by default it expects u16 numeric value in the arg1.
  
  Obtained from:	Yandex LLC
  MFC after:	2 weeks
  Sponsored by:	Yandex LLC

Modified:
  head/sbin/ipfw/ipfw2.c
  head/sys/netinet/ip_fw.h
  head/sys/netpfil/ipfw/ip_fw_eaction.c
  head/sys/netpfil/ipfw/ip_fw_sockopt.c

Modified: head/sbin/ipfw/ipfw2.c
==============================================================================
--- head/sbin/ipfw/ipfw2.c	Mon Apr  3 02:26:30 2017	(r316433)
+++ head/sbin/ipfw/ipfw2.c	Mon Apr  3 02:44:40 2017	(r316434)
@@ -1642,6 +1642,22 @@ show_static_rule(struct cmdline_opts *co
 			break;
 		}
 
+		case O_EXTERNAL_DATA: {
+			if (has_eaction == NULL)
+				break;
+			/*
+			 * Currently we support data formatting only for
+			 * external data with datalen u16. For unknown data
+			 * print its size in bytes.
+			 */
+			if (cmd->len == F_INSN_SIZE(ipfw_insn))
+				bprintf(bp, " %u", cmd->arg1);
+			else
+				bprintf(bp, " %ubytes",
+				    cmd->len * sizeof(uint32_t));
+			break;
+		}
+
 		case O_SETDSCP:
 		    {
 			const char *code;

Modified: head/sys/netinet/ip_fw.h
==============================================================================
--- head/sys/netinet/ip_fw.h	Mon Apr  3 02:26:30 2017	(r316433)
+++ head/sys/netinet/ip_fw.h	Mon Apr  3 02:44:40 2017	(r316434)
@@ -281,6 +281,7 @@ enum ipfw_opcodes {		/* arguments (4 byt
 
 	O_EXTERNAL_ACTION,	/* arg1=id of external action handler */
 	O_EXTERNAL_INSTANCE,	/* arg1=id of eaction handler instance */
+	O_EXTERNAL_DATA,	/* variable length data */
 
 	O_LAST_OPCODE		/* not an opcode!		*/
 };

Modified: head/sys/netpfil/ipfw/ip_fw_eaction.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw_eaction.c	Mon Apr  3 02:26:30 2017	(r316433)
+++ head/sys/netpfil/ipfw/ip_fw_eaction.c	Mon Apr  3 02:44:40 2017	(r316434)
@@ -1,6 +1,6 @@
 /*-
- * Copyright (c) 2016 Yandex LLC
- * Copyright (c) 2016 Andrey V. Elsukov <ae at FreeBSD.org>
+ * Copyright (c) 2016-2017 Yandex LLC
+ * Copyright (c) 2016-2017 Andrey V. Elsukov <ae at FreeBSD.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -57,7 +57,7 @@ __FBSDID("$FreeBSD$");
  * rules.
  * Module should implement opcode handler with type ipfw_eaction_t.
  * This handler will be called by ipfw_chk() function when
- * O_EXTERNAL_ACTION opcode will be matched. The handler must return
+ * O_EXTERNAL_ACTION opcode is matched. The handler must return
  * value used as return value in ipfw_chk(), i.e. IP_FW_PASS,
  * IP_FW_DENY (see ip_fw_private.h).
  * Also the last argument must be set by handler. If it is zero,
@@ -69,9 +69,12 @@ __FBSDID("$FreeBSD$");
  * This function will return eaction_id, that can be used by module.
  *
  * It is possible to pass some additional information to external
- * action handler via the O_EXTERNAL_INSTANCE opcode. This opcode
- * will be next after the O_EXTERNAL_ACTION opcode. cmd->arg1 will
- * contain index of named object related to instance of external action.
+ * action handler using O_EXTERNAL_INSTANCE and O_EXTERNAL_DATA opcodes.
+ * Such opcodes should be next after the O_EXTERNAL_ACTION opcode.
+ * For the O_EXTERNAL_INSTANCE opcode the cmd->arg1 contains index of named
+ * object related to an instance of external action.
+ * For the O_EXTERNAL_DATA opcode the cmd contains the data that can be used
+ * by external action handler without needing to create named instance.
  *
  * In case when eaction module uses named instances, it should register
  * opcode rewriting routines for O_EXTERNAL_INSTANCE opcode. The
@@ -284,11 +287,13 @@ reset_eaction_obj(struct ip_fw_chain *ch
 		/*
 		 * Since named_object related to this instance will be
 		 * also destroyed, truncate the chain of opcodes to
-		 * remove O_EXTERNAL_INSTANCE opcode.
+		 * remove the rest of cmd chain just after O_EXTERNAL_ACTION
+		 * opcode.
 		 */
 		if (rule->act_ofs < rule->cmd_len - 1) {
-			EACTION_DEBUG("truncate rule %d", rule->rulenum);
-			rule->cmd_len--;
+			EACTION_DEBUG("truncate rule %d: len %u -> %u",
+			    rule->rulenum, rule->cmd_len, rule->act_ofs + 1);
+			rule->cmd_len = rule->act_ofs + 1;
 		}
 	}
 	IPFW_WUNLOCK(ch);

Modified: head/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- head/sys/netpfil/ipfw/ip_fw_sockopt.c	Mon Apr  3 02:26:30 2017	(r316433)
+++ head/sys/netpfil/ipfw/ip_fw_sockopt.c	Mon Apr  3 02:44:40 2017	(r316434)
@@ -1736,11 +1736,16 @@ check_ipfw_rule_body(ipfw_insn *cmd, int
 				return (EINVAL);
 			}
 			ci->object_opcodes++;
-			/* Do we have O_EXTERNAL_INSTANCE opcode? */
+			/*
+			 * Do we have O_EXTERNAL_INSTANCE or O_EXTERNAL_DATA
+			 * opcode?
+			 */
 			if (l != cmdlen) {
 				l -= cmdlen;
 				cmd += cmdlen;
 				cmdlen = F_LEN(cmd);
+				if (cmd->opcode == O_EXTERNAL_DATA)
+					goto check_action;
 				if (cmd->opcode != O_EXTERNAL_INSTANCE) {
 					printf("ipfw: invalid opcode "
 					    "next to external action %u\n",
@@ -2618,11 +2623,11 @@ unref_rule_objects(struct ip_fw_chain *c
 			continue;
 		no = rw->find_bykidx(ch, kidx);
 
-		KASSERT(no != NULL, ("table id %d not found", kidx));
+		KASSERT(no != NULL, ("object id %d not found", kidx));
 		KASSERT(no->subtype == subtype,
-		    ("wrong type %d (%d) for table id %d",
+		    ("wrong type %d (%d) for object id %d",
 		    no->subtype, subtype, kidx));
-		KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
+		KASSERT(no->refcnt > 0, ("refcount for object %d is %d",
 		    kidx, no->refcnt));
 
 		if (no->refcnt == 1 && rw->destroy_object != NULL)


More information about the svn-src-all mailing list