aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/netfilter/ipset/ip_set.h60
-rw-r--r--include/linux/netfilter_bridge.h50
-rw-r--r--include/linux/skbuff.h14
-rw-r--r--include/net/ip_vs.h15
-rw-r--r--include/net/neighbour.h2
-rw-r--r--include/net/netfilter/ipv4/nf_reject.h2
-rw-r--r--include/net/netfilter/ipv6/nf_reject.h2
-rw-r--r--include/net/netfilter/nf_nat.h10
-rw-r--r--include/net/netfilter/nf_tables.h2
-rw-r--r--include/uapi/linux/ip_vs.h3
-rw-r--r--include/uapi/linux/netfilter/ipset/ip_set.h12
-rw-r--r--include/uapi/linux/netfilter/nf_tables.h17
-rw-r--r--include/uapi/linux/netfilter/xt_set.h10
-rw-r--r--net/Kconfig7
-rw-r--r--net/bridge/Makefile5
-rw-r--r--net/bridge/br.c14
-rw-r--r--net/bridge/br_device.c4
-rw-r--r--net/bridge/br_forward.c2
-rw-r--r--net/bridge/br_input.c1
-rw-r--r--net/bridge/br_netfilter.c116
-rw-r--r--net/bridge/br_netlink.c2
-rw-r--r--net/bridge/br_nf_core.c96
-rw-r--r--net/bridge/br_private.h12
-rw-r--r--net/bridge/br_sysfs_br.c4
-rw-r--r--net/ipv4/netfilter/Kconfig46
-rw-r--r--net/ipv6/netfilter/Kconfig50
-rw-r--r--net/netfilter/ipset/Kconfig9
-rw-r--r--net/netfilter/ipset/Makefile1
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_gen.h4
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ip.c11
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_ipmac.c11
-rw-r--r--net/netfilter/ipset/ip_set_bitmap_port.c11
-rw-r--r--net/netfilter/ipset/ip_set_core.c30
-rw-r--r--net/netfilter/ipset/ip_set_hash_gen.h16
-rw-r--r--net/netfilter/ipset/ip_set_hash_ip.c14
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipmark.c14
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipport.c14
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportip.c14
-rw-r--r--net/netfilter/ipset/ip_set_hash_ipportnet.c14
-rw-r--r--net/netfilter/ipset/ip_set_hash_mac.c173
-rw-r--r--net/netfilter/ipset/ip_set_hash_net.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netiface.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netnet.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netport.c16
-rw-r--r--net/netfilter/ipset/ip_set_hash_netportnet.c16
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c19
-rw-r--r--net/netfilter/ipvs/Kconfig10
-rw-r--r--net/netfilter/ipvs/Makefile1
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c74
-rw-r--r--net/netfilter/ipvs/ip_vs_core.c15
-rw-r--r--net/netfilter/ipvs/ip_vs_ctl.c112
-rw-r--r--net/netfilter/ipvs/ip_vs_dh.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_fo.c79
-rw-r--r--net/netfilter/ipvs/ip_vs_ftp.c6
-rw-r--r--net/netfilter/ipvs/ip_vs_lblc.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_lblcr.c12
-rw-r--r--net/netfilter/ipvs/ip_vs_lc.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_nq.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_sctp.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_proto_tcp.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_rr.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_sed.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_sh.c8
-rw-r--r--net/netfilter/ipvs/ip_vs_sync.c13
-rw-r--r--net/netfilter/ipvs/ip_vs_wlc.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_wrr.c2
-rw-r--r--net/netfilter/ipvs/ip_vs_xmit.c388
-rw-r--r--net/netfilter/nf_conntrack_proto_generic.c26
-rw-r--r--net/netfilter/nf_tables_api.c146
-rw-r--r--net/netfilter/nfnetlink.c6
-rw-r--r--net/netfilter/x_tables.c30
-rw-r--r--net/netfilter/xt_set.c155
72 files changed, 1595 insertions, 512 deletions
diff --git a/include/linux/netfilter/ipset/ip_set.h b/include/linux/netfilter/ipset/ip_set.h
index 96afc29184be..f1606fa6132d 100644
--- a/include/linux/netfilter/ipset/ip_set.h
+++ b/include/linux/netfilter/ipset/ip_set.h
@@ -57,6 +57,8 @@ enum ip_set_extension {
57 IPSET_EXT_COUNTER = (1 << IPSET_EXT_BIT_COUNTER), 57 IPSET_EXT_COUNTER = (1 << IPSET_EXT_BIT_COUNTER),
58 IPSET_EXT_BIT_COMMENT = 2, 58 IPSET_EXT_BIT_COMMENT = 2,
59 IPSET_EXT_COMMENT = (1 << IPSET_EXT_BIT_COMMENT), 59 IPSET_EXT_COMMENT = (1 << IPSET_EXT_BIT_COMMENT),
60 IPSET_EXT_BIT_SKBINFO = 3,
61 IPSET_EXT_SKBINFO = (1 << IPSET_EXT_BIT_SKBINFO),
60 /* Mark set with an extension which needs to call destroy */ 62 /* Mark set with an extension which needs to call destroy */
61 IPSET_EXT_BIT_DESTROY = 7, 63 IPSET_EXT_BIT_DESTROY = 7,
62 IPSET_EXT_DESTROY = (1 << IPSET_EXT_BIT_DESTROY), 64 IPSET_EXT_DESTROY = (1 << IPSET_EXT_BIT_DESTROY),
@@ -65,12 +67,14 @@ enum ip_set_extension {
65#define SET_WITH_TIMEOUT(s) ((s)->extensions & IPSET_EXT_TIMEOUT) 67#define SET_WITH_TIMEOUT(s) ((s)->extensions & IPSET_EXT_TIMEOUT)
66#define SET_WITH_COUNTER(s) ((s)->extensions & IPSET_EXT_COUNTER) 68#define SET_WITH_COUNTER(s) ((s)->extensions & IPSET_EXT_COUNTER)
67#define SET_WITH_COMMENT(s) ((s)->extensions & IPSET_EXT_COMMENT) 69#define SET_WITH_COMMENT(s) ((s)->extensions & IPSET_EXT_COMMENT)
70#define SET_WITH_SKBINFO(s) ((s)->extensions & IPSET_EXT_SKBINFO)
68#define SET_WITH_FORCEADD(s) ((s)->flags & IPSET_CREATE_FLAG_FORCEADD) 71#define SET_WITH_FORCEADD(s) ((s)->flags & IPSET_CREATE_FLAG_FORCEADD)
69 72
70/* Extension id, in size order */ 73/* Extension id, in size order */
71enum ip_set_ext_id { 74enum ip_set_ext_id {
72 IPSET_EXT_ID_COUNTER = 0, 75 IPSET_EXT_ID_COUNTER = 0,
73 IPSET_EXT_ID_TIMEOUT, 76 IPSET_EXT_ID_TIMEOUT,
77 IPSET_EXT_ID_SKBINFO,
74 IPSET_EXT_ID_COMMENT, 78 IPSET_EXT_ID_COMMENT,
75 IPSET_EXT_ID_MAX, 79 IPSET_EXT_ID_MAX,
76}; 80};
@@ -92,6 +96,10 @@ struct ip_set_ext {
92 u64 packets; 96 u64 packets;
93 u64 bytes; 97 u64 bytes;
94 u32 timeout; 98 u32 timeout;
99 u32 skbmark;
100 u32 skbmarkmask;
101 u32 skbprio;
102 u16 skbqueue;
95 char *comment; 103 char *comment;
96}; 104};
97 105
@@ -104,6 +112,13 @@ struct ip_set_comment {
104 char *str; 112 char *str;
105}; 113};
106 114
115struct ip_set_skbinfo {
116 u32 skbmark;
117 u32 skbmarkmask;
118 u32 skbprio;
119 u16 skbqueue;
120};
121
107struct ip_set; 122struct ip_set;
108 123
109#define ext_timeout(e, s) \ 124#define ext_timeout(e, s) \
@@ -112,7 +127,8 @@ struct ip_set;
112(struct ip_set_counter *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COUNTER]) 127(struct ip_set_counter *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COUNTER])
113#define ext_comment(e, s) \ 128#define ext_comment(e, s) \
114(struct ip_set_comment *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COMMENT]) 129(struct ip_set_comment *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_COMMENT])
115 130#define ext_skbinfo(e, s) \
131(struct ip_set_skbinfo *)(((void *)(e)) + (s)->offset[IPSET_EXT_ID_SKBINFO])
116 132
117typedef int (*ipset_adtfn)(struct ip_set *set, void *value, 133typedef int (*ipset_adtfn)(struct ip_set *set, void *value,
118 const struct ip_set_ext *ext, 134 const struct ip_set_ext *ext,
@@ -256,6 +272,8 @@ ip_set_put_flags(struct sk_buff *skb, struct ip_set *set)
256 cadt_flags |= IPSET_FLAG_WITH_COUNTERS; 272 cadt_flags |= IPSET_FLAG_WITH_COUNTERS;
257 if (SET_WITH_COMMENT(set)) 273 if (SET_WITH_COMMENT(set))
258 cadt_flags |= IPSET_FLAG_WITH_COMMENT; 274 cadt_flags |= IPSET_FLAG_WITH_COMMENT;
275 if (SET_WITH_SKBINFO(set))
276 cadt_flags |= IPSET_FLAG_WITH_SKBINFO;
259 if (SET_WITH_FORCEADD(set)) 277 if (SET_WITH_FORCEADD(set))
260 cadt_flags |= IPSET_FLAG_WITH_FORCEADD; 278 cadt_flags |= IPSET_FLAG_WITH_FORCEADD;
261 279
@@ -304,6 +322,43 @@ ip_set_update_counter(struct ip_set_counter *counter,
304 } 322 }
305} 323}
306 324
325static inline void
326ip_set_get_skbinfo(struct ip_set_skbinfo *skbinfo,
327 const struct ip_set_ext *ext,
328 struct ip_set_ext *mext, u32 flags)
329{
330 mext->skbmark = skbinfo->skbmark;
331 mext->skbmarkmask = skbinfo->skbmarkmask;
332 mext->skbprio = skbinfo->skbprio;
333 mext->skbqueue = skbinfo->skbqueue;
334}
335static inline bool
336ip_set_put_skbinfo(struct sk_buff *skb, struct ip_set_skbinfo *skbinfo)
337{
338 /* Send nonzero parameters only */
339 return ((skbinfo->skbmark || skbinfo->skbmarkmask) &&
340 nla_put_net64(skb, IPSET_ATTR_SKBMARK,
341 cpu_to_be64((u64)skbinfo->skbmark << 32 |
342 skbinfo->skbmarkmask))) ||
343 (skbinfo->skbprio &&
344 nla_put_net32(skb, IPSET_ATTR_SKBPRIO,
345 cpu_to_be32(skbinfo->skbprio))) ||
346 (skbinfo->skbqueue &&
347 nla_put_net16(skb, IPSET_ATTR_SKBQUEUE,
348 cpu_to_be16(skbinfo->skbqueue)));
349
350}
351
352static inline void
353ip_set_init_skbinfo(struct ip_set_skbinfo *skbinfo,
354 const struct ip_set_ext *ext)
355{
356 skbinfo->skbmark = ext->skbmark;
357 skbinfo->skbmarkmask = ext->skbmarkmask;
358 skbinfo->skbprio = ext->skbprio;
359 skbinfo->skbqueue = ext->skbqueue;
360}
361
307static inline bool 362static inline bool
308ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter) 363ip_set_put_counter(struct sk_buff *skb, struct ip_set_counter *counter)
309{ 364{
@@ -497,6 +552,9 @@ ip_set_put_extensions(struct sk_buff *skb, const struct ip_set *set,
497 if (SET_WITH_COMMENT(set) && 552 if (SET_WITH_COMMENT(set) &&
498 ip_set_put_comment(skb, ext_comment(e, set))) 553 ip_set_put_comment(skb, ext_comment(e, set)))
499 return -EMSGSIZE; 554 return -EMSGSIZE;
555 if (SET_WITH_SKBINFO(set) &&
556 ip_set_put_skbinfo(skb, ext_skbinfo(e, set)))
557 return -EMSGSIZE;
500 return 0; 558 return 0;
501} 559}
502 560
diff --git a/include/linux/netfilter_bridge.h b/include/linux/netfilter_bridge.h
index 8ab1c278b66d..c755e4971fa3 100644
--- a/include/linux/netfilter_bridge.h
+++ b/include/linux/netfilter_bridge.h
@@ -15,7 +15,7 @@ enum nf_br_hook_priorities {
15 NF_BR_PRI_LAST = INT_MAX, 15 NF_BR_PRI_LAST = INT_MAX,
16}; 16};
17 17
18#ifdef CONFIG_BRIDGE_NETFILTER 18#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
19 19
20#define BRNF_PKT_TYPE 0x01 20#define BRNF_PKT_TYPE 0x01
21#define BRNF_BRIDGED_DNAT 0x02 21#define BRNF_BRIDGED_DNAT 0x02
@@ -24,16 +24,6 @@ enum nf_br_hook_priorities {
24#define BRNF_8021Q 0x10 24#define BRNF_8021Q 0x10
25#define BRNF_PPPoE 0x20 25#define BRNF_PPPoE 0x20
26 26
27/* Only used in br_forward.c */
28int nf_bridge_copy_header(struct sk_buff *skb);
29static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
30{
31 if (skb->nf_bridge &&
32 skb->nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))
33 return nf_bridge_copy_header(skb);
34 return 0;
35}
36
37static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb) 27static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
38{ 28{
39 switch (skb->protocol) { 29 switch (skb->protocol) {
@@ -46,6 +36,44 @@ static inline unsigned int nf_bridge_encap_header_len(const struct sk_buff *skb)
46 } 36 }
47} 37}
48 38
39static inline void nf_bridge_update_protocol(struct sk_buff *skb)
40{
41 if (skb->nf_bridge->mask & BRNF_8021Q)
42 skb->protocol = htons(ETH_P_8021Q);
43 else if (skb->nf_bridge->mask & BRNF_PPPoE)
44 skb->protocol = htons(ETH_P_PPP_SES);
45}
46
47/* Fill in the header for fragmented IP packets handled by
48 * the IPv4 connection tracking code.
49 *
50 * Only used in br_forward.c
51 */
52static inline int nf_bridge_copy_header(struct sk_buff *skb)
53{
54 int err;
55 unsigned int header_size;
56
57 nf_bridge_update_protocol(skb);
58 header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
59 err = skb_cow_head(skb, header_size);
60 if (err)
61 return err;
62
63 skb_copy_to_linear_data_offset(skb, -header_size,
64 skb->nf_bridge->data, header_size);
65 __skb_push(skb, nf_bridge_encap_header_len(skb));
66 return 0;
67}
68
69static inline int nf_bridge_maybe_copy_header(struct sk_buff *skb)
70{
71 if (skb->nf_bridge &&
72 skb->nf_bridge->mask & (BRNF_BRIDGED | BRNF_BRIDGED_DNAT))
73 return nf_bridge_copy_header(skb);
74 return 0;
75}
76
49static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb) 77static inline unsigned int nf_bridge_mtu_reduction(const struct sk_buff *skb)
50{ 78{
51 if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE)) 79 if (unlikely(skb->nf_bridge->mask & BRNF_PPPoE))
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index b6cced304b26..262efdbc346b 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -156,7 +156,7 @@ struct nf_conntrack {
156}; 156};
157#endif 157#endif
158 158
159#ifdef CONFIG_BRIDGE_NETFILTER 159#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
160struct nf_bridge_info { 160struct nf_bridge_info {
161 atomic_t use; 161 atomic_t use;
162 unsigned int mask; 162 unsigned int mask;
@@ -534,7 +534,7 @@ struct sk_buff {
534#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 534#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
535 struct nf_conntrack *nfct; 535 struct nf_conntrack *nfct;
536#endif 536#endif
537#ifdef CONFIG_BRIDGE_NETFILTER 537#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
538 struct nf_bridge_info *nf_bridge; 538 struct nf_bridge_info *nf_bridge;
539#endif 539#endif
540 unsigned int len, 540 unsigned int len,
@@ -556,8 +556,6 @@ struct sk_buff {
556 /* one bit hole */ 556 /* one bit hole */
557 kmemcheck_bitfield_end(flags1); 557 kmemcheck_bitfield_end(flags1);
558 558
559
560
561 /* fields enclosed in headers_start/headers_end are copied 559 /* fields enclosed in headers_start/headers_end are copied
562 * using a single memcpy() in __copy_skb_header() 560 * using a single memcpy() in __copy_skb_header()
563 */ 561 */
@@ -3016,7 +3014,7 @@ static inline void nf_conntrack_get(struct nf_conntrack *nfct)
3016 atomic_inc(&nfct->use); 3014 atomic_inc(&nfct->use);
3017} 3015}
3018#endif 3016#endif
3019#ifdef CONFIG_BRIDGE_NETFILTER 3017#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3020static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge) 3018static inline void nf_bridge_put(struct nf_bridge_info *nf_bridge)
3021{ 3019{
3022 if (nf_bridge && atomic_dec_and_test(&nf_bridge->use)) 3020 if (nf_bridge && atomic_dec_and_test(&nf_bridge->use))
@@ -3034,7 +3032,7 @@ static inline void nf_reset(struct sk_buff *skb)
3034 nf_conntrack_put(skb->nfct); 3032 nf_conntrack_put(skb->nfct);
3035 skb->nfct = NULL; 3033 skb->nfct = NULL;
3036#endif 3034#endif
3037#ifdef CONFIG_BRIDGE_NETFILTER 3035#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3038 nf_bridge_put(skb->nf_bridge); 3036 nf_bridge_put(skb->nf_bridge);
3039 skb->nf_bridge = NULL; 3037 skb->nf_bridge = NULL;
3040#endif 3038#endif
@@ -3057,7 +3055,7 @@ static inline void __nf_copy(struct sk_buff *dst, const struct sk_buff *src,
3057 if (copy) 3055 if (copy)
3058 dst->nfctinfo = src->nfctinfo; 3056 dst->nfctinfo = src->nfctinfo;
3059#endif 3057#endif
3060#ifdef CONFIG_BRIDGE_NETFILTER 3058#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3061 dst->nf_bridge = src->nf_bridge; 3059 dst->nf_bridge = src->nf_bridge;
3062 nf_bridge_get(src->nf_bridge); 3060 nf_bridge_get(src->nf_bridge);
3063#endif 3061#endif
@@ -3072,7 +3070,7 @@ static inline void nf_copy(struct sk_buff *dst, const struct sk_buff *src)
3072#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) 3070#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
3073 nf_conntrack_put(dst->nfct); 3071 nf_conntrack_put(dst->nfct);
3074#endif 3072#endif
3075#ifdef CONFIG_BRIDGE_NETFILTER 3073#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
3076 nf_bridge_put(dst->nf_bridge); 3074 nf_bridge_put(dst->nf_bridge);
3077#endif 3075#endif
3078 __nf_copy(dst, src, true); 3076 __nf_copy(dst, src, true);
diff --git a/include/net/ip_vs.h b/include/net/ip_vs.h
index 624a8a54806d..576d7f0bed5d 100644
--- a/include/net/ip_vs.h
+++ b/include/net/ip_vs.h
@@ -535,6 +535,7 @@ struct ip_vs_conn {
535 union nf_inet_addr daddr; /* destination address */ 535 union nf_inet_addr daddr; /* destination address */
536 volatile __u32 flags; /* status flags */ 536 volatile __u32 flags; /* status flags */
537 __u16 protocol; /* Which protocol (TCP/UDP) */ 537 __u16 protocol; /* Which protocol (TCP/UDP) */
538 __u16 daf; /* Address family of the dest */
538#ifdef CONFIG_NET_NS 539#ifdef CONFIG_NET_NS
539 struct net *net; /* Name space */ 540 struct net *net; /* Name space */
540#endif 541#endif
@@ -648,6 +649,9 @@ struct ip_vs_dest_user_kern {
648 /* thresholds for active connections */ 649 /* thresholds for active connections */
649 u32 u_threshold; /* upper threshold */ 650 u32 u_threshold; /* upper threshold */
650 u32 l_threshold; /* lower threshold */ 651 u32 l_threshold; /* lower threshold */
652
653 /* Address family of addr */
654 u16 af;
651}; 655};
652 656
653 657
@@ -986,6 +990,10 @@ struct netns_ipvs {
986 char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN]; 990 char backup_mcast_ifn[IP_VS_IFNAME_MAXLEN];
987 /* net name space ptr */ 991 /* net name space ptr */
988 struct net *net; /* Needed by timer routines */ 992 struct net *net; /* Needed by timer routines */
993 /* Number of heterogeneous destinations, needed because
994 * heterogeneous are not supported when synchronization is
995 * enabled */
996 unsigned int mixed_address_family_dests;
989}; 997};
990 998
991#define DEFAULT_SYNC_THRESHOLD 3 999#define DEFAULT_SYNC_THRESHOLD 3
@@ -1210,7 +1218,7 @@ static inline void __ip_vs_conn_put(struct ip_vs_conn *cp)
1210void ip_vs_conn_put(struct ip_vs_conn *cp); 1218void ip_vs_conn_put(struct ip_vs_conn *cp);
1211void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport); 1219void ip_vs_conn_fill_cport(struct ip_vs_conn *cp, __be16 cport);
1212 1220
1213struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, 1221struct ip_vs_conn *ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
1214 const union nf_inet_addr *daddr, 1222 const union nf_inet_addr *daddr,
1215 __be16 dport, unsigned int flags, 1223 __be16 dport, unsigned int flags,
1216 struct ip_vs_dest *dest, __u32 fwmark); 1224 struct ip_vs_dest *dest, __u32 fwmark);
@@ -1396,8 +1404,9 @@ void ip_vs_unregister_nl_ioctl(void);
1396int ip_vs_control_init(void); 1404int ip_vs_control_init(void);
1397void ip_vs_control_cleanup(void); 1405void ip_vs_control_cleanup(void);
1398struct ip_vs_dest * 1406struct ip_vs_dest *
1399ip_vs_find_dest(struct net *net, int af, const union nf_inet_addr *daddr, 1407ip_vs_find_dest(struct net *net, int svc_af, int dest_af,
1400 __be16 dport, const union nf_inet_addr *vaddr, __be16 vport, 1408 const union nf_inet_addr *daddr, __be16 dport,
1409 const union nf_inet_addr *vaddr, __be16 vport,
1401 __u16 protocol, __u32 fwmark, __u32 flags); 1410 __u16 protocol, __u32 fwmark, __u32 flags);
1402void ip_vs_try_bind_dest(struct ip_vs_conn *cp); 1411void ip_vs_try_bind_dest(struct ip_vs_conn *cp);
1403 1412
diff --git a/include/net/neighbour.h b/include/net/neighbour.h
index 47f425464f84..f60558d0254c 100644
--- a/include/net/neighbour.h
+++ b/include/net/neighbour.h
@@ -373,7 +373,7 @@ static inline int neigh_event_send(struct neighbour *neigh, struct sk_buff *skb)
373 return 0; 373 return 0;
374} 374}
375 375
376#ifdef CONFIG_BRIDGE_NETFILTER 376#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
377static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb) 377static inline int neigh_hh_bridge(struct hh_cache *hh, struct sk_buff *skb)
378{ 378{
379 unsigned int seq, hh_alen; 379 unsigned int seq, hh_alen;
diff --git a/include/net/netfilter/ipv4/nf_reject.h b/include/net/netfilter/ipv4/nf_reject.h
index 931fbf812171..f713b5a31d62 100644
--- a/include/net/netfilter/ipv4/nf_reject.h
+++ b/include/net/netfilter/ipv4/nf_reject.h
@@ -98,7 +98,7 @@ static void nf_send_reset(struct sk_buff *oldskb, int hook)
98 98
99 nf_ct_attach(nskb, oldskb); 99 nf_ct_attach(nskb, oldskb);
100 100
101#ifdef CONFIG_BRIDGE_NETFILTER 101#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
102 /* If we use ip_local_out for bridged traffic, the MAC source on 102 /* If we use ip_local_out for bridged traffic, the MAC source on
103 * the RST will be ours, instead of the destination's. This confuses 103 * the RST will be ours, instead of the destination's. This confuses
104 * some routers/firewalls, and they drop the packet. So we need to 104 * some routers/firewalls, and they drop the packet. So we need to
diff --git a/include/net/netfilter/ipv6/nf_reject.h b/include/net/netfilter/ipv6/nf_reject.h
index 710d17ed70b4..7a10cfcd8e33 100644
--- a/include/net/netfilter/ipv6/nf_reject.h
+++ b/include/net/netfilter/ipv6/nf_reject.h
@@ -147,7 +147,7 @@ static void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
147 147
148 nf_ct_attach(nskb, oldskb); 148 nf_ct_attach(nskb, oldskb);
149 149
150#ifdef CONFIG_BRIDGE_NETFILTER 150#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
151 /* If we use ip6_local_out for bridged traffic, the MAC source on 151 /* If we use ip6_local_out for bridged traffic, the MAC source on
152 * the RST will be ours, instead of the destination's. This confuses 152 * the RST will be ours, instead of the destination's. This confuses
153 * some routers/firewalls, and they drop the packet. So we need to 153 * some routers/firewalls, and they drop the packet. So we need to
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h
index a71dd333ac68..344b1ab19220 100644
--- a/include/net/netfilter/nf_nat.h
+++ b/include/net/netfilter/nf_nat.h
@@ -32,10 +32,8 @@ struct nf_conn_nat {
32 struct hlist_node bysource; 32 struct hlist_node bysource;
33 struct nf_conn *ct; 33 struct nf_conn *ct;
34 union nf_conntrack_nat_help help; 34 union nf_conntrack_nat_help help;
35#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \ 35#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
36 defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) || \ 36 IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
37 defined(CONFIG_IP6_NF_TARGET_MASQUERADE) || \
38 defined(CONFIG_IP6_NF_TARGET_MASQUERADE_MODULE)
39 int masq_index; 37 int masq_index;
40#endif 38#endif
41}; 39};
@@ -68,8 +66,8 @@ static inline bool nf_nat_oif_changed(unsigned int hooknum,
68 struct nf_conn_nat *nat, 66 struct nf_conn_nat *nat,
69 const struct net_device *out) 67 const struct net_device *out)
70{ 68{
71#if IS_ENABLED(CONFIG_IP_NF_TARGET_MASQUERADE) || \ 69#if IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV4) || \
72 IS_ENABLED(CONFIG_IP6_NF_TARGET_MASQUERADE) 70 IS_ENABLED(CONFIG_NF_NAT_MASQUERADE_IPV6)
73 return nat->masq_index && hooknum == NF_INET_POST_ROUTING && 71 return nat->masq_index && hooknum == NF_INET_POST_ROUTING &&
74 CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL && 72 CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL &&
75 nat->masq_index != out->ifindex; 73 nat->masq_index != out->ifindex;
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index c4d86198d3d6..3d7292392fac 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -241,6 +241,7 @@ void nft_unregister_set(struct nft_set_ops *ops);
241 * @dtype: data type (verdict or numeric type defined by userspace) 241 * @dtype: data type (verdict or numeric type defined by userspace)
242 * @size: maximum set size 242 * @size: maximum set size
243 * @nelems: number of elements 243 * @nelems: number of elements
244 * @policy: set parameterization (see enum nft_set_policies)
244 * @ops: set ops 245 * @ops: set ops
245 * @flags: set flags 246 * @flags: set flags
246 * @klen: key length 247 * @klen: key length
@@ -255,6 +256,7 @@ struct nft_set {
255 u32 dtype; 256 u32 dtype;
256 u32 size; 257 u32 size;
257 u32 nelems; 258 u32 nelems;
259 u16 policy;
258 /* runtime data below here */ 260 /* runtime data below here */
259 const struct nft_set_ops *ops ____cacheline_aligned; 261 const struct nft_set_ops *ops ____cacheline_aligned;
260 u16 flags; 262 u16 flags;
diff --git a/include/uapi/linux/ip_vs.h b/include/uapi/linux/ip_vs.h
index fbcffe8041f7..cabe95d5b461 100644
--- a/include/uapi/linux/ip_vs.h
+++ b/include/uapi/linux/ip_vs.h
@@ -384,6 +384,9 @@ enum {
384 IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */ 384 IPVS_DEST_ATTR_PERSIST_CONNS, /* persistent connections */
385 385
386 IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */ 386 IPVS_DEST_ATTR_STATS, /* nested attribute for dest stats */
387
388 IPVS_DEST_ATTR_ADDR_FAMILY, /* Address family of address */
389
387 __IPVS_DEST_ATTR_MAX, 390 __IPVS_DEST_ATTR_MAX,
388}; 391};
389 392
diff --git a/include/uapi/linux/netfilter/ipset/ip_set.h b/include/uapi/linux/netfilter/ipset/ip_set.h
index 78c2f2e79920..ca03119111a2 100644
--- a/include/uapi/linux/netfilter/ipset/ip_set.h
+++ b/include/uapi/linux/netfilter/ipset/ip_set.h
@@ -115,6 +115,9 @@ enum {
115 IPSET_ATTR_BYTES, 115 IPSET_ATTR_BYTES,
116 IPSET_ATTR_PACKETS, 116 IPSET_ATTR_PACKETS,
117 IPSET_ATTR_COMMENT, 117 IPSET_ATTR_COMMENT,
118 IPSET_ATTR_SKBMARK,
119 IPSET_ATTR_SKBPRIO,
120 IPSET_ATTR_SKBQUEUE,
118 __IPSET_ATTR_ADT_MAX, 121 __IPSET_ATTR_ADT_MAX,
119}; 122};
120#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1) 123#define IPSET_ATTR_ADT_MAX (__IPSET_ATTR_ADT_MAX - 1)
@@ -147,6 +150,7 @@ enum ipset_errno {
147 IPSET_ERR_COUNTER, 150 IPSET_ERR_COUNTER,
148 IPSET_ERR_COMMENT, 151 IPSET_ERR_COMMENT,
149 IPSET_ERR_INVALID_MARKMASK, 152 IPSET_ERR_INVALID_MARKMASK,
153 IPSET_ERR_SKBINFO,
150 154
151 /* Type specific error codes */ 155 /* Type specific error codes */
152 IPSET_ERR_TYPE_SPECIFIC = 4352, 156 IPSET_ERR_TYPE_SPECIFIC = 4352,
@@ -170,6 +174,12 @@ enum ipset_cmd_flags {
170 IPSET_FLAG_MATCH_COUNTERS = (1 << IPSET_FLAG_BIT_MATCH_COUNTERS), 174 IPSET_FLAG_MATCH_COUNTERS = (1 << IPSET_FLAG_BIT_MATCH_COUNTERS),
171 IPSET_FLAG_BIT_RETURN_NOMATCH = 7, 175 IPSET_FLAG_BIT_RETURN_NOMATCH = 7,
172 IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH), 176 IPSET_FLAG_RETURN_NOMATCH = (1 << IPSET_FLAG_BIT_RETURN_NOMATCH),
177 IPSET_FLAG_BIT_MAP_SKBMARK = 8,
178 IPSET_FLAG_MAP_SKBMARK = (1 << IPSET_FLAG_BIT_MAP_SKBMARK),
179 IPSET_FLAG_BIT_MAP_SKBPRIO = 9,
180 IPSET_FLAG_MAP_SKBPRIO = (1 << IPSET_FLAG_BIT_MAP_SKBPRIO),
181 IPSET_FLAG_BIT_MAP_SKBQUEUE = 10,
182 IPSET_FLAG_MAP_SKBQUEUE = (1 << IPSET_FLAG_BIT_MAP_SKBQUEUE),
173 IPSET_FLAG_CMD_MAX = 15, 183 IPSET_FLAG_CMD_MAX = 15,
174}; 184};
175 185
@@ -187,6 +197,8 @@ enum ipset_cadt_flags {
187 IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT), 197 IPSET_FLAG_WITH_COMMENT = (1 << IPSET_FLAG_BIT_WITH_COMMENT),
188 IPSET_FLAG_BIT_WITH_FORCEADD = 5, 198 IPSET_FLAG_BIT_WITH_FORCEADD = 5,
189 IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD), 199 IPSET_FLAG_WITH_FORCEADD = (1 << IPSET_FLAG_BIT_WITH_FORCEADD),
200 IPSET_FLAG_BIT_WITH_SKBINFO = 6,
201 IPSET_FLAG_WITH_SKBINFO = (1 << IPSET_FLAG_BIT_WITH_SKBINFO),
190 IPSET_FLAG_CADT_MAX = 15, 202 IPSET_FLAG_CADT_MAX = 15,
191}; 203};
192 204
diff --git a/include/uapi/linux/netfilter/nf_tables.h b/include/uapi/linux/netfilter/nf_tables.h
index eeec0ae845ef..b72ccfeaf865 100644
--- a/include/uapi/linux/netfilter/nf_tables.h
+++ b/include/uapi/linux/netfilter/nf_tables.h
@@ -51,6 +51,8 @@ enum nft_verdicts {
51 * @NFT_MSG_NEWSETELEM: create a new set element (enum nft_set_elem_attributes) 51 * @NFT_MSG_NEWSETELEM: create a new set element (enum nft_set_elem_attributes)
52 * @NFT_MSG_GETSETELEM: get a set element (enum nft_set_elem_attributes) 52 * @NFT_MSG_GETSETELEM: get a set element (enum nft_set_elem_attributes)
53 * @NFT_MSG_DELSETELEM: delete a set element (enum nft_set_elem_attributes) 53 * @NFT_MSG_DELSETELEM: delete a set element (enum nft_set_elem_attributes)
54 * @NFT_MSG_NEWGEN: announce a new generation, only for events (enum nft_gen_attributes)
55 * @NFT_MSG_GETGEN: get the rule-set generation (enum nft_gen_attributes)
54 */ 56 */
55enum nf_tables_msg_types { 57enum nf_tables_msg_types {
56 NFT_MSG_NEWTABLE, 58 NFT_MSG_NEWTABLE,
@@ -68,6 +70,8 @@ enum nf_tables_msg_types {
68 NFT_MSG_NEWSETELEM, 70 NFT_MSG_NEWSETELEM,
69 NFT_MSG_GETSETELEM, 71 NFT_MSG_GETSETELEM,
70 NFT_MSG_DELSETELEM, 72 NFT_MSG_DELSETELEM,
73 NFT_MSG_NEWGEN,
74 NFT_MSG_GETGEN,
71 NFT_MSG_MAX, 75 NFT_MSG_MAX,
72}; 76};
73 77
@@ -806,9 +810,22 @@ enum nft_nat_attributes {
806 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32) 810 * @NFTA_MASQ_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
807 */ 811 */
808enum nft_masq_attributes { 812enum nft_masq_attributes {
813 NFTA_MASQ_UNSPEC,
809 NFTA_MASQ_FLAGS, 814 NFTA_MASQ_FLAGS,
810 __NFTA_MASQ_MAX 815 __NFTA_MASQ_MAX
811}; 816};
812#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1) 817#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
813 818
819/**
820 * enum nft_gen_attributes - nf_tables ruleset generation attributes
821 *
822 * @NFTA_GEN_ID: Ruleset generation ID (NLA_U32)
823 */
824enum nft_gen_attributes {
825 NFTA_GEN_UNSPEC,
826 NFTA_GEN_ID,
827 __NFTA_GEN_MAX
828};
829#define NFTA_GEN_MAX (__NFTA_GEN_MAX - 1)
830
814#endif /* _LINUX_NF_TABLES_H */ 831#endif /* _LINUX_NF_TABLES_H */
diff --git a/include/uapi/linux/netfilter/xt_set.h b/include/uapi/linux/netfilter/xt_set.h
index 964d3d42f874..d6a1df1f2947 100644
--- a/include/uapi/linux/netfilter/xt_set.h
+++ b/include/uapi/linux/netfilter/xt_set.h
@@ -71,4 +71,14 @@ struct xt_set_info_match_v3 {
71 __u32 flags; 71 __u32 flags;
72}; 72};
73 73
74/* Revision 3 target */
75
76struct xt_set_info_target_v3 {
77 struct xt_set_info add_set;
78 struct xt_set_info del_set;
79 struct xt_set_info map_set;
80 __u32 flags;
81 __u32 timeout;
82};
83
74#endif /*_XT_SET_H*/ 84#endif /*_XT_SET_H*/
diff --git a/net/Kconfig b/net/Kconfig
index 4051fdfa4367..dc5d700d05e7 100644
--- a/net/Kconfig
+++ b/net/Kconfig
@@ -176,10 +176,11 @@ config NETFILTER_ADVANCED
176 If unsure, say Y. 176 If unsure, say Y.
177 177
178config BRIDGE_NETFILTER 178config BRIDGE_NETFILTER
179 bool "Bridged IP/ARP packets filtering" 179 tristate "Bridged IP/ARP packets filtering"
180 depends on BRIDGE && NETFILTER && INET 180 depends on (BRIDGE || BRIDGE=n)
181 depends on NETFILTER && INET
181 depends on NETFILTER_ADVANCED 182 depends on NETFILTER_ADVANCED
182 default y 183 default m
183 ---help--- 184 ---help---
184 Enabling this option will let arptables resp. iptables see bridged 185 Enabling this option will let arptables resp. iptables see bridged
185 ARP resp. IP traffic. If you want a bridging firewall, you probably 186 ARP resp. IP traffic. If you want a bridging firewall, you probably
diff --git a/net/bridge/Makefile b/net/bridge/Makefile
index 8590b942bffa..5e3eac5dc8b9 100644
--- a/net/bridge/Makefile
+++ b/net/bridge/Makefile
@@ -6,11 +6,12 @@ obj-$(CONFIG_BRIDGE) += bridge.o
6 6
7bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \ 7bridge-y := br.o br_device.o br_fdb.o br_forward.o br_if.o br_input.o \
8 br_ioctl.o br_stp.o br_stp_bpdu.o \ 8 br_ioctl.o br_stp.o br_stp_bpdu.o \
9 br_stp_if.o br_stp_timer.o br_netlink.o 9 br_stp_if.o br_stp_timer.o br_netlink.o \
10 br_nf_core.o
10 11
11bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o 12bridge-$(CONFIG_SYSFS) += br_sysfs_if.o br_sysfs_br.o
12 13
13bridge-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o 14obj-$(CONFIG_BRIDGE_NETFILTER) += br_netfilter.o
14 15
15bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o 16bridge-$(CONFIG_BRIDGE_IGMP_SNOOPING) += br_multicast.o br_mdb.o
16 17
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 1a755a1e5410..44425aff7cba 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -161,7 +161,7 @@ static int __init br_init(void)
161 if (err) 161 if (err)
162 goto err_out1; 162 goto err_out1;
163 163
164 err = br_netfilter_init(); 164 err = br_nf_core_init();
165 if (err) 165 if (err)
166 goto err_out2; 166 goto err_out2;
167 167
@@ -179,11 +179,16 @@ static int __init br_init(void)
179 br_fdb_test_addr_hook = br_fdb_test_addr; 179 br_fdb_test_addr_hook = br_fdb_test_addr;
180#endif 180#endif
181 181
182 pr_info("bridge: automatic filtering via arp/ip/ip6tables has been "
183 "deprecated. Update your scripts to load br_netfilter if you "
184 "need this.\n");
185
182 return 0; 186 return 0;
187
183err_out4: 188err_out4:
184 unregister_netdevice_notifier(&br_device_notifier); 189 unregister_netdevice_notifier(&br_device_notifier);
185err_out3: 190err_out3:
186 br_netfilter_fini(); 191 br_nf_core_fini();
187err_out2: 192err_out2:
188 unregister_pernet_subsys(&br_net_ops); 193 unregister_pernet_subsys(&br_net_ops);
189err_out1: 194err_out1:
@@ -196,20 +201,17 @@ err_out:
196static void __exit br_deinit(void) 201static void __exit br_deinit(void)
197{ 202{
198 stp_proto_unregister(&br_stp_proto); 203 stp_proto_unregister(&br_stp_proto);
199
200 br_netlink_fini(); 204 br_netlink_fini();
201 unregister_netdevice_notifier(&br_device_notifier); 205 unregister_netdevice_notifier(&br_device_notifier);
202 brioctl_set(NULL); 206 brioctl_set(NULL);
203
204 unregister_pernet_subsys(&br_net_ops); 207 unregister_pernet_subsys(&br_net_ops);
205 208
206 rcu_barrier(); /* Wait for completion of call_rcu()'s */ 209 rcu_barrier(); /* Wait for completion of call_rcu()'s */
207 210
208 br_netfilter_fini(); 211 br_nf_core_fini();
209#if IS_ENABLED(CONFIG_ATM_LANE) 212#if IS_ENABLED(CONFIG_ATM_LANE)
210 br_fdb_test_addr_hook = NULL; 213 br_fdb_test_addr_hook = NULL;
211#endif 214#endif
212
213 br_fdb_fini(); 215 br_fdb_fini();
214} 216}
215 217
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c
index 568cccd39a3d..659cac15c0df 100644
--- a/net/bridge/br_device.c
+++ b/net/bridge/br_device.c
@@ -36,7 +36,7 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev)
36 u16 vid = 0; 36 u16 vid = 0;
37 37
38 rcu_read_lock(); 38 rcu_read_lock();
39#ifdef CONFIG_BRIDGE_NETFILTER 39#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
40 if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { 40 if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) {
41 br_nf_pre_routing_finish_bridge_slow(skb); 41 br_nf_pre_routing_finish_bridge_slow(skb);
42 rcu_read_unlock(); 42 rcu_read_unlock();
@@ -167,7 +167,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu)
167 167
168 dev->mtu = new_mtu; 168 dev->mtu = new_mtu;
169 169
170#ifdef CONFIG_BRIDGE_NETFILTER 170#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
171 /* remember the MTU in the rtable for PMTU */ 171 /* remember the MTU in the rtable for PMTU */
172 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); 172 dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu);
173#endif 173#endif
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index 056b67b0e277..992ec49a96aa 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -49,6 +49,7 @@ int br_dev_queue_push_xmit(struct sk_buff *skb)
49 49
50 return 0; 50 return 0;
51} 51}
52EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
52 53
53int br_forward_finish(struct sk_buff *skb) 54int br_forward_finish(struct sk_buff *skb)
54{ 55{
@@ -56,6 +57,7 @@ int br_forward_finish(struct sk_buff *skb)
56 br_dev_queue_push_xmit); 57 br_dev_queue_push_xmit);
57 58
58} 59}
60EXPORT_SYMBOL_GPL(br_forward_finish);
59 61
60static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) 62static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb)
61{ 63{
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index 366c43649079..6fd5522df696 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -140,6 +140,7 @@ drop:
140 kfree_skb(skb); 140 kfree_skb(skb);
141 goto out; 141 goto out;
142} 142}
143EXPORT_SYMBOL_GPL(br_handle_frame_finish);
143 144
144/* note: already called with rcu_read_lock */ 145/* note: already called with rcu_read_lock */
145static int br_handle_local_finish(struct sk_buff *skb) 146static int br_handle_local_finish(struct sk_buff *skb)
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c
index a615264cf01a..97e43937aaca 100644
--- a/net/bridge/br_netfilter.c
+++ b/net/bridge/br_netfilter.c
@@ -111,66 +111,6 @@ static inline __be16 pppoe_proto(const struct sk_buff *skb)
111 pppoe_proto(skb) == htons(PPP_IPV6) && \ 111 pppoe_proto(skb) == htons(PPP_IPV6) && \
112 brnf_filter_pppoe_tagged) 112 brnf_filter_pppoe_tagged)
113 113
114static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
115 struct sk_buff *skb, u32 mtu)
116{
117}
118
119static void fake_redirect(struct dst_entry *dst, struct sock *sk,
120 struct sk_buff *skb)
121{
122}
123
124static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
125{
126 return NULL;
127}
128
129static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
130 struct sk_buff *skb,
131 const void *daddr)
132{
133 return NULL;
134}
135
136static unsigned int fake_mtu(const struct dst_entry *dst)
137{
138 return dst->dev->mtu;
139}
140
141static struct dst_ops fake_dst_ops = {
142 .family = AF_INET,
143 .protocol = cpu_to_be16(ETH_P_IP),
144 .update_pmtu = fake_update_pmtu,
145 .redirect = fake_redirect,
146 .cow_metrics = fake_cow_metrics,
147 .neigh_lookup = fake_neigh_lookup,
148 .mtu = fake_mtu,
149};
150
151/*
152 * Initialize bogus route table used to keep netfilter happy.
153 * Currently, we fill in the PMTU entry because netfilter
154 * refragmentation needs it, and the rt_flags entry because
155 * ipt_REJECT needs it. Future netfilter modules might
156 * require us to fill additional fields.
157 */
158static const u32 br_dst_default_metrics[RTAX_MAX] = {
159 [RTAX_MTU - 1] = 1500,
160};
161
162void br_netfilter_rtable_init(struct net_bridge *br)
163{
164 struct rtable *rt = &br->fake_rtable;
165
166 atomic_set(&rt->dst.__refcnt, 1);
167 rt->dst.dev = br->dev;
168 rt->dst.path = &rt->dst;
169 dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
170 rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE;
171 rt->dst.ops = &fake_dst_ops;
172}
173
174static inline struct rtable *bridge_parent_rtable(const struct net_device *dev) 114static inline struct rtable *bridge_parent_rtable(const struct net_device *dev)
175{ 115{
176 struct net_bridge_port *port; 116 struct net_bridge_port *port;
@@ -245,14 +185,6 @@ static inline void nf_bridge_save_header(struct sk_buff *skb)
245 skb->nf_bridge->data, header_size); 185 skb->nf_bridge->data, header_size);
246} 186}
247 187
248static inline void nf_bridge_update_protocol(struct sk_buff *skb)
249{
250 if (skb->nf_bridge->mask & BRNF_8021Q)
251 skb->protocol = htons(ETH_P_8021Q);
252 else if (skb->nf_bridge->mask & BRNF_PPPoE)
253 skb->protocol = htons(ETH_P_PPP_SES);
254}
255
256/* When handing a packet over to the IP layer 188/* When handing a packet over to the IP layer
257 * check whether we have a skb that is in the 189 * check whether we have a skb that is in the
258 * expected format 190 * expected format
@@ -320,26 +252,6 @@ drop:
320 return -1; 252 return -1;
321} 253}
322 254
323/* Fill in the header for fragmented IP packets handled by
324 * the IPv4 connection tracking code.
325 */
326int nf_bridge_copy_header(struct sk_buff *skb)
327{
328 int err;
329 unsigned int header_size;
330
331 nf_bridge_update_protocol(skb);
332 header_size = ETH_HLEN + nf_bridge_encap_header_len(skb);
333 err = skb_cow_head(skb, header_size);
334 if (err)
335 return err;
336
337 skb_copy_to_linear_data_offset(skb, -header_size,
338 skb->nf_bridge->data, header_size);
339 __skb_push(skb, nf_bridge_encap_header_len(skb));
340 return 0;
341}
342
343/* PF_BRIDGE/PRE_ROUTING *********************************************/ 255/* PF_BRIDGE/PRE_ROUTING *********************************************/
344/* Undo the changes made for ip6tables PREROUTING and continue the 256/* Undo the changes made for ip6tables PREROUTING and continue the
345 * bridge PRE_ROUTING hook. */ 257 * bridge PRE_ROUTING hook. */
@@ -1059,38 +971,42 @@ static struct ctl_table brnf_table[] = {
1059}; 971};
1060#endif 972#endif
1061 973
1062int __init br_netfilter_init(void) 974static int __init br_netfilter_init(void)
1063{ 975{
1064 int ret; 976 int ret;
1065 977
1066 ret = dst_entries_init(&fake_dst_ops); 978 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1067 if (ret < 0) 979 if (ret < 0)
1068 return ret; 980 return ret;
1069 981
1070 ret = nf_register_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1071 if (ret < 0) {
1072 dst_entries_destroy(&fake_dst_ops);
1073 return ret;
1074 }
1075#ifdef CONFIG_SYSCTL 982#ifdef CONFIG_SYSCTL
1076 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table); 983 brnf_sysctl_header = register_net_sysctl(&init_net, "net/bridge", brnf_table);
1077 if (brnf_sysctl_header == NULL) { 984 if (brnf_sysctl_header == NULL) {
1078 printk(KERN_WARNING 985 printk(KERN_WARNING
1079 "br_netfilter: can't register to sysctl.\n"); 986 "br_netfilter: can't register to sysctl.\n");
1080 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 987 ret = -ENOMEM;
1081 dst_entries_destroy(&fake_dst_ops); 988 goto err1;
1082 return -ENOMEM;
1083 } 989 }
1084#endif 990#endif
1085 printk(KERN_NOTICE "Bridge firewalling registered\n"); 991 printk(KERN_NOTICE "Bridge firewalling registered\n");
1086 return 0; 992 return 0;
993err1:
994 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
995 return ret;
1087} 996}
1088 997
1089void br_netfilter_fini(void) 998static void __exit br_netfilter_fini(void)
1090{ 999{
1091 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops)); 1000 nf_unregister_hooks(br_nf_ops, ARRAY_SIZE(br_nf_ops));
1092#ifdef CONFIG_SYSCTL 1001#ifdef CONFIG_SYSCTL
1093 unregister_net_sysctl_table(brnf_sysctl_header); 1002 unregister_net_sysctl_table(brnf_sysctl_header);
1094#endif 1003#endif
1095 dst_entries_destroy(&fake_dst_ops);
1096} 1004}
1005
1006module_init(br_netfilter_init);
1007module_exit(br_netfilter_fini);
1008
1009MODULE_LICENSE("GPL");
1010MODULE_AUTHOR("Lennert Buytenhek <buytenh@gnu.org>");
1011MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>");
1012MODULE_DESCRIPTION("Linux ethernet netfilter firewall bridge");
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c
index 90a91e137acc..0fa66b83685f 100644
--- a/net/bridge/br_netlink.c
+++ b/net/bridge/br_netlink.c
@@ -602,7 +602,7 @@ out_af:
602 return err; 602 return err;
603} 603}
604 604
605void __exit br_netlink_fini(void) 605void br_netlink_fini(void)
606{ 606{
607 br_mdb_uninit(); 607 br_mdb_uninit();
608 rtnl_af_unregister(&br_af_ops); 608 rtnl_af_unregister(&br_af_ops);
diff --git a/net/bridge/br_nf_core.c b/net/bridge/br_nf_core.c
new file mode 100644
index 000000000000..387cb3bd017c
--- /dev/null
+++ b/net/bridge/br_nf_core.c
@@ -0,0 +1,96 @@
1/*
2 * Handle firewalling core
3 * Linux ethernet bridge
4 *
5 * Authors:
6 * Lennert Buytenhek <buytenh@gnu.org>
7 * Bart De Schuymer <bdschuym@pandora.be>
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 *
14 * Lennert dedicates this file to Kerstin Wurdinger.
15 */
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/in_route.h>
20#include <linux/inetdevice.h>
21#include <net/route.h>
22
23#include "br_private.h"
24#ifdef CONFIG_SYSCTL
25#include <linux/sysctl.h>
26#endif
27
28static void fake_update_pmtu(struct dst_entry *dst, struct sock *sk,
29 struct sk_buff *skb, u32 mtu)
30{
31}
32
33static void fake_redirect(struct dst_entry *dst, struct sock *sk,
34 struct sk_buff *skb)
35{
36}
37
38static u32 *fake_cow_metrics(struct dst_entry *dst, unsigned long old)
39{
40 return NULL;
41}
42
43static struct neighbour *fake_neigh_lookup(const struct dst_entry *dst,
44 struct sk_buff *skb,
45 const void *daddr)
46{
47 return NULL;
48}
49
50static unsigned int fake_mtu(const struct dst_entry *dst)
51{
52 return dst->dev->mtu;
53}
54
55static struct dst_ops fake_dst_ops = {
56 .family = AF_INET,
57 .protocol = cpu_to_be16(ETH_P_IP),
58 .update_pmtu = fake_update_pmtu,
59 .redirect = fake_redirect,
60 .cow_metrics = fake_cow_metrics,
61 .neigh_lookup = fake_neigh_lookup,
62 .mtu = fake_mtu,
63};
64
65/*
66 * Initialize bogus route table used to keep netfilter happy.
67 * Currently, we fill in the PMTU entry because netfilter
68 * refragmentation needs it, and the rt_flags entry because
69 * ipt_REJECT needs it. Future netfilter modules might
70 * require us to fill additional fields.
71 */
72static const u32 br_dst_default_metrics[RTAX_MAX] = {
73 [RTAX_MTU - 1] = 1500,
74};
75
76void br_netfilter_rtable_init(struct net_bridge *br)
77{
78 struct rtable *rt = &br->fake_rtable;
79
80 atomic_set(&rt->dst.__refcnt, 1);
81 rt->dst.dev = br->dev;
82 rt->dst.path = &rt->dst;
83 dst_init_metrics(&rt->dst, br_dst_default_metrics, true);
84 rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE;
85 rt->dst.ops = &fake_dst_ops;
86}
87
88int __init br_nf_core_init(void)
89{
90 return dst_entries_init(&fake_dst_ops);
91}
92
93void br_nf_core_fini(void)
94{
95 dst_entries_destroy(&fake_dst_ops);
96}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index b6c04cbcfdc5..f53592fc3ef9 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -221,7 +221,7 @@ struct net_bridge
221 struct pcpu_sw_netstats __percpu *stats; 221 struct pcpu_sw_netstats __percpu *stats;
222 spinlock_t hash_lock; 222 spinlock_t hash_lock;
223 struct hlist_head hash[BR_HASH_SIZE]; 223 struct hlist_head hash[BR_HASH_SIZE];
224#ifdef CONFIG_BRIDGE_NETFILTER 224#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
225 struct rtable fake_rtable; 225 struct rtable fake_rtable;
226 bool nf_call_iptables; 226 bool nf_call_iptables;
227 bool nf_call_ip6tables; 227 bool nf_call_ip6tables;
@@ -754,13 +754,13 @@ static inline int br_vlan_enabled(struct net_bridge *br)
754#endif 754#endif
755 755
756/* br_netfilter.c */ 756/* br_netfilter.c */
757#ifdef CONFIG_BRIDGE_NETFILTER 757#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
758int br_netfilter_init(void); 758int br_nf_core_init(void);
759void br_netfilter_fini(void); 759void br_nf_core_fini(void);
760void br_netfilter_rtable_init(struct net_bridge *); 760void br_netfilter_rtable_init(struct net_bridge *);
761#else 761#else
762#define br_netfilter_init() (0) 762static inline int br_nf_core_init(void) { return 0; }
763#define br_netfilter_fini() do { } while (0) 763static inline void br_nf_core_fini(void) {}
764#define br_netfilter_rtable_init(x) 764#define br_netfilter_rtable_init(x)
765#endif 765#endif
766 766
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index c9e2572b15f4..cb431c6016ee 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -629,7 +629,7 @@ static ssize_t multicast_startup_query_interval_store(
629} 629}
630static DEVICE_ATTR_RW(multicast_startup_query_interval); 630static DEVICE_ATTR_RW(multicast_startup_query_interval);
631#endif 631#endif
632#ifdef CONFIG_BRIDGE_NETFILTER 632#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
633static ssize_t nf_call_iptables_show( 633static ssize_t nf_call_iptables_show(
634 struct device *d, struct device_attribute *attr, char *buf) 634 struct device *d, struct device_attribute *attr, char *buf)
635{ 635{
@@ -763,7 +763,7 @@ static struct attribute *bridge_attrs[] = {
763 &dev_attr_multicast_query_response_interval.attr, 763 &dev_attr_multicast_query_response_interval.attr,
764 &dev_attr_multicast_startup_query_interval.attr, 764 &dev_attr_multicast_startup_query_interval.attr,
765#endif 765#endif
766#ifdef CONFIG_BRIDGE_NETFILTER 766#if IS_ENABLED(CONFIG_BRIDGE_NETFILTER)
767 &dev_attr_nf_call_iptables.attr, 767 &dev_attr_nf_call_iptables.attr,
768 &dev_attr_nf_call_ip6tables.attr, 768 &dev_attr_nf_call_ip6tables.attr,
769 &dev_attr_nf_call_arptables.attr, 769 &dev_attr_nf_call_arptables.attr,
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
index d189c5262bdb..345242a79db6 100644
--- a/net/ipv4/netfilter/Kconfig
+++ b/net/ipv4/netfilter/Kconfig
@@ -61,16 +61,6 @@ config NFT_CHAIN_ROUTE_IPV4
61 fields such as the source, destination, type of service and 61 fields such as the source, destination, type of service and
62 the packet mark. 62 the packet mark.
63 63
64config NFT_CHAIN_NAT_IPV4
65 depends on NF_TABLES_IPV4
66 depends on NF_NAT_IPV4 && NFT_NAT
67 tristate "IPv4 nf_tables nat chain support"
68 help
69 This option enables the "nat" chain for IPv4 in nf_tables. This
70 chain type is used to perform Network Address Translation (NAT)
71 packet transformations such as the source, destination address and
72 source and destination ports.
73
74config NFT_REJECT_IPV4 64config NFT_REJECT_IPV4
75 depends on NF_TABLES_IPV4 65 depends on NF_TABLES_IPV4
76 default NFT_REJECT 66 default NFT_REJECT
@@ -94,6 +84,30 @@ config NF_NAT_IPV4
94 84
95if NF_NAT_IPV4 85if NF_NAT_IPV4
96 86
87config NFT_CHAIN_NAT_IPV4
88 depends on NF_TABLES_IPV4
89 tristate "IPv4 nf_tables nat chain support"
90 help
91 This option enables the "nat" chain for IPv4 in nf_tables. This
92 chain type is used to perform Network Address Translation (NAT)
93 packet transformations such as the source, destination address and
94 source and destination ports.
95
96config NF_NAT_MASQUERADE_IPV4
97 tristate "IPv4 masquerade support"
98 help
99 This is the kernel functionality to provide NAT in the masquerade
100 flavour (automatic source address selection).
101
102config NFT_MASQ_IPV4
103 tristate "IPv4 masquerading support for nf_tables"
104 depends on NF_TABLES_IPV4
105 depends on NFT_MASQ
106 select NF_NAT_MASQUERADE_IPV4
107 help
108 This is the expression that provides IPv4 masquerading support for
109 nf_tables.
110
97config NF_NAT_SNMP_BASIC 111config NF_NAT_SNMP_BASIC
98 tristate "Basic SNMP-ALG support" 112 tristate "Basic SNMP-ALG support"
99 depends on NF_CONNTRACK_SNMP 113 depends on NF_CONNTRACK_SNMP
@@ -232,18 +246,6 @@ config IP_NF_NAT
232 246
233if IP_NF_NAT 247if IP_NF_NAT
234 248
235config NF_NAT_MASQUERADE_IPV4
236 tristate "IPv4 masquerade support"
237 help
238 This is the kernel functionality to provide NAT in the masquerade
239 flavour (automatic source address selection).
240
241config NFT_MASQ_IPV4
242 tristate "IPv4 masquerading support for nf_tables"
243 depends on NF_TABLES_IPV4
244 depends on NFT_MASQ
245 select NF_NAT_MASQUERADE_IPV4
246
247config IP_NF_TARGET_MASQUERADE 249config IP_NF_TARGET_MASQUERADE
248 tristate "MASQUERADE target support" 250 tristate "MASQUERADE target support"
249 select NF_NAT_MASQUERADE_IPV4 251 select NF_NAT_MASQUERADE_IPV4
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index a8f25306a46a..bb1a40db7be1 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,16 +40,6 @@ config NFT_CHAIN_ROUTE_IPV6
40 fields such as the source, destination, flowlabel, hop-limit and 40 fields such as the source, destination, flowlabel, hop-limit and
41 the packet mark. 41 the packet mark.
42 42
43config NFT_CHAIN_NAT_IPV6
44 depends on NF_TABLES_IPV6
45 depends on NF_NAT_IPV6 && NFT_NAT
46 tristate "IPv6 nf_tables nat chain support"
47 help
48 This option enables the "nat" chain for IPv6 in nf_tables. This
49 chain type is used to perform Network Address Translation (NAT)
50 packet transformations such as the source, destination address and
51 source and destination ports.
52
53config NFT_REJECT_IPV6 43config NFT_REJECT_IPV6
54 depends on NF_TABLES_IPV6 44 depends on NF_TABLES_IPV6
55 default NFT_REJECT 45 default NFT_REJECT
@@ -70,6 +60,34 @@ config NF_NAT_IPV6
70 forms of full Network Address Port Translation. This can be 60 forms of full Network Address Port Translation. This can be
71 controlled by iptables or nft. 61 controlled by iptables or nft.
72 62
63if NF_NAT_IPV6
64
65config NFT_CHAIN_NAT_IPV6
66 depends on NF_TABLES_IPV6
67 tristate "IPv6 nf_tables nat chain support"
68 help
69 This option enables the "nat" chain for IPv6 in nf_tables. This
70 chain type is used to perform Network Address Translation (NAT)
71 packet transformations such as the source, destination address and
72 source and destination ports.
73
74config NF_NAT_MASQUERADE_IPV6
75 tristate "IPv6 masquerade support"
76 help
77 This is the kernel functionality to provide NAT in the masquerade
78 flavour (automatic source address selection) for IPv6.
79
80config NFT_MASQ_IPV6
81 tristate "IPv6 masquerade support for nf_tables"
82 depends on NF_TABLES_IPV6
83 depends on NFT_MASQ
84 select NF_NAT_MASQUERADE_IPV6
85 help
86 This is the expression that provides IPv4 masquerading support for
87 nf_tables.
88
89endif # NF_NAT_IPV6
90
73config IP6_NF_IPTABLES 91config IP6_NF_IPTABLES
74 tristate "IP6 tables support (required for filtering)" 92 tristate "IP6 tables support (required for filtering)"
75 depends on INET && IPV6 93 depends on INET && IPV6
@@ -258,18 +276,6 @@ config IP6_NF_NAT
258 276
259if IP6_NF_NAT 277if IP6_NF_NAT
260 278
261config NF_NAT_MASQUERADE_IPV6
262 tristate "IPv6 masquerade support"
263 help
264 This is the kernel functionality to provide NAT in the masquerade
265 flavour (automatic source address selection) for IPv6.
266
267config NFT_MASQ_IPV6
268 tristate "IPv6 masquerade support for nf_tables"
269 depends on NF_TABLES_IPV6
270 depends on NFT_MASQ
271 select NF_NAT_MASQUERADE_IPV6
272
273config IP6_NF_TARGET_MASQUERADE 279config IP6_NF_TARGET_MASQUERADE
274 tristate "MASQUERADE target support" 280 tristate "MASQUERADE target support"
275 select NF_NAT_MASQUERADE_IPV6 281 select NF_NAT_MASQUERADE_IPV6
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig
index 2f7f5c32c6f9..234a8ec82076 100644
--- a/net/netfilter/ipset/Kconfig
+++ b/net/netfilter/ipset/Kconfig
@@ -99,6 +99,15 @@ config IP_SET_HASH_IPPORTNET
99 99
100 To compile it as a module, choose M here. If unsure, say N. 100 To compile it as a module, choose M here. If unsure, say N.
101 101
102config IP_SET_HASH_MAC
103 tristate "hash:mac set support"
104 depends on IP_SET
105 help
106 This option adds the hash:mac set type support, by which
107 one can store MAC (ethernet address) elements in a set.
108
109 To compile it as a module, choose M here. If unsure, say N.
110
102config IP_SET_HASH_NETPORTNET 111config IP_SET_HASH_NETPORTNET
103 tristate "hash:net,port,net set support" 112 tristate "hash:net,port,net set support"
104 depends on IP_SET 113 depends on IP_SET
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile
index 231f10196cb9..3dbd5e958489 100644
--- a/net/netfilter/ipset/Makefile
+++ b/net/netfilter/ipset/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_IP_SET_HASH_IPMARK) += ip_set_hash_ipmark.o
18obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o 18obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o
19obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o 19obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o
20obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o 20obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o
21obj-$(CONFIG_IP_SET_HASH_MAC) += ip_set_hash_mac.o
21obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o 22obj-$(CONFIG_IP_SET_HASH_NET) += ip_set_hash_net.o
22obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o 23obj-$(CONFIG_IP_SET_HASH_NETPORT) += ip_set_hash_netport.o
23obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o 24obj-$(CONFIG_IP_SET_HASH_NETIFACE) += ip_set_hash_netiface.o
diff --git a/net/netfilter/ipset/ip_set_bitmap_gen.h b/net/netfilter/ipset/ip_set_bitmap_gen.h
index f2c7d83dc23f..6f024a8a1534 100644
--- a/net/netfilter/ipset/ip_set_bitmap_gen.h
+++ b/net/netfilter/ipset/ip_set_bitmap_gen.h
@@ -128,6 +128,8 @@ mtype_test(struct ip_set *set, void *value, const struct ip_set_ext *ext,
128 return 0; 128 return 0;
129 if (SET_WITH_COUNTER(set)) 129 if (SET_WITH_COUNTER(set))
130 ip_set_update_counter(ext_counter(x, set), ext, mext, flags); 130 ip_set_update_counter(ext_counter(x, set), ext, mext, flags);
131 if (SET_WITH_SKBINFO(set))
132 ip_set_get_skbinfo(ext_skbinfo(x, set), ext, mext, flags);
131 return 1; 133 return 1;
132} 134}
133 135
@@ -161,6 +163,8 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext,
161 ip_set_init_counter(ext_counter(x, set), ext); 163 ip_set_init_counter(ext_counter(x, set), ext);
162 if (SET_WITH_COMMENT(set)) 164 if (SET_WITH_COMMENT(set))
163 ip_set_init_comment(ext_comment(x, set), ext); 165 ip_set_init_comment(ext_comment(x, set), ext);
166 if (SET_WITH_SKBINFO(set))
167 ip_set_init_skbinfo(ext_skbinfo(x, set), ext);
164 return 0; 168 return 0;
165} 169}
166 170
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c
index dafdb39ef042..55b083ec587a 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ip.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ip.c
@@ -27,7 +27,8 @@
27 27
28#define IPSET_TYPE_REV_MIN 0 28#define IPSET_TYPE_REV_MIN 0
29/* 1 Counter support added */ 29/* 1 Counter support added */
30#define IPSET_TYPE_REV_MAX 2 /* Comment support added */ 30/* 2 Comment support added */
31#define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
31 32
32MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -139,7 +140,10 @@ bitmap_ip_uadt(struct ip_set *set, struct nlattr *tb[],
139 if (unlikely(!tb[IPSET_ATTR_IP] || 140 if (unlikely(!tb[IPSET_ATTR_IP] ||
140 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 141 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
141 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 142 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
142 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 143 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
144 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
145 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
146 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
143 return -IPSET_ERR_PROTOCOL; 147 return -IPSET_ERR_PROTOCOL;
144 148
145 if (tb[IPSET_ATTR_LINENO]) 149 if (tb[IPSET_ATTR_LINENO])
@@ -357,6 +361,9 @@ static struct ip_set_type bitmap_ip_type __read_mostly = {
357 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 361 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
358 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 362 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
359 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 363 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
364 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
365 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
366 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
360 }, 367 },
361 .me = THIS_MODULE, 368 .me = THIS_MODULE,
362}; 369};
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
index dbad505e79e3..86104744b00f 100644
--- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c
+++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c
@@ -27,7 +27,8 @@
27 27
28#define IPSET_TYPE_REV_MIN 0 28#define IPSET_TYPE_REV_MIN 0
29/* 1 Counter support added */ 29/* 1 Counter support added */
30#define IPSET_TYPE_REV_MAX 2 /* Comment support added */ 30/* 2 Comment support added */
31#define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
31 32
32MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -240,7 +241,10 @@ bitmap_ipmac_uadt(struct ip_set *set, struct nlattr *tb[],
240 if (unlikely(!tb[IPSET_ATTR_IP] || 241 if (unlikely(!tb[IPSET_ATTR_IP] ||
241 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 242 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
242 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 243 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
243 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 244 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
245 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
246 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
247 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
244 return -IPSET_ERR_PROTOCOL; 248 return -IPSET_ERR_PROTOCOL;
245 249
246 if (tb[IPSET_ATTR_LINENO]) 250 if (tb[IPSET_ATTR_LINENO])
@@ -394,6 +398,9 @@ static struct ip_set_type bitmap_ipmac_type = {
394 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 398 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
395 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 399 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
396 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 400 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
401 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
402 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
403 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
397 }, 404 },
398 .me = THIS_MODULE, 405 .me = THIS_MODULE,
399}; 406};
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c
index a4b65ae1986c..005dd36444c3 100644
--- a/net/netfilter/ipset/ip_set_bitmap_port.c
+++ b/net/netfilter/ipset/ip_set_bitmap_port.c
@@ -22,7 +22,8 @@
22 22
23#define IPSET_TYPE_REV_MIN 0 23#define IPSET_TYPE_REV_MIN 0
24/* 1 Counter support added */ 24/* 1 Counter support added */
25#define IPSET_TYPE_REV_MAX 2 /* Comment support added */ 25/* 2 Comment support added */
26#define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
26 27
27MODULE_LICENSE("GPL"); 28MODULE_LICENSE("GPL");
28MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 29MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -139,7 +140,10 @@ bitmap_port_uadt(struct ip_set *set, struct nlattr *tb[],
139 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 140 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
140 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 141 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
141 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 142 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
142 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 143 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
144 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
145 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
146 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
143 return -IPSET_ERR_PROTOCOL; 147 return -IPSET_ERR_PROTOCOL;
144 148
145 if (tb[IPSET_ATTR_LINENO]) 149 if (tb[IPSET_ATTR_LINENO])
@@ -291,6 +295,9 @@ static struct ip_set_type bitmap_port_type = {
291 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 295 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
292 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 296 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
293 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 297 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
298 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
299 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
300 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
294 }, 301 },
295 .me = THIS_MODULE, 302 .me = THIS_MODULE,
296}; 303};
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 5593e97426c4..26c795e6b57f 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -337,6 +337,12 @@ const struct ip_set_ext_type ip_set_extensions[] = {
337 .len = sizeof(unsigned long), 337 .len = sizeof(unsigned long),
338 .align = __alignof__(unsigned long), 338 .align = __alignof__(unsigned long),
339 }, 339 },
340 [IPSET_EXT_ID_SKBINFO] = {
341 .type = IPSET_EXT_SKBINFO,
342 .flag = IPSET_FLAG_WITH_SKBINFO,
343 .len = sizeof(struct ip_set_skbinfo),
344 .align = __alignof__(struct ip_set_skbinfo),
345 },
340 [IPSET_EXT_ID_COMMENT] = { 346 [IPSET_EXT_ID_COMMENT] = {
341 .type = IPSET_EXT_COMMENT | IPSET_EXT_DESTROY, 347 .type = IPSET_EXT_COMMENT | IPSET_EXT_DESTROY,
342 .flag = IPSET_FLAG_WITH_COMMENT, 348 .flag = IPSET_FLAG_WITH_COMMENT,
@@ -382,6 +388,7 @@ int
382ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[], 388ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
383 struct ip_set_ext *ext) 389 struct ip_set_ext *ext)
384{ 390{
391 u64 fullmark;
385 if (tb[IPSET_ATTR_TIMEOUT]) { 392 if (tb[IPSET_ATTR_TIMEOUT]) {
386 if (!(set->extensions & IPSET_EXT_TIMEOUT)) 393 if (!(set->extensions & IPSET_EXT_TIMEOUT))
387 return -IPSET_ERR_TIMEOUT; 394 return -IPSET_ERR_TIMEOUT;
@@ -402,7 +409,25 @@ ip_set_get_extensions(struct ip_set *set, struct nlattr *tb[],
402 return -IPSET_ERR_COMMENT; 409 return -IPSET_ERR_COMMENT;
403 ext->comment = ip_set_comment_uget(tb[IPSET_ATTR_COMMENT]); 410 ext->comment = ip_set_comment_uget(tb[IPSET_ATTR_COMMENT]);
404 } 411 }
405 412 if (tb[IPSET_ATTR_SKBMARK]) {
413 if (!(set->extensions & IPSET_EXT_SKBINFO))
414 return -IPSET_ERR_SKBINFO;
415 fullmark = be64_to_cpu(nla_get_be64(tb[IPSET_ATTR_SKBMARK]));
416 ext->skbmark = fullmark >> 32;
417 ext->skbmarkmask = fullmark & 0xffffffff;
418 }
419 if (tb[IPSET_ATTR_SKBPRIO]) {
420 if (!(set->extensions & IPSET_EXT_SKBINFO))
421 return -IPSET_ERR_SKBINFO;
422 ext->skbprio = be32_to_cpu(nla_get_be32(
423 tb[IPSET_ATTR_SKBPRIO]));
424 }
425 if (tb[IPSET_ATTR_SKBQUEUE]) {
426 if (!(set->extensions & IPSET_EXT_SKBINFO))
427 return -IPSET_ERR_SKBINFO;
428 ext->skbqueue = be16_to_cpu(nla_get_be16(
429 tb[IPSET_ATTR_SKBQUEUE]));
430 }
406 return 0; 431 return 0;
407} 432}
408EXPORT_SYMBOL_GPL(ip_set_get_extensions); 433EXPORT_SYMBOL_GPL(ip_set_get_extensions);
@@ -1397,7 +1422,8 @@ call_ad(struct sock *ctnl, struct sk_buff *skb, struct ip_set *set,
1397 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb); 1422 struct nlmsghdr *rep, *nlh = nlmsg_hdr(skb);
1398 struct sk_buff *skb2; 1423 struct sk_buff *skb2;
1399 struct nlmsgerr *errmsg; 1424 struct nlmsgerr *errmsg;
1400 size_t payload = sizeof(*errmsg) + nlmsg_len(nlh); 1425 size_t payload = min(SIZE_MAX,
1426 sizeof(*errmsg) + nlmsg_len(nlh));
1401 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg)); 1427 int min_len = nlmsg_total_size(sizeof(struct nfgenmsg));
1402 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1]; 1428 struct nlattr *cda[IPSET_ATTR_CMD_MAX+1];
1403 struct nlattr *cmdattr; 1429 struct nlattr *cmdattr;
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h
index 8a38890cbe5e..fee7c64e4dd1 100644
--- a/net/netfilter/ipset/ip_set_hash_gen.h
+++ b/net/netfilter/ipset/ip_set_hash_gen.h
@@ -720,6 +720,8 @@ reuse_slot:
720 ip_set_init_counter(ext_counter(data, set), ext); 720 ip_set_init_counter(ext_counter(data, set), ext);
721 if (SET_WITH_COMMENT(set)) 721 if (SET_WITH_COMMENT(set))
722 ip_set_init_comment(ext_comment(data, set), ext); 722 ip_set_init_comment(ext_comment(data, set), ext);
723 if (SET_WITH_SKBINFO(set))
724 ip_set_init_skbinfo(ext_skbinfo(data, set), ext);
723 725
724out: 726out:
725 rcu_read_unlock_bh(); 727 rcu_read_unlock_bh();
@@ -797,6 +799,9 @@ mtype_data_match(struct mtype_elem *data, const struct ip_set_ext *ext,
797 if (SET_WITH_COUNTER(set)) 799 if (SET_WITH_COUNTER(set))
798 ip_set_update_counter(ext_counter(data, set), 800 ip_set_update_counter(ext_counter(data, set),
799 ext, mext, flags); 801 ext, mext, flags);
802 if (SET_WITH_SKBINFO(set))
803 ip_set_get_skbinfo(ext_skbinfo(data, set),
804 ext, mext, flags);
800 return mtype_do_data_match(data); 805 return mtype_do_data_match(data);
801} 806}
802 807
@@ -1049,8 +1054,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1049 struct HTYPE *h; 1054 struct HTYPE *h;
1050 struct htable *t; 1055 struct htable *t;
1051 1056
1057#ifndef IP_SET_PROTO_UNDEF
1052 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) 1058 if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6))
1053 return -IPSET_ERR_INVALID_FAMILY; 1059 return -IPSET_ERR_INVALID_FAMILY;
1060#endif
1054 1061
1055#ifdef IP_SET_HASH_WITH_MARKMASK 1062#ifdef IP_SET_HASH_WITH_MARKMASK
1056 markmask = 0xffffffff; 1063 markmask = 0xffffffff;
@@ -1132,25 +1139,32 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set,
1132 rcu_assign_pointer(h->table, t); 1139 rcu_assign_pointer(h->table, t);
1133 1140
1134 set->data = h; 1141 set->data = h;
1142#ifndef IP_SET_PROTO_UNDEF
1135 if (set->family == NFPROTO_IPV4) { 1143 if (set->family == NFPROTO_IPV4) {
1144#endif
1136 set->variant = &IPSET_TOKEN(HTYPE, 4_variant); 1145 set->variant = &IPSET_TOKEN(HTYPE, 4_variant);
1137 set->dsize = ip_set_elem_len(set, tb, 1146 set->dsize = ip_set_elem_len(set, tb,
1138 sizeof(struct IPSET_TOKEN(HTYPE, 4_elem))); 1147 sizeof(struct IPSET_TOKEN(HTYPE, 4_elem)));
1148#ifndef IP_SET_PROTO_UNDEF
1139 } else { 1149 } else {
1140 set->variant = &IPSET_TOKEN(HTYPE, 6_variant); 1150 set->variant = &IPSET_TOKEN(HTYPE, 6_variant);
1141 set->dsize = ip_set_elem_len(set, tb, 1151 set->dsize = ip_set_elem_len(set, tb,
1142 sizeof(struct IPSET_TOKEN(HTYPE, 6_elem))); 1152 sizeof(struct IPSET_TOKEN(HTYPE, 6_elem)));
1143 } 1153 }
1154#endif
1144 if (tb[IPSET_ATTR_TIMEOUT]) { 1155 if (tb[IPSET_ATTR_TIMEOUT]) {
1145 set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]); 1156 set->timeout = ip_set_timeout_uget(tb[IPSET_ATTR_TIMEOUT]);
1157#ifndef IP_SET_PROTO_UNDEF
1146 if (set->family == NFPROTO_IPV4) 1158 if (set->family == NFPROTO_IPV4)
1159#endif
1147 IPSET_TOKEN(HTYPE, 4_gc_init)(set, 1160 IPSET_TOKEN(HTYPE, 4_gc_init)(set,
1148 IPSET_TOKEN(HTYPE, 4_gc)); 1161 IPSET_TOKEN(HTYPE, 4_gc));
1162#ifndef IP_SET_PROTO_UNDEF
1149 else 1163 else
1150 IPSET_TOKEN(HTYPE, 6_gc_init)(set, 1164 IPSET_TOKEN(HTYPE, 6_gc_init)(set,
1151 IPSET_TOKEN(HTYPE, 6_gc)); 1165 IPSET_TOKEN(HTYPE, 6_gc));
1166#endif
1152 } 1167 }
1153
1154 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n", 1168 pr_debug("create %s hashsize %u (%u) maxelem %u: %p(%p)\n",
1155 set->name, jhash_size(t->htable_bits), 1169 set->name, jhash_size(t->htable_bits),
1156 t->htable_bits, h->maxelem, set->data, t); 1170 t->htable_bits, h->maxelem, set->data, t);
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c
index e52739938533..76959d79e9d1 100644
--- a/net/netfilter/ipset/ip_set_hash_ip.c
+++ b/net/netfilter/ipset/ip_set_hash_ip.c
@@ -26,7 +26,8 @@
26#define IPSET_TYPE_REV_MIN 0 26#define IPSET_TYPE_REV_MIN 0
27/* 1 Counters support */ 27/* 1 Counters support */
28/* 2 Comments support */ 28/* 2 Comments support */
29#define IPSET_TYPE_REV_MAX 3 /* Forceadd support */ 29/* 3 Forceadd support */
30#define IPSET_TYPE_REV_MAX 4 /* skbinfo support */
30 31
31MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -111,7 +112,10 @@ hash_ip4_uadt(struct ip_set *set, struct nlattr *tb[],
111 if (unlikely(!tb[IPSET_ATTR_IP] || 112 if (unlikely(!tb[IPSET_ATTR_IP] ||
112 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 113 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
113 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 114 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
114 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 115 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
116 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
117 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
118 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
115 return -IPSET_ERR_PROTOCOL; 119 return -IPSET_ERR_PROTOCOL;
116 120
117 if (tb[IPSET_ATTR_LINENO]) 121 if (tb[IPSET_ATTR_LINENO])
@@ -247,6 +251,9 @@ hash_ip6_uadt(struct ip_set *set, struct nlattr *tb[],
247 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 251 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
248 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 252 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
249 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 253 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
254 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
255 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
256 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE) ||
250 tb[IPSET_ATTR_IP_TO] || 257 tb[IPSET_ATTR_IP_TO] ||
251 tb[IPSET_ATTR_CIDR])) 258 tb[IPSET_ATTR_CIDR]))
252 return -IPSET_ERR_PROTOCOL; 259 return -IPSET_ERR_PROTOCOL;
@@ -295,6 +302,9 @@ static struct ip_set_type hash_ip_type __read_mostly = {
295 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 302 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
296 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 303 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
297 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 304 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
305 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
306 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
307 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
298 }, 308 },
299 .me = THIS_MODULE, 309 .me = THIS_MODULE,
300}; 310};
diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c
index 4eff0a297254..7abf9788cfa8 100644
--- a/net/netfilter/ipset/ip_set_hash_ipmark.c
+++ b/net/netfilter/ipset/ip_set_hash_ipmark.c
@@ -25,7 +25,8 @@
25#include <linux/netfilter/ipset/ip_set_hash.h> 25#include <linux/netfilter/ipset/ip_set_hash.h>
26 26
27#define IPSET_TYPE_REV_MIN 0 27#define IPSET_TYPE_REV_MIN 0
28#define IPSET_TYPE_REV_MAX 1 /* Forceadd support */ 28/* 1 Forceadd support */
29#define IPSET_TYPE_REV_MAX 2 /* skbinfo support */
29 30
30MODULE_LICENSE("GPL"); 31MODULE_LICENSE("GPL");
31MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>"); 32MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>");
@@ -113,7 +114,10 @@ hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[],
113 !ip_set_attr_netorder(tb, IPSET_ATTR_MARK) || 114 !ip_set_attr_netorder(tb, IPSET_ATTR_MARK) ||
114 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 115 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
115 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 116 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
116 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 117 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
118 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
119 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
120 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
117 return -IPSET_ERR_PROTOCOL; 121 return -IPSET_ERR_PROTOCOL;
118 122
119 if (tb[IPSET_ATTR_LINENO]) 123 if (tb[IPSET_ATTR_LINENO])
@@ -244,6 +248,9 @@ hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[],
244 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 248 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
245 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 249 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
246 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 250 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
251 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
252 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
253 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE) ||
247 tb[IPSET_ATTR_IP_TO] || 254 tb[IPSET_ATTR_IP_TO] ||
248 tb[IPSET_ATTR_CIDR])) 255 tb[IPSET_ATTR_CIDR]))
249 return -IPSET_ERR_PROTOCOL; 256 return -IPSET_ERR_PROTOCOL;
@@ -301,6 +308,9 @@ static struct ip_set_type hash_ipmark_type __read_mostly = {
301 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 308 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
302 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 309 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
303 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 310 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
311 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
312 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
313 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
304 }, 314 },
305 .me = THIS_MODULE, 315 .me = THIS_MODULE,
306}; 316};
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c
index f37a5ae8a5e0..dcbcceb9a52f 100644
--- a/net/netfilter/ipset/ip_set_hash_ipport.c
+++ b/net/netfilter/ipset/ip_set_hash_ipport.c
@@ -28,7 +28,8 @@
28/* 1 SCTP and UDPLITE support added */ 28/* 1 SCTP and UDPLITE support added */
29/* 2 Counters support added */ 29/* 2 Counters support added */
30/* 3 Comments support added */ 30/* 3 Comments support added */
31#define IPSET_TYPE_REV_MAX 4 /* Forceadd support added */ 31/* 4 Forceadd support added */
32#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 35MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -122,7 +123,10 @@ hash_ipport4_uadt(struct ip_set *set, struct nlattr *tb[],
122 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 123 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
123 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 124 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
124 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 125 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
125 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 126 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
127 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
128 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
129 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
126 return -IPSET_ERR_PROTOCOL; 130 return -IPSET_ERR_PROTOCOL;
127 131
128 if (tb[IPSET_ATTR_LINENO]) 132 if (tb[IPSET_ATTR_LINENO])
@@ -287,6 +291,9 @@ hash_ipport6_uadt(struct ip_set *set, struct nlattr *tb[],
287 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 291 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
288 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 292 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
289 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 293 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
294 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
295 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
296 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE) ||
290 tb[IPSET_ATTR_IP_TO] || 297 tb[IPSET_ATTR_IP_TO] ||
291 tb[IPSET_ATTR_CIDR])) 298 tb[IPSET_ATTR_CIDR]))
292 return -IPSET_ERR_PROTOCOL; 299 return -IPSET_ERR_PROTOCOL;
@@ -370,6 +377,9 @@ static struct ip_set_type hash_ipport_type __read_mostly = {
370 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 377 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
371 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 378 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
372 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 379 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
380 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
381 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
382 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
373 }, 383 },
374 .me = THIS_MODULE, 384 .me = THIS_MODULE,
375}; 385};
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c
index 41ef00eda874..7ef93fc887a1 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportip.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportip.c
@@ -28,7 +28,8 @@
28/* 1 SCTP and UDPLITE support added */ 28/* 1 SCTP and UDPLITE support added */
29/* 2 Counters support added */ 29/* 2 Counters support added */
30/* 3 Comments support added */ 30/* 3 Comments support added */
31#define IPSET_TYPE_REV_MAX 4 /* Forceadd support added */ 31/* 4 Forceadd support added */
32#define IPSET_TYPE_REV_MAX 5 /* skbinfo support added */
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 35MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -124,7 +125,10 @@ hash_ipportip4_uadt(struct ip_set *set, struct nlattr *tb[],
124 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) || 125 !ip_set_optattr_netorder(tb, IPSET_ATTR_PORT_TO) ||
125 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 126 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
126 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 127 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
127 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 128 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
129 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
130 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
131 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
128 return -IPSET_ERR_PROTOCOL; 132 return -IPSET_ERR_PROTOCOL;
129 133
130 if (tb[IPSET_ATTR_LINENO]) 134 if (tb[IPSET_ATTR_LINENO])
@@ -295,6 +299,9 @@ hash_ipportip6_uadt(struct ip_set *set, struct nlattr *tb[],
295 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 299 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
296 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 300 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
297 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 301 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
302 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
303 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
304 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE) ||
298 tb[IPSET_ATTR_IP_TO] || 305 tb[IPSET_ATTR_IP_TO] ||
299 tb[IPSET_ATTR_CIDR])) 306 tb[IPSET_ATTR_CIDR]))
300 return -IPSET_ERR_PROTOCOL; 307 return -IPSET_ERR_PROTOCOL;
@@ -382,6 +389,9 @@ static struct ip_set_type hash_ipportip_type __read_mostly = {
382 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 389 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
383 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 390 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
384 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 391 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
392 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
393 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
394 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
385 }, 395 },
386 .me = THIS_MODULE, 396 .me = THIS_MODULE,
387}; 397};
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c
index 7308d84f9277..b6012ad92781 100644
--- a/net/netfilter/ipset/ip_set_hash_ipportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c
@@ -30,7 +30,8 @@
30/* 3 nomatch flag support added */ 30/* 3 nomatch flag support added */
31/* 4 Counters support added */ 31/* 4 Counters support added */
32/* 5 Comments support added */ 32/* 5 Comments support added */
33#define IPSET_TYPE_REV_MAX 6 /* Forceadd support added */ 33/* 6 Forceadd support added */
34#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */
34 35
35MODULE_LICENSE("GPL"); 36MODULE_LICENSE("GPL");
36MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 37MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -179,7 +180,10 @@ hash_ipportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
179 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 180 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
180 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 181 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
181 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 182 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
182 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 183 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
184 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
185 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
186 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
183 return -IPSET_ERR_PROTOCOL; 187 return -IPSET_ERR_PROTOCOL;
184 188
185 if (tb[IPSET_ATTR_LINENO]) 189 if (tb[IPSET_ATTR_LINENO])
@@ -432,6 +436,9 @@ hash_ipportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
432 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 436 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
433 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 437 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
434 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || 438 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
439 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
440 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
441 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE) ||
435 tb[IPSET_ATTR_IP_TO] || 442 tb[IPSET_ATTR_IP_TO] ||
436 tb[IPSET_ATTR_CIDR])) 443 tb[IPSET_ATTR_CIDR]))
437 return -IPSET_ERR_PROTOCOL; 444 return -IPSET_ERR_PROTOCOL;
@@ -541,6 +548,9 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = {
541 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 548 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
542 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 549 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
543 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 550 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
551 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
552 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
553 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
544 }, 554 },
545 .me = THIS_MODULE, 555 .me = THIS_MODULE,
546}; 556};
diff --git a/net/netfilter/ipset/ip_set_hash_mac.c b/net/netfilter/ipset/ip_set_hash_mac.c
new file mode 100644
index 000000000000..65690b52a4d5
--- /dev/null
+++ b/net/netfilter/ipset/ip_set_hash_mac.c
@@ -0,0 +1,173 @@
1/* Copyright (C) 2014 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 as
5 * published by the Free Software Foundation.
6 */
7
8/* Kernel module implementing an IP set type: the hash:mac type */
9
10#include <linux/jhash.h>
11#include <linux/module.h>
12#include <linux/etherdevice.h>
13#include <linux/skbuff.h>
14#include <linux/errno.h>
15#include <linux/if_ether.h>
16#include <net/netlink.h>
17
18#include <linux/netfilter.h>
19#include <linux/netfilter/ipset/ip_set.h>
20#include <linux/netfilter/ipset/ip_set_hash.h>
21
22#define IPSET_TYPE_REV_MIN 0
23#define IPSET_TYPE_REV_MAX 0
24
25MODULE_LICENSE("GPL");
26MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
27IP_SET_MODULE_DESC("hash:mac", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX);
28MODULE_ALIAS("ip_set_hash:mac");
29
30/* Type specific function prefix */
31#define HTYPE hash_mac
32
33/* Member elements */
34struct hash_mac4_elem {
35 /* Zero valued IP addresses cannot be stored */
36 union {
37 unsigned char ether[ETH_ALEN];
38 __be32 foo[2];
39 };
40};
41
42/* Common functions */
43
44static inline bool
45hash_mac4_data_equal(const struct hash_mac4_elem *e1,
46 const struct hash_mac4_elem *e2,
47 u32 *multi)
48{
49 return ether_addr_equal(e1->ether, e2->ether);
50}
51
52static inline bool
53hash_mac4_data_list(struct sk_buff *skb, const struct hash_mac4_elem *e)
54{
55 return nla_put(skb, IPSET_ATTR_ETHER, ETH_ALEN, e->ether);
56}
57
58static inline void
59hash_mac4_data_next(struct hash_mac4_elem *next,
60 const struct hash_mac4_elem *e)
61{
62}
63
64#define MTYPE hash_mac4
65#define PF 4
66#define HOST_MASK 32
67#define IP_SET_EMIT_CREATE
68#define IP_SET_PROTO_UNDEF
69#include "ip_set_hash_gen.h"
70
71/* Zero valued element is not supported */
72static const unsigned char invalid_ether[ETH_ALEN] = { 0 };
73
74static int
75hash_mac4_kadt(struct ip_set *set, const struct sk_buff *skb,
76 const struct xt_action_param *par,
77 enum ipset_adt adt, struct ip_set_adt_opt *opt)
78{
79 ipset_adtfn adtfn = set->variant->adt[adt];
80 struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
81 struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set);
82
83 /* MAC can be src only */
84 if (!(opt->flags & IPSET_DIM_ONE_SRC))
85 return 0;
86
87 if (skb_mac_header(skb) < skb->head ||
88 (skb_mac_header(skb) + ETH_HLEN) > skb->data)
89 return -EINVAL;
90
91 memcpy(e.ether, eth_hdr(skb)->h_source, ETH_ALEN);
92 if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0)
93 return -EINVAL;
94 return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags);
95}
96
97static int
98hash_mac4_uadt(struct ip_set *set, struct nlattr *tb[],
99 enum ipset_adt adt, u32 *lineno, u32 flags, bool retried)
100{
101 ipset_adtfn adtfn = set->variant->adt[adt];
102 struct hash_mac4_elem e = { { .foo[0] = 0, .foo[1] = 0 } };
103 struct ip_set_ext ext = IP_SET_INIT_UEXT(set);
104 int ret;
105
106 if (unlikely(!tb[IPSET_ATTR_ETHER] ||
107 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
108 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
109 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
110 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
111 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
112 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
113 return -IPSET_ERR_PROTOCOL;
114
115 if (tb[IPSET_ATTR_LINENO])
116 *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]);
117
118 ret = ip_set_get_extensions(set, tb, &ext);
119 if (ret)
120 return ret;
121 memcpy(e.ether, nla_data(tb[IPSET_ATTR_ETHER]), ETH_ALEN);
122 if (memcmp(e.ether, invalid_ether, ETH_ALEN) == 0)
123 return -IPSET_ERR_HASH_ELEM;
124
125 return adtfn(set, &e, &ext, &ext, flags);
126}
127
128static struct ip_set_type hash_mac_type __read_mostly = {
129 .name = "hash:mac",
130 .protocol = IPSET_PROTOCOL,
131 .features = IPSET_TYPE_MAC,
132 .dimension = IPSET_DIM_ONE,
133 .family = NFPROTO_UNSPEC,
134 .revision_min = IPSET_TYPE_REV_MIN,
135 .revision_max = IPSET_TYPE_REV_MAX,
136 .create = hash_mac_create,
137 .create_policy = {
138 [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 },
139 [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 },
140 [IPSET_ATTR_PROBES] = { .type = NLA_U8 },
141 [IPSET_ATTR_RESIZE] = { .type = NLA_U8 },
142 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
143 [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 },
144 },
145 .adt_policy = {
146 [IPSET_ATTR_ETHER] = { .type = NLA_BINARY,
147 .len = ETH_ALEN },
148 [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 },
149 [IPSET_ATTR_LINENO] = { .type = NLA_U32 },
150 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
151 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
152 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
153 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
154 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
155 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
156 },
157 .me = THIS_MODULE,
158};
159
160static int __init
161hash_mac_init(void)
162{
163 return ip_set_type_register(&hash_mac_type);
164}
165
166static void __exit
167hash_mac_fini(void)
168{
169 ip_set_type_unregister(&hash_mac_type);
170}
171
172module_init(hash_mac_init);
173module_exit(hash_mac_fini);
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c
index 4c7d495783a3..6b3ac10ac2f1 100644
--- a/net/netfilter/ipset/ip_set_hash_net.c
+++ b/net/netfilter/ipset/ip_set_hash_net.c
@@ -27,7 +27,8 @@
27/* 2 nomatch flag support added */ 27/* 2 nomatch flag support added */
28/* 3 Counters support added */ 28/* 3 Counters support added */
29/* 4 Comments support added */ 29/* 4 Comments support added */
30#define IPSET_TYPE_REV_MAX 5 /* Forceadd support added */ 30/* 5 Forceadd support added */
31#define IPSET_TYPE_REV_MAX 6 /* skbinfo mapping support added */
31 32
32MODULE_LICENSE("GPL"); 33MODULE_LICENSE("GPL");
33MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -150,7 +151,10 @@ hash_net4_uadt(struct ip_set *set, struct nlattr *tb[],
150 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 151 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
151 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 152 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
152 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 153 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
153 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 154 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
155 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
156 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
157 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
154 return -IPSET_ERR_PROTOCOL; 158 return -IPSET_ERR_PROTOCOL;
155 159
156 if (tb[IPSET_ATTR_LINENO]) 160 if (tb[IPSET_ATTR_LINENO])
@@ -318,7 +322,10 @@ hash_net6_uadt(struct ip_set *set, struct nlattr *tb[],
318 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 322 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
319 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 323 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
320 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 324 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
321 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 325 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
326 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
327 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
328 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
322 return -IPSET_ERR_PROTOCOL; 329 return -IPSET_ERR_PROTOCOL;
323 if (unlikely(tb[IPSET_ATTR_IP_TO])) 330 if (unlikely(tb[IPSET_ATTR_IP_TO]))
324 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 331 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
@@ -377,6 +384,9 @@ static struct ip_set_type hash_net_type __read_mostly = {
377 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 384 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
378 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 385 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
379 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 386 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
387 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
388 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
389 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
380 }, 390 },
381 .me = THIS_MODULE, 391 .me = THIS_MODULE,
382}; 392};
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c
index db2606805b35..03cdb69ac9bf 100644
--- a/net/netfilter/ipset/ip_set_hash_netiface.c
+++ b/net/netfilter/ipset/ip_set_hash_netiface.c
@@ -28,7 +28,8 @@
28/* 2 /0 support added */ 28/* 2 /0 support added */
29/* 3 Counters support added */ 29/* 3 Counters support added */
30/* 4 Comments support added */ 30/* 4 Comments support added */
31#define IPSET_TYPE_REV_MAX 5 /* Forceadd support added */ 31/* 5 Forceadd support added */
32#define IPSET_TYPE_REV_MAX 6 /* skbinfo support added */
32 33
33MODULE_LICENSE("GPL"); 34MODULE_LICENSE("GPL");
34MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 35MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -281,7 +282,10 @@ hash_netiface4_uadt(struct ip_set *set, struct nlattr *tb[],
281 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 282 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
282 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 283 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
283 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 284 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
284 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 285 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
286 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
287 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
288 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
285 return -IPSET_ERR_PROTOCOL; 289 return -IPSET_ERR_PROTOCOL;
286 290
287 if (tb[IPSET_ATTR_LINENO]) 291 if (tb[IPSET_ATTR_LINENO])
@@ -514,7 +518,10 @@ hash_netiface6_uadt(struct ip_set *set, struct nlattr *tb[],
514 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 518 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
515 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 519 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
516 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 520 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
517 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 521 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
522 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
523 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
524 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
518 return -IPSET_ERR_PROTOCOL; 525 return -IPSET_ERR_PROTOCOL;
519 if (unlikely(tb[IPSET_ATTR_IP_TO])) 526 if (unlikely(tb[IPSET_ATTR_IP_TO]))
520 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 527 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
@@ -590,6 +597,9 @@ static struct ip_set_type hash_netiface_type __read_mostly = {
590 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 597 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
591 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 598 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
592 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 599 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
600 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
601 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
602 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
593 }, 603 },
594 .me = THIS_MODULE, 604 .me = THIS_MODULE,
595}; 605};
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c
index 96b131366e7b..da00284b3571 100644
--- a/net/netfilter/ipset/ip_set_hash_netnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netnet.c
@@ -24,7 +24,8 @@
24#include <linux/netfilter/ipset/ip_set_hash.h> 24#include <linux/netfilter/ipset/ip_set_hash.h>
25 25
26#define IPSET_TYPE_REV_MIN 0 26#define IPSET_TYPE_REV_MIN 0
27#define IPSET_TYPE_REV_MAX 1 /* Forceadd support added */ 27/* 1 Forceadd support added */
28#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
28 29
29MODULE_LICENSE("GPL"); 30MODULE_LICENSE("GPL");
30MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); 31MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
@@ -171,7 +172,10 @@ hash_netnet4_uadt(struct ip_set *set, struct nlattr *tb[],
171 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 172 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
172 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 173 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
173 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 174 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
174 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 175 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
176 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
177 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
178 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
175 return -IPSET_ERR_PROTOCOL; 179 return -IPSET_ERR_PROTOCOL;
176 180
177 if (tb[IPSET_ATTR_LINENO]) 181 if (tb[IPSET_ATTR_LINENO])
@@ -394,7 +398,10 @@ hash_netnet6_uadt(struct ip_set *set, struct nlattr *tb[],
394 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 398 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
395 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 399 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
396 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 400 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
397 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 401 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
402 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
403 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
404 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
398 return -IPSET_ERR_PROTOCOL; 405 return -IPSET_ERR_PROTOCOL;
399 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) 406 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO]))
400 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 407 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
@@ -462,6 +469,9 @@ static struct ip_set_type hash_netnet_type __read_mostly = {
462 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 469 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
463 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 470 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
464 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 471 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
472 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
473 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
474 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
465 }, 475 },
466 .me = THIS_MODULE, 476 .me = THIS_MODULE,
467}; 477};
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c
index 1c645fbd09c7..c0ddb58d19dc 100644
--- a/net/netfilter/ipset/ip_set_hash_netport.c
+++ b/net/netfilter/ipset/ip_set_hash_netport.c
@@ -29,7 +29,8 @@
29/* 3 nomatch flag support added */ 29/* 3 nomatch flag support added */
30/* 4 Counters support added */ 30/* 4 Counters support added */
31/* 5 Comments support added */ 31/* 5 Comments support added */
32#define IPSET_TYPE_REV_MAX 6 /* Forceadd support added */ 32/* 6 Forceadd support added */
33#define IPSET_TYPE_REV_MAX 7 /* skbinfo support added */
33 34
34MODULE_LICENSE("GPL"); 35MODULE_LICENSE("GPL");
35MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 36MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -172,7 +173,10 @@ hash_netport4_uadt(struct ip_set *set, struct nlattr *tb[],
172 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 173 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
173 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 174 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
174 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 175 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
175 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 176 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
177 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
178 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
179 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
176 return -IPSET_ERR_PROTOCOL; 180 return -IPSET_ERR_PROTOCOL;
177 181
178 if (tb[IPSET_ATTR_LINENO]) 182 if (tb[IPSET_ATTR_LINENO])
@@ -389,7 +393,10 @@ hash_netport6_uadt(struct ip_set *set, struct nlattr *tb[],
389 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 393 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
390 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 394 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
391 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 395 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
392 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 396 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
397 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
398 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
399 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
393 return -IPSET_ERR_PROTOCOL; 400 return -IPSET_ERR_PROTOCOL;
394 if (unlikely(tb[IPSET_ATTR_IP_TO])) 401 if (unlikely(tb[IPSET_ATTR_IP_TO]))
395 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 402 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
@@ -489,6 +496,9 @@ static struct ip_set_type hash_netport_type __read_mostly = {
489 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 496 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
490 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 497 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
491 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 498 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
499 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
500 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
501 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
492 }, 502 },
493 .me = THIS_MODULE, 503 .me = THIS_MODULE,
494}; 504};
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c
index 2f0034347189..b8053d675fc3 100644
--- a/net/netfilter/ipset/ip_set_hash_netportnet.c
+++ b/net/netfilter/ipset/ip_set_hash_netportnet.c
@@ -26,7 +26,8 @@
26 26
27#define IPSET_TYPE_REV_MIN 0 27#define IPSET_TYPE_REV_MIN 0
28/* 0 Comments support added */ 28/* 0 Comments support added */
29#define IPSET_TYPE_REV_MAX 1 /* Forceadd support added */ 29/* 1 Forceadd support added */
30#define IPSET_TYPE_REV_MAX 2 /* skbinfo support added */
30 31
31MODULE_LICENSE("GPL"); 32MODULE_LICENSE("GPL");
32MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); 33MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>");
@@ -189,7 +190,10 @@ hash_netportnet4_uadt(struct ip_set *set, struct nlattr *tb[],
189 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 190 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
190 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 191 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
191 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 192 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
192 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 193 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
194 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
195 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
196 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
193 return -IPSET_ERR_PROTOCOL; 197 return -IPSET_ERR_PROTOCOL;
194 198
195 if (tb[IPSET_ATTR_LINENO]) 199 if (tb[IPSET_ATTR_LINENO])
@@ -460,7 +464,10 @@ hash_netportnet6_uadt(struct ip_set *set, struct nlattr *tb[],
460 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 464 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
461 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 465 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
462 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 466 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
463 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 467 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
468 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
469 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
470 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
464 return -IPSET_ERR_PROTOCOL; 471 return -IPSET_ERR_PROTOCOL;
465 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO])) 472 if (unlikely(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_IP2_TO]))
466 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED; 473 return -IPSET_ERR_HASH_RANGE_UNSUPPORTED;
@@ -569,6 +576,9 @@ static struct ip_set_type hash_netportnet_type __read_mostly = {
569 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 576 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
570 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 577 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
571 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 578 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
579 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
580 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
581 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
572 }, 582 },
573 .me = THIS_MODULE, 583 .me = THIS_MODULE,
574}; 584};
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index f87adbad6076..f8f682806e36 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -17,7 +17,8 @@
17 17
18#define IPSET_TYPE_REV_MIN 0 18#define IPSET_TYPE_REV_MIN 0
19/* 1 Counters support added */ 19/* 1 Counters support added */
20#define IPSET_TYPE_REV_MAX 2 /* Comments support added */ 20/* 2 Comments support added */
21#define IPSET_TYPE_REV_MAX 3 /* skbinfo support added */
21 22
22MODULE_LICENSE("GPL"); 23MODULE_LICENSE("GPL");
23MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); 24MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>");
@@ -73,6 +74,10 @@ list_set_ktest(struct ip_set *set, const struct sk_buff *skb,
73 ip_set_update_counter(ext_counter(e, set), 74 ip_set_update_counter(ext_counter(e, set),
74 ext, &opt->ext, 75 ext, &opt->ext,
75 cmdflags); 76 cmdflags);
77 if (SET_WITH_SKBINFO(set))
78 ip_set_get_skbinfo(ext_skbinfo(e, set),
79 ext, &opt->ext,
80 cmdflags);
76 return ret; 81 return ret;
77 } 82 }
78 } 83 }
@@ -197,6 +202,8 @@ list_set_add(struct ip_set *set, u32 i, struct set_adt_elem *d,
197 ip_set_init_counter(ext_counter(e, set), ext); 202 ip_set_init_counter(ext_counter(e, set), ext);
198 if (SET_WITH_COMMENT(set)) 203 if (SET_WITH_COMMENT(set))
199 ip_set_init_comment(ext_comment(e, set), ext); 204 ip_set_init_comment(ext_comment(e, set), ext);
205 if (SET_WITH_SKBINFO(set))
206 ip_set_init_skbinfo(ext_skbinfo(e, set), ext);
200 return 0; 207 return 0;
201} 208}
202 209
@@ -307,6 +314,8 @@ list_set_uadd(struct ip_set *set, void *value, const struct ip_set_ext *ext,
307 ip_set_init_counter(ext_counter(e, set), ext); 314 ip_set_init_counter(ext_counter(e, set), ext);
308 if (SET_WITH_COMMENT(set)) 315 if (SET_WITH_COMMENT(set))
309 ip_set_init_comment(ext_comment(e, set), ext); 316 ip_set_init_comment(ext_comment(e, set), ext);
317 if (SET_WITH_SKBINFO(set))
318 ip_set_init_skbinfo(ext_skbinfo(e, set), ext);
310 /* Set is already added to the list */ 319 /* Set is already added to the list */
311 ip_set_put_byindex(map->net, d->id); 320 ip_set_put_byindex(map->net, d->id);
312 return 0; 321 return 0;
@@ -378,7 +387,10 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[],
378 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || 387 !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) ||
379 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) || 388 !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS) ||
380 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || 389 !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) ||
381 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) 390 !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) ||
391 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBMARK) ||
392 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBPRIO) ||
393 !ip_set_optattr_netorder(tb, IPSET_ATTR_SKBQUEUE)))
382 return -IPSET_ERR_PROTOCOL; 394 return -IPSET_ERR_PROTOCOL;
383 395
384 if (tb[IPSET_ATTR_LINENO]) 396 if (tb[IPSET_ATTR_LINENO])
@@ -667,6 +679,9 @@ static struct ip_set_type list_set_type __read_mostly = {
667 [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, 679 [IPSET_ATTR_BYTES] = { .type = NLA_U64 },
668 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, 680 [IPSET_ATTR_PACKETS] = { .type = NLA_U64 },
669 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, 681 [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING },
682 [IPSET_ATTR_SKBMARK] = { .type = NLA_U64 },
683 [IPSET_ATTR_SKBPRIO] = { .type = NLA_U32 },
684 [IPSET_ATTR_SKBQUEUE] = { .type = NLA_U16 },
670 }, 685 },
671 .me = THIS_MODULE, 686 .me = THIS_MODULE,
672}; 687};
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig
index 0c3b1670b0d1..3b6929dec748 100644
--- a/net/netfilter/ipvs/Kconfig
+++ b/net/netfilter/ipvs/Kconfig
@@ -152,6 +152,16 @@ config IP_VS_WLC
152 If you want to compile it in kernel, say Y. To compile it as a 152 If you want to compile it in kernel, say Y. To compile it as a
153 module, choose M here. If unsure, say N. 153 module, choose M here. If unsure, say N.
154 154
155config IP_VS_FO
156 tristate "weighted failover scheduling"
157 ---help---
158 The weighted failover scheduling algorithm directs network
159 connections to the server with the highest weight that is
160 currently available.
161
162 If you want to compile it in kernel, say Y. To compile it as a
163 module, choose M here. If unsure, say N.
164
155config IP_VS_LBLC 165config IP_VS_LBLC
156 tristate "locality-based least-connection scheduling" 166 tristate "locality-based least-connection scheduling"
157 ---help--- 167 ---help---
diff --git a/net/netfilter/ipvs/Makefile b/net/netfilter/ipvs/Makefile
index 34ee602ddb66..38b2723b2e3d 100644
--- a/net/netfilter/ipvs/Makefile
+++ b/net/netfilter/ipvs/Makefile
@@ -26,6 +26,7 @@ obj-$(CONFIG_IP_VS_RR) += ip_vs_rr.o
26obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o 26obj-$(CONFIG_IP_VS_WRR) += ip_vs_wrr.o
27obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o 27obj-$(CONFIG_IP_VS_LC) += ip_vs_lc.o
28obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o 28obj-$(CONFIG_IP_VS_WLC) += ip_vs_wlc.o
29obj-$(CONFIG_IP_VS_FO) += ip_vs_fo.o
29obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o 30obj-$(CONFIG_IP_VS_LBLC) += ip_vs_lblc.o
30obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o 31obj-$(CONFIG_IP_VS_LBLCR) += ip_vs_lblcr.o
31obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o 32obj-$(CONFIG_IP_VS_DH) += ip_vs_dh.o
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 610e19c0e13f..b0f7b626b56d 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -27,6 +27,7 @@
27 27
28#include <linux/interrupt.h> 28#include <linux/interrupt.h>
29#include <linux/in.h> 29#include <linux/in.h>
30#include <linux/inet.h>
30#include <linux/net.h> 31#include <linux/net.h>
31#include <linux/kernel.h> 32#include <linux/kernel.h>
32#include <linux/module.h> 33#include <linux/module.h>
@@ -77,6 +78,13 @@ static unsigned int ip_vs_conn_rnd __read_mostly;
77#define CT_LOCKARRAY_SIZE (1<<CT_LOCKARRAY_BITS) 78#define CT_LOCKARRAY_SIZE (1<<CT_LOCKARRAY_BITS)
78#define CT_LOCKARRAY_MASK (CT_LOCKARRAY_SIZE-1) 79#define CT_LOCKARRAY_MASK (CT_LOCKARRAY_SIZE-1)
79 80
81/* We need an addrstrlen that works with or without v6 */
82#ifdef CONFIG_IP_VS_IPV6
83#define IP_VS_ADDRSTRLEN INET6_ADDRSTRLEN
84#else
85#define IP_VS_ADDRSTRLEN (8+1)
86#endif
87
80struct ip_vs_aligned_lock 88struct ip_vs_aligned_lock
81{ 89{
82 spinlock_t l; 90 spinlock_t l;
@@ -488,7 +496,12 @@ static inline void ip_vs_bind_xmit(struct ip_vs_conn *cp)
488 break; 496 break;
489 497
490 case IP_VS_CONN_F_TUNNEL: 498 case IP_VS_CONN_F_TUNNEL:
491 cp->packet_xmit = ip_vs_tunnel_xmit; 499#ifdef CONFIG_IP_VS_IPV6
500 if (cp->daf == AF_INET6)
501 cp->packet_xmit = ip_vs_tunnel_xmit_v6;
502 else
503#endif
504 cp->packet_xmit = ip_vs_tunnel_xmit;
492 break; 505 break;
493 506
494 case IP_VS_CONN_F_DROUTE: 507 case IP_VS_CONN_F_DROUTE:
@@ -514,7 +527,10 @@ static inline void ip_vs_bind_xmit_v6(struct ip_vs_conn *cp)
514 break; 527 break;
515 528
516 case IP_VS_CONN_F_TUNNEL: 529 case IP_VS_CONN_F_TUNNEL:
517 cp->packet_xmit = ip_vs_tunnel_xmit_v6; 530 if (cp->daf == AF_INET6)
531 cp->packet_xmit = ip_vs_tunnel_xmit_v6;
532 else
533 cp->packet_xmit = ip_vs_tunnel_xmit;
518 break; 534 break;
519 535
520 case IP_VS_CONN_F_DROUTE: 536 case IP_VS_CONN_F_DROUTE:
@@ -580,7 +596,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest)
580 ip_vs_proto_name(cp->protocol), 596 ip_vs_proto_name(cp->protocol),
581 IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), 597 IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
582 IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), 598 IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
583 IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport), 599 IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
584 ip_vs_fwd_tag(cp), cp->state, 600 ip_vs_fwd_tag(cp), cp->state,
585 cp->flags, atomic_read(&cp->refcnt), 601 cp->flags, atomic_read(&cp->refcnt),
586 atomic_read(&dest->refcnt)); 602 atomic_read(&dest->refcnt));
@@ -616,7 +632,13 @@ void ip_vs_try_bind_dest(struct ip_vs_conn *cp)
616 struct ip_vs_dest *dest; 632 struct ip_vs_dest *dest;
617 633
618 rcu_read_lock(); 634 rcu_read_lock();
619 dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, &cp->daddr, 635
636 /* This function is only invoked by the synchronization code. We do
637 * not currently support heterogeneous pools with synchronization,
638 * so we can make the assumption that the svc_af is the same as the
639 * dest_af
640 */
641 dest = ip_vs_find_dest(ip_vs_conn_net(cp), cp->af, cp->af, &cp->daddr,
620 cp->dport, &cp->vaddr, cp->vport, 642 cp->dport, &cp->vaddr, cp->vport,
621 cp->protocol, cp->fwmark, cp->flags); 643 cp->protocol, cp->fwmark, cp->flags);
622 if (dest) { 644 if (dest) {
@@ -671,7 +693,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp)
671 ip_vs_proto_name(cp->protocol), 693 ip_vs_proto_name(cp->protocol),
672 IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport), 694 IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
673 IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport), 695 IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
674 IP_VS_DBG_ADDR(cp->af, &cp->daddr), ntohs(cp->dport), 696 IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
675 ip_vs_fwd_tag(cp), cp->state, 697 ip_vs_fwd_tag(cp), cp->state,
676 cp->flags, atomic_read(&cp->refcnt), 698 cp->flags, atomic_read(&cp->refcnt),
677 atomic_read(&dest->refcnt)); 699 atomic_read(&dest->refcnt));
@@ -740,7 +762,7 @@ int ip_vs_check_template(struct ip_vs_conn *ct)
740 ntohs(ct->cport), 762 ntohs(ct->cport),
741 IP_VS_DBG_ADDR(ct->af, &ct->vaddr), 763 IP_VS_DBG_ADDR(ct->af, &ct->vaddr),
742 ntohs(ct->vport), 764 ntohs(ct->vport),
743 IP_VS_DBG_ADDR(ct->af, &ct->daddr), 765 IP_VS_DBG_ADDR(ct->daf, &ct->daddr),
744 ntohs(ct->dport)); 766 ntohs(ct->dport));
745 767
746 /* 768 /*
@@ -848,7 +870,7 @@ void ip_vs_conn_expire_now(struct ip_vs_conn *cp)
848 * Create a new connection entry and hash it into the ip_vs_conn_tab 870 * Create a new connection entry and hash it into the ip_vs_conn_tab
849 */ 871 */
850struct ip_vs_conn * 872struct ip_vs_conn *
851ip_vs_conn_new(const struct ip_vs_conn_param *p, 873ip_vs_conn_new(const struct ip_vs_conn_param *p, int dest_af,
852 const union nf_inet_addr *daddr, __be16 dport, unsigned int flags, 874 const union nf_inet_addr *daddr, __be16 dport, unsigned int flags,
853 struct ip_vs_dest *dest, __u32 fwmark) 875 struct ip_vs_dest *dest, __u32 fwmark)
854{ 876{
@@ -867,6 +889,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
867 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp); 889 setup_timer(&cp->timer, ip_vs_conn_expire, (unsigned long)cp);
868 ip_vs_conn_net_set(cp, p->net); 890 ip_vs_conn_net_set(cp, p->net);
869 cp->af = p->af; 891 cp->af = p->af;
892 cp->daf = dest_af;
870 cp->protocol = p->protocol; 893 cp->protocol = p->protocol;
871 ip_vs_addr_set(p->af, &cp->caddr, p->caddr); 894 ip_vs_addr_set(p->af, &cp->caddr, p->caddr);
872 cp->cport = p->cport; 895 cp->cport = p->cport;
@@ -874,7 +897,7 @@ ip_vs_conn_new(const struct ip_vs_conn_param *p,
874 ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af, 897 ip_vs_addr_set(p->protocol == IPPROTO_IP ? AF_UNSPEC : p->af,
875 &cp->vaddr, p->vaddr); 898 &cp->vaddr, p->vaddr);
876 cp->vport = p->vport; 899 cp->vport = p->vport;
877 ip_vs_addr_set(p->af, &cp->daddr, daddr); 900 ip_vs_addr_set(cp->daf, &cp->daddr, daddr);
878 cp->dport = dport; 901 cp->dport = dport;
879 cp->flags = flags; 902 cp->flags = flags;
880 cp->fwmark = fwmark; 903 cp->fwmark = fwmark;
@@ -1036,6 +1059,7 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
1036 struct net *net = seq_file_net(seq); 1059 struct net *net = seq_file_net(seq);
1037 char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3]; 1060 char pe_data[IP_VS_PENAME_MAXLEN + IP_VS_PEDATA_MAXLEN + 3];
1038 size_t len = 0; 1061 size_t len = 0;
1062 char dbuf[IP_VS_ADDRSTRLEN];
1039 1063
1040 if (!ip_vs_conn_net_eq(cp, net)) 1064 if (!ip_vs_conn_net_eq(cp, net))
1041 return 0; 1065 return 0;
@@ -1050,24 +1074,32 @@ static int ip_vs_conn_seq_show(struct seq_file *seq, void *v)
1050 pe_data[len] = '\0'; 1074 pe_data[len] = '\0';
1051 1075
1052#ifdef CONFIG_IP_VS_IPV6 1076#ifdef CONFIG_IP_VS_IPV6
1077 if (cp->daf == AF_INET6)
1078 snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
1079 else
1080#endif
1081 snprintf(dbuf, sizeof(dbuf), "%08X",
1082 ntohl(cp->daddr.ip));
1083
1084#ifdef CONFIG_IP_VS_IPV6
1053 if (cp->af == AF_INET6) 1085 if (cp->af == AF_INET6)
1054 seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X " 1086 seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
1055 "%pI6 %04X %-11s %7lu%s\n", 1087 "%s %04X %-11s %7lu%s\n",
1056 ip_vs_proto_name(cp->protocol), 1088 ip_vs_proto_name(cp->protocol),
1057 &cp->caddr.in6, ntohs(cp->cport), 1089 &cp->caddr.in6, ntohs(cp->cport),
1058 &cp->vaddr.in6, ntohs(cp->vport), 1090 &cp->vaddr.in6, ntohs(cp->vport),
1059 &cp->daddr.in6, ntohs(cp->dport), 1091 dbuf, ntohs(cp->dport),
1060 ip_vs_state_name(cp->protocol, cp->state), 1092 ip_vs_state_name(cp->protocol, cp->state),
1061 (cp->timer.expires-jiffies)/HZ, pe_data); 1093 (cp->timer.expires-jiffies)/HZ, pe_data);
1062 else 1094 else
1063#endif 1095#endif
1064 seq_printf(seq, 1096 seq_printf(seq,
1065 "%-3s %08X %04X %08X %04X" 1097 "%-3s %08X %04X %08X %04X"
1066 " %08X %04X %-11s %7lu%s\n", 1098 " %s %04X %-11s %7lu%s\n",
1067 ip_vs_proto_name(cp->protocol), 1099 ip_vs_proto_name(cp->protocol),
1068 ntohl(cp->caddr.ip), ntohs(cp->cport), 1100 ntohl(cp->caddr.ip), ntohs(cp->cport),
1069 ntohl(cp->vaddr.ip), ntohs(cp->vport), 1101 ntohl(cp->vaddr.ip), ntohs(cp->vport),
1070 ntohl(cp->daddr.ip), ntohs(cp->dport), 1102 dbuf, ntohs(cp->dport),
1071 ip_vs_state_name(cp->protocol, cp->state), 1103 ip_vs_state_name(cp->protocol, cp->state),
1072 (cp->timer.expires-jiffies)/HZ, pe_data); 1104 (cp->timer.expires-jiffies)/HZ, pe_data);
1073 } 1105 }
@@ -1105,6 +1137,7 @@ static const char *ip_vs_origin_name(unsigned int flags)
1105 1137
1106static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v) 1138static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
1107{ 1139{
1140 char dbuf[IP_VS_ADDRSTRLEN];
1108 1141
1109 if (v == SEQ_START_TOKEN) 1142 if (v == SEQ_START_TOKEN)
1110 seq_puts(seq, 1143 seq_puts(seq,
@@ -1117,12 +1150,21 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
1117 return 0; 1150 return 0;
1118 1151
1119#ifdef CONFIG_IP_VS_IPV6 1152#ifdef CONFIG_IP_VS_IPV6
1153 if (cp->daf == AF_INET6)
1154 snprintf(dbuf, sizeof(dbuf), "%pI6", &cp->daddr.in6);
1155 else
1156#endif
1157 snprintf(dbuf, sizeof(dbuf), "%08X",
1158 ntohl(cp->daddr.ip));
1159
1160#ifdef CONFIG_IP_VS_IPV6
1120 if (cp->af == AF_INET6) 1161 if (cp->af == AF_INET6)
1121 seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X %pI6 %04X %-11s %-6s %7lu\n", 1162 seq_printf(seq, "%-3s %pI6 %04X %pI6 %04X "
1163 "%s %04X %-11s %-6s %7lu\n",
1122 ip_vs_proto_name(cp->protocol), 1164 ip_vs_proto_name(cp->protocol),
1123 &cp->caddr.in6, ntohs(cp->cport), 1165 &cp->caddr.in6, ntohs(cp->cport),
1124 &cp->vaddr.in6, ntohs(cp->vport), 1166 &cp->vaddr.in6, ntohs(cp->vport),
1125 &cp->daddr.in6, ntohs(cp->dport), 1167 dbuf, ntohs(cp->dport),
1126 ip_vs_state_name(cp->protocol, cp->state), 1168 ip_vs_state_name(cp->protocol, cp->state),
1127 ip_vs_origin_name(cp->flags), 1169 ip_vs_origin_name(cp->flags),
1128 (cp->timer.expires-jiffies)/HZ); 1170 (cp->timer.expires-jiffies)/HZ);
@@ -1130,11 +1172,11 @@ static int ip_vs_conn_sync_seq_show(struct seq_file *seq, void *v)
1130#endif 1172#endif
1131 seq_printf(seq, 1173 seq_printf(seq,
1132 "%-3s %08X %04X %08X %04X " 1174 "%-3s %08X %04X %08X %04X "
1133 "%08X %04X %-11s %-6s %7lu\n", 1175 "%s %04X %-11s %-6s %7lu\n",
1134 ip_vs_proto_name(cp->protocol), 1176 ip_vs_proto_name(cp->protocol),
1135 ntohl(cp->caddr.ip), ntohs(cp->cport), 1177 ntohl(cp->caddr.ip), ntohs(cp->cport),
1136 ntohl(cp->vaddr.ip), ntohs(cp->vport), 1178 ntohl(cp->vaddr.ip), ntohs(cp->vport),
1137 ntohl(cp->daddr.ip), ntohs(cp->dport), 1179 dbuf, ntohs(cp->dport),
1138 ip_vs_state_name(cp->protocol, cp->state), 1180 ip_vs_state_name(cp->protocol, cp->state),
1139 ip_vs_origin_name(cp->flags), 1181 ip_vs_origin_name(cp->flags),
1140 (cp->timer.expires-jiffies)/HZ); 1182 (cp->timer.expires-jiffies)/HZ);
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c
index 5c34e8d42e01..990decba1fe4 100644
--- a/net/netfilter/ipvs/ip_vs_core.c
+++ b/net/netfilter/ipvs/ip_vs_core.c
@@ -328,7 +328,7 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
328 * This adds param.pe_data to the template, 328 * This adds param.pe_data to the template,
329 * and thus param.pe_data will be destroyed 329 * and thus param.pe_data will be destroyed
330 * when the template expires */ 330 * when the template expires */
331 ct = ip_vs_conn_new(&param, &dest->addr, dport, 331 ct = ip_vs_conn_new(&param, dest->af, &dest->addr, dport,
332 IP_VS_CONN_F_TEMPLATE, dest, skb->mark); 332 IP_VS_CONN_F_TEMPLATE, dest, skb->mark);
333 if (ct == NULL) { 333 if (ct == NULL) {
334 kfree(param.pe_data); 334 kfree(param.pe_data);
@@ -357,7 +357,8 @@ ip_vs_sched_persist(struct ip_vs_service *svc,
357 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr, 357 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, &iph->saddr,
358 src_port, &iph->daddr, dst_port, &param); 358 src_port, &iph->daddr, dst_port, &param);
359 359
360 cp = ip_vs_conn_new(&param, &dest->addr, dport, flags, dest, skb->mark); 360 cp = ip_vs_conn_new(&param, dest->af, &dest->addr, dport, flags, dest,
361 skb->mark);
361 if (cp == NULL) { 362 if (cp == NULL) {
362 ip_vs_conn_put(ct); 363 ip_vs_conn_put(ct);
363 *ignored = -1; 364 *ignored = -1;
@@ -479,7 +480,7 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
479 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, 480 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
480 &iph->saddr, pptr[0], &iph->daddr, 481 &iph->saddr, pptr[0], &iph->daddr,
481 pptr[1], &p); 482 pptr[1], &p);
482 cp = ip_vs_conn_new(&p, &dest->addr, 483 cp = ip_vs_conn_new(&p, dest->af, &dest->addr,
483 dest->port ? dest->port : pptr[1], 484 dest->port ? dest->port : pptr[1],
484 flags, dest, skb->mark); 485 flags, dest, skb->mark);
485 if (!cp) { 486 if (!cp) {
@@ -491,9 +492,9 @@ ip_vs_schedule(struct ip_vs_service *svc, struct sk_buff *skb,
491 IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u " 492 IP_VS_DBG_BUF(6, "Schedule fwd:%c c:%s:%u v:%s:%u "
492 "d:%s:%u conn->flags:%X conn->refcnt:%d\n", 493 "d:%s:%u conn->flags:%X conn->refcnt:%d\n",
493 ip_vs_fwd_tag(cp), 494 ip_vs_fwd_tag(cp),
494 IP_VS_DBG_ADDR(svc->af, &cp->caddr), ntohs(cp->cport), 495 IP_VS_DBG_ADDR(cp->af, &cp->caddr), ntohs(cp->cport),
495 IP_VS_DBG_ADDR(svc->af, &cp->vaddr), ntohs(cp->vport), 496 IP_VS_DBG_ADDR(cp->af, &cp->vaddr), ntohs(cp->vport),
496 IP_VS_DBG_ADDR(svc->af, &cp->daddr), ntohs(cp->dport), 497 IP_VS_DBG_ADDR(cp->daf, &cp->daddr), ntohs(cp->dport),
497 cp->flags, atomic_read(&cp->refcnt)); 498 cp->flags, atomic_read(&cp->refcnt));
498 499
499 ip_vs_conn_stats(cp, svc); 500 ip_vs_conn_stats(cp, svc);
@@ -550,7 +551,7 @@ int ip_vs_leave(struct ip_vs_service *svc, struct sk_buff *skb,
550 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol, 551 ip_vs_conn_fill_param(svc->net, svc->af, iph->protocol,
551 &iph->saddr, pptr[0], 552 &iph->saddr, pptr[0],
552 &iph->daddr, pptr[1], &p); 553 &iph->daddr, pptr[1], &p);
553 cp = ip_vs_conn_new(&p, &daddr, 0, 554 cp = ip_vs_conn_new(&p, svc->af, &daddr, 0,
554 IP_VS_CONN_F_BYPASS | flags, 555 IP_VS_CONN_F_BYPASS | flags,
555 NULL, skb->mark); 556 NULL, skb->mark);
556 if (!cp) 557 if (!cp)
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c
index bd2b208ba56c..ac7ba689efe7 100644
--- a/net/netfilter/ipvs/ip_vs_ctl.c
+++ b/net/netfilter/ipvs/ip_vs_ctl.c
@@ -574,8 +574,8 @@ bool ip_vs_has_real_service(struct net *net, int af, __u16 protocol,
574 * Called under RCU lock. 574 * Called under RCU lock.
575 */ 575 */
576static struct ip_vs_dest * 576static struct ip_vs_dest *
577ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, 577ip_vs_lookup_dest(struct ip_vs_service *svc, int dest_af,
578 __be16 dport) 578 const union nf_inet_addr *daddr, __be16 dport)
579{ 579{
580 struct ip_vs_dest *dest; 580 struct ip_vs_dest *dest;
581 581
@@ -583,9 +583,9 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
583 * Find the destination for the given service 583 * Find the destination for the given service
584 */ 584 */
585 list_for_each_entry_rcu(dest, &svc->destinations, n_list) { 585 list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
586 if ((dest->af == svc->af) 586 if ((dest->af == dest_af) &&
587 && ip_vs_addr_equal(svc->af, &dest->addr, daddr) 587 ip_vs_addr_equal(dest_af, &dest->addr, daddr) &&
588 && (dest->port == dport)) { 588 (dest->port == dport)) {
589 /* HIT */ 589 /* HIT */
590 return dest; 590 return dest;
591 } 591 }
@@ -602,7 +602,7 @@ ip_vs_lookup_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
602 * on the backup. 602 * on the backup.
603 * Called under RCU lock, no refcnt is returned. 603 * Called under RCU lock, no refcnt is returned.
604 */ 604 */
605struct ip_vs_dest *ip_vs_find_dest(struct net *net, int af, 605struct ip_vs_dest *ip_vs_find_dest(struct net *net, int svc_af, int dest_af,
606 const union nf_inet_addr *daddr, 606 const union nf_inet_addr *daddr,
607 __be16 dport, 607 __be16 dport,
608 const union nf_inet_addr *vaddr, 608 const union nf_inet_addr *vaddr,
@@ -613,14 +613,14 @@ struct ip_vs_dest *ip_vs_find_dest(struct net *net, int af,
613 struct ip_vs_service *svc; 613 struct ip_vs_service *svc;
614 __be16 port = dport; 614 __be16 port = dport;
615 615
616 svc = ip_vs_service_find(net, af, fwmark, protocol, vaddr, vport); 616 svc = ip_vs_service_find(net, svc_af, fwmark, protocol, vaddr, vport);
617 if (!svc) 617 if (!svc)
618 return NULL; 618 return NULL;
619 if (fwmark && (flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ) 619 if (fwmark && (flags & IP_VS_CONN_F_FWD_MASK) != IP_VS_CONN_F_MASQ)
620 port = 0; 620 port = 0;
621 dest = ip_vs_lookup_dest(svc, daddr, port); 621 dest = ip_vs_lookup_dest(svc, dest_af, daddr, port);
622 if (!dest) 622 if (!dest)
623 dest = ip_vs_lookup_dest(svc, daddr, port ^ dport); 623 dest = ip_vs_lookup_dest(svc, dest_af, daddr, port ^ dport);
624 return dest; 624 return dest;
625} 625}
626 626
@@ -657,8 +657,8 @@ static void __ip_vs_dst_cache_reset(struct ip_vs_dest *dest)
657 * scheduling. 657 * scheduling.
658 */ 658 */
659static struct ip_vs_dest * 659static struct ip_vs_dest *
660ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr, 660ip_vs_trash_get_dest(struct ip_vs_service *svc, int dest_af,
661 __be16 dport) 661 const union nf_inet_addr *daddr, __be16 dport)
662{ 662{
663 struct ip_vs_dest *dest; 663 struct ip_vs_dest *dest;
664 struct netns_ipvs *ipvs = net_ipvs(svc->net); 664 struct netns_ipvs *ipvs = net_ipvs(svc->net);
@@ -671,11 +671,11 @@ ip_vs_trash_get_dest(struct ip_vs_service *svc, const union nf_inet_addr *daddr,
671 IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, " 671 IP_VS_DBG_BUF(3, "Destination %u/%s:%u still in trash, "
672 "dest->refcnt=%d\n", 672 "dest->refcnt=%d\n",
673 dest->vfwmark, 673 dest->vfwmark,
674 IP_VS_DBG_ADDR(svc->af, &dest->addr), 674 IP_VS_DBG_ADDR(dest->af, &dest->addr),
675 ntohs(dest->port), 675 ntohs(dest->port),
676 atomic_read(&dest->refcnt)); 676 atomic_read(&dest->refcnt));
677 if (dest->af == svc->af && 677 if (dest->af == dest_af &&
678 ip_vs_addr_equal(svc->af, &dest->addr, daddr) && 678 ip_vs_addr_equal(dest_af, &dest->addr, daddr) &&
679 dest->port == dport && 679 dest->port == dport &&
680 dest->vfwmark == svc->fwmark && 680 dest->vfwmark == svc->fwmark &&
681 dest->protocol == svc->protocol && 681 dest->protocol == svc->protocol &&
@@ -779,6 +779,12 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
779 struct ip_vs_scheduler *sched; 779 struct ip_vs_scheduler *sched;
780 int conn_flags; 780 int conn_flags;
781 781
782 /* We cannot modify an address and change the address family */
783 BUG_ON(!add && udest->af != dest->af);
784
785 if (add && udest->af != svc->af)
786 ipvs->mixed_address_family_dests++;
787
782 /* set the weight and the flags */ 788 /* set the weight and the flags */
783 atomic_set(&dest->weight, udest->weight); 789 atomic_set(&dest->weight, udest->weight);
784 conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK; 790 conn_flags = udest->conn_flags & IP_VS_CONN_F_DEST_MASK;
@@ -816,6 +822,8 @@ __ip_vs_update_dest(struct ip_vs_service *svc, struct ip_vs_dest *dest,
816 dest->u_threshold = udest->u_threshold; 822 dest->u_threshold = udest->u_threshold;
817 dest->l_threshold = udest->l_threshold; 823 dest->l_threshold = udest->l_threshold;
818 824
825 dest->af = udest->af;
826
819 spin_lock_bh(&dest->dst_lock); 827 spin_lock_bh(&dest->dst_lock);
820 __ip_vs_dst_cache_reset(dest); 828 __ip_vs_dst_cache_reset(dest);
821 spin_unlock_bh(&dest->dst_lock); 829 spin_unlock_bh(&dest->dst_lock);
@@ -847,7 +855,7 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
847 EnterFunction(2); 855 EnterFunction(2);
848 856
849#ifdef CONFIG_IP_VS_IPV6 857#ifdef CONFIG_IP_VS_IPV6
850 if (svc->af == AF_INET6) { 858 if (udest->af == AF_INET6) {
851 atype = ipv6_addr_type(&udest->addr.in6); 859 atype = ipv6_addr_type(&udest->addr.in6);
852 if ((!(atype & IPV6_ADDR_UNICAST) || 860 if ((!(atype & IPV6_ADDR_UNICAST) ||
853 atype & IPV6_ADDR_LINKLOCAL) && 861 atype & IPV6_ADDR_LINKLOCAL) &&
@@ -875,12 +883,12 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
875 u64_stats_init(&ip_vs_dest_stats->syncp); 883 u64_stats_init(&ip_vs_dest_stats->syncp);
876 } 884 }
877 885
878 dest->af = svc->af; 886 dest->af = udest->af;
879 dest->protocol = svc->protocol; 887 dest->protocol = svc->protocol;
880 dest->vaddr = svc->addr; 888 dest->vaddr = svc->addr;
881 dest->vport = svc->port; 889 dest->vport = svc->port;
882 dest->vfwmark = svc->fwmark; 890 dest->vfwmark = svc->fwmark;
883 ip_vs_addr_copy(svc->af, &dest->addr, &udest->addr); 891 ip_vs_addr_copy(udest->af, &dest->addr, &udest->addr);
884 dest->port = udest->port; 892 dest->port = udest->port;
885 893
886 atomic_set(&dest->activeconns, 0); 894 atomic_set(&dest->activeconns, 0);
@@ -928,11 +936,11 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
928 return -ERANGE; 936 return -ERANGE;
929 } 937 }
930 938
931 ip_vs_addr_copy(svc->af, &daddr, &udest->addr); 939 ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
932 940
933 /* We use function that requires RCU lock */ 941 /* We use function that requires RCU lock */
934 rcu_read_lock(); 942 rcu_read_lock();
935 dest = ip_vs_lookup_dest(svc, &daddr, dport); 943 dest = ip_vs_lookup_dest(svc, udest->af, &daddr, dport);
936 rcu_read_unlock(); 944 rcu_read_unlock();
937 945
938 if (dest != NULL) { 946 if (dest != NULL) {
@@ -944,12 +952,12 @@ ip_vs_add_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
944 * Check if the dest already exists in the trash and 952 * Check if the dest already exists in the trash and
945 * is from the same service 953 * is from the same service
946 */ 954 */
947 dest = ip_vs_trash_get_dest(svc, &daddr, dport); 955 dest = ip_vs_trash_get_dest(svc, udest->af, &daddr, dport);
948 956
949 if (dest != NULL) { 957 if (dest != NULL) {
950 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, " 958 IP_VS_DBG_BUF(3, "Get destination %s:%u from trash, "
951 "dest->refcnt=%d, service %u/%s:%u\n", 959 "dest->refcnt=%d, service %u/%s:%u\n",
952 IP_VS_DBG_ADDR(svc->af, &daddr), ntohs(dport), 960 IP_VS_DBG_ADDR(udest->af, &daddr), ntohs(dport),
953 atomic_read(&dest->refcnt), 961 atomic_read(&dest->refcnt),
954 dest->vfwmark, 962 dest->vfwmark,
955 IP_VS_DBG_ADDR(svc->af, &dest->vaddr), 963 IP_VS_DBG_ADDR(svc->af, &dest->vaddr),
@@ -992,11 +1000,11 @@ ip_vs_edit_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
992 return -ERANGE; 1000 return -ERANGE;
993 } 1001 }
994 1002
995 ip_vs_addr_copy(svc->af, &daddr, &udest->addr); 1003 ip_vs_addr_copy(udest->af, &daddr, &udest->addr);
996 1004
997 /* We use function that requires RCU lock */ 1005 /* We use function that requires RCU lock */
998 rcu_read_lock(); 1006 rcu_read_lock();
999 dest = ip_vs_lookup_dest(svc, &daddr, dport); 1007 dest = ip_vs_lookup_dest(svc, udest->af, &daddr, dport);
1000 rcu_read_unlock(); 1008 rcu_read_unlock();
1001 1009
1002 if (dest == NULL) { 1010 if (dest == NULL) {
@@ -1055,6 +1063,9 @@ static void __ip_vs_unlink_dest(struct ip_vs_service *svc,
1055 list_del_rcu(&dest->n_list); 1063 list_del_rcu(&dest->n_list);
1056 svc->num_dests--; 1064 svc->num_dests--;
1057 1065
1066 if (dest->af != svc->af)
1067 net_ipvs(svc->net)->mixed_address_family_dests--;
1068
1058 if (svcupd) { 1069 if (svcupd) {
1059 struct ip_vs_scheduler *sched; 1070 struct ip_vs_scheduler *sched;
1060 1071
@@ -1078,7 +1089,7 @@ ip_vs_del_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest)
1078 1089
1079 /* We use function that requires RCU lock */ 1090 /* We use function that requires RCU lock */
1080 rcu_read_lock(); 1091 rcu_read_lock();
1081 dest = ip_vs_lookup_dest(svc, &udest->addr, dport); 1092 dest = ip_vs_lookup_dest(svc, udest->af, &udest->addr, dport);
1082 rcu_read_unlock(); 1093 rcu_read_unlock();
1083 1094
1084 if (dest == NULL) { 1095 if (dest == NULL) {
@@ -2244,6 +2255,7 @@ static void ip_vs_copy_udest_compat(struct ip_vs_dest_user_kern *udest,
2244 udest->weight = udest_compat->weight; 2255 udest->weight = udest_compat->weight;
2245 udest->u_threshold = udest_compat->u_threshold; 2256 udest->u_threshold = udest_compat->u_threshold;
2246 udest->l_threshold = udest_compat->l_threshold; 2257 udest->l_threshold = udest_compat->l_threshold;
2258 udest->af = AF_INET;
2247} 2259}
2248 2260
2249static int 2261static int
@@ -2480,6 +2492,12 @@ __ip_vs_get_dest_entries(struct net *net, const struct ip_vs_get_dests *get,
2480 if (count >= get->num_dests) 2492 if (count >= get->num_dests)
2481 break; 2493 break;
2482 2494
2495 /* Cannot expose heterogeneous members via sockopt
2496 * interface
2497 */
2498 if (dest->af != svc->af)
2499 continue;
2500
2483 entry.addr = dest->addr.ip; 2501 entry.addr = dest->addr.ip;
2484 entry.port = dest->port; 2502 entry.port = dest->port;
2485 entry.conn_flags = atomic_read(&dest->conn_flags); 2503 entry.conn_flags = atomic_read(&dest->conn_flags);
@@ -2777,6 +2795,7 @@ static const struct nla_policy ip_vs_dest_policy[IPVS_DEST_ATTR_MAX + 1] = {
2777 [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 }, 2795 [IPVS_DEST_ATTR_INACT_CONNS] = { .type = NLA_U32 },
2778 [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 }, 2796 [IPVS_DEST_ATTR_PERSIST_CONNS] = { .type = NLA_U32 },
2779 [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED }, 2797 [IPVS_DEST_ATTR_STATS] = { .type = NLA_NESTED },
2798 [IPVS_DEST_ATTR_ADDR_FAMILY] = { .type = NLA_U16 },
2780}; 2799};
2781 2800
2782static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type, 2801static int ip_vs_genl_fill_stats(struct sk_buff *skb, int container_type,
@@ -3032,7 +3051,8 @@ static int ip_vs_genl_fill_dest(struct sk_buff *skb, struct ip_vs_dest *dest)
3032 nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS, 3051 nla_put_u32(skb, IPVS_DEST_ATTR_INACT_CONNS,
3033 atomic_read(&dest->inactconns)) || 3052 atomic_read(&dest->inactconns)) ||
3034 nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS, 3053 nla_put_u32(skb, IPVS_DEST_ATTR_PERSIST_CONNS,
3035 atomic_read(&dest->persistconns))) 3054 atomic_read(&dest->persistconns)) ||
3055 nla_put_u16(skb, IPVS_DEST_ATTR_ADDR_FAMILY, dest->af))
3036 goto nla_put_failure; 3056 goto nla_put_failure;
3037 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats)) 3057 if (ip_vs_genl_fill_stats(skb, IPVS_DEST_ATTR_STATS, &dest->stats))
3038 goto nla_put_failure; 3058 goto nla_put_failure;
@@ -3113,6 +3133,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
3113{ 3133{
3114 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1]; 3134 struct nlattr *attrs[IPVS_DEST_ATTR_MAX + 1];
3115 struct nlattr *nla_addr, *nla_port; 3135 struct nlattr *nla_addr, *nla_port;
3136 struct nlattr *nla_addr_family;
3116 3137
3117 /* Parse mandatory identifying destination fields first */ 3138 /* Parse mandatory identifying destination fields first */
3118 if (nla == NULL || 3139 if (nla == NULL ||
@@ -3121,6 +3142,7 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
3121 3142
3122 nla_addr = attrs[IPVS_DEST_ATTR_ADDR]; 3143 nla_addr = attrs[IPVS_DEST_ATTR_ADDR];
3123 nla_port = attrs[IPVS_DEST_ATTR_PORT]; 3144 nla_port = attrs[IPVS_DEST_ATTR_PORT];
3145 nla_addr_family = attrs[IPVS_DEST_ATTR_ADDR_FAMILY];
3124 3146
3125 if (!(nla_addr && nla_port)) 3147 if (!(nla_addr && nla_port))
3126 return -EINVAL; 3148 return -EINVAL;
@@ -3130,6 +3152,11 @@ static int ip_vs_genl_parse_dest(struct ip_vs_dest_user_kern *udest,
3130 nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr)); 3152 nla_memcpy(&udest->addr, nla_addr, sizeof(udest->addr));
3131 udest->port = nla_get_be16(nla_port); 3153 udest->port = nla_get_be16(nla_port);
3132 3154
3155 if (nla_addr_family)
3156 udest->af = nla_get_u16(nla_addr_family);
3157 else
3158 udest->af = 0;
3159
3133 /* If a full entry was requested, check for the additional fields */ 3160 /* If a full entry was requested, check for the additional fields */
3134 if (full_entry) { 3161 if (full_entry) {
3135 struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh, 3162 struct nlattr *nla_fwd, *nla_weight, *nla_u_thresh,
@@ -3234,6 +3261,12 @@ static int ip_vs_genl_new_daemon(struct net *net, struct nlattr **attrs)
3234 attrs[IPVS_DAEMON_ATTR_SYNC_ID])) 3261 attrs[IPVS_DAEMON_ATTR_SYNC_ID]))
3235 return -EINVAL; 3262 return -EINVAL;
3236 3263
3264 /* The synchronization protocol is incompatible with mixed family
3265 * services
3266 */
3267 if (net_ipvs(net)->mixed_address_family_dests > 0)
3268 return -EINVAL;
3269
3237 return start_sync_thread(net, 3270 return start_sync_thread(net,
3238 nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]), 3271 nla_get_u32(attrs[IPVS_DAEMON_ATTR_STATE]),
3239 nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]), 3272 nla_data(attrs[IPVS_DAEMON_ATTR_MCAST_IFN]),
@@ -3357,6 +3390,35 @@ static int ip_vs_genl_set_cmd(struct sk_buff *skb, struct genl_info *info)
3357 need_full_dest); 3390 need_full_dest);
3358 if (ret) 3391 if (ret)
3359 goto out; 3392 goto out;
3393
3394 /* Old protocols did not allow the user to specify address
3395 * family, so we set it to zero instead. We also didn't
3396 * allow heterogeneous pools in the old code, so it's safe
3397 * to assume that this will have the same address family as
3398 * the service.
3399 */
3400 if (udest.af == 0)
3401 udest.af = svc->af;
3402
3403 if (udest.af != svc->af) {
3404 /* The synchronization protocol is incompatible
3405 * with mixed family services
3406 */
3407 if (net_ipvs(net)->sync_state) {
3408 ret = -EINVAL;
3409 goto out;
3410 }
3411
3412 /* Which connection types do we support? */
3413 switch (udest.conn_flags) {
3414 case IP_VS_CONN_F_TUNNEL:
3415 /* We are able to forward this */
3416 break;
3417 default:
3418 ret = -EINVAL;
3419 goto out;
3420 }
3421 }
3360 } 3422 }
3361 3423
3362 switch (cmd) { 3424 switch (cmd) {
diff --git a/net/netfilter/ipvs/ip_vs_dh.c b/net/netfilter/ipvs/ip_vs_dh.c
index c3b84546ea9e..6be5c538b71e 100644
--- a/net/netfilter/ipvs/ip_vs_dh.c
+++ b/net/netfilter/ipvs/ip_vs_dh.c
@@ -234,7 +234,7 @@ ip_vs_dh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
234 234
235 IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n", 235 IP_VS_DBG_BUF(6, "DH: destination IP address %s --> server %s:%d\n",
236 IP_VS_DBG_ADDR(svc->af, &iph->daddr), 236 IP_VS_DBG_ADDR(svc->af, &iph->daddr),
237 IP_VS_DBG_ADDR(svc->af, &dest->addr), 237 IP_VS_DBG_ADDR(dest->af, &dest->addr),
238 ntohs(dest->port)); 238 ntohs(dest->port));
239 239
240 return dest; 240 return dest;
diff --git a/net/netfilter/ipvs/ip_vs_fo.c b/net/netfilter/ipvs/ip_vs_fo.c
new file mode 100644
index 000000000000..e09874d02938
--- /dev/null
+++ b/net/netfilter/ipvs/ip_vs_fo.c
@@ -0,0 +1,79 @@
1/*
2 * IPVS: Weighted Fail Over module
3 *
4 * Authors: Kenny Mathis <kmathis@chokepoint.net>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 *
11 * Changes:
12 * Kenny Mathis : added initial functionality based on weight
13 *
14 */
15
16#define KMSG_COMPONENT "IPVS"
17#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
18
19#include <linux/module.h>
20#include <linux/kernel.h>
21
22#include <net/ip_vs.h>
23
24/* Weighted Fail Over Module */
25static struct ip_vs_dest *
26ip_vs_fo_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
27 struct ip_vs_iphdr *iph)
28{
29 struct ip_vs_dest *dest, *hweight = NULL;
30 int hw = 0; /* Track highest weight */
31
32 IP_VS_DBG(6, "ip_vs_fo_schedule(): Scheduling...\n");
33
34 /* Basic failover functionality
35 * Find virtual server with highest weight and send it traffic
36 */
37 list_for_each_entry_rcu(dest, &svc->destinations, n_list) {
38 if (!(dest->flags & IP_VS_DEST_F_OVERLOAD) &&
39 atomic_read(&dest->weight) > hw) {
40 hweight = dest;
41 hw = atomic_read(&dest->weight);
42 }
43 }
44
45 if (hweight) {
46 IP_VS_DBG_BUF(6, "FO: server %s:%u activeconns %d weight %d\n",
47 IP_VS_DBG_ADDR(hweight->af, &hweight->addr),
48 ntohs(hweight->port),
49 atomic_read(&hweight->activeconns),
50 atomic_read(&hweight->weight));
51 return hweight;
52 }
53
54 ip_vs_scheduler_err(svc, "no destination available");
55 return NULL;
56}
57
58static struct ip_vs_scheduler ip_vs_fo_scheduler = {
59 .name = "fo",
60 .refcnt = ATOMIC_INIT(0),
61 .module = THIS_MODULE,
62 .n_list = LIST_HEAD_INIT(ip_vs_fo_scheduler.n_list),
63 .schedule = ip_vs_fo_schedule,
64};
65
66static int __init ip_vs_fo_init(void)
67{
68 return register_ip_vs_scheduler(&ip_vs_fo_scheduler);
69}
70
71static void __exit ip_vs_fo_cleanup(void)
72{
73 unregister_ip_vs_scheduler(&ip_vs_fo_scheduler);
74 synchronize_rcu();
75}
76
77module_init(ip_vs_fo_init);
78module_exit(ip_vs_fo_cleanup);
79MODULE_LICENSE("GPL");
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c
index 77c173282f38..a64fa15790e5 100644
--- a/net/netfilter/ipvs/ip_vs_ftp.c
+++ b/net/netfilter/ipvs/ip_vs_ftp.c
@@ -233,7 +233,8 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
233 ip_vs_conn_fill_param(ip_vs_conn_net(cp), 233 ip_vs_conn_fill_param(ip_vs_conn_net(cp),
234 AF_INET, IPPROTO_TCP, &cp->caddr, 234 AF_INET, IPPROTO_TCP, &cp->caddr,
235 0, &cp->vaddr, port, &p); 235 0, &cp->vaddr, port, &p);
236 n_cp = ip_vs_conn_new(&p, &from, port, 236 /* As above, this is ipv4 only */
237 n_cp = ip_vs_conn_new(&p, AF_INET, &from, port,
237 IP_VS_CONN_F_NO_CPORT | 238 IP_VS_CONN_F_NO_CPORT |
238 IP_VS_CONN_F_NFCT, 239 IP_VS_CONN_F_NFCT,
239 cp->dest, skb->mark); 240 cp->dest, skb->mark);
@@ -396,7 +397,8 @@ static int ip_vs_ftp_in(struct ip_vs_app *app, struct ip_vs_conn *cp,
396 htons(ntohs(cp->vport)-1), &p); 397 htons(ntohs(cp->vport)-1), &p);
397 n_cp = ip_vs_conn_in_get(&p); 398 n_cp = ip_vs_conn_in_get(&p);
398 if (!n_cp) { 399 if (!n_cp) {
399 n_cp = ip_vs_conn_new(&p, &cp->daddr, 400 /* This is ipv4 only */
401 n_cp = ip_vs_conn_new(&p, AF_INET, &cp->daddr,
400 htons(ntohs(cp->dport)-1), 402 htons(ntohs(cp->dport)-1),
401 IP_VS_CONN_F_NFCT, cp->dest, 403 IP_VS_CONN_F_NFCT, cp->dest,
402 skb->mark); 404 skb->mark);
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c
index 547ff33c1efd..127f14046c51 100644
--- a/net/netfilter/ipvs/ip_vs_lblc.c
+++ b/net/netfilter/ipvs/ip_vs_lblc.c
@@ -199,11 +199,11 @@ ip_vs_lblc_get(int af, struct ip_vs_lblc_table *tbl,
199 */ 199 */
200static inline struct ip_vs_lblc_entry * 200static inline struct ip_vs_lblc_entry *
201ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr, 201ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
202 struct ip_vs_dest *dest) 202 u16 af, struct ip_vs_dest *dest)
203{ 203{
204 struct ip_vs_lblc_entry *en; 204 struct ip_vs_lblc_entry *en;
205 205
206 en = ip_vs_lblc_get(dest->af, tbl, daddr); 206 en = ip_vs_lblc_get(af, tbl, daddr);
207 if (en) { 207 if (en) {
208 if (en->dest == dest) 208 if (en->dest == dest)
209 return en; 209 return en;
@@ -213,8 +213,8 @@ ip_vs_lblc_new(struct ip_vs_lblc_table *tbl, const union nf_inet_addr *daddr,
213 if (!en) 213 if (!en)
214 return NULL; 214 return NULL;
215 215
216 en->af = dest->af; 216 en->af = af;
217 ip_vs_addr_copy(dest->af, &en->addr, daddr); 217 ip_vs_addr_copy(af, &en->addr, daddr);
218 en->lastuse = jiffies; 218 en->lastuse = jiffies;
219 219
220 ip_vs_dest_hold(dest); 220 ip_vs_dest_hold(dest);
@@ -521,13 +521,13 @@ ip_vs_lblc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
521 /* If we fail to create a cache entry, we'll just use the valid dest */ 521 /* If we fail to create a cache entry, we'll just use the valid dest */
522 spin_lock_bh(&svc->sched_lock); 522 spin_lock_bh(&svc->sched_lock);
523 if (!tbl->dead) 523 if (!tbl->dead)
524 ip_vs_lblc_new(tbl, &iph->daddr, dest); 524 ip_vs_lblc_new(tbl, &iph->daddr, svc->af, dest);
525 spin_unlock_bh(&svc->sched_lock); 525 spin_unlock_bh(&svc->sched_lock);
526 526
527out: 527out:
528 IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n", 528 IP_VS_DBG_BUF(6, "LBLC: destination IP address %s --> server %s:%d\n",
529 IP_VS_DBG_ADDR(svc->af, &iph->daddr), 529 IP_VS_DBG_ADDR(svc->af, &iph->daddr),
530 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); 530 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
531 531
532 return dest; 532 return dest;
533} 533}
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c
index 3f21a2f47de1..2229d2d8bbe0 100644
--- a/net/netfilter/ipvs/ip_vs_lblcr.c
+++ b/net/netfilter/ipvs/ip_vs_lblcr.c
@@ -362,18 +362,18 @@ ip_vs_lblcr_get(int af, struct ip_vs_lblcr_table *tbl,
362 */ 362 */
363static inline struct ip_vs_lblcr_entry * 363static inline struct ip_vs_lblcr_entry *
364ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr, 364ip_vs_lblcr_new(struct ip_vs_lblcr_table *tbl, const union nf_inet_addr *daddr,
365 struct ip_vs_dest *dest) 365 u16 af, struct ip_vs_dest *dest)
366{ 366{
367 struct ip_vs_lblcr_entry *en; 367 struct ip_vs_lblcr_entry *en;
368 368
369 en = ip_vs_lblcr_get(dest->af, tbl, daddr); 369 en = ip_vs_lblcr_get(af, tbl, daddr);
370 if (!en) { 370 if (!en) {
371 en = kmalloc(sizeof(*en), GFP_ATOMIC); 371 en = kmalloc(sizeof(*en), GFP_ATOMIC);
372 if (!en) 372 if (!en)
373 return NULL; 373 return NULL;
374 374
375 en->af = dest->af; 375 en->af = af;
376 ip_vs_addr_copy(dest->af, &en->addr, daddr); 376 ip_vs_addr_copy(af, &en->addr, daddr);
377 en->lastuse = jiffies; 377 en->lastuse = jiffies;
378 378
379 /* initialize its dest set */ 379 /* initialize its dest set */
@@ -706,13 +706,13 @@ ip_vs_lblcr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
706 /* If we fail to create a cache entry, we'll just use the valid dest */ 706 /* If we fail to create a cache entry, we'll just use the valid dest */
707 spin_lock_bh(&svc->sched_lock); 707 spin_lock_bh(&svc->sched_lock);
708 if (!tbl->dead) 708 if (!tbl->dead)
709 ip_vs_lblcr_new(tbl, &iph->daddr, dest); 709 ip_vs_lblcr_new(tbl, &iph->daddr, svc->af, dest);
710 spin_unlock_bh(&svc->sched_lock); 710 spin_unlock_bh(&svc->sched_lock);
711 711
712out: 712out:
713 IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n", 713 IP_VS_DBG_BUF(6, "LBLCR: destination IP address %s --> server %s:%d\n",
714 IP_VS_DBG_ADDR(svc->af, &iph->daddr), 714 IP_VS_DBG_ADDR(svc->af, &iph->daddr),
715 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); 715 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
716 716
717 return dest; 717 return dest;
718} 718}
diff --git a/net/netfilter/ipvs/ip_vs_lc.c b/net/netfilter/ipvs/ip_vs_lc.c
index 2bdcb1cf2127..19a0769a989a 100644
--- a/net/netfilter/ipvs/ip_vs_lc.c
+++ b/net/netfilter/ipvs/ip_vs_lc.c
@@ -59,7 +59,7 @@ ip_vs_lc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
59 else 59 else
60 IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d " 60 IP_VS_DBG_BUF(6, "LC: server %s:%u activeconns %d "
61 "inactconns %d\n", 61 "inactconns %d\n",
62 IP_VS_DBG_ADDR(svc->af, &least->addr), 62 IP_VS_DBG_ADDR(least->af, &least->addr),
63 ntohs(least->port), 63 ntohs(least->port),
64 atomic_read(&least->activeconns), 64 atomic_read(&least->activeconns),
65 atomic_read(&least->inactconns)); 65 atomic_read(&least->inactconns));
diff --git a/net/netfilter/ipvs/ip_vs_nq.c b/net/netfilter/ipvs/ip_vs_nq.c
index 961a6de9bb29..a8b63401e773 100644
--- a/net/netfilter/ipvs/ip_vs_nq.c
+++ b/net/netfilter/ipvs/ip_vs_nq.c
@@ -107,7 +107,8 @@ ip_vs_nq_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
107 out: 107 out:
108 IP_VS_DBG_BUF(6, "NQ: server %s:%u " 108 IP_VS_DBG_BUF(6, "NQ: server %s:%u "
109 "activeconns %d refcnt %d weight %d overhead %d\n", 109 "activeconns %d refcnt %d weight %d overhead %d\n",
110 IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), 110 IP_VS_DBG_ADDR(least->af, &least->addr),
111 ntohs(least->port),
111 atomic_read(&least->activeconns), 112 atomic_read(&least->activeconns),
112 atomic_read(&least->refcnt), 113 atomic_read(&least->refcnt),
113 atomic_read(&least->weight), loh); 114 atomic_read(&least->weight), loh);
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c
index 2f7ea7564044..5b84c0b56642 100644
--- a/net/netfilter/ipvs/ip_vs_proto_sctp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c
@@ -432,7 +432,7 @@ set_sctp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
432 pd->pp->name, 432 pd->pp->name,
433 ((direction == IP_VS_DIR_OUTPUT) ? 433 ((direction == IP_VS_DIR_OUTPUT) ?
434 "output " : "input "), 434 "output " : "input "),
435 IP_VS_DBG_ADDR(cp->af, &cp->daddr), 435 IP_VS_DBG_ADDR(cp->daf, &cp->daddr),
436 ntohs(cp->dport), 436 ntohs(cp->dport),
437 IP_VS_DBG_ADDR(cp->af, &cp->caddr), 437 IP_VS_DBG_ADDR(cp->af, &cp->caddr),
438 ntohs(cp->cport), 438 ntohs(cp->cport),
diff --git a/net/netfilter/ipvs/ip_vs_proto_tcp.c b/net/netfilter/ipvs/ip_vs_proto_tcp.c
index e3a697234a98..8e92beb0cca9 100644
--- a/net/netfilter/ipvs/ip_vs_proto_tcp.c
+++ b/net/netfilter/ipvs/ip_vs_proto_tcp.c
@@ -510,7 +510,7 @@ set_tcp_state(struct ip_vs_proto_data *pd, struct ip_vs_conn *cp,
510 th->fin ? 'F' : '.', 510 th->fin ? 'F' : '.',
511 th->ack ? 'A' : '.', 511 th->ack ? 'A' : '.',
512 th->rst ? 'R' : '.', 512 th->rst ? 'R' : '.',
513 IP_VS_DBG_ADDR(cp->af, &cp->daddr), 513 IP_VS_DBG_ADDR(cp->daf, &cp->daddr),
514 ntohs(cp->dport), 514 ntohs(cp->dport),
515 IP_VS_DBG_ADDR(cp->af, &cp->caddr), 515 IP_VS_DBG_ADDR(cp->af, &cp->caddr),
516 ntohs(cp->cport), 516 ntohs(cp->cport),
diff --git a/net/netfilter/ipvs/ip_vs_rr.c b/net/netfilter/ipvs/ip_vs_rr.c
index 176b87c35e34..58bacfc461ee 100644
--- a/net/netfilter/ipvs/ip_vs_rr.c
+++ b/net/netfilter/ipvs/ip_vs_rr.c
@@ -95,7 +95,7 @@ stop:
95 spin_unlock_bh(&svc->sched_lock); 95 spin_unlock_bh(&svc->sched_lock);
96 IP_VS_DBG_BUF(6, "RR: server %s:%u " 96 IP_VS_DBG_BUF(6, "RR: server %s:%u "
97 "activeconns %d refcnt %d weight %d\n", 97 "activeconns %d refcnt %d weight %d\n",
98 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), 98 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
99 atomic_read(&dest->activeconns), 99 atomic_read(&dest->activeconns),
100 atomic_read(&dest->refcnt), atomic_read(&dest->weight)); 100 atomic_read(&dest->refcnt), atomic_read(&dest->weight));
101 101
diff --git a/net/netfilter/ipvs/ip_vs_sed.c b/net/netfilter/ipvs/ip_vs_sed.c
index e446b9fa7424..f8e2d00f528b 100644
--- a/net/netfilter/ipvs/ip_vs_sed.c
+++ b/net/netfilter/ipvs/ip_vs_sed.c
@@ -108,7 +108,8 @@ ip_vs_sed_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
108 108
109 IP_VS_DBG_BUF(6, "SED: server %s:%u " 109 IP_VS_DBG_BUF(6, "SED: server %s:%u "
110 "activeconns %d refcnt %d weight %d overhead %d\n", 110 "activeconns %d refcnt %d weight %d overhead %d\n",
111 IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), 111 IP_VS_DBG_ADDR(least->af, &least->addr),
112 ntohs(least->port),
112 atomic_read(&least->activeconns), 113 atomic_read(&least->activeconns),
113 atomic_read(&least->refcnt), 114 atomic_read(&least->refcnt),
114 atomic_read(&least->weight), loh); 115 atomic_read(&least->weight), loh);
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c
index cc65b2f42cd4..98a13433b68c 100644
--- a/net/netfilter/ipvs/ip_vs_sh.c
+++ b/net/netfilter/ipvs/ip_vs_sh.c
@@ -138,7 +138,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
138 return dest; 138 return dest;
139 139
140 IP_VS_DBG_BUF(6, "SH: selected unavailable server %s:%d, reselecting", 140 IP_VS_DBG_BUF(6, "SH: selected unavailable server %s:%d, reselecting",
141 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port)); 141 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port));
142 142
143 /* if the original dest is unavailable, loop around the table 143 /* if the original dest is unavailable, loop around the table
144 * starting from ihash to find a new dest 144 * starting from ihash to find a new dest
@@ -153,7 +153,7 @@ ip_vs_sh_get_fallback(struct ip_vs_service *svc, struct ip_vs_sh_state *s,
153 return dest; 153 return dest;
154 IP_VS_DBG_BUF(6, "SH: selected unavailable " 154 IP_VS_DBG_BUF(6, "SH: selected unavailable "
155 "server %s:%d (offset %d), reselecting", 155 "server %s:%d (offset %d), reselecting",
156 IP_VS_DBG_ADDR(svc->af, &dest->addr), 156 IP_VS_DBG_ADDR(dest->af, &dest->addr),
157 ntohs(dest->port), roffset); 157 ntohs(dest->port), roffset);
158 } 158 }
159 159
@@ -192,7 +192,7 @@ ip_vs_sh_reassign(struct ip_vs_sh_state *s, struct ip_vs_service *svc)
192 RCU_INIT_POINTER(b->dest, dest); 192 RCU_INIT_POINTER(b->dest, dest);
193 193
194 IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n", 194 IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n",
195 i, IP_VS_DBG_ADDR(svc->af, &dest->addr), 195 i, IP_VS_DBG_ADDR(dest->af, &dest->addr),
196 atomic_read(&dest->weight)); 196 atomic_read(&dest->weight));
197 197
198 /* Don't move to next dest until filling weight */ 198 /* Don't move to next dest until filling weight */
@@ -342,7 +342,7 @@ ip_vs_sh_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
342 342
343 IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n", 343 IP_VS_DBG_BUF(6, "SH: source IP address %s --> server %s:%d\n",
344 IP_VS_DBG_ADDR(svc->af, &iph->saddr), 344 IP_VS_DBG_ADDR(svc->af, &iph->saddr),
345 IP_VS_DBG_ADDR(svc->af, &dest->addr), 345 IP_VS_DBG_ADDR(dest->af, &dest->addr),
346 ntohs(dest->port)); 346 ntohs(dest->port));
347 347
348 return dest; 348 return dest;
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c
index eadffb29dec0..7162c86fd50d 100644
--- a/net/netfilter/ipvs/ip_vs_sync.c
+++ b/net/netfilter/ipvs/ip_vs_sync.c
@@ -880,10 +880,17 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param,
880 * but still handled. 880 * but still handled.
881 */ 881 */
882 rcu_read_lock(); 882 rcu_read_lock();
883 dest = ip_vs_find_dest(net, type, daddr, dport, param->vaddr, 883 /* This function is only invoked by the synchronization
884 param->vport, protocol, fwmark, flags); 884 * code. We do not currently support heterogeneous pools
885 * with synchronization, so we can make the assumption that
886 * the svc_af is the same as the dest_af
887 */
888 dest = ip_vs_find_dest(net, type, type, daddr, dport,
889 param->vaddr, param->vport, protocol,
890 fwmark, flags);
885 891
886 cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); 892 cp = ip_vs_conn_new(param, type, daddr, dport, flags, dest,
893 fwmark);
887 rcu_read_unlock(); 894 rcu_read_unlock();
888 if (!cp) { 895 if (!cp) {
889 kfree(param->pe_data); 896 kfree(param->pe_data);
diff --git a/net/netfilter/ipvs/ip_vs_wlc.c b/net/netfilter/ipvs/ip_vs_wlc.c
index b5b4650d50a9..6b366fd90554 100644
--- a/net/netfilter/ipvs/ip_vs_wlc.c
+++ b/net/netfilter/ipvs/ip_vs_wlc.c
@@ -80,7 +80,8 @@ ip_vs_wlc_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
80 80
81 IP_VS_DBG_BUF(6, "WLC: server %s:%u " 81 IP_VS_DBG_BUF(6, "WLC: server %s:%u "
82 "activeconns %d refcnt %d weight %d overhead %d\n", 82 "activeconns %d refcnt %d weight %d overhead %d\n",
83 IP_VS_DBG_ADDR(svc->af, &least->addr), ntohs(least->port), 83 IP_VS_DBG_ADDR(least->af, &least->addr),
84 ntohs(least->port),
84 atomic_read(&least->activeconns), 85 atomic_read(&least->activeconns),
85 atomic_read(&least->refcnt), 86 atomic_read(&least->refcnt),
86 atomic_read(&least->weight), loh); 87 atomic_read(&least->weight), loh);
diff --git a/net/netfilter/ipvs/ip_vs_wrr.c b/net/netfilter/ipvs/ip_vs_wrr.c
index 0546cd572d6b..17e6d4406ca7 100644
--- a/net/netfilter/ipvs/ip_vs_wrr.c
+++ b/net/netfilter/ipvs/ip_vs_wrr.c
@@ -216,7 +216,7 @@ ip_vs_wrr_schedule(struct ip_vs_service *svc, const struct sk_buff *skb,
216found: 216found:
217 IP_VS_DBG_BUF(6, "WRR: server %s:%u " 217 IP_VS_DBG_BUF(6, "WRR: server %s:%u "
218 "activeconns %d refcnt %d weight %d\n", 218 "activeconns %d refcnt %d weight %d\n",
219 IP_VS_DBG_ADDR(svc->af, &dest->addr), ntohs(dest->port), 219 IP_VS_DBG_ADDR(dest->af, &dest->addr), ntohs(dest->port),
220 atomic_read(&dest->activeconns), 220 atomic_read(&dest->activeconns),
221 atomic_read(&dest->refcnt), 221 atomic_read(&dest->refcnt),
222 atomic_read(&dest->weight)); 222 atomic_read(&dest->weight));
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c
index 56896a412bce..91f17c1eb8a2 100644
--- a/net/netfilter/ipvs/ip_vs_xmit.c
+++ b/net/netfilter/ipvs/ip_vs_xmit.c
@@ -157,18 +157,113 @@ retry:
157 return rt; 157 return rt;
158} 158}
159 159
160#ifdef CONFIG_IP_VS_IPV6
161static inline int __ip_vs_is_local_route6(struct rt6_info *rt)
162{
163 return rt->dst.dev && rt->dst.dev->flags & IFF_LOOPBACK;
164}
165#endif
166
167static inline bool crosses_local_route_boundary(int skb_af, struct sk_buff *skb,
168 int rt_mode,
169 bool new_rt_is_local)
170{
171 bool rt_mode_allow_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL);
172 bool rt_mode_allow_non_local = !!(rt_mode & IP_VS_RT_MODE_LOCAL);
173 bool rt_mode_allow_redirect = !!(rt_mode & IP_VS_RT_MODE_RDR);
174 bool source_is_loopback;
175 bool old_rt_is_local;
176
177#ifdef CONFIG_IP_VS_IPV6
178 if (skb_af == AF_INET6) {
179 int addr_type = ipv6_addr_type(&ipv6_hdr(skb)->saddr);
180
181 source_is_loopback =
182 (!skb->dev || skb->dev->flags & IFF_LOOPBACK) &&
183 (addr_type & IPV6_ADDR_LOOPBACK);
184 old_rt_is_local = __ip_vs_is_local_route6(
185 (struct rt6_info *)skb_dst(skb));
186 } else
187#endif
188 {
189 source_is_loopback = ipv4_is_loopback(ip_hdr(skb)->saddr);
190 old_rt_is_local = skb_rtable(skb)->rt_flags & RTCF_LOCAL;
191 }
192
193 if (unlikely(new_rt_is_local)) {
194 if (!rt_mode_allow_local)
195 return true;
196 if (!rt_mode_allow_redirect && !old_rt_is_local)
197 return true;
198 } else {
199 if (!rt_mode_allow_non_local)
200 return true;
201 if (source_is_loopback)
202 return true;
203 }
204 return false;
205}
206
207static inline void maybe_update_pmtu(int skb_af, struct sk_buff *skb, int mtu)
208{
209 struct sock *sk = skb->sk;
210 struct rtable *ort = skb_rtable(skb);
211
212 if (!skb->dev && sk && sk->sk_state != TCP_TIME_WAIT)
213 ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
214}
215
216static inline bool ensure_mtu_is_adequate(int skb_af, int rt_mode,
217 struct ip_vs_iphdr *ipvsh,
218 struct sk_buff *skb, int mtu)
219{
220#ifdef CONFIG_IP_VS_IPV6
221 if (skb_af == AF_INET6) {
222 struct net *net = dev_net(skb_dst(skb)->dev);
223
224 if (unlikely(__mtu_check_toobig_v6(skb, mtu))) {
225 if (!skb->dev)
226 skb->dev = net->loopback_dev;
227 /* only send ICMP too big on first fragment */
228 if (!ipvsh->fragoffs)
229 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
230 IP_VS_DBG(1, "frag needed for %pI6c\n",
231 &ipv6_hdr(skb)->saddr);
232 return false;
233 }
234 } else
235#endif
236 {
237 struct netns_ipvs *ipvs = net_ipvs(skb_net(skb));
238
239 /* If we're going to tunnel the packet and pmtu discovery
240 * is disabled, we'll just fragment it anyway
241 */
242 if ((rt_mode & IP_VS_RT_MODE_TUNNEL) && !sysctl_pmtu_disc(ipvs))
243 return true;
244
245 if (unlikely(ip_hdr(skb)->frag_off & htons(IP_DF) &&
246 skb->len > mtu && !skb_is_gso(skb))) {
247 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
248 htonl(mtu));
249 IP_VS_DBG(1, "frag needed for %pI4\n",
250 &ip_hdr(skb)->saddr);
251 return false;
252 }
253 }
254
255 return true;
256}
257
160/* Get route to destination or remote server */ 258/* Get route to destination or remote server */
161static int 259static int
162__ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, 260__ip_vs_get_out_rt(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
163 __be32 daddr, int rt_mode, __be32 *ret_saddr) 261 __be32 daddr, int rt_mode, __be32 *ret_saddr,
262 struct ip_vs_iphdr *ipvsh)
164{ 263{
165 struct net *net = dev_net(skb_dst(skb)->dev); 264 struct net *net = dev_net(skb_dst(skb)->dev);
166 struct netns_ipvs *ipvs = net_ipvs(net);
167 struct ip_vs_dest_dst *dest_dst; 265 struct ip_vs_dest_dst *dest_dst;
168 struct rtable *rt; /* Route to the other host */ 266 struct rtable *rt; /* Route to the other host */
169 struct rtable *ort; /* Original route */
170 struct iphdr *iph;
171 __be16 df;
172 int mtu; 267 int mtu;
173 int local, noref = 1; 268 int local, noref = 1;
174 269
@@ -218,30 +313,14 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
218 } 313 }
219 314
220 local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0; 315 local = (rt->rt_flags & RTCF_LOCAL) ? 1 : 0;
221 if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) & 316 if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
222 rt_mode)) { 317 local))) {
223 IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI4\n", 318 IP_VS_DBG_RL("We are crossing local and non-local addresses"
224 (rt->rt_flags & RTCF_LOCAL) ? 319 " daddr=%pI4\n", &dest->addr.ip);
225 "local":"non-local", &daddr);
226 goto err_put; 320 goto err_put;
227 } 321 }
228 iph = ip_hdr(skb); 322
229 if (likely(!local)) { 323 if (unlikely(local)) {
230 if (unlikely(ipv4_is_loopback(iph->saddr))) {
231 IP_VS_DBG_RL("Stopping traffic from loopback address "
232 "%pI4 to non-local address, dest: %pI4\n",
233 &iph->saddr, &daddr);
234 goto err_put;
235 }
236 } else {
237 ort = skb_rtable(skb);
238 if (!(rt_mode & IP_VS_RT_MODE_RDR) &&
239 !(ort->rt_flags & RTCF_LOCAL)) {
240 IP_VS_DBG_RL("Redirect from non-local address %pI4 to "
241 "local requires NAT method, dest: %pI4\n",
242 &iph->daddr, &daddr);
243 goto err_put;
244 }
245 /* skb to local stack, preserve old route */ 324 /* skb to local stack, preserve old route */
246 if (!noref) 325 if (!noref)
247 ip_rt_put(rt); 326 ip_rt_put(rt);
@@ -250,28 +329,17 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest,
250 329
251 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) { 330 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) {
252 mtu = dst_mtu(&rt->dst); 331 mtu = dst_mtu(&rt->dst);
253 df = iph->frag_off & htons(IP_DF);
254 } else { 332 } else {
255 struct sock *sk = skb->sk;
256
257 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr); 333 mtu = dst_mtu(&rt->dst) - sizeof(struct iphdr);
258 if (mtu < 68) { 334 if (mtu < 68) {
259 IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); 335 IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__);
260 goto err_put; 336 goto err_put;
261 } 337 }
262 ort = skb_rtable(skb); 338 maybe_update_pmtu(skb_af, skb, mtu);
263 if (!skb->dev && sk && sk->sk_state != TCP_TIME_WAIT)
264 ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
265 /* MTU check allowed? */
266 df = sysctl_pmtu_disc(ipvs) ? iph->frag_off & htons(IP_DF) : 0;
267 } 339 }
268 340
269 /* MTU checking */ 341 if (!ensure_mtu_is_adequate(skb_af, rt_mode, ipvsh, skb, mtu))
270 if (unlikely(df && skb->len > mtu && !skb_is_gso(skb))) {
271 icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
272 IP_VS_DBG(1, "frag needed for %pI4\n", &iph->saddr);
273 goto err_put; 342 goto err_put;
274 }
275 343
276 skb_dst_drop(skb); 344 skb_dst_drop(skb);
277 if (noref) { 345 if (noref) {
@@ -295,12 +363,6 @@ err_unreach:
295} 363}
296 364
297#ifdef CONFIG_IP_VS_IPV6 365#ifdef CONFIG_IP_VS_IPV6
298
299static inline int __ip_vs_is_local_route6(struct rt6_info *rt)
300{
301 return rt->dst.dev && rt->dst.dev->flags & IFF_LOOPBACK;
302}
303
304static struct dst_entry * 366static struct dst_entry *
305__ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr, 367__ip_vs_route_output_v6(struct net *net, struct in6_addr *daddr,
306 struct in6_addr *ret_saddr, int do_xfrm) 368 struct in6_addr *ret_saddr, int do_xfrm)
@@ -339,14 +401,13 @@ out_err:
339 * Get route to destination or remote server 401 * Get route to destination or remote server
340 */ 402 */
341static int 403static int
342__ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, 404__ip_vs_get_out_rt_v6(int skb_af, struct sk_buff *skb, struct ip_vs_dest *dest,
343 struct in6_addr *daddr, struct in6_addr *ret_saddr, 405 struct in6_addr *daddr, struct in6_addr *ret_saddr,
344 struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode) 406 struct ip_vs_iphdr *ipvsh, int do_xfrm, int rt_mode)
345{ 407{
346 struct net *net = dev_net(skb_dst(skb)->dev); 408 struct net *net = dev_net(skb_dst(skb)->dev);
347 struct ip_vs_dest_dst *dest_dst; 409 struct ip_vs_dest_dst *dest_dst;
348 struct rt6_info *rt; /* Route to the other host */ 410 struct rt6_info *rt; /* Route to the other host */
349 struct rt6_info *ort; /* Original route */
350 struct dst_entry *dst; 411 struct dst_entry *dst;
351 int mtu; 412 int mtu;
352 int local, noref = 1; 413 int local, noref = 1;
@@ -393,32 +454,15 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
393 } 454 }
394 455
395 local = __ip_vs_is_local_route6(rt); 456 local = __ip_vs_is_local_route6(rt);
396 if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) & 457
397 rt_mode)) { 458 if (unlikely(crosses_local_route_boundary(skb_af, skb, rt_mode,
398 IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6c\n", 459 local))) {
399 local ? "local":"non-local", daddr); 460 IP_VS_DBG_RL("We are crossing local and non-local addresses"
461 " daddr=%pI6\n", &dest->addr.in6);
400 goto err_put; 462 goto err_put;
401 } 463 }
402 if (likely(!local)) { 464
403 if (unlikely((!skb->dev || skb->dev->flags & IFF_LOOPBACK) && 465 if (unlikely(local)) {
404 ipv6_addr_type(&ipv6_hdr(skb)->saddr) &
405 IPV6_ADDR_LOOPBACK)) {
406 IP_VS_DBG_RL("Stopping traffic from loopback address "
407 "%pI6c to non-local address, "
408 "dest: %pI6c\n",
409 &ipv6_hdr(skb)->saddr, daddr);
410 goto err_put;
411 }
412 } else {
413 ort = (struct rt6_info *) skb_dst(skb);
414 if (!(rt_mode & IP_VS_RT_MODE_RDR) &&
415 !__ip_vs_is_local_route6(ort)) {
416 IP_VS_DBG_RL("Redirect from non-local address %pI6c "
417 "to local requires NAT method, "
418 "dest: %pI6c\n",
419 &ipv6_hdr(skb)->daddr, daddr);
420 goto err_put;
421 }
422 /* skb to local stack, preserve old route */ 466 /* skb to local stack, preserve old route */
423 if (!noref) 467 if (!noref)
424 dst_release(&rt->dst); 468 dst_release(&rt->dst);
@@ -429,28 +473,17 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest,
429 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL))) 473 if (likely(!(rt_mode & IP_VS_RT_MODE_TUNNEL)))
430 mtu = dst_mtu(&rt->dst); 474 mtu = dst_mtu(&rt->dst);
431 else { 475 else {
432 struct sock *sk = skb->sk;
433
434 mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr); 476 mtu = dst_mtu(&rt->dst) - sizeof(struct ipv6hdr);
435 if (mtu < IPV6_MIN_MTU) { 477 if (mtu < IPV6_MIN_MTU) {
436 IP_VS_DBG_RL("%s(): mtu less than %d\n", __func__, 478 IP_VS_DBG_RL("%s(): mtu less than %d\n", __func__,
437 IPV6_MIN_MTU); 479 IPV6_MIN_MTU);
438 goto err_put; 480 goto err_put;
439 } 481 }
440 ort = (struct rt6_info *) skb_dst(skb); 482 maybe_update_pmtu(skb_af, skb, mtu);
441 if (!skb->dev && sk && sk->sk_state != TCP_TIME_WAIT)
442 ort->dst.ops->update_pmtu(&ort->dst, sk, NULL, mtu);
443 } 483 }
444 484
445 if (unlikely(__mtu_check_toobig_v6(skb, mtu))) { 485 if (!ensure_mtu_is_adequate(skb_af, rt_mode, ipvsh, skb, mtu))
446 if (!skb->dev)
447 skb->dev = net->loopback_dev;
448 /* only send ICMP too big on first fragment */
449 if (!ipvsh->fragoffs)
450 icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
451 IP_VS_DBG(1, "frag needed for %pI6c\n", &ipv6_hdr(skb)->saddr);
452 goto err_put; 486 goto err_put;
453 }
454 487
455 skb_dst_drop(skb); 488 skb_dst_drop(skb);
456 if (noref) { 489 if (noref) {
@@ -556,8 +589,8 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
556 EnterFunction(10); 589 EnterFunction(10);
557 590
558 rcu_read_lock(); 591 rcu_read_lock();
559 if (__ip_vs_get_out_rt(skb, NULL, iph->daddr, IP_VS_RT_MODE_NON_LOCAL, 592 if (__ip_vs_get_out_rt(cp->af, skb, NULL, iph->daddr,
560 NULL) < 0) 593 IP_VS_RT_MODE_NON_LOCAL, NULL, ipvsh) < 0)
561 goto tx_error; 594 goto tx_error;
562 595
563 ip_send_check(iph); 596 ip_send_check(iph);
@@ -586,7 +619,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
586 EnterFunction(10); 619 EnterFunction(10);
587 620
588 rcu_read_lock(); 621 rcu_read_lock();
589 if (__ip_vs_get_out_rt_v6(skb, NULL, &ipvsh->daddr.in6, NULL, 622 if (__ip_vs_get_out_rt_v6(cp->af, skb, NULL, &ipvsh->daddr.in6, NULL,
590 ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0) 623 ipvsh, 0, IP_VS_RT_MODE_NON_LOCAL) < 0)
591 goto tx_error; 624 goto tx_error;
592 625
@@ -633,10 +666,10 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
633 } 666 }
634 667
635 was_input = rt_is_input_route(skb_rtable(skb)); 668 was_input = rt_is_input_route(skb_rtable(skb));
636 local = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, 669 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip,
637 IP_VS_RT_MODE_LOCAL | 670 IP_VS_RT_MODE_LOCAL |
638 IP_VS_RT_MODE_NON_LOCAL | 671 IP_VS_RT_MODE_NON_LOCAL |
639 IP_VS_RT_MODE_RDR, NULL); 672 IP_VS_RT_MODE_RDR, NULL, ipvsh);
640 if (local < 0) 673 if (local < 0)
641 goto tx_error; 674 goto tx_error;
642 rt = skb_rtable(skb); 675 rt = skb_rtable(skb);
@@ -721,8 +754,8 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
721 IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p)); 754 IP_VS_DBG(10, "filled cport=%d\n", ntohs(*p));
722 } 755 }
723 756
724 local = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, 757 local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
725 ipvsh, 0, 758 NULL, ipvsh, 0,
726 IP_VS_RT_MODE_LOCAL | 759 IP_VS_RT_MODE_LOCAL |
727 IP_VS_RT_MODE_NON_LOCAL | 760 IP_VS_RT_MODE_NON_LOCAL |
728 IP_VS_RT_MODE_RDR); 761 IP_VS_RT_MODE_RDR);
@@ -791,6 +824,81 @@ tx_error:
791} 824}
792#endif 825#endif
793 826
827/* When forwarding a packet, we must ensure that we've got enough headroom
828 * for the encapsulation packet in the skb. This also gives us an
829 * opportunity to figure out what the payload_len, dsfield, ttl, and df
830 * values should be, so that we won't need to look at the old ip header
831 * again
832 */
833static struct sk_buff *
834ip_vs_prepare_tunneled_skb(struct sk_buff *skb, int skb_af,
835 unsigned int max_headroom, __u8 *next_protocol,
836 __u32 *payload_len, __u8 *dsfield, __u8 *ttl,
837 __be16 *df)
838{
839 struct sk_buff *new_skb = NULL;
840 struct iphdr *old_iph = NULL;
841#ifdef CONFIG_IP_VS_IPV6
842 struct ipv6hdr *old_ipv6h = NULL;
843#endif
844
845 if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) {
846 new_skb = skb_realloc_headroom(skb, max_headroom);
847 if (!new_skb)
848 goto error;
849 consume_skb(skb);
850 skb = new_skb;
851 }
852
853#ifdef CONFIG_IP_VS_IPV6
854 if (skb_af == AF_INET6) {
855 old_ipv6h = ipv6_hdr(skb);
856 *next_protocol = IPPROTO_IPV6;
857 if (payload_len)
858 *payload_len =
859 ntohs(old_ipv6h->payload_len) +
860 sizeof(*old_ipv6h);
861 *dsfield = ipv6_get_dsfield(old_ipv6h);
862 *ttl = old_ipv6h->hop_limit;
863 if (df)
864 *df = 0;
865 } else
866#endif
867 {
868 old_iph = ip_hdr(skb);
869 /* Copy DF, reset fragment offset and MF */
870 if (df)
871 *df = (old_iph->frag_off & htons(IP_DF));
872 *next_protocol = IPPROTO_IPIP;
873
874 /* fix old IP header checksum */
875 ip_send_check(old_iph);
876 *dsfield = ipv4_get_dsfield(old_iph);
877 *ttl = old_iph->ttl;
878 if (payload_len)
879 *payload_len = ntohs(old_iph->tot_len);
880 }
881
882 return skb;
883error:
884 kfree_skb(skb);
885 return ERR_PTR(-ENOMEM);
886}
887
888static inline int __tun_gso_type_mask(int encaps_af, int orig_af)
889{
890 if (encaps_af == AF_INET) {
891 if (orig_af == AF_INET)
892 return SKB_GSO_IPIP;
893
894 return SKB_GSO_SIT;
895 }
896
897 /* GSO: we need to provide proper SKB_GSO_ value for IPv6:
898 * SKB_GSO_SIT/IPV6
899 */
900 return 0;
901}
794 902
795/* 903/*
796 * IP Tunneling transmitter 904 * IP Tunneling transmitter
@@ -819,9 +927,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
819 struct rtable *rt; /* Route to the other host */ 927 struct rtable *rt; /* Route to the other host */
820 __be32 saddr; /* Source for tunnel */ 928 __be32 saddr; /* Source for tunnel */
821 struct net_device *tdev; /* Device to other host */ 929 struct net_device *tdev; /* Device to other host */
822 struct iphdr *old_iph = ip_hdr(skb); 930 __u8 next_protocol = 0;
823 u8 tos = old_iph->tos; 931 __u8 dsfield = 0;
824 __be16 df; 932 __u8 ttl = 0;
933 __be16 df = 0;
934 __be16 *dfp = NULL;
825 struct iphdr *iph; /* Our new IP header */ 935 struct iphdr *iph; /* Our new IP header */
826 unsigned int max_headroom; /* The extra header space needed */ 936 unsigned int max_headroom; /* The extra header space needed */
827 int ret, local; 937 int ret, local;
@@ -829,11 +939,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
829 EnterFunction(10); 939 EnterFunction(10);
830 940
831 rcu_read_lock(); 941 rcu_read_lock();
832 local = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, 942 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip,
833 IP_VS_RT_MODE_LOCAL | 943 IP_VS_RT_MODE_LOCAL |
834 IP_VS_RT_MODE_NON_LOCAL | 944 IP_VS_RT_MODE_NON_LOCAL |
835 IP_VS_RT_MODE_CONNECT | 945 IP_VS_RT_MODE_CONNECT |
836 IP_VS_RT_MODE_TUNNEL, &saddr); 946 IP_VS_RT_MODE_TUNNEL, &saddr, ipvsh);
837 if (local < 0) 947 if (local < 0)
838 goto tx_error; 948 goto tx_error;
839 if (local) { 949 if (local) {
@@ -844,29 +954,21 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
844 rt = skb_rtable(skb); 954 rt = skb_rtable(skb);
845 tdev = rt->dst.dev; 955 tdev = rt->dst.dev;
846 956
847 /* Copy DF, reset fragment offset and MF */
848 df = sysctl_pmtu_disc(ipvs) ? old_iph->frag_off & htons(IP_DF) : 0;
849
850 /* 957 /*
851 * Okay, now see if we can stuff it in the buffer as-is. 958 * Okay, now see if we can stuff it in the buffer as-is.
852 */ 959 */
853 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr); 960 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct iphdr);
854 961
855 if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { 962 /* We only care about the df field if sysctl_pmtu_disc(ipvs) is set */
856 struct sk_buff *new_skb = 963 dfp = sysctl_pmtu_disc(ipvs) ? &df : NULL;
857 skb_realloc_headroom(skb, max_headroom); 964 skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom,
858 965 &next_protocol, NULL, &dsfield,
859 if (!new_skb) 966 &ttl, dfp);
860 goto tx_error; 967 if (IS_ERR(skb))
861 consume_skb(skb); 968 goto tx_error;
862 skb = new_skb;
863 old_iph = ip_hdr(skb);
864 }
865
866 /* fix old IP header checksum */
867 ip_send_check(old_iph);
868 969
869 skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP); 970 skb = iptunnel_handle_offloads(
971 skb, false, __tun_gso_type_mask(AF_INET, cp->af));
870 if (IS_ERR(skb)) 972 if (IS_ERR(skb))
871 goto tx_error; 973 goto tx_error;
872 974
@@ -883,11 +985,11 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
883 iph->version = 4; 985 iph->version = 4;
884 iph->ihl = sizeof(struct iphdr)>>2; 986 iph->ihl = sizeof(struct iphdr)>>2;
885 iph->frag_off = df; 987 iph->frag_off = df;
886 iph->protocol = IPPROTO_IPIP; 988 iph->protocol = next_protocol;
887 iph->tos = tos; 989 iph->tos = dsfield;
888 iph->daddr = cp->daddr.ip; 990 iph->daddr = cp->daddr.ip;
889 iph->saddr = saddr; 991 iph->saddr = saddr;
890 iph->ttl = old_iph->ttl; 992 iph->ttl = ttl;
891 ip_select_ident(skb, NULL); 993 ip_select_ident(skb, NULL);
892 994
893 /* Another hack: avoid icmp_send in ip_fragment */ 995 /* Another hack: avoid icmp_send in ip_fragment */
@@ -920,7 +1022,10 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
920 struct rt6_info *rt; /* Route to the other host */ 1022 struct rt6_info *rt; /* Route to the other host */
921 struct in6_addr saddr; /* Source for tunnel */ 1023 struct in6_addr saddr; /* Source for tunnel */
922 struct net_device *tdev; /* Device to other host */ 1024 struct net_device *tdev; /* Device to other host */
923 struct ipv6hdr *old_iph = ipv6_hdr(skb); 1025 __u8 next_protocol = 0;
1026 __u32 payload_len = 0;
1027 __u8 dsfield = 0;
1028 __u8 ttl = 0;
924 struct ipv6hdr *iph; /* Our new IP header */ 1029 struct ipv6hdr *iph; /* Our new IP header */
925 unsigned int max_headroom; /* The extra header space needed */ 1030 unsigned int max_headroom; /* The extra header space needed */
926 int ret, local; 1031 int ret, local;
@@ -928,7 +1033,7 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
928 EnterFunction(10); 1033 EnterFunction(10);
929 1034
930 rcu_read_lock(); 1035 rcu_read_lock();
931 local = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, 1036 local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
932 &saddr, ipvsh, 1, 1037 &saddr, ipvsh, 1,
933 IP_VS_RT_MODE_LOCAL | 1038 IP_VS_RT_MODE_LOCAL |
934 IP_VS_RT_MODE_NON_LOCAL | 1039 IP_VS_RT_MODE_NON_LOCAL |
@@ -948,19 +1053,14 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
948 */ 1053 */
949 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr); 1054 max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(struct ipv6hdr);
950 1055
951 if (skb_headroom(skb) < max_headroom || skb_cloned(skb)) { 1056 skb = ip_vs_prepare_tunneled_skb(skb, cp->af, max_headroom,
952 struct sk_buff *new_skb = 1057 &next_protocol, &payload_len,
953 skb_realloc_headroom(skb, max_headroom); 1058 &dsfield, &ttl, NULL);
954 1059 if (IS_ERR(skb))
955 if (!new_skb) 1060 goto tx_error;
956 goto tx_error;
957 consume_skb(skb);
958 skb = new_skb;
959 old_iph = ipv6_hdr(skb);
960 }
961 1061
962 /* GSO: we need to provide proper SKB_GSO_ value for IPv6 */ 1062 skb = iptunnel_handle_offloads(
963 skb = iptunnel_handle_offloads(skb, false, 0); /* SKB_GSO_SIT/IPV6 */ 1063 skb, false, __tun_gso_type_mask(AF_INET6, cp->af));
964 if (IS_ERR(skb)) 1064 if (IS_ERR(skb))
965 goto tx_error; 1065 goto tx_error;
966 1066
@@ -975,14 +1075,13 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
975 */ 1075 */
976 iph = ipv6_hdr(skb); 1076 iph = ipv6_hdr(skb);
977 iph->version = 6; 1077 iph->version = 6;
978 iph->nexthdr = IPPROTO_IPV6; 1078 iph->nexthdr = next_protocol;
979 iph->payload_len = old_iph->payload_len; 1079 iph->payload_len = htons(payload_len);
980 be16_add_cpu(&iph->payload_len, sizeof(*old_iph));
981 memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); 1080 memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl));
982 ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph)); 1081 ipv6_change_dsfield(iph, 0, dsfield);
983 iph->daddr = cp->daddr.in6; 1082 iph->daddr = cp->daddr.in6;
984 iph->saddr = saddr; 1083 iph->saddr = saddr;
985 iph->hop_limit = old_iph->hop_limit; 1084 iph->hop_limit = ttl;
986 1085
987 /* Another hack: avoid icmp_send in ip_fragment */ 1086 /* Another hack: avoid icmp_send in ip_fragment */
988 skb->ignore_df = 1; 1087 skb->ignore_df = 1;
@@ -1021,10 +1120,10 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1021 EnterFunction(10); 1120 EnterFunction(10);
1022 1121
1023 rcu_read_lock(); 1122 rcu_read_lock();
1024 local = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, 1123 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip,
1025 IP_VS_RT_MODE_LOCAL | 1124 IP_VS_RT_MODE_LOCAL |
1026 IP_VS_RT_MODE_NON_LOCAL | 1125 IP_VS_RT_MODE_NON_LOCAL |
1027 IP_VS_RT_MODE_KNOWN_NH, NULL); 1126 IP_VS_RT_MODE_KNOWN_NH, NULL, ipvsh);
1028 if (local < 0) 1127 if (local < 0)
1029 goto tx_error; 1128 goto tx_error;
1030 if (local) { 1129 if (local) {
@@ -1060,8 +1159,8 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1060 EnterFunction(10); 1159 EnterFunction(10);
1061 1160
1062 rcu_read_lock(); 1161 rcu_read_lock();
1063 local = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, 1162 local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
1064 ipvsh, 0, 1163 NULL, ipvsh, 0,
1065 IP_VS_RT_MODE_LOCAL | 1164 IP_VS_RT_MODE_LOCAL |
1066 IP_VS_RT_MODE_NON_LOCAL); 1165 IP_VS_RT_MODE_NON_LOCAL);
1067 if (local < 0) 1166 if (local < 0)
@@ -1128,7 +1227,8 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp,
1128 IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | 1227 IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
1129 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; 1228 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
1130 rcu_read_lock(); 1229 rcu_read_lock();
1131 local = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, rt_mode, NULL); 1230 local = __ip_vs_get_out_rt(cp->af, skb, cp->dest, cp->daddr.ip, rt_mode,
1231 NULL, iph);
1132 if (local < 0) 1232 if (local < 0)
1133 goto tx_error; 1233 goto tx_error;
1134 rt = skb_rtable(skb); 1234 rt = skb_rtable(skb);
@@ -1219,8 +1319,8 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
1219 IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | 1319 IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL |
1220 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; 1320 IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL;
1221 rcu_read_lock(); 1321 rcu_read_lock();
1222 local = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, 1322 local = __ip_vs_get_out_rt_v6(cp->af, skb, cp->dest, &cp->daddr.in6,
1223 ipvsh, 0, rt_mode); 1323 NULL, ipvsh, 0, rt_mode);
1224 if (local < 0) 1324 if (local < 0)
1225 goto tx_error; 1325 goto tx_error;
1226 rt = (struct rt6_info *) skb_dst(skb); 1326 rt = (struct rt6_info *) skb_dst(skb);
diff --git a/net/netfilter/nf_conntrack_proto_generic.c b/net/netfilter/nf_conntrack_proto_generic.c
index d25f29377648..957c1db66652 100644
--- a/net/netfilter/nf_conntrack_proto_generic.c
+++ b/net/netfilter/nf_conntrack_proto_generic.c
@@ -14,6 +14,30 @@
14 14
15static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ; 15static unsigned int nf_ct_generic_timeout __read_mostly = 600*HZ;
16 16
17static bool nf_generic_should_process(u8 proto)
18{
19 switch (proto) {
20#ifdef CONFIG_NF_CT_PROTO_SCTP_MODULE
21 case IPPROTO_SCTP:
22 return false;
23#endif
24#ifdef CONFIG_NF_CT_PROTO_DCCP_MODULE
25 case IPPROTO_DCCP:
26 return false;
27#endif
28#ifdef CONFIG_NF_CT_PROTO_GRE_MODULE
29 case IPPROTO_GRE:
30 return false;
31#endif
32#ifdef CONFIG_NF_CT_PROTO_UDPLITE_MODULE
33 case IPPROTO_UDPLITE:
34 return false;
35#endif
36 default:
37 return true;
38 }
39}
40
17static inline struct nf_generic_net *generic_pernet(struct net *net) 41static inline struct nf_generic_net *generic_pernet(struct net *net)
18{ 42{
19 return &net->ct.nf_ct_proto.generic; 43 return &net->ct.nf_ct_proto.generic;
@@ -67,7 +91,7 @@ static int generic_packet(struct nf_conn *ct,
67static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb, 91static bool generic_new(struct nf_conn *ct, const struct sk_buff *skb,
68 unsigned int dataoff, unsigned int *timeouts) 92 unsigned int dataoff, unsigned int *timeouts)
69{ 93{
70 return true; 94 return nf_generic_should_process(nf_ct_protonum(ct));
71} 95}
72 96
73#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT) 97#if IS_ENABLED(CONFIG_NF_CT_NETLINK_TIMEOUT)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 82374601577e..19e79f0d9ad2 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -405,9 +405,9 @@ static const struct nla_policy nft_table_policy[NFTA_TABLE_MAX + 1] = {
405 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 }, 405 [NFTA_TABLE_FLAGS] = { .type = NLA_U32 },
406}; 406};
407 407
408static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq, 408static int nf_tables_fill_table_info(struct sk_buff *skb, struct net *net,
409 int event, u32 flags, int family, 409 u32 portid, u32 seq, int event, u32 flags,
410 const struct nft_table *table) 410 int family, const struct nft_table *table)
411{ 411{
412 struct nlmsghdr *nlh; 412 struct nlmsghdr *nlh;
413 struct nfgenmsg *nfmsg; 413 struct nfgenmsg *nfmsg;
@@ -420,7 +420,7 @@ static int nf_tables_fill_table_info(struct sk_buff *skb, u32 portid, u32 seq,
420 nfmsg = nlmsg_data(nlh); 420 nfmsg = nlmsg_data(nlh);
421 nfmsg->nfgen_family = family; 421 nfmsg->nfgen_family = family;
422 nfmsg->version = NFNETLINK_V0; 422 nfmsg->version = NFNETLINK_V0;
423 nfmsg->res_id = 0; 423 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
424 424
425 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) || 425 if (nla_put_string(skb, NFTA_TABLE_NAME, table->name) ||
426 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) || 426 nla_put_be32(skb, NFTA_TABLE_FLAGS, htonl(table->flags)) ||
@@ -448,8 +448,8 @@ static int nf_tables_table_notify(const struct nft_ctx *ctx, int event)
448 if (skb == NULL) 448 if (skb == NULL)
449 goto err; 449 goto err;
450 450
451 err = nf_tables_fill_table_info(skb, ctx->portid, ctx->seq, event, 0, 451 err = nf_tables_fill_table_info(skb, ctx->net, ctx->portid, ctx->seq,
452 ctx->afi->family, ctx->table); 452 event, 0, ctx->afi->family, ctx->table);
453 if (err < 0) { 453 if (err < 0) {
454 kfree_skb(skb); 454 kfree_skb(skb);
455 goto err; 455 goto err;
@@ -488,7 +488,7 @@ static int nf_tables_dump_tables(struct sk_buff *skb,
488 if (idx > s_idx) 488 if (idx > s_idx)
489 memset(&cb->args[1], 0, 489 memset(&cb->args[1], 0,
490 sizeof(cb->args) - sizeof(cb->args[0])); 490 sizeof(cb->args) - sizeof(cb->args[0]));
491 if (nf_tables_fill_table_info(skb, 491 if (nf_tables_fill_table_info(skb, net,
492 NETLINK_CB(cb->skb).portid, 492 NETLINK_CB(cb->skb).portid,
493 cb->nlh->nlmsg_seq, 493 cb->nlh->nlmsg_seq,
494 NFT_MSG_NEWTABLE, 494 NFT_MSG_NEWTABLE,
@@ -540,7 +540,7 @@ static int nf_tables_gettable(struct sock *nlsk, struct sk_buff *skb,
540 if (!skb2) 540 if (!skb2)
541 return -ENOMEM; 541 return -ENOMEM;
542 542
543 err = nf_tables_fill_table_info(skb2, NETLINK_CB(skb).portid, 543 err = nf_tables_fill_table_info(skb2, net, NETLINK_CB(skb).portid,
544 nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0, 544 nlh->nlmsg_seq, NFT_MSG_NEWTABLE, 0,
545 family, table); 545 family, table);
546 if (err < 0) 546 if (err < 0)
@@ -914,9 +914,9 @@ nla_put_failure:
914 return -ENOSPC; 914 return -ENOSPC;
915} 915}
916 916
917static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq, 917static int nf_tables_fill_chain_info(struct sk_buff *skb, struct net *net,
918 int event, u32 flags, int family, 918 u32 portid, u32 seq, int event, u32 flags,
919 const struct nft_table *table, 919 int family, const struct nft_table *table,
920 const struct nft_chain *chain) 920 const struct nft_chain *chain)
921{ 921{
922 struct nlmsghdr *nlh; 922 struct nlmsghdr *nlh;
@@ -930,7 +930,7 @@ static int nf_tables_fill_chain_info(struct sk_buff *skb, u32 portid, u32 seq,
930 nfmsg = nlmsg_data(nlh); 930 nfmsg = nlmsg_data(nlh);
931 nfmsg->nfgen_family = family; 931 nfmsg->nfgen_family = family;
932 nfmsg->version = NFNETLINK_V0; 932 nfmsg->version = NFNETLINK_V0;
933 nfmsg->res_id = 0; 933 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
934 934
935 if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name)) 935 if (nla_put_string(skb, NFTA_CHAIN_TABLE, table->name))
936 goto nla_put_failure; 936 goto nla_put_failure;
@@ -988,8 +988,8 @@ static int nf_tables_chain_notify(const struct nft_ctx *ctx, int event)
988 if (skb == NULL) 988 if (skb == NULL)
989 goto err; 989 goto err;
990 990
991 err = nf_tables_fill_chain_info(skb, ctx->portid, ctx->seq, event, 0, 991 err = nf_tables_fill_chain_info(skb, ctx->net, ctx->portid, ctx->seq,
992 ctx->afi->family, ctx->table, 992 event, 0, ctx->afi->family, ctx->table,
993 ctx->chain); 993 ctx->chain);
994 if (err < 0) { 994 if (err < 0) {
995 kfree_skb(skb); 995 kfree_skb(skb);
@@ -1031,7 +1031,8 @@ static int nf_tables_dump_chains(struct sk_buff *skb,
1031 if (idx > s_idx) 1031 if (idx > s_idx)
1032 memset(&cb->args[1], 0, 1032 memset(&cb->args[1], 0,
1033 sizeof(cb->args) - sizeof(cb->args[0])); 1033 sizeof(cb->args) - sizeof(cb->args[0]));
1034 if (nf_tables_fill_chain_info(skb, NETLINK_CB(cb->skb).portid, 1034 if (nf_tables_fill_chain_info(skb, net,
1035 NETLINK_CB(cb->skb).portid,
1035 cb->nlh->nlmsg_seq, 1036 cb->nlh->nlmsg_seq,
1036 NFT_MSG_NEWCHAIN, 1037 NFT_MSG_NEWCHAIN,
1037 NLM_F_MULTI, 1038 NLM_F_MULTI,
@@ -1090,7 +1091,7 @@ static int nf_tables_getchain(struct sock *nlsk, struct sk_buff *skb,
1090 if (!skb2) 1091 if (!skb2)
1091 return -ENOMEM; 1092 return -ENOMEM;
1092 1093
1093 err = nf_tables_fill_chain_info(skb2, NETLINK_CB(skb).portid, 1094 err = nf_tables_fill_chain_info(skb2, net, NETLINK_CB(skb).portid,
1094 nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0, 1095 nlh->nlmsg_seq, NFT_MSG_NEWCHAIN, 0,
1095 family, table, chain); 1096 family, table, chain);
1096 if (err < 0) 1097 if (err < 0)
@@ -1647,8 +1648,9 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = {
1647 .len = NFT_USERDATA_MAXLEN }, 1648 .len = NFT_USERDATA_MAXLEN },
1648}; 1649};
1649 1650
1650static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, 1651static int nf_tables_fill_rule_info(struct sk_buff *skb, struct net *net,
1651 int event, u32 flags, int family, 1652 u32 portid, u32 seq, int event,
1653 u32 flags, int family,
1652 const struct nft_table *table, 1654 const struct nft_table *table,
1653 const struct nft_chain *chain, 1655 const struct nft_chain *chain,
1654 const struct nft_rule *rule) 1656 const struct nft_rule *rule)
@@ -1668,7 +1670,7 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq,
1668 nfmsg = nlmsg_data(nlh); 1670 nfmsg = nlmsg_data(nlh);
1669 nfmsg->nfgen_family = family; 1671 nfmsg->nfgen_family = family;
1670 nfmsg->version = NFNETLINK_V0; 1672 nfmsg->version = NFNETLINK_V0;
1671 nfmsg->res_id = 0; 1673 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
1672 1674
1673 if (nla_put_string(skb, NFTA_RULE_TABLE, table->name)) 1675 if (nla_put_string(skb, NFTA_RULE_TABLE, table->name))
1674 goto nla_put_failure; 1676 goto nla_put_failure;
@@ -1724,8 +1726,8 @@ static int nf_tables_rule_notify(const struct nft_ctx *ctx,
1724 if (skb == NULL) 1726 if (skb == NULL)
1725 goto err; 1727 goto err;
1726 1728
1727 err = nf_tables_fill_rule_info(skb, ctx->portid, ctx->seq, event, 0, 1729 err = nf_tables_fill_rule_info(skb, ctx->net, ctx->portid, ctx->seq,
1728 ctx->afi->family, ctx->table, 1730 event, 0, ctx->afi->family, ctx->table,
1729 ctx->chain, rule); 1731 ctx->chain, rule);
1730 if (err < 0) { 1732 if (err < 0) {
1731 kfree_skb(skb); 1733 kfree_skb(skb);
@@ -1771,7 +1773,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
1771 if (idx > s_idx) 1773 if (idx > s_idx)
1772 memset(&cb->args[1], 0, 1774 memset(&cb->args[1], 0,
1773 sizeof(cb->args) - sizeof(cb->args[0])); 1775 sizeof(cb->args) - sizeof(cb->args[0]));
1774 if (nf_tables_fill_rule_info(skb, NETLINK_CB(cb->skb).portid, 1776 if (nf_tables_fill_rule_info(skb, net, NETLINK_CB(cb->skb).portid,
1775 cb->nlh->nlmsg_seq, 1777 cb->nlh->nlmsg_seq,
1776 NFT_MSG_NEWRULE, 1778 NFT_MSG_NEWRULE,
1777 NLM_F_MULTI | NLM_F_APPEND, 1779 NLM_F_MULTI | NLM_F_APPEND,
@@ -1837,7 +1839,7 @@ static int nf_tables_getrule(struct sock *nlsk, struct sk_buff *skb,
1837 if (!skb2) 1839 if (!skb2)
1838 return -ENOMEM; 1840 return -ENOMEM;
1839 1841
1840 err = nf_tables_fill_rule_info(skb2, NETLINK_CB(skb).portid, 1842 err = nf_tables_fill_rule_info(skb2, net, NETLINK_CB(skb).portid,
1841 nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0, 1843 nlh->nlmsg_seq, NFT_MSG_NEWRULE, 0,
1842 family, table, chain, rule); 1844 family, table, chain, rule);
1843 if (err < 0) 1845 if (err < 0)
@@ -2321,7 +2323,7 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2321 nfmsg = nlmsg_data(nlh); 2323 nfmsg = nlmsg_data(nlh);
2322 nfmsg->nfgen_family = ctx->afi->family; 2324 nfmsg->nfgen_family = ctx->afi->family;
2323 nfmsg->version = NFNETLINK_V0; 2325 nfmsg->version = NFNETLINK_V0;
2324 nfmsg->res_id = 0; 2326 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
2325 2327
2326 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name)) 2328 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
2327 goto nla_put_failure; 2329 goto nla_put_failure;
@@ -2342,6 +2344,11 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
2342 goto nla_put_failure; 2344 goto nla_put_failure;
2343 } 2345 }
2344 2346
2347 if (set->policy != NFT_SET_POL_PERFORMANCE) {
2348 if (nla_put_be32(skb, NFTA_SET_POLICY, htonl(set->policy)))
2349 goto nla_put_failure;
2350 }
2351
2345 desc = nla_nest_start(skb, NFTA_SET_DESC); 2352 desc = nla_nest_start(skb, NFTA_SET_DESC);
2346 if (desc == NULL) 2353 if (desc == NULL)
2347 goto nla_put_failure; 2354 goto nla_put_failure;
@@ -2667,6 +2674,7 @@ static int nf_tables_newset(struct sock *nlsk, struct sk_buff *skb,
2667 set->dlen = desc.dlen; 2674 set->dlen = desc.dlen;
2668 set->flags = flags; 2675 set->flags = flags;
2669 set->size = desc.size; 2676 set->size = desc.size;
2677 set->policy = policy;
2670 2678
2671 err = ops->init(set, &desc, nla); 2679 err = ops->init(set, &desc, nla);
2672 if (err < 0) 2680 if (err < 0)
@@ -2925,7 +2933,7 @@ static int nf_tables_dump_set(struct sk_buff *skb, struct netlink_callback *cb)
2925 nfmsg = nlmsg_data(nlh); 2933 nfmsg = nlmsg_data(nlh);
2926 nfmsg->nfgen_family = ctx.afi->family; 2934 nfmsg->nfgen_family = ctx.afi->family;
2927 nfmsg->version = NFNETLINK_V0; 2935 nfmsg->version = NFNETLINK_V0;
2928 nfmsg->res_id = 0; 2936 nfmsg->res_id = htons(ctx.net->nft.base_seq & 0xffff);
2929 2937
2930 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, ctx.table->name)) 2938 if (nla_put_string(skb, NFTA_SET_ELEM_LIST_TABLE, ctx.table->name))
2931 goto nla_put_failure; 2939 goto nla_put_failure;
@@ -3006,7 +3014,7 @@ static int nf_tables_fill_setelem_info(struct sk_buff *skb,
3006 nfmsg = nlmsg_data(nlh); 3014 nfmsg = nlmsg_data(nlh);
3007 nfmsg->nfgen_family = ctx->afi->family; 3015 nfmsg->nfgen_family = ctx->afi->family;
3008 nfmsg->version = NFNETLINK_V0; 3016 nfmsg->version = NFNETLINK_V0;
3009 nfmsg->res_id = 0; 3017 nfmsg->res_id = htons(ctx->net->nft.base_seq & 0xffff);
3010 3018
3011 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name)) 3019 if (nla_put_string(skb, NFTA_SET_TABLE, ctx->table->name))
3012 goto nla_put_failure; 3020 goto nla_put_failure;
@@ -3293,6 +3301,87 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb,
3293 return err; 3301 return err;
3294} 3302}
3295 3303
3304static int nf_tables_fill_gen_info(struct sk_buff *skb, struct net *net,
3305 u32 portid, u32 seq)
3306{
3307 struct nlmsghdr *nlh;
3308 struct nfgenmsg *nfmsg;
3309 int event = (NFNL_SUBSYS_NFTABLES << 8) | NFT_MSG_NEWGEN;
3310
3311 nlh = nlmsg_put(skb, portid, seq, event, sizeof(struct nfgenmsg), 0);
3312 if (nlh == NULL)
3313 goto nla_put_failure;
3314
3315 nfmsg = nlmsg_data(nlh);
3316 nfmsg->nfgen_family = AF_UNSPEC;
3317 nfmsg->version = NFNETLINK_V0;
3318 nfmsg->res_id = htons(net->nft.base_seq & 0xffff);
3319
3320 if (nla_put_be32(skb, NFTA_GEN_ID, htonl(net->nft.base_seq)))
3321 goto nla_put_failure;
3322
3323 return nlmsg_end(skb, nlh);
3324
3325nla_put_failure:
3326 nlmsg_trim(skb, nlh);
3327 return -EMSGSIZE;
3328}
3329
3330static int nf_tables_gen_notify(struct net *net, struct sk_buff *skb, int event)
3331{
3332 struct nlmsghdr *nlh = nlmsg_hdr(skb);
3333 struct sk_buff *skb2;
3334 int err;
3335
3336 if (nlmsg_report(nlh) &&
3337 !nfnetlink_has_listeners(net, NFNLGRP_NFTABLES))
3338 return 0;
3339
3340 err = -ENOBUFS;
3341 skb2 = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL);
3342 if (skb2 == NULL)
3343 goto err;
3344
3345 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
3346 nlh->nlmsg_seq);
3347 if (err < 0) {
3348 kfree_skb(skb2);
3349 goto err;
3350 }
3351
3352 err = nfnetlink_send(skb2, net, NETLINK_CB(skb).portid,
3353 NFNLGRP_NFTABLES, nlmsg_report(nlh), GFP_KERNEL);
3354err:
3355 if (err < 0) {
3356 nfnetlink_set_err(net, NETLINK_CB(skb).portid, NFNLGRP_NFTABLES,
3357 err);
3358 }
3359 return err;
3360}
3361
3362static int nf_tables_getgen(struct sock *nlsk, struct sk_buff *skb,
3363 const struct nlmsghdr *nlh,
3364 const struct nlattr * const nla[])
3365{
3366 struct net *net = sock_net(skb->sk);
3367 struct sk_buff *skb2;
3368 int err;
3369
3370 skb2 = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL);
3371 if (skb2 == NULL)
3372 return -ENOMEM;
3373
3374 err = nf_tables_fill_gen_info(skb2, net, NETLINK_CB(skb).portid,
3375 nlh->nlmsg_seq);
3376 if (err < 0)
3377 goto err;
3378
3379 return nlmsg_unicast(nlsk, skb2, NETLINK_CB(skb).portid);
3380err:
3381 kfree_skb(skb2);
3382 return err;
3383}
3384
3296static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = { 3385static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3297 [NFT_MSG_NEWTABLE] = { 3386 [NFT_MSG_NEWTABLE] = {
3298 .call_batch = nf_tables_newtable, 3387 .call_batch = nf_tables_newtable,
@@ -3369,6 +3458,9 @@ static const struct nfnl_callback nf_tables_cb[NFT_MSG_MAX] = {
3369 .attr_count = NFTA_SET_ELEM_LIST_MAX, 3458 .attr_count = NFTA_SET_ELEM_LIST_MAX,
3370 .policy = nft_set_elem_list_policy, 3459 .policy = nft_set_elem_list_policy,
3371 }, 3460 },
3461 [NFT_MSG_GETGEN] = {
3462 .call = nf_tables_getgen,
3463 },
3372}; 3464};
3373 3465
3374static void nft_chain_commit_update(struct nft_trans *trans) 3466static void nft_chain_commit_update(struct nft_trans *trans)
@@ -3526,6 +3618,8 @@ static int nf_tables_commit(struct sk_buff *skb)
3526 call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu); 3618 call_rcu(&trans->rcu_head, nf_tables_commit_release_rcu);
3527 } 3619 }
3528 3620
3621 nf_tables_gen_notify(net, skb, NFT_MSG_NEWGEN);
3622
3529 return 0; 3623 return 0;
3530} 3624}
3531 3625
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c
index c138b8fbe280..f77d3f7f22b5 100644
--- a/net/netfilter/nfnetlink.c
+++ b/net/netfilter/nfnetlink.c
@@ -333,7 +333,7 @@ replay:
333 * original skb. 333 * original skb.
334 */ 334 */
335 if (err == -EAGAIN) { 335 if (err == -EAGAIN) {
336 ss->abort(skb); 336 ss->abort(oskb);
337 nfnl_unlock(subsys_id); 337 nfnl_unlock(subsys_id);
338 kfree_skb(nskb); 338 kfree_skb(nskb);
339 goto replay; 339 goto replay;
@@ -357,9 +357,9 @@ ack:
357 } 357 }
358done: 358done:
359 if (success && done) 359 if (success && done)
360 ss->commit(skb); 360 ss->commit(oskb);
361 else 361 else
362 ss->abort(skb); 362 ss->abort(oskb);
363 363
364 nfnl_unlock(subsys_id); 364 nfnl_unlock(subsys_id);
365 kfree_skb(nskb); 365 kfree_skb(nskb);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 272ae4d6fdf4..133eb4772f12 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -1101,22 +1101,11 @@ static const struct seq_operations xt_match_seq_ops = {
1101 1101
1102static int xt_match_open(struct inode *inode, struct file *file) 1102static int xt_match_open(struct inode *inode, struct file *file)
1103{ 1103{
1104 struct seq_file *seq;
1105 struct nf_mttg_trav *trav; 1104 struct nf_mttg_trav *trav;
1106 int ret; 1105 trav = __seq_open_private(file, &xt_match_seq_ops, sizeof(*trav));
1107 1106 if (!trav)
1108 trav = kmalloc(sizeof(*trav), GFP_KERNEL);
1109 if (trav == NULL)
1110 return -ENOMEM; 1107 return -ENOMEM;
1111 1108
1112 ret = seq_open(file, &xt_match_seq_ops);
1113 if (ret < 0) {
1114 kfree(trav);
1115 return ret;
1116 }
1117
1118 seq = file->private_data;
1119 seq->private = trav;
1120 trav->nfproto = (unsigned long)PDE_DATA(inode); 1109 trav->nfproto = (unsigned long)PDE_DATA(inode);
1121 return 0; 1110 return 0;
1122} 1111}
@@ -1165,22 +1154,11 @@ static const struct seq_operations xt_target_seq_ops = {
1165 1154
1166static int xt_target_open(struct inode *inode, struct file *file) 1155static int xt_target_open(struct inode *inode, struct file *file)
1167{ 1156{
1168 struct seq_file *seq;
1169 struct nf_mttg_trav *trav; 1157 struct nf_mttg_trav *trav;
1170 int ret; 1158 trav = __seq_open_private(file, &xt_target_seq_ops, sizeof(*trav));
1171 1159 if (!trav)
1172 trav = kmalloc(sizeof(*trav), GFP_KERNEL);
1173 if (trav == NULL)
1174 return -ENOMEM; 1160 return -ENOMEM;
1175 1161
1176 ret = seq_open(file, &xt_target_seq_ops);
1177 if (ret < 0) {
1178 kfree(trav);
1179 return ret;
1180 }
1181
1182 seq = file->private_data;
1183 seq->private = trav;
1184 trav->nfproto = (unsigned long)PDE_DATA(inode); 1162 trav->nfproto = (unsigned long)PDE_DATA(inode);
1185 return 0; 1163 return 0;
1186} 1164}
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c
index cb70f6ec5695..5732cd64acc0 100644
--- a/net/netfilter/xt_set.c
+++ b/net/netfilter/xt_set.c
@@ -366,6 +366,140 @@ set_target_v2(struct sk_buff *skb, const struct xt_action_param *par)
366#define set_target_v2_checkentry set_target_v1_checkentry 366#define set_target_v2_checkentry set_target_v1_checkentry
367#define set_target_v2_destroy set_target_v1_destroy 367#define set_target_v2_destroy set_target_v1_destroy
368 368
369/* Revision 3 target */
370
371static unsigned int
372set_target_v3(struct sk_buff *skb, const struct xt_action_param *par)
373{
374 const struct xt_set_info_target_v3 *info = par->targinfo;
375 ADT_OPT(add_opt, par->family, info->add_set.dim,
376 info->add_set.flags, info->flags, info->timeout);
377 ADT_OPT(del_opt, par->family, info->del_set.dim,
378 info->del_set.flags, 0, UINT_MAX);
379 ADT_OPT(map_opt, par->family, info->map_set.dim,
380 info->map_set.flags, 0, UINT_MAX);
381
382 int ret;
383
384 /* Normalize to fit into jiffies */
385 if (add_opt.ext.timeout != IPSET_NO_TIMEOUT &&
386 add_opt.ext.timeout > UINT_MAX/MSEC_PER_SEC)
387 add_opt.ext.timeout = UINT_MAX/MSEC_PER_SEC;
388 if (info->add_set.index != IPSET_INVALID_ID)
389 ip_set_add(info->add_set.index, skb, par, &add_opt);
390 if (info->del_set.index != IPSET_INVALID_ID)
391 ip_set_del(info->del_set.index, skb, par, &del_opt);
392 if (info->map_set.index != IPSET_INVALID_ID) {
393 map_opt.cmdflags |= info->flags & (IPSET_FLAG_MAP_SKBMARK |
394 IPSET_FLAG_MAP_SKBPRIO |
395 IPSET_FLAG_MAP_SKBQUEUE);
396 ret = match_set(info->map_set.index, skb, par, &map_opt,
397 info->map_set.flags & IPSET_INV_MATCH);
398 if (!ret)
399 return XT_CONTINUE;
400 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBMARK)
401 skb->mark = (skb->mark & ~(map_opt.ext.skbmarkmask))
402 ^ (map_opt.ext.skbmark);
403 if (map_opt.cmdflags & IPSET_FLAG_MAP_SKBPRIO)
404 skb->priority = map_opt.ext.skbprio;
405 if ((map_opt.cmdflags & IPSET_FLAG_MAP_SKBQUEUE) &&
406 skb->dev &&
407 skb->dev->real_num_tx_queues > map_opt.ext.skbqueue)
408 skb_set_queue_mapping(skb, map_opt.ext.skbqueue);
409 }
410 return XT_CONTINUE;
411}
412
413
414static int
415set_target_v3_checkentry(const struct xt_tgchk_param *par)
416{
417 const struct xt_set_info_target_v3 *info = par->targinfo;
418 ip_set_id_t index;
419
420 if (info->add_set.index != IPSET_INVALID_ID) {
421 index = ip_set_nfnl_get_byindex(par->net,
422 info->add_set.index);
423 if (index == IPSET_INVALID_ID) {
424 pr_warn("Cannot find add_set index %u as target\n",
425 info->add_set.index);
426 return -ENOENT;
427 }
428 }
429
430 if (info->del_set.index != IPSET_INVALID_ID) {
431 index = ip_set_nfnl_get_byindex(par->net,
432 info->del_set.index);
433 if (index == IPSET_INVALID_ID) {
434 pr_warn("Cannot find del_set index %u as target\n",
435 info->del_set.index);
436 if (info->add_set.index != IPSET_INVALID_ID)
437 ip_set_nfnl_put(par->net,
438 info->add_set.index);
439 return -ENOENT;
440 }
441 }
442
443 if (info->map_set.index != IPSET_INVALID_ID) {
444 if (strncmp(par->table, "mangle", 7)) {
445 pr_warn("--map-set only usable from mangle table\n");
446 return -EINVAL;
447 }
448 if (((info->flags & IPSET_FLAG_MAP_SKBPRIO) |
449 (info->flags & IPSET_FLAG_MAP_SKBQUEUE)) &&
450 !(par->hook_mask & (1 << NF_INET_FORWARD |
451 1 << NF_INET_LOCAL_OUT |
452 1 << NF_INET_POST_ROUTING))) {
453 pr_warn("mapping of prio or/and queue is allowed only"
454 "from OUTPUT/FORWARD/POSTROUTING chains\n");
455 return -EINVAL;
456 }
457 index = ip_set_nfnl_get_byindex(par->net,
458 info->map_set.index);
459 if (index == IPSET_INVALID_ID) {
460 pr_warn("Cannot find map_set index %u as target\n",
461 info->map_set.index);
462 if (info->add_set.index != IPSET_INVALID_ID)
463 ip_set_nfnl_put(par->net,
464 info->add_set.index);
465 if (info->del_set.index != IPSET_INVALID_ID)
466 ip_set_nfnl_put(par->net,
467 info->del_set.index);
468 return -ENOENT;
469 }
470 }
471
472 if (info->add_set.dim > IPSET_DIM_MAX ||
473 info->del_set.dim > IPSET_DIM_MAX ||
474 info->map_set.dim > IPSET_DIM_MAX) {
475 pr_warn("Protocol error: SET target dimension "
476 "is over the limit!\n");
477 if (info->add_set.index != IPSET_INVALID_ID)
478 ip_set_nfnl_put(par->net, info->add_set.index);
479 if (info->del_set.index != IPSET_INVALID_ID)
480 ip_set_nfnl_put(par->net, info->del_set.index);
481 if (info->map_set.index != IPSET_INVALID_ID)
482 ip_set_nfnl_put(par->net, info->map_set.index);
483 return -ERANGE;
484 }
485
486 return 0;
487}
488
489static void
490set_target_v3_destroy(const struct xt_tgdtor_param *par)
491{
492 const struct xt_set_info_target_v3 *info = par->targinfo;
493
494 if (info->add_set.index != IPSET_INVALID_ID)
495 ip_set_nfnl_put(par->net, info->add_set.index);
496 if (info->del_set.index != IPSET_INVALID_ID)
497 ip_set_nfnl_put(par->net, info->del_set.index);
498 if (info->map_set.index != IPSET_INVALID_ID)
499 ip_set_nfnl_put(par->net, info->map_set.index);
500}
501
502
369static struct xt_match set_matches[] __read_mostly = { 503static struct xt_match set_matches[] __read_mostly = {
370 { 504 {
371 .name = "set", 505 .name = "set",
@@ -493,6 +627,27 @@ static struct xt_target set_targets[] __read_mostly = {
493 .destroy = set_target_v2_destroy, 627 .destroy = set_target_v2_destroy,
494 .me = THIS_MODULE 628 .me = THIS_MODULE
495 }, 629 },
630 /* --map-set support */
631 {
632 .name = "SET",
633 .revision = 3,
634 .family = NFPROTO_IPV4,
635 .target = set_target_v3,
636 .targetsize = sizeof(struct xt_set_info_target_v3),
637 .checkentry = set_target_v3_checkentry,
638 .destroy = set_target_v3_destroy,
639 .me = THIS_MODULE
640 },
641 {
642 .name = "SET",
643 .revision = 3,
644 .family = NFPROTO_IPV6,
645 .target = set_target_v3,
646 .targetsize = sizeof(struct xt_set_info_target_v3),
647 .checkentry = set_target_v3_checkentry,
648 .destroy = set_target_v3_destroy,
649 .me = THIS_MODULE
650 },
496}; 651};
497 652
498static int __init xt_set_init(void) 653static int __init xt_set_init(void)