</para>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term><option>netdev</option></term>
+ <listitem>
+ <para>
+ Netdev address family, handling packets from ingress.
+ </para>
+ </listitem>
+ </varlistentry>
</variablelist>
</para>
<para>
The bridge address family handles ethernet packets traversing bridge devices.
</para>
</refsect2>
+ <refsect2>
+ <title>Netdev address family</title>
+ <para>
+ The Netdev address family handles packets from ingress.
+ </para>
+ <para>
+ <table frame="all">
+ <title>Netdev address family hooks</title>
+ <tgroup cols='2' align='left' colsep='1' rowsep='1' pgwide="1">
+ <colspec colname='c1' colwidth="1*"/>
+ <colspec colname='c2' colwidth="5*"/>
+ <thead>
+ <row>
+ <entry>Hook</entry>
+ <entry>Description</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row>
+ <entry>ingress</entry>
+ <entry>
+ All packets entering the system are processed by this hook. It is invoked
+ before layer 3 protocol handlers and it can be used for early filtering and
+ policing.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+ </para>
+ </refsect2>
+
</refsect1>
<refsect1>
<member><literal>inet</literal></member>
<member><literal>arp</literal></member>
<member><literal>bridge</literal></member>
+ <member><literal>netdev</literal></member>
</simplelist>.
The <literal>inet</literal> address family is a dummy family which is used to create
<arg choice="req"><replaceable>hook</replaceable></arg>
<arg choice="req"><replaceable>priority</replaceable></arg>
<arg choice="req"><replaceable>policy</replaceable></arg>
+ <arg choice="req"><replaceable>device</replaceable></arg>
</cmdsynopsis>
<cmdsynopsis>
<group choice="req">
#define NF_DROP_ERR(x) (((-x) << 16) | NF_DROP)
/* only for userspace compatibility */
+#ifndef __KERNEL__
/* Generic cache responses from hook functions.
<= 0x2000 is used for protocol-flags. */
#define NFC_UNKNOWN 0x4000
/* NF_VERDICT_BITS should be 8 now, but userspace might break if this changes */
#define NF_VERDICT_BITS 16
+#endif
enum nf_inet_hooks {
NF_INET_PRE_ROUTING,
NF_INET_NUMHOOKS
};
+enum nf_dev_hooks {
+ NF_NETDEV_INGRESS,
+ NF_NETDEV_NUMHOOKS
+};
+
enum {
NFPROTO_UNSPEC = 0,
NFPROTO_INET = 1,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
+ NFPROTO_NETDEV = 5,
NFPROTO_BRIDGE = 7,
NFPROTO_IPV6 = 10,
NFPROTO_DECNET = 12,
* @priority: hook priority (base chains)
* @policy: default chain policy (base chains)
* @type: chain type
+ * @dev: device (if any)
* @rules: rules contained in the chain
*/
struct chain {
int priority;
int policy;
const char *type;
+ const char *dev;
struct scope scope;
struct list_head rules;
};
else if (!strcmp(hook, "output"))
return NF_ARP_OUT;
break;
+ case NFPROTO_NETDEV:
+ if (!strcmp(hook, "ingress"))
+ return NF_NETDEV_INGRESS;
+ break;
default:
break;
}
if (chain->policy != -1)
nft_chain_attr_set_u32(nlc, NFT_CHAIN_ATTR_POLICY,
chain->policy);
+ if (chain->dev != NULL)
+ nft_chain_attr_set_str(nlc, NFT_CHAIN_ATTR_DEV,
+ chain->dev);
}
netlink_dump_chain(nlc);
xstrdup(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_TYPE));
chain->policy =
nft_chain_attr_get_u32(nlc, NFT_CHAIN_ATTR_POLICY);
+ if (nft_chain_attr_is_set(nlc, NFT_CHAIN_ATTR_DEV)) {
+ chain->dev =
+ xstrdup(nft_chain_attr_get_str(nlc, NFT_CHAIN_ATTR_DEV));
+ }
chain->flags |= CHAIN_F_BASECHAIN;
}
%token DEFINE "define"
%token HOOK "hook"
+%token DEVICE "device"
%token TABLE "table"
%token TABLES "tables"
%token CHAIN "chain"
%token RULESET "ruleset"
%token INET "inet"
+%token NETDEV "netdev"
%token ADD "add"
%token UPDATE "update"
$<chain>0->priority = -$7;
$<chain>0->flags |= CHAIN_F_BASECHAIN;
}
+ | TYPE STRING HOOK STRING DEVICE STRING PRIORITY NUM
+ {
+ $<chain>0->type = chain_type_name_lookup($2);
+ if ($<chain>0->type == NULL) {
+ erec_queue(error(&@2, "unknown chain type %s", $2),
+ state->msgs);
+ YYERROR;
+ }
+ $<chain>0->hookstr = chain_hookname_lookup($4);
+ if ($<chain>0->hookstr == NULL) {
+ erec_queue(error(&@4, "unknown chain hook %s", $4),
+ state->msgs);
+ YYERROR;
+ }
+ $<chain>0->dev = $6;
+ $<chain>0->priority = $8;
+ $<chain>0->flags |= CHAIN_F_BASECHAIN;
+ }
+ | TYPE STRING HOOK STRING DEVICE STRING PRIORITY DASH NUM
+ {
+ $<chain>0->type = chain_type_name_lookup($2);
+ if ($<chain>0->type == NULL) {
+ erec_queue(error(&@2, "unknown type name %s", $2),
+ state->msgs);
+ YYERROR;
+ }
+ $<chain>0->hookstr = chain_hookname_lookup($4);
+ $<chain>0->dev = $6;
+ $<chain>0->priority = -$9;
+ $<chain>0->flags |= CHAIN_F_BASECHAIN;
+ }
;
policy_spec : POLICY chain_policy
| INET { $$ = NFPROTO_INET; }
| ARP { $$ = NFPROTO_ARP; }
| BRIDGE { $$ = NFPROTO_BRIDGE; }
+ | NETDEV { $$ = NFPROTO_NETDEV; }
;
table_spec : family_spec identifier
}
break;
case NFPROTO_BRIDGE:
+ case NFPROTO_NETDEV:
switch (expr->payload.base) {
case PROTO_BASE_LL_HDR:
desc = &proto_eth;
const struct hook_proto_desc hook_proto_desc[] = {
[NFPROTO_BRIDGE] = HOOK_PROTO_DESC(PROTO_BASE_LL_HDR, &proto_eth),
+ [NFPROTO_NETDEV] = HOOK_PROTO_DESC(PROTO_BASE_LL_HDR, &proto_eth),
[NFPROTO_INET] = HOOK_PROTO_DESC(PROTO_BASE_LL_HDR, &proto_inet),
[NFPROTO_IPV4] = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_ip),
[NFPROTO_IPV6] = HOOK_PROTO_DESC(PROTO_BASE_NETWORK_HDR, &proto_ip6),
"forward",
"postrouting",
"output",
+ "ingress",
NULL,
};
return "ip6";
case NFPROTO_INET:
return "inet";
+ case NFPROTO_NETDEV:
+ return "netdev";
case NFPROTO_ARP:
return "arp";
case NFPROTO_BRIDGE:
default:
break;
}
+ break;
+ case NFPROTO_NETDEV:
+ switch (hooknum) {
+ case NF_NETDEV_INGRESS:
+ return "ingress";
+ }
+ break;
default:
break;
};
printf("\tchain %s {\n", chain->handle.chain);
if (chain->flags & CHAIN_F_BASECHAIN) {
- printf("\t\ttype %s hook %s priority %d; policy %s;\n",
- chain->type,
- hooknum2str(chain->handle.family, chain->hooknum),
- chain->priority, chain_policy2str(chain->policy));
+ if (chain->dev != NULL) {
+ printf("\t\ttype %s hook %s device %s priority %d;\n",
+ chain->type,
+ hooknum2str(chain->handle.family, chain->hooknum),
+ chain->dev, chain->priority);
+ } else {
+ printf("\t\ttype %s hook %s priority %d;\n",
+ chain->type,
+ hooknum2str(chain->handle.family, chain->hooknum),
+ chain->priority);
+ }
}
list_for_each_entry(rule, &chain->rules, list) {
printf("\t\t");
"describe" { return DESCRIBE; }
"hook" { return HOOK; }
+"device" { return DEVICE; }
"table" { return TABLE; }
"tables" { return TABLES; }
"chain" { return CHAIN; }
"to" { return TO; }
"inet" { return INET; }
+"netdev" { return NETDEV; }
"add" { return ADD; }
"update" { return UPDATE; }