Hi Dave, This is the 4th version of our interface group patches. The only difference from the previous one is in the first patch (single notification and atomic changes in rtnetlink) plus in iptables code: parameter in-ifgroup changed to ifgroup-in (and ifgroup-out). I had to add IFLA_NET_NS_PID in the iproute2 patches as in kernel v2.6.24-rc1. Usage as before: ip link set eth0 group 4 iptables -A INPUT -m ifgroup --ifgroup-in 4/0xf -j ACCEPT iptables -A FORWARD -m ifgroup --ifgroup-in 4 --ifgroup-out 5 -j DROP Patches: [1/3] rtnetlink: setlink changes atomic with single notification [2/3] Interface group: core (netlink) part [3/3] Netfilter Interface group match [iptables] Interface group match [iproute 1/2] Added IFLA_NET_NS_PID as in kernel v2.6.24-rc1 [iproute 2/2] Interface group as new ip link option Please apply, Attila -
In do_setlink the device changes are atomic and notifications will be sent
at the end of the function once if any modification occured and once if
address has been changed.
Signed-off-by: Laszlo Attila Toth <panther@balabit.hu>
---
net/core/rtnetlink.c | 34 ++++++++++++++++++++++++----------
1 files changed, 24 insertions(+), 10 deletions(-)
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 4a2640d..ecf4dc5 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -537,7 +537,7 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id,
EXPORT_SYMBOL_GPL(rtnl_put_cacheinfo);
-static void set_operstate(struct net_device *dev, unsigned char transition)
+static int set_operstate(struct net_device *dev, unsigned char transition)
{
unsigned char operstate = dev->operstate;
@@ -560,8 +560,9 @@ static void set_operstate(struct net_device *dev, unsigned char transition)
write_lock_bh(&dev_base_lock);
dev->operstate = operstate;
write_unlock_bh(&dev_base_lock);
- netdev_state_change(dev);
- }
+ return 1;
+ } else
+ return 0;
}
static void copy_rtnl_link_stats(struct rtnl_link_stats *a,
@@ -855,6 +856,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
if (tb[IFLA_BROADCAST]) {
nla_memcpy(dev->broadcast, tb[IFLA_BROADCAST], dev->addr_len);
send_addr_notify = 1;
+ modified = 1;
}
if (ifm->ifi_flags || ifm->ifi_change) {
@@ -867,16 +869,26 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm,
dev_change_flags(dev, flags);
}
- if (tb[IFLA_TXQLEN])
- dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ if (tb[IFLA_TXQLEN]) {
+ if (dev->tx_queue_len != nla_get_u32(tb[IFLA_TXQLEN])) {
+ write_lock_bh(&dev_base_lock);
+ dev->tx_queue_len = nla_get_u32(tb[IFLA_TXQLEN]);
+ write_unlock_bh(&dev_base_lock);
+ modified = 1;
+ }
+ }
- if (tb[IFLA_OPERSTATE])
- set_operstate(dev, nla_get_u8(tb[IFLA_OPERSTATE]));
+ if ...Interface groups let handle different interfaces together especially in netfilter modules. Modified net device structure and netlink interface. Signed-off-by: Laszlo Attila Toth <panther@balabit.hu> --- include/linux/if_link.h | 2 ++ include/linux/netdevice.h | 2 ++ net/core/rtnetlink.c | 11 +++++++++++ 3 files changed, 15 insertions(+), 0 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 84c3492..722b25c 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -79,6 +79,8 @@ enum IFLA_LINKINFO, #define IFLA_LINKINFO IFLA_LINKINFO IFLA_NET_NS_PID, + IFLA_IFGROUP, +#define IFLA_IFGROUP IFLA_IFGROUP __IFLA_MAX }; diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index c4de536..87aa550 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h @@ -519,6 +519,8 @@ struct net_device /* Interface index. Unique device identifier */ int ifindex; int iflink; + /* interface group this interface belongs to */ + u_int32_t ifgroup; struct net_device_stats* (*get_stats)(struct net_device *dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index ecf4dc5..f13883d 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -611,6 +611,7 @@ static inline size_t if_nlmsg_size(const struct net_device *dev) + nla_total_size(4) /* IFLA_MTU */ + nla_total_size(4) /* IFLA_LINK */ + nla_total_size(4) /* IFLA_MASTER */ + + nla_total_size(4) /* IFLA_IFGROUP */ + nla_total_size(1) /* IFLA_OPERSTATE */ + nla_total_size(1) /* IFLA_LINKMODE */ + rtnl_link_get_size(dev); /* IFLA_LINKINFO */ @@ -648,6 +649,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, if (dev->master) NLA_PUT_U32(skb, IFLA_MASTER, dev->master->ifindex); + if (dev->ifgroup) + NLA_PUT_U32(skb, IFLA_IFGROUP, dev->ifgroup); + if (dev->qdisc_sleeping) NLA_PUT_STRING(skb, IFLA_QDISC, ...
Interface group values can be checked on both input and output interfaces.
Signed-off-by: Laszlo Attila Toth <panther@balabit.hu>
---
include/linux/netfilter/xt_ifgroup.h | 18 +++++
net/netfilter/Kconfig | 16 +++++
net/netfilter/Makefile | 1 +
net/netfilter/xt_ifgroup.c | 121 ++++++++++++++++++++++++++++++++++
4 files changed, 156 insertions(+), 0 deletions(-)
diff --git a/include/linux/netfilter/xt_ifgroup.h b/include/linux/netfilter/xt_ifgroup.h
new file mode 100644
index 0000000..9ac75de
--- /dev/null
+++ b/include/linux/netfilter/xt_ifgroup.h
@@ -0,0 +1,18 @@
+#ifndef _XT_IFGROUP_H
+#define _XT_IFGROUP_H
+
+#define XT_IFGROUP_INVERT_IN 0x01
+#define XT_IFGROUP_INVERT_OUT 0x02
+#define XT_IFGROUP_MATCH_IN 0x04
+#define XT_IFGROUP_MATCH_OUT 0x08
+
+struct xt_ifgroup_info {
+ u_int32_t in_group;
+ u_int32_t in_mask;
+ u_int32_t out_group;
+ u_int32_t out_mask;
+ u_int8_t flags;
+};
+
+#endif /*_XT_IFGROUP_H*/
+
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
index d7a600a..0e0cd4f 100644
--- a/net/netfilter/Kconfig
+++ b/net/netfilter/Kconfig
@@ -597,6 +597,22 @@ config NETFILTER_XT_MATCH_QUOTA
If you want to compile it as a module, say M here and read
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
+config NETFILTER_XT_MATCH_IFGROUP
+ tristate '"ifgroup" interface group match support'
+ depends on NETFILTER_XTABLES
+ help
+ Interface group matching allows you to match a packet by
+ its incoming interface "group", settable using ip link set
+ group
+
+ Typical usage is to assign dynamic interfaces to a group
+ when they come up using "ip link set group" and then match
+ incoming packets with a rule like this:
+
+ iptables -A INPUT -m ifgroup --if-group openvpn-rw1 -j LOG
+
+ To compile it as a module, choose M here. If unsure, say N.
+
config NETFILTER_XT_MATCH_REALM
tristate '"realm" match support'
depends on NETFILTER_XTABLES
diff ...Interface group values can be checked on both input and output interfaces
with optional mask.
Signed-off-by: Laszlo Attila Toth <panther@balabit.hu>
---
Makefile | 2
libip6t_ifgroup.man | 36 +++++++
libipt_ifgroup.man | 36 +++++++
libxt_ifgroup.c | 196 +++++++++++++++++++++++++++++++++++++++++++
linux/netfilter/xt_ifgroup.h | 18 +++
5 files changed, 287 insertions(+), 1 deletion(-)
Index: include/linux/netfilter/xt_ifgroup.h
===================================================================
--- include/linux/netfilter/xt_ifgroup.h (revision 0)
+++ include/linux/netfilter/xt_ifgroup.h (revision 0)
@@ -0,0 +1,18 @@
+#ifndef _XT_IFGROUP_H
+#define _XT_IFGROUP_H
+
+#define XT_IFGROUP_INVERT_IN 0x01
+#define XT_IFGROUP_INVERT_OUT 0x02
+#define XT_IFGROUP_MATCH_IN 0x04
+#define XT_IFGROUP_MATCH_OUT 0x08
+
+struct xt_ifgroup_info {
+ u_int32_t in_group;
+ u_int32_t in_mask;
+ u_int32_t out_group;
+ u_int32_t out_mask;
+ u_int8_t flags;
+};
+
+#endif /*_XT_IFGROUP_H*/
+
Index: extensions/libxt_ifgroup.c
===================================================================
--- extensions/libxt_ifgroup.c (revision 0)
+++ extensions/libxt_ifgroup.c (revision 0)
@@ -0,0 +1,196 @@
+/*
+ * Shared library add-on to iptables to match
+ * packets by the incoming interface group.
+ *
+ * (c) 2006, 2007 Balazs Scheidler <bazsi@balabit.hu>,
+ * Laszlo Attila Toth <panther@balabit.hu>
+ */
+#include <stdio.h>
+#include <netdb.h>
+#include <string.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <xtables.h>
+#include <linux/netfilter/xt_ifgroup.h>
+
+static void
+ifgroup_help(void)
+{
+ printf(
+"ifgroup v%s options:\n"
+" --ifgroup-in [!] group[/mask] incoming interface group and its mask\n"
+" --ifgroup-out [!] group[/mask] outgoing interface group and its mask\n"
+"\n", IPTABLES_VERSION);
+}
+
+static struct option opts[] = {
+ {"ifgroup-in", 1, 0, '1'},
+ {"ifgroup-out", ...Signed-off-by: Laszlo Attila Toth <panther@balabit.hu> --- include/linux/if_link.h | 1 + 1 files changed, 1 insertions(+), 0 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index 23b3a8e..c948395 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -78,6 +78,7 @@ enum IFLA_LINKMODE, IFLA_LINKINFO, #define IFLA_LINKINFO IFLA_LINKINFO + IFLA_NET_NS_PID, __IFLA_MAX }; -- 1.5.2.5 -
Interfaces can be grouped and each group has an unique positive integer ID. It can be set via ip link. Symbolic names can be specified in /etc/iproute2/rt_ifgroup. Signed-off-by: Laszlo Attila Toth <panther@balabit.hu> --- include/linux/if_link.h | 2 + include/rt_names.h | 2 + ip/ipaddress.c | 4 +++ ip/iplink.c | 11 ++++++++ lib/rt_names.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ man/man8/ip.8 | 5 ++++ 6 files changed, 86 insertions(+), 0 deletions(-) diff --git a/include/linux/if_link.h b/include/linux/if_link.h index c948395..5a2d071 100644 --- a/include/linux/if_link.h +++ b/include/linux/if_link.h @@ -79,6 +79,8 @@ enum IFLA_LINKINFO, #define IFLA_LINKINFO IFLA_LINKINFO IFLA_NET_NS_PID, + IFLA_IFGROUP, +#define IFLA_IFGROUP IFLA_IFGROUP __IFLA_MAX }; diff --git a/include/rt_names.h b/include/rt_names.h index 07a10e0..72c5247 100644 --- a/include/rt_names.h +++ b/include/rt_names.h @@ -8,11 +8,13 @@ char* rtnl_rtscope_n2a(int id, char *buf, int len); char* rtnl_rttable_n2a(__u32 id, char *buf, int len); char* rtnl_rtrealm_n2a(int id, char *buf, int len); char* rtnl_dsfield_n2a(int id, char *buf, int len); +char* rtnl_ifgroup_n2a(int id, char *buf, int len); int rtnl_rtprot_a2n(__u32 *id, char *arg); int rtnl_rtscope_a2n(__u32 *id, char *arg); int rtnl_rttable_a2n(__u32 *id, char *arg); int rtnl_rtrealm_a2n(__u32 *id, char *arg); int rtnl_dsfield_a2n(__u32 *id, char *arg); +int rtnl_ifgroup_a2n(__u32 *id, char *arg); const char *inet_proto_n2a(int proto, char *buf, int len); int inet_proto_a2n(char *buf); diff --git a/ip/ipaddress.c b/ip/ipaddress.c index d1c6620..1ecbe03 100644 --- a/ip/ipaddress.c +++ b/ip/ipaddress.c @@ -227,6 +227,10 @@ int print_linkinfo(const struct sockaddr_nl *who, fprintf(fp, "mtu %u ", *(int*)RTA_DATA(tb[IFLA_MTU])); if (tb[IFLA_QDISC]) fprintf(fp, "qdisc %s ", (char*)RTA_DATA(tb[IFLA_QDISC])); + if (tb[IFLA_IFGROUP]) ...
Just a suggestion: not printing the mask when its ~0 would -
If you'd remove the extra space it would fit on a 80 character line. -
The locking looks unnecessary, the rtnl should be enough. I'm not even sure why its used for operstate and linkmode, AFAICS they are also protected by the rtnl. -
Hm, ok. In this case operstate and linkmode can be unprotected as code cleanup, am I right? Or leave them unchanged? And notification is only needed if something was changed. -- Attila -
There seems to be a single case where operstate is used without the rtnl (under dev_base_lock), in dev_get_flags() invoked by dev_ifsioc_locked(). But that looks like a bug, there are many callers of dev_change_flags() that only take the rtnl. So this Yes. -
