diff options
Diffstat (limited to 'net/bridge')
| -rw-r--r-- | net/bridge/br_fdb.c | 26 | ||||
| -rw-r--r-- | net/bridge/br_if.c | 2 | ||||
| -rw-r--r-- | net/bridge/br_multicast.c | 39 | ||||
| -rw-r--r-- | net/bridge/br_netlink.c | 1 | ||||
| -rw-r--r-- | net/bridge/br_private.h | 5 | ||||
| -rw-r--r-- | net/bridge/br_vlan.c | 24 | ||||
| -rw-r--r-- | net/bridge/netfilter/Kconfig | 25 | ||||
| -rw-r--r-- | net/bridge/netfilter/Makefile | 5 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebt_log.c | 47 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebt_ulog.c | 393 | ||||
| -rw-r--r-- | net/bridge/netfilter/ebtables.c | 10 | ||||
| -rw-r--r-- | net/bridge/netfilter/nf_log_bridge.c | 96 | ||||
| -rw-r--r-- | net/bridge/netfilter/nft_reject_bridge.c | 67 |
13 files changed, 261 insertions, 479 deletions
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b524c36c1273..6f6c95cfe8f2 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
| @@ -93,7 +93,7 @@ static void fdb_rcu_free(struct rcu_head *head) | |||
| 93 | static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) | 93 | static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) |
| 94 | { | 94 | { |
| 95 | int err; | 95 | int err; |
| 96 | struct net_bridge_port *p, *tmp; | 96 | struct net_bridge_port *p; |
| 97 | 97 | ||
| 98 | ASSERT_RTNL(); | 98 | ASSERT_RTNL(); |
| 99 | 99 | ||
| @@ -107,11 +107,9 @@ static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) | |||
| 107 | 107 | ||
| 108 | return; | 108 | return; |
| 109 | undo: | 109 | undo: |
| 110 | list_for_each_entry(tmp, &br->port_list, list) { | 110 | list_for_each_entry_continue_reverse(p, &br->port_list, list) { |
| 111 | if (tmp == p) | 111 | if (!br_promisc_port(p)) |
| 112 | break; | 112 | dev_uc_del(p->dev, addr); |
| 113 | if (!br_promisc_port(tmp)) | ||
| 114 | dev_uc_del(tmp->dev, addr); | ||
| 115 | } | 113 | } |
| 116 | } | 114 | } |
| 117 | 115 | ||
| @@ -631,7 +629,7 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, | |||
| 631 | if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) | 629 | if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) |
| 632 | goto nla_put_failure; | 630 | goto nla_put_failure; |
| 633 | 631 | ||
| 634 | if (nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id)) | 632 | if (fdb->vlan_id && nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id)) |
| 635 | goto nla_put_failure; | 633 | goto nla_put_failure; |
| 636 | 634 | ||
| 637 | return nlmsg_end(skb, nlh); | 635 | return nlmsg_end(skb, nlh); |
| @@ -678,6 +676,7 @@ errout: | |||
| 678 | int br_fdb_dump(struct sk_buff *skb, | 676 | int br_fdb_dump(struct sk_buff *skb, |
| 679 | struct netlink_callback *cb, | 677 | struct netlink_callback *cb, |
| 680 | struct net_device *dev, | 678 | struct net_device *dev, |
| 679 | struct net_device *filter_dev, | ||
| 681 | int idx) | 680 | int idx) |
| 682 | { | 681 | { |
| 683 | struct net_bridge *br = netdev_priv(dev); | 682 | struct net_bridge *br = netdev_priv(dev); |
| @@ -693,6 +692,19 @@ int br_fdb_dump(struct sk_buff *skb, | |||
| 693 | if (idx < cb->args[0]) | 692 | if (idx < cb->args[0]) |
| 694 | goto skip; | 693 | goto skip; |
| 695 | 694 | ||
| 695 | if (filter_dev && | ||
| 696 | (!f->dst || f->dst->dev != filter_dev)) { | ||
| 697 | if (filter_dev != dev) | ||
| 698 | goto skip; | ||
| 699 | /* !f->dst is a speacial case for bridge | ||
| 700 | * It means the MAC belongs to the bridge | ||
| 701 | * Therefore need a little more filtering | ||
| 702 | * we only want to dump the !f->dst case | ||
| 703 | */ | ||
| 704 | if (f->dst) | ||
| 705 | goto skip; | ||
| 706 | } | ||
| 707 | |||
| 696 | if (fdb_fill_info(skb, br, f, | 708 | if (fdb_fill_info(skb, br, f, |
| 697 | NETLINK_CB(cb->skb).portid, | 709 | NETLINK_CB(cb->skb).portid, |
| 698 | cb->nlh->nlmsg_seq, | 710 | cb->nlh->nlmsg_seq, |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 3eca3fdf8fe1..078d336a1f37 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -344,7 +344,7 @@ int br_add_bridge(struct net *net, const char *name) | |||
| 344 | struct net_device *dev; | 344 | struct net_device *dev; |
| 345 | int res; | 345 | int res; |
| 346 | 346 | ||
| 347 | dev = alloc_netdev(sizeof(struct net_bridge), name, | 347 | dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN, |
| 348 | br_dev_setup); | 348 | br_dev_setup); |
| 349 | 349 | ||
| 350 | if (!dev) | 350 | if (!dev) |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index abfa0b65a111..7751c92c8c57 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -1174,7 +1174,7 @@ static void br_multicast_add_router(struct net_bridge *br, | |||
| 1174 | } | 1174 | } |
| 1175 | 1175 | ||
| 1176 | if (slot) | 1176 | if (slot) |
| 1177 | hlist_add_after_rcu(slot, &port->rlist); | 1177 | hlist_add_behind_rcu(&port->rlist, slot); |
| 1178 | else | 1178 | else |
| 1179 | hlist_add_head_rcu(&port->rlist, &br->router_list); | 1179 | hlist_add_head_rcu(&port->rlist, &br->router_list); |
| 1180 | } | 1180 | } |
| @@ -2216,6 +2216,43 @@ unlock: | |||
| 2216 | EXPORT_SYMBOL_GPL(br_multicast_list_adjacent); | 2216 | EXPORT_SYMBOL_GPL(br_multicast_list_adjacent); |
| 2217 | 2217 | ||
| 2218 | /** | 2218 | /** |
| 2219 | * br_multicast_has_querier_anywhere - Checks for a querier on a bridge | ||
| 2220 | * @dev: The bridge port providing the bridge on which to check for a querier | ||
| 2221 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 | ||
| 2222 | * | ||
| 2223 | * Checks whether the given interface has a bridge on top and if so returns | ||
| 2224 | * true if a valid querier exists anywhere on the bridged link layer. | ||
| 2225 | * Otherwise returns false. | ||
| 2226 | */ | ||
| 2227 | bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto) | ||
| 2228 | { | ||
| 2229 | struct net_bridge *br; | ||
| 2230 | struct net_bridge_port *port; | ||
| 2231 | struct ethhdr eth; | ||
| 2232 | bool ret = false; | ||
| 2233 | |||
| 2234 | rcu_read_lock(); | ||
| 2235 | if (!br_port_exists(dev)) | ||
| 2236 | goto unlock; | ||
| 2237 | |||
| 2238 | port = br_port_get_rcu(dev); | ||
| 2239 | if (!port || !port->br) | ||
| 2240 | goto unlock; | ||
| 2241 | |||
| 2242 | br = port->br; | ||
| 2243 | |||
| 2244 | memset(ð, 0, sizeof(eth)); | ||
| 2245 | eth.h_proto = htons(proto); | ||
| 2246 | |||
| 2247 | ret = br_multicast_querier_exists(br, ð); | ||
| 2248 | |||
| 2249 | unlock: | ||
| 2250 | rcu_read_unlock(); | ||
| 2251 | return ret; | ||
| 2252 | } | ||
| 2253 | EXPORT_SYMBOL_GPL(br_multicast_has_querier_anywhere); | ||
| 2254 | |||
| 2255 | /** | ||
| 2219 | * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port | 2256 | * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port |
| 2220 | * @dev: The bridge port adjacent to which to check for a querier | 2257 | * @dev: The bridge port adjacent to which to check for a querier |
| 2221 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 | 2258 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 26edb518b839..cb5fcf62f663 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
| @@ -208,7 +208,6 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
| 208 | int err = 0; | 208 | int err = 0; |
| 209 | struct net_bridge_port *port = br_port_get_rtnl(dev); | 209 | struct net_bridge_port *port = br_port_get_rtnl(dev); |
| 210 | 210 | ||
| 211 | /* not a bridge port and */ | ||
| 212 | if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) | 211 | if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) |
| 213 | goto out; | 212 | goto out; |
| 214 | 213 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 23caf5b0309e..b6c04cbcfdc5 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -309,6 +309,9 @@ struct br_input_skb_cb { | |||
| 309 | int igmp; | 309 | int igmp; |
| 310 | int mrouters_only; | 310 | int mrouters_only; |
| 311 | #endif | 311 | #endif |
| 312 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||
| 313 | bool vlan_filtered; | ||
| 314 | #endif | ||
| 312 | }; | 315 | }; |
| 313 | 316 | ||
| 314 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) | 317 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) |
| @@ -399,7 +402,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], | |||
| 399 | int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, | 402 | int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, |
| 400 | const unsigned char *addr, u16 nlh_flags); | 403 | const unsigned char *addr, u16 nlh_flags); |
| 401 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | 404 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, |
| 402 | struct net_device *dev, int idx); | 405 | struct net_device *dev, struct net_device *fdev, int idx); |
| 403 | int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); | 406 | int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); |
| 404 | void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); | 407 | void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); |
| 405 | 408 | ||
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 2b2774fe0703..3ba57fcdcd13 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -27,9 +27,13 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags) | |||
| 27 | { | 27 | { |
| 28 | if (flags & BRIDGE_VLAN_INFO_PVID) | 28 | if (flags & BRIDGE_VLAN_INFO_PVID) |
| 29 | __vlan_add_pvid(v, vid); | 29 | __vlan_add_pvid(v, vid); |
| 30 | else | ||
| 31 | __vlan_delete_pvid(v, vid); | ||
| 30 | 32 | ||
| 31 | if (flags & BRIDGE_VLAN_INFO_UNTAGGED) | 33 | if (flags & BRIDGE_VLAN_INFO_UNTAGGED) |
| 32 | set_bit(vid, v->untagged_bitmap); | 34 | set_bit(vid, v->untagged_bitmap); |
| 35 | else | ||
| 36 | clear_bit(vid, v->untagged_bitmap); | ||
| 33 | } | 37 | } |
| 34 | 38 | ||
| 35 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | 39 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) |
| @@ -55,10 +59,8 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | |||
| 55 | 59 | ||
| 56 | if (p) { | 60 | if (p) { |
| 57 | /* Add VLAN to the device filter if it is supported. | 61 | /* Add VLAN to the device filter if it is supported. |
| 58 | * Stricly speaking, this is not necessary now, since | 62 | * This ensures tagged traffic enters the bridge when |
| 59 | * devices are made promiscuous by the bridge, but if | 63 | * promiscuous mode is disabled by br_manage_promisc(). |
| 60 | * that ever changes this code will allow tagged | ||
| 61 | * traffic to enter the bridge. | ||
| 62 | */ | 64 | */ |
| 63 | err = vlan_vid_add(dev, br->vlan_proto, vid); | 65 | err = vlan_vid_add(dev, br->vlan_proto, vid); |
| 64 | if (err) | 66 | if (err) |
| @@ -127,7 +129,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, | |||
| 127 | { | 129 | { |
| 128 | u16 vid; | 130 | u16 vid; |
| 129 | 131 | ||
| 130 | if (!br->vlan_enabled) | 132 | /* If this packet was not filtered at input, let it pass */ |
| 133 | if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) | ||
| 131 | goto out; | 134 | goto out; |
| 132 | 135 | ||
| 133 | /* Vlan filter table must be configured at this point. The | 136 | /* Vlan filter table must be configured at this point. The |
| @@ -166,8 +169,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 166 | /* If VLAN filtering is disabled on the bridge, all packets are | 169 | /* If VLAN filtering is disabled on the bridge, all packets are |
| 167 | * permitted. | 170 | * permitted. |
| 168 | */ | 171 | */ |
| 169 | if (!br->vlan_enabled) | 172 | if (!br->vlan_enabled) { |
| 173 | BR_INPUT_SKB_CB(skb)->vlan_filtered = false; | ||
| 170 | return true; | 174 | return true; |
| 175 | } | ||
| 171 | 176 | ||
| 172 | /* If there are no vlan in the permitted list, all packets are | 177 | /* If there are no vlan in the permitted list, all packets are |
| 173 | * rejected. | 178 | * rejected. |
| @@ -175,6 +180,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 175 | if (!v) | 180 | if (!v) |
| 176 | goto drop; | 181 | goto drop; |
| 177 | 182 | ||
| 183 | BR_INPUT_SKB_CB(skb)->vlan_filtered = true; | ||
| 178 | proto = br->vlan_proto; | 184 | proto = br->vlan_proto; |
| 179 | 185 | ||
| 180 | /* If vlan tx offload is disabled on bridge device and frame was | 186 | /* If vlan tx offload is disabled on bridge device and frame was |
| @@ -183,7 +189,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 183 | */ | 189 | */ |
| 184 | if (unlikely(!vlan_tx_tag_present(skb) && | 190 | if (unlikely(!vlan_tx_tag_present(skb) && |
| 185 | skb->protocol == proto)) { | 191 | skb->protocol == proto)) { |
| 186 | skb = vlan_untag(skb); | 192 | skb = skb_vlan_untag(skb); |
| 187 | if (unlikely(!skb)) | 193 | if (unlikely(!skb)) |
| 188 | return false; | 194 | return false; |
| 189 | } | 195 | } |
| @@ -253,7 +259,8 @@ bool br_allowed_egress(struct net_bridge *br, | |||
| 253 | { | 259 | { |
| 254 | u16 vid; | 260 | u16 vid; |
| 255 | 261 | ||
| 256 | if (!br->vlan_enabled) | 262 | /* If this packet was not filtered at input, let it pass */ |
| 263 | if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) | ||
| 257 | return true; | 264 | return true; |
| 258 | 265 | ||
| 259 | if (!v) | 266 | if (!v) |
| @@ -272,6 +279,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) | |||
| 272 | struct net_bridge *br = p->br; | 279 | struct net_bridge *br = p->br; |
| 273 | struct net_port_vlans *v; | 280 | struct net_port_vlans *v; |
| 274 | 281 | ||
| 282 | /* If filtering was disabled at input, let it pass. */ | ||
| 275 | if (!br->vlan_enabled) | 283 | if (!br->vlan_enabled) |
| 276 | return true; | 284 | return true; |
| 277 | 285 | ||
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index 629dc77874a9..9cebf47ac840 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig | |||
| @@ -14,6 +14,15 @@ config NFT_BRIDGE_META | |||
| 14 | help | 14 | help |
| 15 | Add support for bridge dedicated meta key. | 15 | Add support for bridge dedicated meta key. |
| 16 | 16 | ||
| 17 | config NFT_BRIDGE_REJECT | ||
| 18 | tristate "Netfilter nf_tables bridge reject support" | ||
| 19 | depends on NFT_REJECT && NFT_REJECT_IPV4 && NFT_REJECT_IPV6 | ||
| 20 | help | ||
| 21 | Add support to reject packets. | ||
| 22 | |||
| 23 | config NF_LOG_BRIDGE | ||
| 24 | tristate "Bridge packet logging" | ||
| 25 | |||
| 17 | endif # NF_TABLES_BRIDGE | 26 | endif # NF_TABLES_BRIDGE |
| 18 | 27 | ||
| 19 | menuconfig BRIDGE_NF_EBTABLES | 28 | menuconfig BRIDGE_NF_EBTABLES |
| @@ -202,22 +211,6 @@ config BRIDGE_EBT_LOG | |||
| 202 | 211 | ||
| 203 | To compile it as a module, choose M here. If unsure, say N. | 212 | To compile it as a module, choose M here. If unsure, say N. |
| 204 | 213 | ||
| 205 | config BRIDGE_EBT_ULOG | ||
| 206 | tristate "ebt: ulog support (OBSOLETE)" | ||
| 207 | help | ||
| 208 | This option enables the old bridge-specific "ebt_ulog" implementation | ||
| 209 | which has been obsoleted by the new "nfnetlink_log" code (see | ||
| 210 | CONFIG_NETFILTER_NETLINK_LOG). | ||
| 211 | |||
| 212 | This option adds the ulog watcher, that you can use in any rule | ||
| 213 | in any ebtables table. The packet is passed to a userspace | ||
| 214 | logging daemon using netlink multicast sockets. This differs | ||
| 215 | from the log watcher in the sense that the complete packet is | ||
| 216 | sent to userspace instead of a descriptive text and that | ||
| 217 | netlink multicast sockets are used instead of the syslog. | ||
| 218 | |||
| 219 | To compile it as a module, choose M here. If unsure, say N. | ||
| 220 | |||
| 221 | config BRIDGE_EBT_NFLOG | 214 | config BRIDGE_EBT_NFLOG |
| 222 | tristate "ebt: nflog support" | 215 | tristate "ebt: nflog support" |
| 223 | help | 216 | help |
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 6f2f3943d66f..be4d0cea78ce 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile | |||
| @@ -4,6 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o | 5 | obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o |
| 6 | obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o | 6 | obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o |
| 7 | obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o | ||
| 8 | |||
| 9 | # packet logging | ||
| 10 | obj-$(CONFIG_NF_LOG_BRIDGE) += nf_log_bridge.o | ||
| 7 | 11 | ||
| 8 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o | 12 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o |
| 9 | 13 | ||
| @@ -33,5 +37,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o | |||
| 33 | 37 | ||
| 34 | # watchers | 38 | # watchers |
| 35 | obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o | 39 | obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o |
| 36 | obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o | ||
| 37 | obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o | 40 | obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 5322a36867a3..17f2e4bc2a29 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
| @@ -186,6 +186,10 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 186 | li.u.log.level = info->loglevel; | 186 | li.u.log.level = info->loglevel; |
| 187 | li.u.log.logflags = info->bitmask; | 187 | li.u.log.logflags = info->bitmask; |
| 188 | 188 | ||
| 189 | /* Remember that we have to use ebt_log_packet() not to break backward | ||
| 190 | * compatibility. We cannot use the default bridge packet logger via | ||
| 191 | * nf_log_packet() with NFT_LOG_TYPE_LOG here. --Pablo | ||
| 192 | */ | ||
| 189 | if (info->bitmask & EBT_LOG_NFLOG) | 193 | if (info->bitmask & EBT_LOG_NFLOG) |
| 190 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, | 194 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, |
| 191 | par->in, par->out, &li, "%s", info->prefix); | 195 | par->in, par->out, &li, "%s", info->prefix); |
| @@ -205,54 +209,13 @@ static struct xt_target ebt_log_tg_reg __read_mostly = { | |||
| 205 | .me = THIS_MODULE, | 209 | .me = THIS_MODULE, |
| 206 | }; | 210 | }; |
| 207 | 211 | ||
| 208 | static struct nf_logger ebt_log_logger __read_mostly = { | ||
| 209 | .name = "ebt_log", | ||
| 210 | .logfn = &ebt_log_packet, | ||
| 211 | .me = THIS_MODULE, | ||
| 212 | }; | ||
| 213 | |||
| 214 | static int __net_init ebt_log_net_init(struct net *net) | ||
| 215 | { | ||
| 216 | nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger); | ||
| 217 | return 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static void __net_exit ebt_log_net_fini(struct net *net) | ||
| 221 | { | ||
| 222 | nf_log_unset(net, &ebt_log_logger); | ||
| 223 | } | ||
| 224 | |||
| 225 | static struct pernet_operations ebt_log_net_ops = { | ||
| 226 | .init = ebt_log_net_init, | ||
| 227 | .exit = ebt_log_net_fini, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static int __init ebt_log_init(void) | 212 | static int __init ebt_log_init(void) |
| 231 | { | 213 | { |
| 232 | int ret; | 214 | return xt_register_target(&ebt_log_tg_reg); |
| 233 | |||
| 234 | ret = register_pernet_subsys(&ebt_log_net_ops); | ||
| 235 | if (ret < 0) | ||
| 236 | goto err_pernet; | ||
| 237 | |||
| 238 | ret = xt_register_target(&ebt_log_tg_reg); | ||
| 239 | if (ret < 0) | ||
| 240 | goto err_target; | ||
| 241 | |||
| 242 | nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); | ||
| 243 | |||
| 244 | return ret; | ||
| 245 | |||
| 246 | err_target: | ||
| 247 | unregister_pernet_subsys(&ebt_log_net_ops); | ||
| 248 | err_pernet: | ||
| 249 | return ret; | ||
| 250 | } | 215 | } |
| 251 | 216 | ||
| 252 | static void __exit ebt_log_fini(void) | 217 | static void __exit ebt_log_fini(void) |
| 253 | { | 218 | { |
| 254 | unregister_pernet_subsys(&ebt_log_net_ops); | ||
| 255 | nf_log_unregister(&ebt_log_logger); | ||
| 256 | xt_unregister_target(&ebt_log_tg_reg); | 219 | xt_unregister_target(&ebt_log_tg_reg); |
| 257 | } | 220 | } |
| 258 | 221 | ||
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c deleted file mode 100644 index 7c470c371e14..000000000000 --- a/net/bridge/netfilter/ebt_ulog.c +++ /dev/null | |||
| @@ -1,393 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * netfilter module for userspace bridged Ethernet frames logging daemons | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Bart De Schuymer <bdschuym@pandora.be> | ||
| 6 | * Harald Welte <laforge@netfilter.org> | ||
| 7 | * | ||
| 8 | * November, 2004 | ||
| 9 | * | ||
| 10 | * Based on ipt_ULOG.c, which is | ||
| 11 | * (C) 2000-2002 by Harald Welte <laforge@netfilter.org> | ||
| 12 | * | ||
| 13 | * This module accepts two parameters: | ||
| 14 | * | ||
| 15 | * nlbufsiz: | ||
| 16 | * The parameter specifies how big the buffer for each netlink multicast | ||
| 17 | * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will | ||
| 18 | * get accumulated in the kernel until they are sent to userspace. It is | ||
| 19 | * NOT possible to allocate more than 128kB, and it is strongly discouraged, | ||
| 20 | * because atomically allocating 128kB inside the network rx softirq is not | ||
| 21 | * reliable. Please also keep in mind that this buffer size is allocated for | ||
| 22 | * each nlgroup you are using, so the total kernel memory usage increases | ||
| 23 | * by that factor. | ||
| 24 | * | ||
| 25 | * flushtimeout: | ||
| 26 | * Specify, after how many hundredths of a second the queue should be | ||
| 27 | * flushed even if it is not full yet. | ||
| 28 | * | ||
| 29 | */ | ||
| 30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 31 | #include <linux/module.h> | ||
| 32 | #include <linux/slab.h> | ||
| 33 | #include <linux/spinlock.h> | ||
| 34 | #include <linux/socket.h> | ||
| 35 | #include <linux/skbuff.h> | ||
| 36 | #include <linux/kernel.h> | ||
| 37 | #include <linux/timer.h> | ||
| 38 | #include <net/netlink.h> | ||
| 39 | #include <linux/netdevice.h> | ||
| 40 | #include <linux/netfilter/x_tables.h> | ||
| 41 | #include <linux/netfilter_bridge/ebtables.h> | ||
| 42 | #include <linux/netfilter_bridge/ebt_ulog.h> | ||
| 43 | #include <net/netfilter/nf_log.h> | ||
| 44 | #include <net/netns/generic.h> | ||
| 45 | #include <net/sock.h> | ||
| 46 | #include "../br_private.h" | ||
| 47 | |||
| 48 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | ||
| 49 | module_param(nlbufsiz, uint, 0600); | ||
| 50 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " | ||
| 51 | "(defaults to 4096)"); | ||
| 52 | |||
| 53 | static unsigned int flushtimeout = 10; | ||
| 54 | module_param(flushtimeout, uint, 0600); | ||
| 55 | MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) " | ||
| 56 | "(defaults to 10)"); | ||
| 57 | |||
| 58 | typedef struct { | ||
| 59 | unsigned int qlen; /* number of nlmsgs' in the skb */ | ||
| 60 | struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ | ||
| 61 | struct sk_buff *skb; /* the pre-allocated skb */ | ||
| 62 | struct timer_list timer; /* the timer function */ | ||
| 63 | spinlock_t lock; /* the per-queue lock */ | ||
| 64 | } ebt_ulog_buff_t; | ||
| 65 | |||
| 66 | static int ebt_ulog_net_id __read_mostly; | ||
| 67 | struct ebt_ulog_net { | ||
| 68 | unsigned int nlgroup[EBT_ULOG_MAXNLGROUPS]; | ||
| 69 | ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; | ||
| 70 | struct sock *ebtulognl; | ||
| 71 | }; | ||
| 72 | |||
| 73 | static struct ebt_ulog_net *ebt_ulog_pernet(struct net *net) | ||
| 74 | { | ||
| 75 | return net_generic(net, ebt_ulog_net_id); | ||
| 76 | } | ||
| 77 | |||
| 78 | /* send one ulog_buff_t to userspace */ | ||
| 79 | static void ulog_send(struct ebt_ulog_net *ebt, unsigned int nlgroup) | ||
| 80 | { | ||
| 81 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[nlgroup]; | ||
| 82 | |||
| 83 | del_timer(&ub->timer); | ||
| 84 | |||
| 85 | if (!ub->skb) | ||
| 86 | return; | ||
| 87 | |||
| 88 | /* last nlmsg needs NLMSG_DONE */ | ||
| 89 | if (ub->qlen > 1) | ||
| 90 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | ||
| 91 | |||
| 92 | NETLINK_CB(ub->skb).dst_group = nlgroup + 1; | ||
| 93 | netlink_broadcast(ebt->ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); | ||
| 94 | |||
| 95 | ub->qlen = 0; | ||
| 96 | ub->skb = NULL; | ||
| 97 | } | ||
| 98 | |||
| 99 | /* timer function to flush queue in flushtimeout time */ | ||
| 100 | static void ulog_timer(unsigned long data) | ||
| 101 | { | ||
| 102 | struct ebt_ulog_net *ebt = container_of((void *)data, | ||
| 103 | struct ebt_ulog_net, | ||
| 104 | nlgroup[*(unsigned int *)data]); | ||
| 105 | |||
| 106 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[*(unsigned int *)data]; | ||
| 107 | spin_lock_bh(&ub->lock); | ||
| 108 | if (ub->skb) | ||
| 109 | ulog_send(ebt, *(unsigned int *)data); | ||
| 110 | spin_unlock_bh(&ub->lock); | ||
| 111 | } | ||
| 112 | |||
| 113 | static struct sk_buff *ulog_alloc_skb(unsigned int size) | ||
| 114 | { | ||
| 115 | struct sk_buff *skb; | ||
| 116 | unsigned int n; | ||
| 117 | |||
| 118 | n = max(size, nlbufsiz); | ||
| 119 | skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN); | ||
| 120 | if (!skb) { | ||
| 121 | if (n > size) { | ||
| 122 | /* try to allocate only as much as we need for | ||
| 123 | * current packet */ | ||
| 124 | skb = alloc_skb(size, GFP_ATOMIC); | ||
| 125 | if (!skb) | ||
| 126 | pr_debug("cannot even allocate buffer of size %ub\n", | ||
| 127 | size); | ||
| 128 | } | ||
| 129 | } | ||
| 130 | |||
| 131 | return skb; | ||
| 132 | } | ||
| 133 | |||
| 134 | static void ebt_ulog_packet(struct net *net, unsigned int hooknr, | ||
| 135 | const struct sk_buff *skb, | ||
| 136 | const struct net_device *in, | ||
| 137 | const struct net_device *out, | ||
| 138 | const struct ebt_ulog_info *uloginfo, | ||
| 139 | const char *prefix) | ||
| 140 | { | ||
| 141 | ebt_ulog_packet_msg_t *pm; | ||
| 142 | size_t size, copy_len; | ||
| 143 | struct nlmsghdr *nlh; | ||
| 144 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
| 145 | unsigned int group = uloginfo->nlgroup; | ||
| 146 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; | ||
| 147 | spinlock_t *lock = &ub->lock; | ||
| 148 | ktime_t kt; | ||
| 149 | |||
| 150 | if ((uloginfo->cprange == 0) || | ||
| 151 | (uloginfo->cprange > skb->len + ETH_HLEN)) | ||
| 152 | copy_len = skb->len + ETH_HLEN; | ||
| 153 | else | ||
| 154 | copy_len = uloginfo->cprange; | ||
| 155 | |||
| 156 | size = nlmsg_total_size(sizeof(*pm) + copy_len); | ||
| 157 | if (size > nlbufsiz) { | ||
| 158 | pr_debug("Size %Zd needed, but nlbufsiz=%d\n", size, nlbufsiz); | ||
| 159 | return; | ||
| 160 | } | ||
| 161 | |||
| 162 | spin_lock_bh(lock); | ||
| 163 | |||
| 164 | if (!ub->skb) { | ||
| 165 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
| 166 | goto unlock; | ||
| 167 | } else if (size > skb_tailroom(ub->skb)) { | ||
| 168 | ulog_send(ebt, group); | ||
| 169 | |||
| 170 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
| 171 | goto unlock; | ||
| 172 | } | ||
| 173 | |||
| 174 | nlh = nlmsg_put(ub->skb, 0, ub->qlen, 0, | ||
| 175 | size - NLMSG_ALIGN(sizeof(*nlh)), 0); | ||
| 176 | if (!nlh) { | ||
| 177 | kfree_skb(ub->skb); | ||
| 178 | ub->skb = NULL; | ||
| 179 | goto unlock; | ||
| 180 | } | ||
| 181 | ub->qlen++; | ||
| 182 | |||
| 183 | pm = nlmsg_data(nlh); | ||
| 184 | memset(pm, 0, sizeof(*pm)); | ||
| 185 | |||
| 186 | /* Fill in the ulog data */ | ||
| 187 | pm->version = EBT_ULOG_VERSION; | ||
| 188 | kt = ktime_get_real(); | ||
| 189 | pm->stamp = ktime_to_timeval(kt); | ||
| 190 | if (ub->qlen == 1) | ||
| 191 | ub->skb->tstamp = kt; | ||
| 192 | pm->data_len = copy_len; | ||
| 193 | pm->mark = skb->mark; | ||
| 194 | pm->hook = hooknr; | ||
| 195 | if (uloginfo->prefix != NULL) | ||
| 196 | strcpy(pm->prefix, uloginfo->prefix); | ||
| 197 | |||
| 198 | if (in) { | ||
| 199 | strcpy(pm->physindev, in->name); | ||
| 200 | /* If in isn't a bridge, then physindev==indev */ | ||
| 201 | if (br_port_exists(in)) | ||
| 202 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 203 | strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name); | ||
| 204 | else | ||
| 205 | strcpy(pm->indev, in->name); | ||
| 206 | } | ||
| 207 | |||
| 208 | if (out) { | ||
| 209 | /* If out exists, then out is a bridge port */ | ||
| 210 | strcpy(pm->physoutdev, out->name); | ||
| 211 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 212 | strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name); | ||
| 213 | } | ||
| 214 | |||
| 215 | if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) | ||
| 216 | BUG(); | ||
| 217 | |||
| 218 | if (ub->qlen > 1) | ||
| 219 | ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; | ||
| 220 | |||
| 221 | ub->lastnlh = nlh; | ||
| 222 | |||
| 223 | if (ub->qlen >= uloginfo->qthreshold) | ||
| 224 | ulog_send(ebt, group); | ||
| 225 | else if (!timer_pending(&ub->timer)) { | ||
| 226 | ub->timer.expires = jiffies + flushtimeout * HZ / 100; | ||
| 227 | add_timer(&ub->timer); | ||
| 228 | } | ||
| 229 | |||
| 230 | unlock: | ||
| 231 | spin_unlock_bh(lock); | ||
| 232 | } | ||
| 233 | |||
| 234 | /* this function is registered with the netfilter core */ | ||
| 235 | static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum, | ||
| 236 | const struct sk_buff *skb, const struct net_device *in, | ||
| 237 | const struct net_device *out, const struct nf_loginfo *li, | ||
| 238 | const char *prefix) | ||
| 239 | { | ||
| 240 | struct ebt_ulog_info loginfo; | ||
| 241 | |||
| 242 | if (!li || li->type != NF_LOG_TYPE_ULOG) { | ||
| 243 | loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP; | ||
| 244 | loginfo.cprange = 0; | ||
| 245 | loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD; | ||
| 246 | loginfo.prefix[0] = '\0'; | ||
| 247 | } else { | ||
| 248 | loginfo.nlgroup = li->u.ulog.group; | ||
| 249 | loginfo.cprange = li->u.ulog.copy_len; | ||
| 250 | loginfo.qthreshold = li->u.ulog.qthreshold; | ||
| 251 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); | ||
| 252 | } | ||
| 253 | |||
| 254 | ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix); | ||
| 255 | } | ||
| 256 | |||
| 257 | static unsigned int | ||
| 258 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
| 259 | { | ||
| 260 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
| 261 | |||
| 262 | ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out, | ||
| 263 | par->targinfo, NULL); | ||
| 264 | return EBT_CONTINUE; | ||
| 265 | } | ||
| 266 | |||
| 267 | static int ebt_ulog_tg_check(const struct xt_tgchk_param *par) | ||
| 268 | { | ||
| 269 | struct ebt_ulog_info *uloginfo = par->targinfo; | ||
| 270 | |||
| 271 | if (!par->net->xt.ebt_ulog_warn_deprecated) { | ||
| 272 | pr_info("ebt_ulog is deprecated and it will be removed soon, " | ||
| 273 | "use ebt_nflog instead\n"); | ||
| 274 | par->net->xt.ebt_ulog_warn_deprecated = true; | ||
| 275 | } | ||
| 276 | |||
| 277 | if (uloginfo->nlgroup > 31) | ||
| 278 | return -EINVAL; | ||
| 279 | |||
| 280 | uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; | ||
| 281 | |||
| 282 | if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) | ||
| 283 | uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | static struct xt_target ebt_ulog_tg_reg __read_mostly = { | ||
| 289 | .name = "ulog", | ||
| 290 | .revision = 0, | ||
| 291 | .family = NFPROTO_BRIDGE, | ||
| 292 | .target = ebt_ulog_tg, | ||
| 293 | .checkentry = ebt_ulog_tg_check, | ||
| 294 | .targetsize = sizeof(struct ebt_ulog_info), | ||
| 295 | .me = THIS_MODULE, | ||
| 296 | }; | ||
| 297 | |||
| 298 | static struct nf_logger ebt_ulog_logger __read_mostly = { | ||
| 299 | .name = "ebt_ulog", | ||
| 300 | .logfn = &ebt_log_packet, | ||
| 301 | .me = THIS_MODULE, | ||
| 302 | }; | ||
| 303 | |||
| 304 | static int __net_init ebt_ulog_net_init(struct net *net) | ||
| 305 | { | ||
| 306 | int i; | ||
| 307 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
| 308 | |||
| 309 | struct netlink_kernel_cfg cfg = { | ||
| 310 | .groups = EBT_ULOG_MAXNLGROUPS, | ||
| 311 | }; | ||
| 312 | |||
| 313 | /* initialize ulog_buffers */ | ||
| 314 | for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { | ||
| 315 | ebt->nlgroup[i] = i; | ||
| 316 | setup_timer(&ebt->ulog_buffers[i].timer, ulog_timer, | ||
| 317 | (unsigned long)&ebt->nlgroup[i]); | ||
| 318 | spin_lock_init(&ebt->ulog_buffers[i].lock); | ||
| 319 | } | ||
| 320 | |||
| 321 | ebt->ebtulognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); | ||
| 322 | if (!ebt->ebtulognl) | ||
| 323 | return -ENOMEM; | ||
| 324 | |||
| 325 | nf_log_set(net, NFPROTO_BRIDGE, &ebt_ulog_logger); | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static void __net_exit ebt_ulog_net_fini(struct net *net) | ||
| 330 | { | ||
| 331 | int i; | ||
| 332 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
| 333 | |||
| 334 | nf_log_unset(net, &ebt_ulog_logger); | ||
| 335 | for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { | ||
| 336 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[i]; | ||
| 337 | del_timer(&ub->timer); | ||
| 338 | |||
| 339 | if (ub->skb) { | ||
| 340 | kfree_skb(ub->skb); | ||
| 341 | ub->skb = NULL; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | netlink_kernel_release(ebt->ebtulognl); | ||
| 345 | } | ||
| 346 | |||
| 347 | static struct pernet_operations ebt_ulog_net_ops = { | ||
| 348 | .init = ebt_ulog_net_init, | ||
| 349 | .exit = ebt_ulog_net_fini, | ||
| 350 | .id = &ebt_ulog_net_id, | ||
| 351 | .size = sizeof(struct ebt_ulog_net), | ||
| 352 | }; | ||
| 353 | |||
| 354 | static int __init ebt_ulog_init(void) | ||
| 355 | { | ||
| 356 | int ret; | ||
| 357 | |||
| 358 | if (nlbufsiz >= 128*1024) { | ||
| 359 | pr_warn("Netlink buffer has to be <= 128kB," | ||
| 360 | "please try a smaller nlbufsiz parameter.\n"); | ||
| 361 | return -EINVAL; | ||
| 362 | } | ||
| 363 | |||
| 364 | ret = register_pernet_subsys(&ebt_ulog_net_ops); | ||
| 365 | if (ret) | ||
| 366 | goto out_pernet; | ||
| 367 | |||
| 368 | ret = xt_register_target(&ebt_ulog_tg_reg); | ||
| 369 | if (ret) | ||
| 370 | goto out_target; | ||
| 371 | |||
| 372 | nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); | ||
| 373 | |||
| 374 | return 0; | ||
| 375 | |||
| 376 | out_target: | ||
| 377 | unregister_pernet_subsys(&ebt_ulog_net_ops); | ||
| 378 | out_pernet: | ||
| 379 | return ret; | ||
| 380 | } | ||
| 381 | |||
| 382 | static void __exit ebt_ulog_fini(void) | ||
| 383 | { | ||
| 384 | nf_log_unregister(&ebt_ulog_logger); | ||
| 385 | xt_unregister_target(&ebt_ulog_tg_reg); | ||
| 386 | unregister_pernet_subsys(&ebt_ulog_net_ops); | ||
| 387 | } | ||
| 388 | |||
| 389 | module_init(ebt_ulog_init); | ||
| 390 | module_exit(ebt_ulog_fini); | ||
| 391 | MODULE_LICENSE("GPL"); | ||
| 392 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | ||
| 393 | MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG"); | ||
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 1059ed3bc255..6d69631b9f4d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -327,10 +327,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | |||
| 327 | char name[EBT_FUNCTION_MAXNAMELEN]; | 327 | char name[EBT_FUNCTION_MAXNAMELEN]; |
| 328 | } *e; | 328 | } *e; |
| 329 | 329 | ||
| 330 | *error = mutex_lock_interruptible(mutex); | 330 | mutex_lock(mutex); |
| 331 | if (*error != 0) | ||
| 332 | return NULL; | ||
| 333 | |||
| 334 | list_for_each_entry(e, head, list) { | 331 | list_for_each_entry(e, head, list) { |
| 335 | if (strcmp(e->name, name) == 0) | 332 | if (strcmp(e->name, name) == 0) |
| 336 | return e; | 333 | return e; |
| @@ -1203,10 +1200,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table) | |||
| 1203 | 1200 | ||
| 1204 | table->private = newinfo; | 1201 | table->private = newinfo; |
| 1205 | rwlock_init(&table->lock); | 1202 | rwlock_init(&table->lock); |
| 1206 | ret = mutex_lock_interruptible(&ebt_mutex); | 1203 | mutex_lock(&ebt_mutex); |
| 1207 | if (ret != 0) | ||
| 1208 | goto free_chainstack; | ||
| 1209 | |||
| 1210 | list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { | 1204 | list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { |
| 1211 | if (strcmp(t->name, table->name) == 0) { | 1205 | if (strcmp(t->name, table->name) == 0) { |
| 1212 | ret = -EEXIST; | 1206 | ret = -EEXIST; |
diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c new file mode 100644 index 000000000000..5d9953a90929 --- /dev/null +++ b/net/bridge/netfilter/nf_log_bridge.c | |||
| @@ -0,0 +1,96 @@ | |||
| 1 | /* | ||
| 2 | * (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/spinlock.h> | ||
| 11 | #include <linux/skbuff.h> | ||
| 12 | #include <linux/if_bridge.h> | ||
| 13 | #include <linux/ip.h> | ||
| 14 | #include <net/route.h> | ||
| 15 | |||
| 16 | #include <linux/netfilter.h> | ||
| 17 | #include <net/netfilter/nf_log.h> | ||
| 18 | |||
| 19 | static void nf_log_bridge_packet(struct net *net, u_int8_t pf, | ||
| 20 | unsigned int hooknum, | ||
| 21 | const struct sk_buff *skb, | ||
| 22 | const struct net_device *in, | ||
| 23 | const struct net_device *out, | ||
| 24 | const struct nf_loginfo *loginfo, | ||
| 25 | const char *prefix) | ||
| 26 | { | ||
| 27 | switch (eth_hdr(skb)->h_proto) { | ||
| 28 | case htons(ETH_P_IP): | ||
| 29 | nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out, | ||
| 30 | loginfo, "%s", prefix); | ||
| 31 | break; | ||
| 32 | case htons(ETH_P_IPV6): | ||
| 33 | nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out, | ||
| 34 | loginfo, "%s", prefix); | ||
| 35 | break; | ||
| 36 | case htons(ETH_P_ARP): | ||
| 37 | case htons(ETH_P_RARP): | ||
| 38 | nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out, | ||
| 39 | loginfo, "%s", prefix); | ||
| 40 | break; | ||
| 41 | } | ||
| 42 | } | ||
| 43 | |||
| 44 | static struct nf_logger nf_bridge_logger __read_mostly = { | ||
| 45 | .name = "nf_log_bridge", | ||
| 46 | .type = NF_LOG_TYPE_LOG, | ||
| 47 | .logfn = nf_log_bridge_packet, | ||
| 48 | .me = THIS_MODULE, | ||
| 49 | }; | ||
| 50 | |||
| 51 | static int __net_init nf_log_bridge_net_init(struct net *net) | ||
| 52 | { | ||
| 53 | nf_log_set(net, NFPROTO_BRIDGE, &nf_bridge_logger); | ||
| 54 | return 0; | ||
| 55 | } | ||
| 56 | |||
| 57 | static void __net_exit nf_log_bridge_net_exit(struct net *net) | ||
| 58 | { | ||
| 59 | nf_log_unset(net, &nf_bridge_logger); | ||
| 60 | } | ||
| 61 | |||
| 62 | static struct pernet_operations nf_log_bridge_net_ops = { | ||
| 63 | .init = nf_log_bridge_net_init, | ||
| 64 | .exit = nf_log_bridge_net_exit, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static int __init nf_log_bridge_init(void) | ||
| 68 | { | ||
| 69 | int ret; | ||
| 70 | |||
| 71 | /* Request to load the real packet loggers. */ | ||
| 72 | nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG); | ||
| 73 | nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG); | ||
| 74 | nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG); | ||
| 75 | |||
| 76 | ret = register_pernet_subsys(&nf_log_bridge_net_ops); | ||
| 77 | if (ret < 0) | ||
| 78 | return ret; | ||
| 79 | |||
| 80 | nf_log_register(NFPROTO_BRIDGE, &nf_bridge_logger); | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | |||
| 84 | static void __exit nf_log_bridge_exit(void) | ||
| 85 | { | ||
| 86 | unregister_pernet_subsys(&nf_log_bridge_net_ops); | ||
| 87 | nf_log_unregister(&nf_bridge_logger); | ||
| 88 | } | ||
| 89 | |||
| 90 | module_init(nf_log_bridge_init); | ||
| 91 | module_exit(nf_log_bridge_exit); | ||
| 92 | |||
| 93 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
| 94 | MODULE_DESCRIPTION("Netfilter bridge packet logging"); | ||
| 95 | MODULE_LICENSE("GPL"); | ||
| 96 | MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 0); | ||
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c new file mode 100644 index 000000000000..ee3ffe93e14e --- /dev/null +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2014 Pablo Neira Ayuso <pablo@netfilter.org> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/init.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/netlink.h> | ||
| 13 | #include <linux/netfilter.h> | ||
| 14 | #include <linux/netfilter/nf_tables.h> | ||
| 15 | #include <net/netfilter/nf_tables.h> | ||
| 16 | #include <net/netfilter/nft_reject.h> | ||
| 17 | |||
| 18 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | ||
| 19 | struct nft_data data[NFT_REG_MAX + 1], | ||
| 20 | const struct nft_pktinfo *pkt) | ||
| 21 | { | ||
| 22 | switch (eth_hdr(pkt->skb)->h_proto) { | ||
| 23 | case htons(ETH_P_IP): | ||
| 24 | return nft_reject_ipv4_eval(expr, data, pkt); | ||
| 25 | case htons(ETH_P_IPV6): | ||
| 26 | return nft_reject_ipv6_eval(expr, data, pkt); | ||
| 27 | default: | ||
| 28 | /* No explicit way to reject this protocol, drop it. */ | ||
| 29 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
| 30 | break; | ||
| 31 | } | ||
| 32 | } | ||
| 33 | |||
| 34 | static struct nft_expr_type nft_reject_bridge_type; | ||
| 35 | static const struct nft_expr_ops nft_reject_bridge_ops = { | ||
| 36 | .type = &nft_reject_bridge_type, | ||
| 37 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
| 38 | .eval = nft_reject_bridge_eval, | ||
| 39 | .init = nft_reject_init, | ||
| 40 | .dump = nft_reject_dump, | ||
| 41 | }; | ||
| 42 | |||
| 43 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | ||
| 44 | .family = NFPROTO_BRIDGE, | ||
| 45 | .name = "reject", | ||
| 46 | .ops = &nft_reject_bridge_ops, | ||
| 47 | .policy = nft_reject_policy, | ||
| 48 | .maxattr = NFTA_REJECT_MAX, | ||
| 49 | .owner = THIS_MODULE, | ||
| 50 | }; | ||
| 51 | |||
| 52 | static int __init nft_reject_bridge_module_init(void) | ||
| 53 | { | ||
| 54 | return nft_register_expr(&nft_reject_bridge_type); | ||
| 55 | } | ||
| 56 | |||
| 57 | static void __exit nft_reject_bridge_module_exit(void) | ||
| 58 | { | ||
| 59 | nft_unregister_expr(&nft_reject_bridge_type); | ||
| 60 | } | ||
| 61 | |||
| 62 | module_init(nft_reject_bridge_module_init); | ||
| 63 | module_exit(nft_reject_bridge_module_exit); | ||
| 64 | |||
| 65 | MODULE_LICENSE("GPL"); | ||
| 66 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
| 67 | MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject"); | ||
