diff options
59 files changed, 1168 insertions, 378 deletions
diff --git a/include/linux/netfilter/Kbuild b/include/linux/netfilter/Kbuild index a1b410c76fc3..e630a2ed4f18 100644 --- a/include/linux/netfilter/Kbuild +++ b/include/linux/netfilter/Kbuild | |||
| @@ -5,7 +5,9 @@ header-y += nf_conntrack_ftp.h | |||
| 5 | header-y += nf_conntrack_sctp.h | 5 | header-y += nf_conntrack_sctp.h |
| 6 | header-y += nf_conntrack_tcp.h | 6 | header-y += nf_conntrack_tcp.h |
| 7 | header-y += nf_conntrack_tuple_common.h | 7 | header-y += nf_conntrack_tuple_common.h |
| 8 | header-y += nf_nat.h | ||
| 8 | header-y += nfnetlink.h | 9 | header-y += nfnetlink.h |
| 10 | header-y += nfnetlink_acct.h | ||
| 9 | header-y += nfnetlink_compat.h | 11 | header-y += nfnetlink_compat.h |
| 10 | header-y += nfnetlink_conntrack.h | 12 | header-y += nfnetlink_conntrack.h |
| 11 | header-y += nfnetlink_log.h | 13 | header-y += nfnetlink_log.h |
| @@ -21,6 +23,7 @@ header-y += xt_DSCP.h | |||
| 21 | header-y += xt_IDLETIMER.h | 23 | header-y += xt_IDLETIMER.h |
| 22 | header-y += xt_LED.h | 24 | header-y += xt_LED.h |
| 23 | header-y += xt_MARK.h | 25 | header-y += xt_MARK.h |
| 26 | header-y += xt_nfacct.h | ||
| 24 | header-y += xt_NFLOG.h | 27 | header-y += xt_NFLOG.h |
| 25 | header-y += xt_NFQUEUE.h | 28 | header-y += xt_NFQUEUE.h |
| 26 | header-y += xt_RATEEST.h | 29 | header-y += xt_RATEEST.h |
diff --git a/include/linux/netfilter/nf_conntrack_common.h b/include/linux/netfilter/nf_conntrack_common.h index 0d3dd66322ec..9e3a2838291b 100644 --- a/include/linux/netfilter/nf_conntrack_common.h +++ b/include/linux/netfilter/nf_conntrack_common.h | |||
| @@ -83,6 +83,10 @@ enum ip_conntrack_status { | |||
| 83 | /* Conntrack is a fake untracked entry */ | 83 | /* Conntrack is a fake untracked entry */ |
| 84 | IPS_UNTRACKED_BIT = 12, | 84 | IPS_UNTRACKED_BIT = 12, |
| 85 | IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), | 85 | IPS_UNTRACKED = (1 << IPS_UNTRACKED_BIT), |
| 86 | |||
| 87 | /* Conntrack has a userspace helper. */ | ||
| 88 | IPS_USERSPACE_HELPER_BIT = 13, | ||
| 89 | IPS_USERSPACE_HELPER = (1 << IPS_USERSPACE_HELPER_BIT), | ||
| 86 | }; | 90 | }; |
| 87 | 91 | ||
| 88 | /* Connection tracking event types */ | 92 | /* Connection tracking event types */ |
diff --git a/include/linux/netfilter/nf_conntrack_tuple_common.h b/include/linux/netfilter/nf_conntrack_tuple_common.h index 2ea22b018a87..2f6bbc5b8125 100644 --- a/include/linux/netfilter/nf_conntrack_tuple_common.h +++ b/include/linux/netfilter/nf_conntrack_tuple_common.h | |||
| @@ -7,6 +7,33 @@ enum ip_conntrack_dir { | |||
| 7 | IP_CT_DIR_MAX | 7 | IP_CT_DIR_MAX |
| 8 | }; | 8 | }; |
| 9 | 9 | ||
| 10 | /* The protocol-specific manipulable parts of the tuple: always in | ||
| 11 | * network order | ||
| 12 | */ | ||
| 13 | union nf_conntrack_man_proto { | ||
| 14 | /* Add other protocols here. */ | ||
| 15 | __be16 all; | ||
| 16 | |||
| 17 | struct { | ||
| 18 | __be16 port; | ||
| 19 | } tcp; | ||
| 20 | struct { | ||
| 21 | __be16 port; | ||
| 22 | } udp; | ||
| 23 | struct { | ||
| 24 | __be16 id; | ||
| 25 | } icmp; | ||
| 26 | struct { | ||
| 27 | __be16 port; | ||
| 28 | } dccp; | ||
| 29 | struct { | ||
| 30 | __be16 port; | ||
| 31 | } sctp; | ||
| 32 | struct { | ||
| 33 | __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */ | ||
| 34 | } gre; | ||
| 35 | }; | ||
| 36 | |||
| 10 | #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) | 37 | #define CTINFO2DIR(ctinfo) ((ctinfo) >= IP_CT_IS_REPLY ? IP_CT_DIR_REPLY : IP_CT_DIR_ORIGINAL) |
| 11 | 38 | ||
| 12 | #endif /* _NF_CONNTRACK_TUPLE_COMMON_H */ | 39 | #endif /* _NF_CONNTRACK_TUPLE_COMMON_H */ |
diff --git a/include/linux/netfilter/nf_nat.h b/include/linux/netfilter/nf_nat.h new file mode 100644 index 000000000000..8df2d13730b2 --- /dev/null +++ b/include/linux/netfilter/nf_nat.h | |||
| @@ -0,0 +1,25 @@ | |||
| 1 | #ifndef _NETFILTER_NF_NAT_H | ||
| 2 | #define _NETFILTER_NF_NAT_H | ||
| 3 | |||
| 4 | #include <linux/netfilter.h> | ||
| 5 | #include <linux/netfilter/nf_conntrack_tuple_common.h> | ||
| 6 | |||
| 7 | #define NF_NAT_RANGE_MAP_IPS 1 | ||
| 8 | #define NF_NAT_RANGE_PROTO_SPECIFIED 2 | ||
| 9 | #define NF_NAT_RANGE_PROTO_RANDOM 4 | ||
| 10 | #define NF_NAT_RANGE_PERSISTENT 8 | ||
| 11 | |||
| 12 | struct nf_nat_ipv4_range { | ||
| 13 | unsigned int flags; | ||
| 14 | __be32 min_ip; | ||
| 15 | __be32 max_ip; | ||
| 16 | union nf_conntrack_man_proto min; | ||
| 17 | union nf_conntrack_man_proto max; | ||
| 18 | }; | ||
| 19 | |||
| 20 | struct nf_nat_ipv4_multi_range_compat { | ||
| 21 | unsigned int rangesize; | ||
| 22 | struct nf_nat_ipv4_range range[1]; | ||
| 23 | }; | ||
| 24 | |||
| 25 | #endif /* _NETFILTER_NF_NAT_H */ | ||
diff --git a/include/linux/netfilter/nfnetlink.h b/include/linux/netfilter/nfnetlink.h index 74d33861473c..b64454c2f79f 100644 --- a/include/linux/netfilter/nfnetlink.h +++ b/include/linux/netfilter/nfnetlink.h | |||
| @@ -48,7 +48,8 @@ struct nfgenmsg { | |||
| 48 | #define NFNL_SUBSYS_ULOG 4 | 48 | #define NFNL_SUBSYS_ULOG 4 |
| 49 | #define NFNL_SUBSYS_OSF 5 | 49 | #define NFNL_SUBSYS_OSF 5 |
| 50 | #define NFNL_SUBSYS_IPSET 6 | 50 | #define NFNL_SUBSYS_IPSET 6 |
| 51 | #define NFNL_SUBSYS_COUNT 7 | 51 | #define NFNL_SUBSYS_ACCT 7 |
| 52 | #define NFNL_SUBSYS_COUNT 8 | ||
| 52 | 53 | ||
| 53 | #ifdef __KERNEL__ | 54 | #ifdef __KERNEL__ |
| 54 | 55 | ||
diff --git a/include/linux/netfilter/nfnetlink_acct.h b/include/linux/netfilter/nfnetlink_acct.h new file mode 100644 index 000000000000..7c4279b4ae7a --- /dev/null +++ b/include/linux/netfilter/nfnetlink_acct.h | |||
| @@ -0,0 +1,36 @@ | |||
| 1 | #ifndef _NFNL_ACCT_H_ | ||
| 2 | #define _NFNL_ACCT_H_ | ||
| 3 | |||
| 4 | #ifndef NFACCT_NAME_MAX | ||
| 5 | #define NFACCT_NAME_MAX 32 | ||
| 6 | #endif | ||
| 7 | |||
| 8 | enum nfnl_acct_msg_types { | ||
| 9 | NFNL_MSG_ACCT_NEW, | ||
| 10 | NFNL_MSG_ACCT_GET, | ||
| 11 | NFNL_MSG_ACCT_GET_CTRZERO, | ||
| 12 | NFNL_MSG_ACCT_DEL, | ||
| 13 | NFNL_MSG_ACCT_MAX | ||
| 14 | }; | ||
| 15 | |||
| 16 | enum nfnl_acct_type { | ||
| 17 | NFACCT_UNSPEC, | ||
| 18 | NFACCT_NAME, | ||
| 19 | NFACCT_PKTS, | ||
| 20 | NFACCT_BYTES, | ||
| 21 | NFACCT_USE, | ||
| 22 | __NFACCT_MAX | ||
| 23 | }; | ||
| 24 | #define NFACCT_MAX (__NFACCT_MAX - 1) | ||
| 25 | |||
| 26 | #ifdef __KERNEL__ | ||
| 27 | |||
| 28 | struct nf_acct; | ||
| 29 | |||
| 30 | extern struct nf_acct *nfnl_acct_find_get(const char *filter_name); | ||
| 31 | extern void nfnl_acct_put(struct nf_acct *acct); | ||
| 32 | extern void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct); | ||
| 33 | |||
| 34 | #endif /* __KERNEL__ */ | ||
| 35 | |||
| 36 | #endif /* _NFNL_ACCT_H */ | ||
diff --git a/include/linux/netfilter/xt_CT.h b/include/linux/netfilter/xt_CT.h index b56e76811c04..6390f0992f36 100644 --- a/include/linux/netfilter/xt_CT.h +++ b/include/linux/netfilter/xt_CT.h | |||
| @@ -3,7 +3,8 @@ | |||
| 3 | 3 | ||
| 4 | #include <linux/types.h> | 4 | #include <linux/types.h> |
| 5 | 5 | ||
| 6 | #define XT_CT_NOTRACK 0x1 | 6 | #define XT_CT_NOTRACK 0x1 |
| 7 | #define XT_CT_USERSPACE_HELPER 0x2 | ||
| 7 | 8 | ||
| 8 | struct xt_ct_target_info { | 9 | struct xt_ct_target_info { |
| 9 | __u16 flags; | 10 | __u16 flags; |
diff --git a/include/linux/netfilter/xt_nfacct.h b/include/linux/netfilter/xt_nfacct.h new file mode 100644 index 000000000000..3e19c8a86576 --- /dev/null +++ b/include/linux/netfilter/xt_nfacct.h | |||
| @@ -0,0 +1,13 @@ | |||
| 1 | #ifndef _XT_NFACCT_MATCH_H | ||
| 2 | #define _XT_NFACCT_MATCH_H | ||
| 3 | |||
| 4 | #include <linux/netfilter/nfnetlink_acct.h> | ||
| 5 | |||
| 6 | struct nf_acct; | ||
| 7 | |||
| 8 | struct xt_nfacct_match_info { | ||
| 9 | char name[NFACCT_NAME_MAX]; | ||
| 10 | struct nf_acct *nfacct; | ||
| 11 | }; | ||
| 12 | |||
| 13 | #endif /* _XT_NFACCT_MATCH_H */ | ||
diff --git a/include/linux/netfilter/xt_rpfilter.h b/include/linux/netfilter/xt_rpfilter.h new file mode 100644 index 000000000000..8358d4f71952 --- /dev/null +++ b/include/linux/netfilter/xt_rpfilter.h | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | #ifndef _XT_RPATH_H | ||
| 2 | #define _XT_RPATH_H | ||
| 3 | |||
| 4 | #include <linux/types.h> | ||
| 5 | |||
| 6 | enum { | ||
| 7 | XT_RPFILTER_LOOSE = 1 << 0, | ||
| 8 | XT_RPFILTER_VALID_MARK = 1 << 1, | ||
| 9 | XT_RPFILTER_ACCEPT_LOCAL = 1 << 2, | ||
| 10 | XT_RPFILTER_INVERT = 1 << 3, | ||
| 11 | #ifdef __KERNEL__ | ||
| 12 | XT_RPFILTER_OPTION_MASK = XT_RPFILTER_LOOSE | | ||
| 13 | XT_RPFILTER_VALID_MARK | | ||
| 14 | XT_RPFILTER_ACCEPT_LOCAL | | ||
| 15 | XT_RPFILTER_INVERT, | ||
| 16 | #endif | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct xt_rpfilter_info { | ||
| 20 | __u8 flags; | ||
| 21 | }; | ||
| 22 | |||
| 23 | #endif | ||
diff --git a/include/linux/netfilter_ipv4/Kbuild b/include/linux/netfilter_ipv4/Kbuild index c3b45480ecf7..f9930c87fff3 100644 --- a/include/linux/netfilter_ipv4/Kbuild +++ b/include/linux/netfilter_ipv4/Kbuild | |||
| @@ -12,4 +12,3 @@ header-y += ipt_ah.h | |||
| 12 | header-y += ipt_ecn.h | 12 | header-y += ipt_ecn.h |
| 13 | header-y += ipt_realm.h | 13 | header-y += ipt_realm.h |
| 14 | header-y += ipt_ttl.h | 14 | header-y += ipt_ttl.h |
| 15 | header-y += nf_nat.h | ||
diff --git a/include/linux/netfilter_ipv4/nf_nat.h b/include/linux/netfilter_ipv4/nf_nat.h deleted file mode 100644 index 7a861d09fc86..000000000000 --- a/include/linux/netfilter_ipv4/nf_nat.h +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | #ifndef _LINUX_NF_NAT_H | ||
| 2 | #define _LINUX_NF_NAT_H | ||
| 3 | |||
| 4 | #include <linux/types.h> | ||
| 5 | |||
| 6 | #define IP_NAT_RANGE_MAP_IPS 1 | ||
| 7 | #define IP_NAT_RANGE_PROTO_SPECIFIED 2 | ||
| 8 | #define IP_NAT_RANGE_PROTO_RANDOM 4 | ||
| 9 | #define IP_NAT_RANGE_PERSISTENT 8 | ||
| 10 | |||
| 11 | /* The protocol-specific manipulable parts of the tuple. */ | ||
| 12 | union nf_conntrack_man_proto { | ||
| 13 | /* Add other protocols here. */ | ||
| 14 | __be16 all; | ||
| 15 | |||
| 16 | struct { | ||
| 17 | __be16 port; | ||
| 18 | } tcp; | ||
| 19 | struct { | ||
| 20 | __be16 port; | ||
| 21 | } udp; | ||
| 22 | struct { | ||
| 23 | __be16 id; | ||
| 24 | } icmp; | ||
| 25 | struct { | ||
| 26 | __be16 port; | ||
| 27 | } dccp; | ||
| 28 | struct { | ||
| 29 | __be16 port; | ||
| 30 | } sctp; | ||
| 31 | struct { | ||
| 32 | __be16 key; /* GRE key is 32bit, PPtP only uses 16bit */ | ||
| 33 | } gre; | ||
| 34 | }; | ||
| 35 | |||
| 36 | /* Single range specification. */ | ||
| 37 | struct nf_nat_range { | ||
| 38 | /* Set to OR of flags above. */ | ||
| 39 | unsigned int flags; | ||
| 40 | |||
| 41 | /* Inclusive: network order. */ | ||
| 42 | __be32 min_ip, max_ip; | ||
| 43 | |||
| 44 | /* Inclusive: network order */ | ||
| 45 | union nf_conntrack_man_proto min, max; | ||
| 46 | }; | ||
| 47 | |||
| 48 | /* For backwards compat: don't use in modern code. */ | ||
| 49 | struct nf_nat_multi_range_compat { | ||
| 50 | unsigned int rangesize; /* Must be 1. */ | ||
| 51 | |||
| 52 | /* hangs off end. */ | ||
| 53 | struct nf_nat_range range[1]; | ||
| 54 | }; | ||
| 55 | |||
| 56 | #define nf_nat_multi_range nf_nat_multi_range_compat | ||
| 57 | |||
| 58 | #endif | ||
diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h index 789d5f47d5e3..2ad92ca4e6f3 100644 --- a/include/net/ip6_route.h +++ b/include/net/ip6_route.h | |||
| @@ -70,6 +70,8 @@ extern void ip6_route_input(struct sk_buff *skb); | |||
| 70 | extern struct dst_entry * ip6_route_output(struct net *net, | 70 | extern struct dst_entry * ip6_route_output(struct net *net, |
| 71 | const struct sock *sk, | 71 | const struct sock *sk, |
| 72 | struct flowi6 *fl6); | 72 | struct flowi6 *fl6); |
| 73 | extern struct dst_entry * ip6_route_lookup(struct net *net, | ||
| 74 | struct flowi6 *fl6, int flags); | ||
| 73 | 75 | ||
| 74 | extern int ip6_route_init(void); | 76 | extern int ip6_route_init(void); |
| 75 | extern void ip6_route_cleanup(void); | 77 | extern void ip6_route_cleanup(void); |
diff --git a/include/net/netfilter/nf_conntrack_acct.h b/include/net/netfilter/nf_conntrack_acct.h index 4e9c63a20db2..463ae8e16696 100644 --- a/include/net/netfilter/nf_conntrack_acct.h +++ b/include/net/netfilter/nf_conntrack_acct.h | |||
| @@ -15,8 +15,8 @@ | |||
| 15 | #include <net/netfilter/nf_conntrack_extend.h> | 15 | #include <net/netfilter/nf_conntrack_extend.h> |
| 16 | 16 | ||
| 17 | struct nf_conn_counter { | 17 | struct nf_conn_counter { |
| 18 | u_int64_t packets; | 18 | atomic64_t packets; |
| 19 | u_int64_t bytes; | 19 | atomic64_t bytes; |
| 20 | }; | 20 | }; |
| 21 | 21 | ||
| 22 | static inline | 22 | static inline |
diff --git a/include/net/netfilter/nf_conntrack_expect.h b/include/net/netfilter/nf_conntrack_expect.h index 0f8a8c587532..4619caadd9d1 100644 --- a/include/net/netfilter/nf_conntrack_expect.h +++ b/include/net/netfilter/nf_conntrack_expect.h | |||
| @@ -91,7 +91,6 @@ static inline void nf_ct_unlink_expect(struct nf_conntrack_expect *exp) | |||
| 91 | 91 | ||
| 92 | void nf_ct_remove_expectations(struct nf_conn *ct); | 92 | void nf_ct_remove_expectations(struct nf_conn *ct); |
| 93 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); | 93 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp); |
| 94 | void nf_ct_remove_userspace_expectations(void); | ||
| 95 | 94 | ||
| 96 | /* Allocate space for an expectation: this is mandatory before calling | 95 | /* Allocate space for an expectation: this is mandatory before calling |
| 97 | nf_ct_expect_related. You will have to call put afterwards. */ | 96 | nf_ct_expect_related. You will have to call put afterwards. */ |
diff --git a/include/net/netfilter/nf_conntrack_tuple.h b/include/net/netfilter/nf_conntrack_tuple.h index 2f8fb77bfdd1..aea3f8221be0 100644 --- a/include/net/netfilter/nf_conntrack_tuple.h +++ b/include/net/netfilter/nf_conntrack_tuple.h | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | 12 | ||
| 13 | #include <linux/netfilter/x_tables.h> | 13 | #include <linux/netfilter/x_tables.h> |
| 14 | #include <linux/netfilter/nf_conntrack_tuple_common.h> | 14 | #include <linux/netfilter/nf_conntrack_tuple_common.h> |
| 15 | #include <linux/netfilter_ipv4/nf_nat.h> | ||
| 16 | #include <linux/list_nulls.h> | 15 | #include <linux/list_nulls.h> |
| 17 | 16 | ||
| 18 | /* A `tuple' is a structure containing the information to uniquely | 17 | /* A `tuple' is a structure containing the information to uniquely |
diff --git a/include/net/netfilter/nf_nat.h b/include/net/netfilter/nf_nat.h index b8872df7285f..b4de990b55f1 100644 --- a/include/net/netfilter/nf_nat.h +++ b/include/net/netfilter/nf_nat.h | |||
| @@ -1,14 +1,12 @@ | |||
| 1 | #ifndef _NF_NAT_H | 1 | #ifndef _NF_NAT_H |
| 2 | #define _NF_NAT_H | 2 | #define _NF_NAT_H |
| 3 | #include <linux/netfilter_ipv4.h> | 3 | #include <linux/netfilter_ipv4.h> |
| 4 | #include <linux/netfilter_ipv4/nf_nat.h> | 4 | #include <linux/netfilter/nf_nat.h> |
| 5 | #include <net/netfilter/nf_conntrack_tuple.h> | 5 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 6 | 6 | ||
| 7 | #define NF_NAT_MAPPING_TYPE_MAX_NAMELEN 16 | ||
| 8 | |||
| 9 | enum nf_nat_manip_type { | 7 | enum nf_nat_manip_type { |
| 10 | IP_NAT_MANIP_SRC, | 8 | NF_NAT_MANIP_SRC, |
| 11 | IP_NAT_MANIP_DST | 9 | NF_NAT_MANIP_DST |
| 12 | }; | 10 | }; |
| 13 | 11 | ||
| 14 | /* SRC manip occurs POST_ROUTING or LOCAL_IN */ | 12 | /* SRC manip occurs POST_ROUTING or LOCAL_IN */ |
| @@ -52,7 +50,7 @@ struct nf_conn_nat { | |||
| 52 | 50 | ||
| 53 | /* Set up the info structure to map into this range. */ | 51 | /* Set up the info structure to map into this range. */ |
| 54 | extern unsigned int nf_nat_setup_info(struct nf_conn *ct, | 52 | extern unsigned int nf_nat_setup_info(struct nf_conn *ct, |
| 55 | const struct nf_nat_range *range, | 53 | const struct nf_nat_ipv4_range *range, |
| 56 | enum nf_nat_manip_type maniptype); | 54 | enum nf_nat_manip_type maniptype); |
| 57 | 55 | ||
| 58 | /* Is this tuple already taken? (not by us)*/ | 56 | /* Is this tuple already taken? (not by us)*/ |
diff --git a/include/net/netfilter/nf_nat_core.h b/include/net/netfilter/nf_nat_core.h index 3dc7b98effeb..b13d8d18d595 100644 --- a/include/net/netfilter/nf_nat_core.h +++ b/include/net/netfilter/nf_nat_core.h | |||
| @@ -20,7 +20,7 @@ extern int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 20 | static inline int nf_nat_initialized(struct nf_conn *ct, | 20 | static inline int nf_nat_initialized(struct nf_conn *ct, |
| 21 | enum nf_nat_manip_type manip) | 21 | enum nf_nat_manip_type manip) |
| 22 | { | 22 | { |
| 23 | if (manip == IP_NAT_MANIP_SRC) | 23 | if (manip == NF_NAT_MANIP_SRC) |
| 24 | return ct->status & IPS_SRC_NAT_DONE; | 24 | return ct->status & IPS_SRC_NAT_DONE; |
| 25 | else | 25 | else |
| 26 | return ct->status & IPS_DST_NAT_DONE; | 26 | return ct->status & IPS_DST_NAT_DONE; |
diff --git a/include/net/netfilter/nf_nat_protocol.h b/include/net/netfilter/nf_nat_protocol.h index 93cc90d28e66..7b0b51165f70 100644 --- a/include/net/netfilter/nf_nat_protocol.h +++ b/include/net/netfilter/nf_nat_protocol.h | |||
| @@ -4,14 +4,12 @@ | |||
| 4 | #include <net/netfilter/nf_nat.h> | 4 | #include <net/netfilter/nf_nat.h> |
| 5 | #include <linux/netfilter/nfnetlink_conntrack.h> | 5 | #include <linux/netfilter/nfnetlink_conntrack.h> |
| 6 | 6 | ||
| 7 | struct nf_nat_range; | 7 | struct nf_nat_ipv4_range; |
| 8 | 8 | ||
| 9 | struct nf_nat_protocol { | 9 | struct nf_nat_protocol { |
| 10 | /* Protocol number. */ | 10 | /* Protocol number. */ |
| 11 | unsigned int protonum; | 11 | unsigned int protonum; |
| 12 | 12 | ||
| 13 | struct module *me; | ||
| 14 | |||
| 15 | /* Translate a packet to the target according to manip type. | 13 | /* Translate a packet to the target according to manip type. |
| 16 | Return true if succeeded. */ | 14 | Return true if succeeded. */ |
| 17 | bool (*manip_pkt)(struct sk_buff *skb, | 15 | bool (*manip_pkt)(struct sk_buff *skb, |
| @@ -30,15 +28,12 @@ struct nf_nat_protocol { | |||
| 30 | possible. Per-protocol part of tuple is initialized to the | 28 | possible. Per-protocol part of tuple is initialized to the |
| 31 | incoming packet. */ | 29 | incoming packet. */ |
| 32 | void (*unique_tuple)(struct nf_conntrack_tuple *tuple, | 30 | void (*unique_tuple)(struct nf_conntrack_tuple *tuple, |
| 33 | const struct nf_nat_range *range, | 31 | const struct nf_nat_ipv4_range *range, |
| 34 | enum nf_nat_manip_type maniptype, | 32 | enum nf_nat_manip_type maniptype, |
| 35 | const struct nf_conn *ct); | 33 | const struct nf_conn *ct); |
| 36 | 34 | ||
| 37 | int (*range_to_nlattr)(struct sk_buff *skb, | ||
| 38 | const struct nf_nat_range *range); | ||
| 39 | |||
| 40 | int (*nlattr_to_range)(struct nlattr *tb[], | 35 | int (*nlattr_to_range)(struct nlattr *tb[], |
| 41 | struct nf_nat_range *range); | 36 | struct nf_nat_ipv4_range *range); |
| 42 | }; | 37 | }; |
| 43 | 38 | ||
| 44 | /* Protocol registration. */ | 39 | /* Protocol registration. */ |
| @@ -61,14 +56,12 @@ extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple, | |||
| 61 | const union nf_conntrack_man_proto *max); | 56 | const union nf_conntrack_man_proto *max); |
| 62 | 57 | ||
| 63 | extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | 58 | extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 64 | const struct nf_nat_range *range, | 59 | const struct nf_nat_ipv4_range *range, |
| 65 | enum nf_nat_manip_type maniptype, | 60 | enum nf_nat_manip_type maniptype, |
| 66 | const struct nf_conn *ct, | 61 | const struct nf_conn *ct, |
| 67 | u_int16_t *rover); | 62 | u_int16_t *rover); |
| 68 | 63 | ||
| 69 | extern int nf_nat_proto_range_to_nlattr(struct sk_buff *skb, | ||
| 70 | const struct nf_nat_range *range); | ||
| 71 | extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], | 64 | extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], |
| 72 | struct nf_nat_range *range); | 65 | struct nf_nat_ipv4_range *range); |
| 73 | 66 | ||
| 74 | #endif /*_NF_NAT_PROTO_H*/ | 67 | #endif /*_NF_NAT_PROTO_H*/ |
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c index 46339ba7a2d3..799fc790b3cf 100644 --- a/net/ipv4/fib_rules.c +++ b/net/ipv4/fib_rules.c | |||
| @@ -67,6 +67,7 @@ int fib_lookup(struct net *net, struct flowi4 *flp, struct fib_result *res) | |||
| 67 | 67 | ||
| 68 | return err; | 68 | return err; |
| 69 | } | 69 | } |
| 70 | EXPORT_SYMBOL_GPL(fib_lookup); | ||
| 70 | 71 | ||
| 71 | static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, | 72 | static int fib4_rule_action(struct fib_rule *rule, struct flowi *flp, |
| 72 | int flags, struct fib_lookup_arg *arg) | 73 | int flags, struct fib_lookup_arg *arg) |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 37b671185c81..d04b13ae18fe 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
| @@ -1607,6 +1607,7 @@ found: | |||
| 1607 | rcu_read_unlock(); | 1607 | rcu_read_unlock(); |
| 1608 | return ret; | 1608 | return ret; |
| 1609 | } | 1609 | } |
| 1610 | EXPORT_SYMBOL_GPL(fib_table_lookup); | ||
| 1610 | 1611 | ||
| 1611 | /* | 1612 | /* |
| 1612 | * Remove the leaf and return parent. | 1613 | * Remove the leaf and return parent. |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index f19f2182894c..7e1f5cdaf11e 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
| @@ -82,6 +82,16 @@ config IP_NF_MATCH_ECN | |||
| 82 | 82 | ||
| 83 | To compile it as a module, choose M here. If unsure, say N. | 83 | To compile it as a module, choose M here. If unsure, say N. |
| 84 | 84 | ||
| 85 | config IP_NF_MATCH_RPFILTER | ||
| 86 | tristate '"rpfilter" reverse path filter match support' | ||
| 87 | depends on NETFILTER_ADVANCED | ||
| 88 | ---help--- | ||
| 89 | This option allows you to match packets whose replies would | ||
| 90 | go out via the interface the packet came in. | ||
| 91 | |||
| 92 | To compile it as a module, choose M here. If unsure, say N. | ||
| 93 | The module will be called ipt_rpfilter. | ||
| 94 | |||
| 85 | config IP_NF_MATCH_TTL | 95 | config IP_NF_MATCH_TTL |
| 86 | tristate '"ttl" match support' | 96 | tristate '"ttl" match support' |
| 87 | depends on NETFILTER_ADVANCED | 97 | depends on NETFILTER_ADVANCED |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index dca2082ec683..123dd88cea53 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
| @@ -50,6 +50,7 @@ obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o | |||
| 50 | # matches | 50 | # matches |
| 51 | obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o | 51 | obj-$(CONFIG_IP_NF_MATCH_AH) += ipt_ah.o |
| 52 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o | 52 | obj-$(CONFIG_IP_NF_MATCH_ECN) += ipt_ecn.o |
| 53 | obj-$(CONFIG_IP_NF_MATCH_RPFILTER) += ipt_rpfilter.o | ||
| 53 | 54 | ||
| 54 | # targets | 55 | # targets |
| 55 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o | 56 | obj-$(CONFIG_IP_NF_TARGET_CLUSTERIP) += ipt_CLUSTERIP.o |
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index 9931152a78b5..2f210c79dc87 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
| @@ -30,9 +30,9 @@ MODULE_DESCRIPTION("Xtables: automatic-address SNAT"); | |||
| 30 | /* FIXME: Multiple targets. --RR */ | 30 | /* FIXME: Multiple targets. --RR */ |
| 31 | static int masquerade_tg_check(const struct xt_tgchk_param *par) | 31 | static int masquerade_tg_check(const struct xt_tgchk_param *par) |
| 32 | { | 32 | { |
| 33 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 33 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 34 | 34 | ||
| 35 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 35 | if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { |
| 36 | pr_debug("bad MAP_IPS.\n"); | 36 | pr_debug("bad MAP_IPS.\n"); |
| 37 | return -EINVAL; | 37 | return -EINVAL; |
| 38 | } | 38 | } |
| @@ -49,8 +49,8 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 49 | struct nf_conn *ct; | 49 | struct nf_conn *ct; |
| 50 | struct nf_conn_nat *nat; | 50 | struct nf_conn_nat *nat; |
| 51 | enum ip_conntrack_info ctinfo; | 51 | enum ip_conntrack_info ctinfo; |
| 52 | struct nf_nat_range newrange; | 52 | struct nf_nat_ipv4_range newrange; |
| 53 | const struct nf_nat_multi_range_compat *mr; | 53 | const struct nf_nat_ipv4_multi_range_compat *mr; |
| 54 | const struct rtable *rt; | 54 | const struct rtable *rt; |
| 55 | __be32 newsrc; | 55 | __be32 newsrc; |
| 56 | 56 | ||
| @@ -79,13 +79,13 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 79 | nat->masq_index = par->out->ifindex; | 79 | nat->masq_index = par->out->ifindex; |
| 80 | 80 | ||
| 81 | /* Transfer from original range. */ | 81 | /* Transfer from original range. */ |
| 82 | newrange = ((struct nf_nat_range) | 82 | newrange = ((struct nf_nat_ipv4_range) |
| 83 | { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, | 83 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, |
| 84 | newsrc, newsrc, | 84 | newsrc, newsrc, |
| 85 | mr->range[0].min, mr->range[0].max }); | 85 | mr->range[0].min, mr->range[0].max }); |
| 86 | 86 | ||
| 87 | /* Hand modified range to generic setup. */ | 87 | /* Hand modified range to generic setup. */ |
| 88 | return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_SRC); | 88 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); |
| 89 | } | 89 | } |
| 90 | 90 | ||
| 91 | static int | 91 | static int |
| @@ -139,7 +139,7 @@ static struct xt_target masquerade_tg_reg __read_mostly = { | |||
| 139 | .name = "MASQUERADE", | 139 | .name = "MASQUERADE", |
| 140 | .family = NFPROTO_IPV4, | 140 | .family = NFPROTO_IPV4, |
| 141 | .target = masquerade_tg, | 141 | .target = masquerade_tg, |
| 142 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 142 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), |
| 143 | .table = "nat", | 143 | .table = "nat", |
| 144 | .hooks = 1 << NF_INET_POST_ROUTING, | 144 | .hooks = 1 << NF_INET_POST_ROUTING, |
| 145 | .checkentry = masquerade_tg_check, | 145 | .checkentry = masquerade_tg_check, |
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index 6cdb298f1035..b5bfbbabf70d 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
| @@ -24,9 +24,9 @@ MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv4 subnets"); | |||
| 24 | 24 | ||
| 25 | static int netmap_tg_check(const struct xt_tgchk_param *par) | 25 | static int netmap_tg_check(const struct xt_tgchk_param *par) |
| 26 | { | 26 | { |
| 27 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 27 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 28 | 28 | ||
| 29 | if (!(mr->range[0].flags & IP_NAT_RANGE_MAP_IPS)) { | 29 | if (!(mr->range[0].flags & NF_NAT_RANGE_MAP_IPS)) { |
| 30 | pr_debug("bad MAP_IPS.\n"); | 30 | pr_debug("bad MAP_IPS.\n"); |
| 31 | return -EINVAL; | 31 | return -EINVAL; |
| 32 | } | 32 | } |
| @@ -43,8 +43,8 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 43 | struct nf_conn *ct; | 43 | struct nf_conn *ct; |
| 44 | enum ip_conntrack_info ctinfo; | 44 | enum ip_conntrack_info ctinfo; |
| 45 | __be32 new_ip, netmask; | 45 | __be32 new_ip, netmask; |
| 46 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 46 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 47 | struct nf_nat_range newrange; | 47 | struct nf_nat_ipv4_range newrange; |
| 48 | 48 | ||
| 49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | 49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
| 50 | par->hooknum == NF_INET_POST_ROUTING || | 50 | par->hooknum == NF_INET_POST_ROUTING || |
| @@ -61,8 +61,8 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 61 | new_ip = ip_hdr(skb)->saddr & ~netmask; | 61 | new_ip = ip_hdr(skb)->saddr & ~netmask; |
| 62 | new_ip |= mr->range[0].min_ip & netmask; | 62 | new_ip |= mr->range[0].min_ip & netmask; |
| 63 | 63 | ||
| 64 | newrange = ((struct nf_nat_range) | 64 | newrange = ((struct nf_nat_ipv4_range) |
| 65 | { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, | 65 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, |
| 66 | new_ip, new_ip, | 66 | new_ip, new_ip, |
| 67 | mr->range[0].min, mr->range[0].max }); | 67 | mr->range[0].min, mr->range[0].max }); |
| 68 | 68 | ||
| @@ -74,7 +74,7 @@ static struct xt_target netmap_tg_reg __read_mostly = { | |||
| 74 | .name = "NETMAP", | 74 | .name = "NETMAP", |
| 75 | .family = NFPROTO_IPV4, | 75 | .family = NFPROTO_IPV4, |
| 76 | .target = netmap_tg, | 76 | .target = netmap_tg, |
| 77 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 77 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), |
| 78 | .table = "nat", | 78 | .table = "nat", |
| 79 | .hooks = (1 << NF_INET_PRE_ROUTING) | | 79 | .hooks = (1 << NF_INET_PRE_ROUTING) | |
| 80 | (1 << NF_INET_POST_ROUTING) | | 80 | (1 << NF_INET_POST_ROUTING) | |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 18a0656505a0..7c0103a5203e 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
| @@ -28,9 +28,9 @@ MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | |||
| 28 | /* FIXME: Take multiple ranges --RR */ | 28 | /* FIXME: Take multiple ranges --RR */ |
| 29 | static int redirect_tg_check(const struct xt_tgchk_param *par) | 29 | static int redirect_tg_check(const struct xt_tgchk_param *par) |
| 30 | { | 30 | { |
| 31 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 31 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 32 | 32 | ||
| 33 | if (mr->range[0].flags & IP_NAT_RANGE_MAP_IPS) { | 33 | if (mr->range[0].flags & NF_NAT_RANGE_MAP_IPS) { |
| 34 | pr_debug("bad MAP_IPS.\n"); | 34 | pr_debug("bad MAP_IPS.\n"); |
| 35 | return -EINVAL; | 35 | return -EINVAL; |
| 36 | } | 36 | } |
| @@ -47,8 +47,8 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 47 | struct nf_conn *ct; | 47 | struct nf_conn *ct; |
| 48 | enum ip_conntrack_info ctinfo; | 48 | enum ip_conntrack_info ctinfo; |
| 49 | __be32 newdst; | 49 | __be32 newdst; |
| 50 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 50 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 51 | struct nf_nat_range newrange; | 51 | struct nf_nat_ipv4_range newrange; |
| 52 | 52 | ||
| 53 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | 53 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
| 54 | par->hooknum == NF_INET_LOCAL_OUT); | 54 | par->hooknum == NF_INET_LOCAL_OUT); |
| @@ -76,20 +76,20 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | /* Transfer from original range. */ | 78 | /* Transfer from original range. */ |
| 79 | newrange = ((struct nf_nat_range) | 79 | newrange = ((struct nf_nat_ipv4_range) |
| 80 | { mr->range[0].flags | IP_NAT_RANGE_MAP_IPS, | 80 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, |
| 81 | newdst, newdst, | 81 | newdst, newdst, |
| 82 | mr->range[0].min, mr->range[0].max }); | 82 | mr->range[0].min, mr->range[0].max }); |
| 83 | 83 | ||
| 84 | /* Hand modified range to generic setup. */ | 84 | /* Hand modified range to generic setup. */ |
| 85 | return nf_nat_setup_info(ct, &newrange, IP_NAT_MANIP_DST); | 85 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | static struct xt_target redirect_tg_reg __read_mostly = { | 88 | static struct xt_target redirect_tg_reg __read_mostly = { |
| 89 | .name = "REDIRECT", | 89 | .name = "REDIRECT", |
| 90 | .family = NFPROTO_IPV4, | 90 | .family = NFPROTO_IPV4, |
| 91 | .target = redirect_tg, | 91 | .target = redirect_tg, |
| 92 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 92 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), |
| 93 | .table = "nat", | 93 | .table = "nat", |
| 94 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | 94 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), |
| 95 | .checkentry = redirect_tg_check, | 95 | .checkentry = redirect_tg_check, |
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c new file mode 100644 index 000000000000..31371be8174b --- /dev/null +++ b/net/ipv4/netfilter/ipt_rpfilter.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Florian Westphal <fw@strlen.de> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * based on fib_frontend.c; Author: Alexey Kuznetsov, <kuznet@ms2.inr.ac.ru> | ||
| 9 | */ | ||
| 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/skbuff.h> | ||
| 13 | #include <linux/netdevice.h> | ||
| 14 | #include <linux/ip.h> | ||
| 15 | #include <net/ip.h> | ||
| 16 | #include <net/ip_fib.h> | ||
| 17 | #include <net/route.h> | ||
| 18 | |||
| 19 | #include <linux/netfilter/xt_rpfilter.h> | ||
| 20 | #include <linux/netfilter/x_tables.h> | ||
| 21 | |||
| 22 | MODULE_LICENSE("GPL"); | ||
| 23 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
| 24 | MODULE_DESCRIPTION("iptables: ipv4 reverse path filter match"); | ||
| 25 | |||
| 26 | /* don't try to find route from mcast/bcast/zeronet */ | ||
| 27 | static __be32 rpfilter_get_saddr(__be32 addr) | ||
| 28 | { | ||
| 29 | if (ipv4_is_multicast(addr) || ipv4_is_lbcast(addr) || | ||
| 30 | ipv4_is_zeronet(addr)) | ||
| 31 | return 0; | ||
| 32 | return addr; | ||
| 33 | } | ||
| 34 | |||
| 35 | static bool rpfilter_lookup_reverse(struct flowi4 *fl4, | ||
| 36 | const struct net_device *dev, u8 flags) | ||
| 37 | { | ||
| 38 | struct fib_result res; | ||
| 39 | bool dev_match; | ||
| 40 | struct net *net = dev_net(dev); | ||
| 41 | int ret __maybe_unused; | ||
| 42 | |||
| 43 | if (fib_lookup(net, fl4, &res)) | ||
| 44 | return false; | ||
| 45 | |||
| 46 | if (res.type != RTN_UNICAST) { | ||
| 47 | if (res.type != RTN_LOCAL || !(flags & XT_RPFILTER_ACCEPT_LOCAL)) | ||
| 48 | return false; | ||
| 49 | } | ||
| 50 | dev_match = false; | ||
| 51 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | ||
| 52 | for (ret = 0; ret < res.fi->fib_nhs; ret++) { | ||
| 53 | struct fib_nh *nh = &res.fi->fib_nh[ret]; | ||
| 54 | |||
| 55 | if (nh->nh_dev == dev) { | ||
| 56 | dev_match = true; | ||
| 57 | break; | ||
| 58 | } | ||
| 59 | } | ||
| 60 | #else | ||
| 61 | if (FIB_RES_DEV(res) == dev) | ||
| 62 | dev_match = true; | ||
| 63 | #endif | ||
| 64 | if (dev_match || flags & XT_RPFILTER_LOOSE) | ||
| 65 | return FIB_RES_NH(res).nh_scope <= RT_SCOPE_HOST; | ||
| 66 | return dev_match; | ||
| 67 | } | ||
| 68 | |||
| 69 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 70 | { | ||
| 71 | const struct xt_rpfilter_info *info; | ||
| 72 | const struct iphdr *iph; | ||
| 73 | struct flowi4 flow; | ||
| 74 | bool invert; | ||
| 75 | |||
| 76 | info = par->matchinfo; | ||
| 77 | invert = info->flags & XT_RPFILTER_INVERT; | ||
| 78 | |||
| 79 | if (par->in->flags & IFF_LOOPBACK) | ||
| 80 | return true ^ invert; | ||
| 81 | |||
| 82 | iph = ip_hdr(skb); | ||
| 83 | if (ipv4_is_multicast(iph->daddr)) { | ||
| 84 | if (ipv4_is_zeronet(iph->saddr)) | ||
| 85 | return ipv4_is_local_multicast(iph->daddr) ^ invert; | ||
| 86 | flow.flowi4_iif = 0; | ||
| 87 | } else { | ||
| 88 | flow.flowi4_iif = dev_net(par->in)->loopback_dev->ifindex; | ||
| 89 | } | ||
| 90 | |||
| 91 | flow.daddr = iph->saddr; | ||
| 92 | flow.saddr = rpfilter_get_saddr(iph->daddr); | ||
| 93 | flow.flowi4_oif = 0; | ||
| 94 | flow.flowi4_mark = info->flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; | ||
| 95 | flow.flowi4_tos = RT_TOS(iph->tos); | ||
| 96 | flow.flowi4_scope = RT_SCOPE_UNIVERSE; | ||
| 97 | |||
| 98 | return rpfilter_lookup_reverse(&flow, par->in, info->flags) ^ invert; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int rpfilter_check(const struct xt_mtchk_param *par) | ||
| 102 | { | ||
| 103 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
| 104 | unsigned int options = ~XT_RPFILTER_OPTION_MASK; | ||
| 105 | if (info->flags & options) { | ||
| 106 | pr_info("unknown options encountered"); | ||
| 107 | return -EINVAL; | ||
| 108 | } | ||
| 109 | |||
| 110 | if (strcmp(par->table, "mangle") != 0 && | ||
| 111 | strcmp(par->table, "raw") != 0) { | ||
| 112 | pr_info("match only valid in the \'raw\' " | ||
| 113 | "or \'mangle\' tables, not \'%s\'.\n", par->table); | ||
| 114 | return -EINVAL; | ||
| 115 | } | ||
| 116 | |||
| 117 | return 0; | ||
| 118 | } | ||
| 119 | |||
| 120 | static struct xt_match rpfilter_mt_reg __read_mostly = { | ||
| 121 | .name = "rpfilter", | ||
| 122 | .family = NFPROTO_IPV4, | ||
| 123 | .checkentry = rpfilter_check, | ||
| 124 | .match = rpfilter_mt, | ||
| 125 | .matchsize = sizeof(struct xt_rpfilter_info), | ||
| 126 | .hooks = (1 << NF_INET_PRE_ROUTING), | ||
| 127 | .me = THIS_MODULE | ||
| 128 | }; | ||
| 129 | |||
| 130 | static int __init rpfilter_mt_init(void) | ||
| 131 | { | ||
| 132 | return xt_register_match(&rpfilter_mt_reg); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void __exit rpfilter_mt_exit(void) | ||
| 136 | { | ||
| 137 | xt_unregister_match(&rpfilter_mt_reg); | ||
| 138 | } | ||
| 139 | |||
| 140 | module_init(rpfilter_mt_init); | ||
| 141 | module_exit(rpfilter_mt_exit); | ||
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 447bc5cfdc6c..acdd002bb540 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | #include <net/netfilter/nf_nat_helper.h> | 30 | #include <net/netfilter/nf_nat_helper.h> |
| 31 | #include <net/netfilter/nf_conntrack_helper.h> | 31 | #include <net/netfilter/nf_conntrack_helper.h> |
| 32 | #include <net/netfilter/nf_conntrack_l3proto.h> | 32 | #include <net/netfilter/nf_conntrack_l3proto.h> |
| 33 | #include <net/netfilter/nf_conntrack_l4proto.h> | ||
| 34 | #include <net/netfilter/nf_conntrack_zones.h> | 33 | #include <net/netfilter/nf_conntrack_zones.h> |
| 35 | 34 | ||
| 36 | static DEFINE_SPINLOCK(nf_nat_lock); | 35 | static DEFINE_SPINLOCK(nf_nat_lock); |
| @@ -57,7 +56,7 @@ hash_by_src(const struct net *net, u16 zone, | |||
| 57 | /* Original src, to ensure we map it consistently if poss. */ | 56 | /* Original src, to ensure we map it consistently if poss. */ |
| 58 | hash = jhash_3words((__force u32)tuple->src.u3.ip, | 57 | hash = jhash_3words((__force u32)tuple->src.u3.ip, |
| 59 | (__force u32)tuple->src.u.all ^ zone, | 58 | (__force u32)tuple->src.u.all ^ zone, |
| 60 | tuple->dst.protonum, 0); | 59 | tuple->dst.protonum, nf_conntrack_hash_rnd); |
| 61 | return ((u64)hash * net->ipv4.nat_htable_size) >> 32; | 60 | return ((u64)hash * net->ipv4.nat_htable_size) >> 32; |
| 62 | } | 61 | } |
| 63 | 62 | ||
| @@ -82,14 +81,14 @@ EXPORT_SYMBOL(nf_nat_used_tuple); | |||
| 82 | * that meet the constraints of range. */ | 81 | * that meet the constraints of range. */ |
| 83 | static int | 82 | static int |
| 84 | in_range(const struct nf_conntrack_tuple *tuple, | 83 | in_range(const struct nf_conntrack_tuple *tuple, |
| 85 | const struct nf_nat_range *range) | 84 | const struct nf_nat_ipv4_range *range) |
| 86 | { | 85 | { |
| 87 | const struct nf_nat_protocol *proto; | 86 | const struct nf_nat_protocol *proto; |
| 88 | int ret = 0; | 87 | int ret = 0; |
| 89 | 88 | ||
| 90 | /* If we are supposed to map IPs, then we must be in the | 89 | /* If we are supposed to map IPs, then we must be in the |
| 91 | range specified, otherwise let this drag us onto a new src IP. */ | 90 | range specified, otherwise let this drag us onto a new src IP. */ |
| 92 | if (range->flags & IP_NAT_RANGE_MAP_IPS) { | 91 | if (range->flags & NF_NAT_RANGE_MAP_IPS) { |
| 93 | if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) || | 92 | if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) || |
| 94 | ntohl(tuple->src.u3.ip) > ntohl(range->max_ip)) | 93 | ntohl(tuple->src.u3.ip) > ntohl(range->max_ip)) |
| 95 | return 0; | 94 | return 0; |
| @@ -97,8 +96,8 @@ in_range(const struct nf_conntrack_tuple *tuple, | |||
| 97 | 96 | ||
| 98 | rcu_read_lock(); | 97 | rcu_read_lock(); |
| 99 | proto = __nf_nat_proto_find(tuple->dst.protonum); | 98 | proto = __nf_nat_proto_find(tuple->dst.protonum); |
| 100 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) || | 99 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) || |
| 101 | proto->in_range(tuple, IP_NAT_MANIP_SRC, | 100 | proto->in_range(tuple, NF_NAT_MANIP_SRC, |
| 102 | &range->min, &range->max)) | 101 | &range->min, &range->max)) |
| 103 | ret = 1; | 102 | ret = 1; |
| 104 | rcu_read_unlock(); | 103 | rcu_read_unlock(); |
| @@ -123,7 +122,7 @@ static int | |||
| 123 | find_appropriate_src(struct net *net, u16 zone, | 122 | find_appropriate_src(struct net *net, u16 zone, |
| 124 | const struct nf_conntrack_tuple *tuple, | 123 | const struct nf_conntrack_tuple *tuple, |
| 125 | struct nf_conntrack_tuple *result, | 124 | struct nf_conntrack_tuple *result, |
| 126 | const struct nf_nat_range *range) | 125 | const struct nf_nat_ipv4_range *range) |
| 127 | { | 126 | { |
| 128 | unsigned int h = hash_by_src(net, zone, tuple); | 127 | unsigned int h = hash_by_src(net, zone, tuple); |
| 129 | const struct nf_conn_nat *nat; | 128 | const struct nf_conn_nat *nat; |
| @@ -157,7 +156,7 @@ find_appropriate_src(struct net *net, u16 zone, | |||
| 157 | */ | 156 | */ |
| 158 | static void | 157 | static void |
| 159 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | 158 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, |
| 160 | const struct nf_nat_range *range, | 159 | const struct nf_nat_ipv4_range *range, |
| 161 | const struct nf_conn *ct, | 160 | const struct nf_conn *ct, |
| 162 | enum nf_nat_manip_type maniptype) | 161 | enum nf_nat_manip_type maniptype) |
| 163 | { | 162 | { |
| @@ -166,10 +165,10 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | |||
| 166 | u_int32_t minip, maxip, j; | 165 | u_int32_t minip, maxip, j; |
| 167 | 166 | ||
| 168 | /* No IP mapping? Do nothing. */ | 167 | /* No IP mapping? Do nothing. */ |
| 169 | if (!(range->flags & IP_NAT_RANGE_MAP_IPS)) | 168 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) |
| 170 | return; | 169 | return; |
| 171 | 170 | ||
| 172 | if (maniptype == IP_NAT_MANIP_SRC) | 171 | if (maniptype == NF_NAT_MANIP_SRC) |
| 173 | var_ipp = &tuple->src.u3.ip; | 172 | var_ipp = &tuple->src.u3.ip; |
| 174 | else | 173 | else |
| 175 | var_ipp = &tuple->dst.u3.ip; | 174 | var_ipp = &tuple->dst.u3.ip; |
| @@ -189,7 +188,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | |||
| 189 | minip = ntohl(range->min_ip); | 188 | minip = ntohl(range->min_ip); |
| 190 | maxip = ntohl(range->max_ip); | 189 | maxip = ntohl(range->max_ip); |
| 191 | j = jhash_2words((__force u32)tuple->src.u3.ip, | 190 | j = jhash_2words((__force u32)tuple->src.u3.ip, |
| 192 | range->flags & IP_NAT_RANGE_PERSISTENT ? | 191 | range->flags & NF_NAT_RANGE_PERSISTENT ? |
| 193 | 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); | 192 | 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); |
| 194 | j = ((u64)j * (maxip - minip + 1)) >> 32; | 193 | j = ((u64)j * (maxip - minip + 1)) >> 32; |
| 195 | *var_ipp = htonl(minip + j); | 194 | *var_ipp = htonl(minip + j); |
| @@ -204,7 +203,7 @@ find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | |||
| 204 | static void | 203 | static void |
| 205 | get_unique_tuple(struct nf_conntrack_tuple *tuple, | 204 | get_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 206 | const struct nf_conntrack_tuple *orig_tuple, | 205 | const struct nf_conntrack_tuple *orig_tuple, |
| 207 | const struct nf_nat_range *range, | 206 | const struct nf_nat_ipv4_range *range, |
| 208 | struct nf_conn *ct, | 207 | struct nf_conn *ct, |
| 209 | enum nf_nat_manip_type maniptype) | 208 | enum nf_nat_manip_type maniptype) |
| 210 | { | 209 | { |
| @@ -219,8 +218,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 219 | This is only required for source (ie. NAT/masq) mappings. | 218 | This is only required for source (ie. NAT/masq) mappings. |
| 220 | So far, we don't do local source mappings, so multiple | 219 | So far, we don't do local source mappings, so multiple |
| 221 | manips not an issue. */ | 220 | manips not an issue. */ |
| 222 | if (maniptype == IP_NAT_MANIP_SRC && | 221 | if (maniptype == NF_NAT_MANIP_SRC && |
| 223 | !(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { | 222 | !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { |
| 224 | /* try the original tuple first */ | 223 | /* try the original tuple first */ |
| 225 | if (in_range(orig_tuple, range)) { | 224 | if (in_range(orig_tuple, range)) { |
| 226 | if (!nf_nat_used_tuple(orig_tuple, ct)) { | 225 | if (!nf_nat_used_tuple(orig_tuple, ct)) { |
| @@ -247,8 +246,8 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 247 | proto = __nf_nat_proto_find(orig_tuple->dst.protonum); | 246 | proto = __nf_nat_proto_find(orig_tuple->dst.protonum); |
| 248 | 247 | ||
| 249 | /* Only bother mapping if it's not already in range and unique */ | 248 | /* Only bother mapping if it's not already in range and unique */ |
| 250 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) { | 249 | if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { |
| 251 | if (range->flags & IP_NAT_RANGE_PROTO_SPECIFIED) { | 250 | if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { |
| 252 | if (proto->in_range(tuple, maniptype, &range->min, | 251 | if (proto->in_range(tuple, maniptype, &range->min, |
| 253 | &range->max) && | 252 | &range->max) && |
| 254 | (range->min.all == range->max.all || | 253 | (range->min.all == range->max.all || |
| @@ -267,7 +266,7 @@ out: | |||
| 267 | 266 | ||
| 268 | unsigned int | 267 | unsigned int |
| 269 | nf_nat_setup_info(struct nf_conn *ct, | 268 | nf_nat_setup_info(struct nf_conn *ct, |
| 270 | const struct nf_nat_range *range, | 269 | const struct nf_nat_ipv4_range *range, |
| 271 | enum nf_nat_manip_type maniptype) | 270 | enum nf_nat_manip_type maniptype) |
| 272 | { | 271 | { |
| 273 | struct net *net = nf_ct_net(ct); | 272 | struct net *net = nf_ct_net(ct); |
| @@ -284,8 +283,8 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 284 | } | 283 | } |
| 285 | } | 284 | } |
| 286 | 285 | ||
| 287 | NF_CT_ASSERT(maniptype == IP_NAT_MANIP_SRC || | 286 | NF_CT_ASSERT(maniptype == NF_NAT_MANIP_SRC || |
| 288 | maniptype == IP_NAT_MANIP_DST); | 287 | maniptype == NF_NAT_MANIP_DST); |
| 289 | BUG_ON(nf_nat_initialized(ct, maniptype)); | 288 | BUG_ON(nf_nat_initialized(ct, maniptype)); |
| 290 | 289 | ||
| 291 | /* What we've got will look like inverse of reply. Normally | 290 | /* What we've got will look like inverse of reply. Normally |
| @@ -306,13 +305,13 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 306 | nf_conntrack_alter_reply(ct, &reply); | 305 | nf_conntrack_alter_reply(ct, &reply); |
| 307 | 306 | ||
| 308 | /* Non-atomic: we own this at the moment. */ | 307 | /* Non-atomic: we own this at the moment. */ |
| 309 | if (maniptype == IP_NAT_MANIP_SRC) | 308 | if (maniptype == NF_NAT_MANIP_SRC) |
| 310 | ct->status |= IPS_SRC_NAT; | 309 | ct->status |= IPS_SRC_NAT; |
| 311 | else | 310 | else |
| 312 | ct->status |= IPS_DST_NAT; | 311 | ct->status |= IPS_DST_NAT; |
| 313 | } | 312 | } |
| 314 | 313 | ||
| 315 | if (maniptype == IP_NAT_MANIP_SRC) { | 314 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 316 | unsigned int srchash; | 315 | unsigned int srchash; |
| 317 | 316 | ||
| 318 | srchash = hash_by_src(net, nf_ct_zone(ct), | 317 | srchash = hash_by_src(net, nf_ct_zone(ct), |
| @@ -327,7 +326,7 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
| 327 | } | 326 | } |
| 328 | 327 | ||
| 329 | /* It's done. */ | 328 | /* It's done. */ |
| 330 | if (maniptype == IP_NAT_MANIP_DST) | 329 | if (maniptype == NF_NAT_MANIP_DST) |
| 331 | ct->status |= IPS_DST_NAT_DONE; | 330 | ct->status |= IPS_DST_NAT_DONE; |
| 332 | else | 331 | else |
| 333 | ct->status |= IPS_SRC_NAT_DONE; | 332 | ct->status |= IPS_SRC_NAT_DONE; |
| @@ -361,7 +360,7 @@ manip_pkt(u_int16_t proto, | |||
| 361 | 360 | ||
| 362 | iph = (void *)skb->data + iphdroff; | 361 | iph = (void *)skb->data + iphdroff; |
| 363 | 362 | ||
| 364 | if (maniptype == IP_NAT_MANIP_SRC) { | 363 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 365 | csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); | 364 | csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); |
| 366 | iph->saddr = target->src.u3.ip; | 365 | iph->saddr = target->src.u3.ip; |
| 367 | } else { | 366 | } else { |
| @@ -381,7 +380,7 @@ unsigned int nf_nat_packet(struct nf_conn *ct, | |||
| 381 | unsigned long statusbit; | 380 | unsigned long statusbit; |
| 382 | enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); | 381 | enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); |
| 383 | 382 | ||
| 384 | if (mtype == IP_NAT_MANIP_SRC) | 383 | if (mtype == NF_NAT_MANIP_SRC) |
| 385 | statusbit = IPS_SRC_NAT; | 384 | statusbit = IPS_SRC_NAT; |
| 386 | else | 385 | else |
| 387 | statusbit = IPS_DST_NAT; | 386 | statusbit = IPS_DST_NAT; |
| @@ -414,8 +413,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 414 | struct icmphdr icmp; | 413 | struct icmphdr icmp; |
| 415 | struct iphdr ip; | 414 | struct iphdr ip; |
| 416 | } *inside; | 415 | } *inside; |
| 417 | const struct nf_conntrack_l4proto *l4proto; | 416 | struct nf_conntrack_tuple target; |
| 418 | struct nf_conntrack_tuple inner, target; | ||
| 419 | int hdrlen = ip_hdrlen(skb); | 417 | int hdrlen = ip_hdrlen(skb); |
| 420 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 418 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
| 421 | unsigned long statusbit; | 419 | unsigned long statusbit; |
| @@ -447,7 +445,7 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 447 | return 0; | 445 | return 0; |
| 448 | } | 446 | } |
| 449 | 447 | ||
| 450 | if (manip == IP_NAT_MANIP_SRC) | 448 | if (manip == NF_NAT_MANIP_SRC) |
| 451 | statusbit = IPS_SRC_NAT; | 449 | statusbit = IPS_SRC_NAT; |
| 452 | else | 450 | else |
| 453 | statusbit = IPS_DST_NAT; | 451 | statusbit = IPS_DST_NAT; |
| @@ -463,16 +461,6 @@ int nf_nat_icmp_reply_translation(struct nf_conn *ct, | |||
| 463 | "dir %s\n", skb, manip, | 461 | "dir %s\n", skb, manip, |
| 464 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | 462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); |
| 465 | 463 | ||
| 466 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
| 467 | l4proto = __nf_ct_l4proto_find(PF_INET, inside->ip.protocol); | ||
| 468 | |||
| 469 | if (!nf_ct_get_tuple(skb, hdrlen + sizeof(struct icmphdr), | ||
| 470 | (hdrlen + | ||
| 471 | sizeof(struct icmphdr) + inside->ip.ihl * 4), | ||
| 472 | (u_int16_t)AF_INET, inside->ip.protocol, | ||
| 473 | &inner, l3proto, l4proto)) | ||
| 474 | return 0; | ||
| 475 | |||
| 476 | /* Change inner back to look like incoming packet. We do the | 464 | /* Change inner back to look like incoming packet. We do the |
| 477 | opposite manip on this hook to normal, because it might not | 465 | opposite manip on this hook to normal, because it might not |
| 478 | pass all hooks (locally-generated ICMP). Consider incoming | 466 | pass all hooks (locally-generated ICMP). Consider incoming |
| @@ -575,26 +563,6 @@ static struct nf_ct_ext_type nat_extend __read_mostly = { | |||
| 575 | #include <linux/netfilter/nfnetlink.h> | 563 | #include <linux/netfilter/nfnetlink.h> |
| 576 | #include <linux/netfilter/nfnetlink_conntrack.h> | 564 | #include <linux/netfilter/nfnetlink_conntrack.h> |
| 577 | 565 | ||
| 578 | static const struct nf_nat_protocol * | ||
| 579 | nf_nat_proto_find_get(u_int8_t protonum) | ||
| 580 | { | ||
| 581 | const struct nf_nat_protocol *p; | ||
| 582 | |||
| 583 | rcu_read_lock(); | ||
| 584 | p = __nf_nat_proto_find(protonum); | ||
| 585 | if (!try_module_get(p->me)) | ||
| 586 | p = &nf_nat_unknown_protocol; | ||
| 587 | rcu_read_unlock(); | ||
| 588 | |||
| 589 | return p; | ||
| 590 | } | ||
| 591 | |||
| 592 | static void | ||
| 593 | nf_nat_proto_put(const struct nf_nat_protocol *p) | ||
| 594 | { | ||
| 595 | module_put(p->me); | ||
| 596 | } | ||
| 597 | |||
| 598 | static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { | 566 | static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { |
| 599 | [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 }, | 567 | [CTA_PROTONAT_PORT_MIN] = { .type = NLA_U16 }, |
| 600 | [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 }, | 568 | [CTA_PROTONAT_PORT_MAX] = { .type = NLA_U16 }, |
| @@ -602,7 +570,7 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { | |||
| 602 | 570 | ||
| 603 | static int nfnetlink_parse_nat_proto(struct nlattr *attr, | 571 | static int nfnetlink_parse_nat_proto(struct nlattr *attr, |
| 604 | const struct nf_conn *ct, | 572 | const struct nf_conn *ct, |
| 605 | struct nf_nat_range *range) | 573 | struct nf_nat_ipv4_range *range) |
| 606 | { | 574 | { |
| 607 | struct nlattr *tb[CTA_PROTONAT_MAX+1]; | 575 | struct nlattr *tb[CTA_PROTONAT_MAX+1]; |
| 608 | const struct nf_nat_protocol *npt; | 576 | const struct nf_nat_protocol *npt; |
| @@ -612,21 +580,23 @@ static int nfnetlink_parse_nat_proto(struct nlattr *attr, | |||
| 612 | if (err < 0) | 580 | if (err < 0) |
| 613 | return err; | 581 | return err; |
| 614 | 582 | ||
| 615 | npt = nf_nat_proto_find_get(nf_ct_protonum(ct)); | 583 | rcu_read_lock(); |
| 584 | npt = __nf_nat_proto_find(nf_ct_protonum(ct)); | ||
| 616 | if (npt->nlattr_to_range) | 585 | if (npt->nlattr_to_range) |
| 617 | err = npt->nlattr_to_range(tb, range); | 586 | err = npt->nlattr_to_range(tb, range); |
| 618 | nf_nat_proto_put(npt); | 587 | rcu_read_unlock(); |
| 619 | return err; | 588 | return err; |
| 620 | } | 589 | } |
| 621 | 590 | ||
| 622 | static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { | 591 | static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { |
| 623 | [CTA_NAT_MINIP] = { .type = NLA_U32 }, | 592 | [CTA_NAT_MINIP] = { .type = NLA_U32 }, |
| 624 | [CTA_NAT_MAXIP] = { .type = NLA_U32 }, | 593 | [CTA_NAT_MAXIP] = { .type = NLA_U32 }, |
| 594 | [CTA_NAT_PROTO] = { .type = NLA_NESTED }, | ||
| 625 | }; | 595 | }; |
| 626 | 596 | ||
| 627 | static int | 597 | static int |
| 628 | nfnetlink_parse_nat(const struct nlattr *nat, | 598 | nfnetlink_parse_nat(const struct nlattr *nat, |
| 629 | const struct nf_conn *ct, struct nf_nat_range *range) | 599 | const struct nf_conn *ct, struct nf_nat_ipv4_range *range) |
| 630 | { | 600 | { |
| 631 | struct nlattr *tb[CTA_NAT_MAX+1]; | 601 | struct nlattr *tb[CTA_NAT_MAX+1]; |
| 632 | int err; | 602 | int err; |
| @@ -646,7 +616,7 @@ nfnetlink_parse_nat(const struct nlattr *nat, | |||
| 646 | range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); | 616 | range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); |
| 647 | 617 | ||
| 648 | if (range->min_ip) | 618 | if (range->min_ip) |
| 649 | range->flags |= IP_NAT_RANGE_MAP_IPS; | 619 | range->flags |= NF_NAT_RANGE_MAP_IPS; |
| 650 | 620 | ||
| 651 | if (!tb[CTA_NAT_PROTO]) | 621 | if (!tb[CTA_NAT_PROTO]) |
| 652 | return 0; | 622 | return 0; |
| @@ -663,7 +633,7 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, | |||
| 663 | enum nf_nat_manip_type manip, | 633 | enum nf_nat_manip_type manip, |
| 664 | const struct nlattr *attr) | 634 | const struct nlattr *attr) |
| 665 | { | 635 | { |
| 666 | struct nf_nat_range range; | 636 | struct nf_nat_ipv4_range range; |
| 667 | 637 | ||
| 668 | if (nfnetlink_parse_nat(attr, ct, &range) < 0) | 638 | if (nfnetlink_parse_nat(attr, ct, &range) < 0) |
| 669 | return -EINVAL; | 639 | return -EINVAL; |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index b9a1136addbd..dc1dd912baf4 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
| @@ -398,7 +398,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
| 398 | static void ip_nat_q931_expect(struct nf_conn *new, | 398 | static void ip_nat_q931_expect(struct nf_conn *new, |
| 399 | struct nf_conntrack_expect *this) | 399 | struct nf_conntrack_expect *this) |
| 400 | { | 400 | { |
| 401 | struct nf_nat_range range; | 401 | struct nf_nat_ipv4_range range; |
| 402 | 402 | ||
| 403 | if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ | 403 | if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ |
| 404 | nf_nat_follow_master(new, this); | 404 | nf_nat_follow_master(new, this); |
| @@ -409,16 +409,16 @@ static void ip_nat_q931_expect(struct nf_conn *new, | |||
| 409 | BUG_ON(new->status & IPS_NAT_DONE_MASK); | 409 | BUG_ON(new->status & IPS_NAT_DONE_MASK); |
| 410 | 410 | ||
| 411 | /* Change src to where master sends to */ | 411 | /* Change src to where master sends to */ |
| 412 | range.flags = IP_NAT_RANGE_MAP_IPS; | 412 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 413 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; | 413 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; |
| 414 | nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); | 414 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); |
| 415 | 415 | ||
| 416 | /* For DST manip, map port here to where it's expected. */ | 416 | /* For DST manip, map port here to where it's expected. */ |
| 417 | range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); | 417 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
| 418 | range.min = range.max = this->saved_proto; | 418 | range.min = range.max = this->saved_proto; |
| 419 | range.min_ip = range.max_ip = | 419 | range.min_ip = range.max_ip = |
| 420 | new->master->tuplehash[!this->dir].tuple.src.u3.ip; | 420 | new->master->tuplehash[!this->dir].tuple.src.u3.ip; |
| 421 | nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); | 421 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | /****************************************************************************/ | 424 | /****************************************************************************/ |
| @@ -496,21 +496,21 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
| 496 | static void ip_nat_callforwarding_expect(struct nf_conn *new, | 496 | static void ip_nat_callforwarding_expect(struct nf_conn *new, |
| 497 | struct nf_conntrack_expect *this) | 497 | struct nf_conntrack_expect *this) |
| 498 | { | 498 | { |
| 499 | struct nf_nat_range range; | 499 | struct nf_nat_ipv4_range range; |
| 500 | 500 | ||
| 501 | /* This must be a fresh one. */ | 501 | /* This must be a fresh one. */ |
| 502 | BUG_ON(new->status & IPS_NAT_DONE_MASK); | 502 | BUG_ON(new->status & IPS_NAT_DONE_MASK); |
| 503 | 503 | ||
| 504 | /* Change src to where master sends to */ | 504 | /* Change src to where master sends to */ |
| 505 | range.flags = IP_NAT_RANGE_MAP_IPS; | 505 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 506 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; | 506 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; |
| 507 | nf_nat_setup_info(new, &range, IP_NAT_MANIP_SRC); | 507 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); |
| 508 | 508 | ||
| 509 | /* For DST manip, map port here to where it's expected. */ | 509 | /* For DST manip, map port here to where it's expected. */ |
| 510 | range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); | 510 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
| 511 | range.min = range.max = this->saved_proto; | 511 | range.min = range.max = this->saved_proto; |
| 512 | range.min_ip = range.max_ip = this->saved_ip; | 512 | range.min_ip = range.max_ip = this->saved_ip; |
| 513 | nf_nat_setup_info(new, &range, IP_NAT_MANIP_DST); | 513 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); |
| 514 | } | 514 | } |
| 515 | 515 | ||
| 516 | /****************************************************************************/ | 516 | /****************************************************************************/ |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index ebc5f8894f99..af65958f6308 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
| @@ -253,12 +253,6 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
| 253 | struct udphdr *udph; | 253 | struct udphdr *udph; |
| 254 | int datalen, oldlen; | 254 | int datalen, oldlen; |
| 255 | 255 | ||
| 256 | /* UDP helpers might accidentally mangle the wrong packet */ | ||
| 257 | iph = ip_hdr(skb); | ||
| 258 | if (skb->len < iph->ihl*4 + sizeof(*udph) + | ||
| 259 | match_offset + match_len) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | if (!skb_make_writable(skb, skb->len)) | 256 | if (!skb_make_writable(skb, skb->len)) |
| 263 | return 0; | 257 | return 0; |
| 264 | 258 | ||
| @@ -430,22 +424,22 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
| 430 | void nf_nat_follow_master(struct nf_conn *ct, | 424 | void nf_nat_follow_master(struct nf_conn *ct, |
| 431 | struct nf_conntrack_expect *exp) | 425 | struct nf_conntrack_expect *exp) |
| 432 | { | 426 | { |
| 433 | struct nf_nat_range range; | 427 | struct nf_nat_ipv4_range range; |
| 434 | 428 | ||
| 435 | /* This must be a fresh one. */ | 429 | /* This must be a fresh one. */ |
| 436 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | 430 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); |
| 437 | 431 | ||
| 438 | /* Change src to where master sends to */ | 432 | /* Change src to where master sends to */ |
| 439 | range.flags = IP_NAT_RANGE_MAP_IPS; | 433 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 440 | range.min_ip = range.max_ip | 434 | range.min_ip = range.max_ip |
| 441 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 435 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; |
| 442 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); | 436 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
| 443 | 437 | ||
| 444 | /* For DST manip, map port here to where it's expected. */ | 438 | /* For DST manip, map port here to where it's expected. */ |
| 445 | range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); | 439 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
| 446 | range.min = range.max = exp->saved_proto; | 440 | range.min = range.max = exp->saved_proto; |
| 447 | range.min_ip = range.max_ip | 441 | range.min_ip = range.max_ip |
| 448 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; | 442 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; |
| 449 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); | 443 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
| 450 | } | 444 | } |
| 451 | EXPORT_SYMBOL(nf_nat_follow_master); | 445 | EXPORT_SYMBOL(nf_nat_follow_master); |
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 3e8284ba46b8..c273d58980ae 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
| @@ -47,7 +47,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
| 47 | struct nf_conntrack_tuple t; | 47 | struct nf_conntrack_tuple t; |
| 48 | const struct nf_ct_pptp_master *ct_pptp_info; | 48 | const struct nf_ct_pptp_master *ct_pptp_info; |
| 49 | const struct nf_nat_pptp *nat_pptp_info; | 49 | const struct nf_nat_pptp *nat_pptp_info; |
| 50 | struct nf_nat_range range; | 50 | struct nf_nat_ipv4_range range; |
| 51 | 51 | ||
| 52 | ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; | 52 | ct_pptp_info = &nfct_help(master)->help.ct_pptp_info; |
| 53 | nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; | 53 | nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; |
| @@ -88,24 +88,24 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
| 88 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | 88 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); |
| 89 | 89 | ||
| 90 | /* Change src to where master sends to */ | 90 | /* Change src to where master sends to */ |
| 91 | range.flags = IP_NAT_RANGE_MAP_IPS; | 91 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 92 | range.min_ip = range.max_ip | 92 | range.min_ip = range.max_ip |
| 93 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 93 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; |
| 94 | if (exp->dir == IP_CT_DIR_ORIGINAL) { | 94 | if (exp->dir == IP_CT_DIR_ORIGINAL) { |
| 95 | range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | 95 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 96 | range.min = range.max = exp->saved_proto; | 96 | range.min = range.max = exp->saved_proto; |
| 97 | } | 97 | } |
| 98 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); | 98 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
| 99 | 99 | ||
| 100 | /* For DST manip, map port here to where it's expected. */ | 100 | /* For DST manip, map port here to where it's expected. */ |
| 101 | range.flags = IP_NAT_RANGE_MAP_IPS; | 101 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 102 | range.min_ip = range.max_ip | 102 | range.min_ip = range.max_ip |
| 103 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; | 103 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; |
| 104 | if (exp->dir == IP_CT_DIR_REPLY) { | 104 | if (exp->dir == IP_CT_DIR_REPLY) { |
| 105 | range.flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | 105 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 106 | range.min = range.max = exp->saved_proto; | 106 | range.min = range.max = exp->saved_proto; |
| 107 | } | 107 | } |
| 108 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); | 108 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | /* outbound packets == from PNS to PAC */ | 111 | /* outbound packets == from PNS to PAC */ |
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/ipv4/netfilter/nf_nat_proto_common.c index a3d997618602..9993bc93e102 100644 --- a/net/ipv4/netfilter/nf_nat_proto_common.c +++ b/net/ipv4/netfilter/nf_nat_proto_common.c | |||
| @@ -26,7 +26,7 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple, | |||
| 26 | { | 26 | { |
| 27 | __be16 port; | 27 | __be16 port; |
| 28 | 28 | ||
| 29 | if (maniptype == IP_NAT_MANIP_SRC) | 29 | if (maniptype == NF_NAT_MANIP_SRC) |
| 30 | port = tuple->src.u.all; | 30 | port = tuple->src.u.all; |
| 31 | else | 31 | else |
| 32 | port = tuple->dst.u.all; | 32 | port = tuple->dst.u.all; |
| @@ -37,7 +37,7 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple, | |||
| 37 | EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); | 37 | EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); |
| 38 | 38 | ||
| 39 | void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | 39 | void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 40 | const struct nf_nat_range *range, | 40 | const struct nf_nat_ipv4_range *range, |
| 41 | enum nf_nat_manip_type maniptype, | 41 | enum nf_nat_manip_type maniptype, |
| 42 | const struct nf_conn *ct, | 42 | const struct nf_conn *ct, |
| 43 | u_int16_t *rover) | 43 | u_int16_t *rover) |
| @@ -46,15 +46,15 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 46 | __be16 *portptr; | 46 | __be16 *portptr; |
| 47 | u_int16_t off; | 47 | u_int16_t off; |
| 48 | 48 | ||
| 49 | if (maniptype == IP_NAT_MANIP_SRC) | 49 | if (maniptype == NF_NAT_MANIP_SRC) |
| 50 | portptr = &tuple->src.u.all; | 50 | portptr = &tuple->src.u.all; |
| 51 | else | 51 | else |
| 52 | portptr = &tuple->dst.u.all; | 52 | portptr = &tuple->dst.u.all; |
| 53 | 53 | ||
| 54 | /* If no range specified... */ | 54 | /* If no range specified... */ |
| 55 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { | 55 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) { |
| 56 | /* If it's dst rewrite, can't change port */ | 56 | /* If it's dst rewrite, can't change port */ |
| 57 | if (maniptype == IP_NAT_MANIP_DST) | 57 | if (maniptype == NF_NAT_MANIP_DST) |
| 58 | return; | 58 | return; |
| 59 | 59 | ||
| 60 | if (ntohs(*portptr) < 1024) { | 60 | if (ntohs(*portptr) < 1024) { |
| @@ -75,9 +75,9 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 75 | range_size = ntohs(range->max.all) - min + 1; | 75 | range_size = ntohs(range->max.all) - min + 1; |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | if (range->flags & IP_NAT_RANGE_PROTO_RANDOM) | 78 | if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) |
| 79 | off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, | 79 | off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, |
| 80 | maniptype == IP_NAT_MANIP_SRC | 80 | maniptype == NF_NAT_MANIP_SRC |
| 81 | ? tuple->dst.u.all | 81 | ? tuple->dst.u.all |
| 82 | : tuple->src.u.all); | 82 | : tuple->src.u.all); |
| 83 | else | 83 | else |
| @@ -87,7 +87,7 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 87 | *portptr = htons(min + off % range_size); | 87 | *portptr = htons(min + off % range_size); |
| 88 | if (++i != range_size && nf_nat_used_tuple(tuple, ct)) | 88 | if (++i != range_size && nf_nat_used_tuple(tuple, ct)) |
| 89 | continue; | 89 | continue; |
| 90 | if (!(range->flags & IP_NAT_RANGE_PROTO_RANDOM)) | 90 | if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) |
| 91 | *rover = off; | 91 | *rover = off; |
| 92 | return; | 92 | return; |
| 93 | } | 93 | } |
| @@ -96,31 +96,19 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 96 | EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple); | 96 | EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple); |
| 97 | 97 | ||
| 98 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 98 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 99 | int nf_nat_proto_range_to_nlattr(struct sk_buff *skb, | ||
| 100 | const struct nf_nat_range *range) | ||
| 101 | { | ||
| 102 | NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MIN, range->min.all); | ||
| 103 | NLA_PUT_BE16(skb, CTA_PROTONAT_PORT_MAX, range->max.all); | ||
| 104 | return 0; | ||
| 105 | |||
| 106 | nla_put_failure: | ||
| 107 | return -1; | ||
| 108 | } | ||
| 109 | EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range); | ||
| 110 | |||
| 111 | int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], | 99 | int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], |
| 112 | struct nf_nat_range *range) | 100 | struct nf_nat_ipv4_range *range) |
| 113 | { | 101 | { |
| 114 | if (tb[CTA_PROTONAT_PORT_MIN]) { | 102 | if (tb[CTA_PROTONAT_PORT_MIN]) { |
| 115 | range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); | 103 | range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); |
| 116 | range->max.all = range->min.tcp.port; | 104 | range->max.all = range->min.tcp.port; |
| 117 | range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | 105 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 118 | } | 106 | } |
| 119 | if (tb[CTA_PROTONAT_PORT_MAX]) { | 107 | if (tb[CTA_PROTONAT_PORT_MAX]) { |
| 120 | range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]); | 108 | range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]); |
| 121 | range->flags |= IP_NAT_RANGE_PROTO_SPECIFIED; | 109 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
| 122 | } | 110 | } |
| 123 | return 0; | 111 | return 0; |
| 124 | } | 112 | } |
| 125 | EXPORT_SYMBOL_GPL(nf_nat_proto_range_to_nlattr); | 113 | EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range); |
| 126 | #endif | 114 | #endif |
diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c index 570faf2667b2..3f67138d187c 100644 --- a/net/ipv4/netfilter/nf_nat_proto_dccp.c +++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c | |||
| @@ -24,7 +24,7 @@ static u_int16_t dccp_port_rover; | |||
| 24 | 24 | ||
| 25 | static void | 25 | static void |
| 26 | dccp_unique_tuple(struct nf_conntrack_tuple *tuple, | 26 | dccp_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 27 | const struct nf_nat_range *range, | 27 | const struct nf_nat_ipv4_range *range, |
| 28 | enum nf_nat_manip_type maniptype, | 28 | enum nf_nat_manip_type maniptype, |
| 29 | const struct nf_conn *ct) | 29 | const struct nf_conn *ct) |
| 30 | { | 30 | { |
| @@ -54,7 +54,7 @@ dccp_manip_pkt(struct sk_buff *skb, | |||
| 54 | iph = (struct iphdr *)(skb->data + iphdroff); | 54 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 55 | hdr = (struct dccp_hdr *)(skb->data + hdroff); | 55 | hdr = (struct dccp_hdr *)(skb->data + hdroff); |
| 56 | 56 | ||
| 57 | if (maniptype == IP_NAT_MANIP_SRC) { | 57 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 58 | oldip = iph->saddr; | 58 | oldip = iph->saddr; |
| 59 | newip = tuple->src.u3.ip; | 59 | newip = tuple->src.u3.ip; |
| 60 | newport = tuple->src.u.dccp.port; | 60 | newport = tuple->src.u.dccp.port; |
| @@ -80,12 +80,10 @@ dccp_manip_pkt(struct sk_buff *skb, | |||
| 80 | 80 | ||
| 81 | static const struct nf_nat_protocol nf_nat_protocol_dccp = { | 81 | static const struct nf_nat_protocol nf_nat_protocol_dccp = { |
| 82 | .protonum = IPPROTO_DCCP, | 82 | .protonum = IPPROTO_DCCP, |
| 83 | .me = THIS_MODULE, | ||
| 84 | .manip_pkt = dccp_manip_pkt, | 83 | .manip_pkt = dccp_manip_pkt, |
| 85 | .in_range = nf_nat_proto_in_range, | 84 | .in_range = nf_nat_proto_in_range, |
| 86 | .unique_tuple = dccp_unique_tuple, | 85 | .unique_tuple = dccp_unique_tuple, |
| 87 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 86 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 88 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 89 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 87 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 90 | #endif | 88 | #endif |
| 91 | }; | 89 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index bc8d83a31c73..46ba0b9ab985 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
| @@ -39,7 +39,7 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); | |||
| 39 | /* generate unique tuple ... */ | 39 | /* generate unique tuple ... */ |
| 40 | static void | 40 | static void |
| 41 | gre_unique_tuple(struct nf_conntrack_tuple *tuple, | 41 | gre_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 42 | const struct nf_nat_range *range, | 42 | const struct nf_nat_ipv4_range *range, |
| 43 | enum nf_nat_manip_type maniptype, | 43 | enum nf_nat_manip_type maniptype, |
| 44 | const struct nf_conn *ct) | 44 | const struct nf_conn *ct) |
| 45 | { | 45 | { |
| @@ -52,12 +52,12 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 52 | if (!ct->master) | 52 | if (!ct->master) |
| 53 | return; | 53 | return; |
| 54 | 54 | ||
| 55 | if (maniptype == IP_NAT_MANIP_SRC) | 55 | if (maniptype == NF_NAT_MANIP_SRC) |
| 56 | keyptr = &tuple->src.u.gre.key; | 56 | keyptr = &tuple->src.u.gre.key; |
| 57 | else | 57 | else |
| 58 | keyptr = &tuple->dst.u.gre.key; | 58 | keyptr = &tuple->dst.u.gre.key; |
| 59 | 59 | ||
| 60 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) { | 60 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) { |
| 61 | pr_debug("%p: NATing GRE PPTP\n", ct); | 61 | pr_debug("%p: NATing GRE PPTP\n", ct); |
| 62 | min = 1; | 62 | min = 1; |
| 63 | range_size = 0xffff; | 63 | range_size = 0xffff; |
| @@ -99,7 +99,7 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, | |||
| 99 | 99 | ||
| 100 | /* we only have destination manip of a packet, since 'source key' | 100 | /* we only have destination manip of a packet, since 'source key' |
| 101 | * is not present in the packet itself */ | 101 | * is not present in the packet itself */ |
| 102 | if (maniptype != IP_NAT_MANIP_DST) | 102 | if (maniptype != NF_NAT_MANIP_DST) |
| 103 | return true; | 103 | return true; |
| 104 | switch (greh->version) { | 104 | switch (greh->version) { |
| 105 | case GRE_VERSION_1701: | 105 | case GRE_VERSION_1701: |
| @@ -119,12 +119,10 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, | |||
| 119 | 119 | ||
| 120 | static const struct nf_nat_protocol gre = { | 120 | static const struct nf_nat_protocol gre = { |
| 121 | .protonum = IPPROTO_GRE, | 121 | .protonum = IPPROTO_GRE, |
| 122 | .me = THIS_MODULE, | ||
| 123 | .manip_pkt = gre_manip_pkt, | 122 | .manip_pkt = gre_manip_pkt, |
| 124 | .in_range = nf_nat_proto_in_range, | 123 | .in_range = nf_nat_proto_in_range, |
| 125 | .unique_tuple = gre_unique_tuple, | 124 | .unique_tuple = gre_unique_tuple, |
| 126 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 125 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 127 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 128 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 126 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 129 | #endif | 127 | #endif |
| 130 | }; | 128 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index 9f4dc1235dc7..b35172851bae 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c | |||
| @@ -30,7 +30,7 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple, | |||
| 30 | 30 | ||
| 31 | static void | 31 | static void |
| 32 | icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | 32 | icmp_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 33 | const struct nf_nat_range *range, | 33 | const struct nf_nat_ipv4_range *range, |
| 34 | enum nf_nat_manip_type maniptype, | 34 | enum nf_nat_manip_type maniptype, |
| 35 | const struct nf_conn *ct) | 35 | const struct nf_conn *ct) |
| 36 | { | 36 | { |
| @@ -40,7 +40,7 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
| 40 | 40 | ||
| 41 | range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; | 41 | range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; |
| 42 | /* If no range specified... */ | 42 | /* If no range specified... */ |
| 43 | if (!(range->flags & IP_NAT_RANGE_PROTO_SPECIFIED)) | 43 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) |
| 44 | range_size = 0xFFFF; | 44 | range_size = 0xFFFF; |
| 45 | 45 | ||
| 46 | for (i = 0; ; ++id) { | 46 | for (i = 0; ; ++id) { |
| @@ -74,12 +74,10 @@ icmp_manip_pkt(struct sk_buff *skb, | |||
| 74 | 74 | ||
| 75 | const struct nf_nat_protocol nf_nat_protocol_icmp = { | 75 | const struct nf_nat_protocol nf_nat_protocol_icmp = { |
| 76 | .protonum = IPPROTO_ICMP, | 76 | .protonum = IPPROTO_ICMP, |
| 77 | .me = THIS_MODULE, | ||
| 78 | .manip_pkt = icmp_manip_pkt, | 77 | .manip_pkt = icmp_manip_pkt, |
| 79 | .in_range = icmp_in_range, | 78 | .in_range = icmp_in_range, |
| 80 | .unique_tuple = icmp_unique_tuple, | 79 | .unique_tuple = icmp_unique_tuple, |
| 81 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 80 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 82 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 83 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 81 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 84 | #endif | 82 | #endif |
| 85 | }; | 83 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/ipv4/netfilter/nf_nat_proto_sctp.c index bd5a80a62a5b..3cce9b6c1c29 100644 --- a/net/ipv4/netfilter/nf_nat_proto_sctp.c +++ b/net/ipv4/netfilter/nf_nat_proto_sctp.c | |||
| @@ -19,7 +19,7 @@ static u_int16_t nf_sctp_port_rover; | |||
| 19 | 19 | ||
| 20 | static void | 20 | static void |
| 21 | sctp_unique_tuple(struct nf_conntrack_tuple *tuple, | 21 | sctp_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 22 | const struct nf_nat_range *range, | 22 | const struct nf_nat_ipv4_range *range, |
| 23 | enum nf_nat_manip_type maniptype, | 23 | enum nf_nat_manip_type maniptype, |
| 24 | const struct nf_conn *ct) | 24 | const struct nf_conn *ct) |
| 25 | { | 25 | { |
| @@ -46,7 +46,7 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
| 46 | iph = (struct iphdr *)(skb->data + iphdroff); | 46 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 47 | hdr = (struct sctphdr *)(skb->data + hdroff); | 47 | hdr = (struct sctphdr *)(skb->data + hdroff); |
| 48 | 48 | ||
| 49 | if (maniptype == IP_NAT_MANIP_SRC) { | 49 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 50 | /* Get rid of src ip and src pt */ | 50 | /* Get rid of src ip and src pt */ |
| 51 | oldip = iph->saddr; | 51 | oldip = iph->saddr; |
| 52 | newip = tuple->src.u3.ip; | 52 | newip = tuple->src.u3.ip; |
| @@ -70,12 +70,10 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
| 70 | 70 | ||
| 71 | static const struct nf_nat_protocol nf_nat_protocol_sctp = { | 71 | static const struct nf_nat_protocol nf_nat_protocol_sctp = { |
| 72 | .protonum = IPPROTO_SCTP, | 72 | .protonum = IPPROTO_SCTP, |
| 73 | .me = THIS_MODULE, | ||
| 74 | .manip_pkt = sctp_manip_pkt, | 73 | .manip_pkt = sctp_manip_pkt, |
| 75 | .in_range = nf_nat_proto_in_range, | 74 | .in_range = nf_nat_proto_in_range, |
| 76 | .unique_tuple = sctp_unique_tuple, | 75 | .unique_tuple = sctp_unique_tuple, |
| 77 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 76 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 78 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 79 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 77 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 80 | #endif | 78 | #endif |
| 81 | }; | 79 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/ipv4/netfilter/nf_nat_proto_tcp.c index 0d67bb80130f..9fb4b4e72bbf 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/ipv4/netfilter/nf_nat_proto_tcp.c | |||
| @@ -23,7 +23,7 @@ static u_int16_t tcp_port_rover; | |||
| 23 | 23 | ||
| 24 | static void | 24 | static void |
| 25 | tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | 25 | tcp_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 26 | const struct nf_nat_range *range, | 26 | const struct nf_nat_ipv4_range *range, |
| 27 | enum nf_nat_manip_type maniptype, | 27 | enum nf_nat_manip_type maniptype, |
| 28 | const struct nf_conn *ct) | 28 | const struct nf_conn *ct) |
| 29 | { | 29 | { |
| @@ -55,7 +55,7 @@ tcp_manip_pkt(struct sk_buff *skb, | |||
| 55 | iph = (struct iphdr *)(skb->data + iphdroff); | 55 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 56 | hdr = (struct tcphdr *)(skb->data + hdroff); | 56 | hdr = (struct tcphdr *)(skb->data + hdroff); |
| 57 | 57 | ||
| 58 | if (maniptype == IP_NAT_MANIP_SRC) { | 58 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 59 | /* Get rid of src ip and src pt */ | 59 | /* Get rid of src ip and src pt */ |
| 60 | oldip = iph->saddr; | 60 | oldip = iph->saddr; |
| 61 | newip = tuple->src.u3.ip; | 61 | newip = tuple->src.u3.ip; |
| @@ -82,12 +82,10 @@ tcp_manip_pkt(struct sk_buff *skb, | |||
| 82 | 82 | ||
| 83 | const struct nf_nat_protocol nf_nat_protocol_tcp = { | 83 | const struct nf_nat_protocol nf_nat_protocol_tcp = { |
| 84 | .protonum = IPPROTO_TCP, | 84 | .protonum = IPPROTO_TCP, |
| 85 | .me = THIS_MODULE, | ||
| 86 | .manip_pkt = tcp_manip_pkt, | 85 | .manip_pkt = tcp_manip_pkt, |
| 87 | .in_range = nf_nat_proto_in_range, | 86 | .in_range = nf_nat_proto_in_range, |
| 88 | .unique_tuple = tcp_unique_tuple, | 87 | .unique_tuple = tcp_unique_tuple, |
| 89 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 88 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 90 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 91 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 89 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 92 | #endif | 90 | #endif |
| 93 | }; | 91 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/ipv4/netfilter/nf_nat_proto_udp.c index 0b1b8601cba7..9883336e628f 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/ipv4/netfilter/nf_nat_proto_udp.c | |||
| @@ -22,7 +22,7 @@ static u_int16_t udp_port_rover; | |||
| 22 | 22 | ||
| 23 | static void | 23 | static void |
| 24 | udp_unique_tuple(struct nf_conntrack_tuple *tuple, | 24 | udp_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 25 | const struct nf_nat_range *range, | 25 | const struct nf_nat_ipv4_range *range, |
| 26 | enum nf_nat_manip_type maniptype, | 26 | enum nf_nat_manip_type maniptype, |
| 27 | const struct nf_conn *ct) | 27 | const struct nf_conn *ct) |
| 28 | { | 28 | { |
| @@ -47,7 +47,7 @@ udp_manip_pkt(struct sk_buff *skb, | |||
| 47 | iph = (struct iphdr *)(skb->data + iphdroff); | 47 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 48 | hdr = (struct udphdr *)(skb->data + hdroff); | 48 | hdr = (struct udphdr *)(skb->data + hdroff); |
| 49 | 49 | ||
| 50 | if (maniptype == IP_NAT_MANIP_SRC) { | 50 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 51 | /* Get rid of src ip and src pt */ | 51 | /* Get rid of src ip and src pt */ |
| 52 | oldip = iph->saddr; | 52 | oldip = iph->saddr; |
| 53 | newip = tuple->src.u3.ip; | 53 | newip = tuple->src.u3.ip; |
| @@ -73,12 +73,10 @@ udp_manip_pkt(struct sk_buff *skb, | |||
| 73 | 73 | ||
| 74 | const struct nf_nat_protocol nf_nat_protocol_udp = { | 74 | const struct nf_nat_protocol nf_nat_protocol_udp = { |
| 75 | .protonum = IPPROTO_UDP, | 75 | .protonum = IPPROTO_UDP, |
| 76 | .me = THIS_MODULE, | ||
| 77 | .manip_pkt = udp_manip_pkt, | 76 | .manip_pkt = udp_manip_pkt, |
| 78 | .in_range = nf_nat_proto_in_range, | 77 | .in_range = nf_nat_proto_in_range, |
| 79 | .unique_tuple = udp_unique_tuple, | 78 | .unique_tuple = udp_unique_tuple, |
| 80 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 79 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 81 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 82 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 80 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 83 | #endif | 81 | #endif |
| 84 | }; | 82 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/ipv4/netfilter/nf_nat_proto_udplite.c index f83ef23e2ab7..d24d10a7beb2 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udplite.c +++ b/net/ipv4/netfilter/nf_nat_proto_udplite.c | |||
| @@ -21,7 +21,7 @@ static u_int16_t udplite_port_rover; | |||
| 21 | 21 | ||
| 22 | static void | 22 | static void |
| 23 | udplite_unique_tuple(struct nf_conntrack_tuple *tuple, | 23 | udplite_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 24 | const struct nf_nat_range *range, | 24 | const struct nf_nat_ipv4_range *range, |
| 25 | enum nf_nat_manip_type maniptype, | 25 | enum nf_nat_manip_type maniptype, |
| 26 | const struct nf_conn *ct) | 26 | const struct nf_conn *ct) |
| 27 | { | 27 | { |
| @@ -47,7 +47,7 @@ udplite_manip_pkt(struct sk_buff *skb, | |||
| 47 | iph = (struct iphdr *)(skb->data + iphdroff); | 47 | iph = (struct iphdr *)(skb->data + iphdroff); |
| 48 | hdr = (struct udphdr *)(skb->data + hdroff); | 48 | hdr = (struct udphdr *)(skb->data + hdroff); |
| 49 | 49 | ||
| 50 | if (maniptype == IP_NAT_MANIP_SRC) { | 50 | if (maniptype == NF_NAT_MANIP_SRC) { |
| 51 | /* Get rid of src ip and src pt */ | 51 | /* Get rid of src ip and src pt */ |
| 52 | oldip = iph->saddr; | 52 | oldip = iph->saddr; |
| 53 | newip = tuple->src.u3.ip; | 53 | newip = tuple->src.u3.ip; |
| @@ -72,12 +72,10 @@ udplite_manip_pkt(struct sk_buff *skb, | |||
| 72 | 72 | ||
| 73 | static const struct nf_nat_protocol nf_nat_protocol_udplite = { | 73 | static const struct nf_nat_protocol nf_nat_protocol_udplite = { |
| 74 | .protonum = IPPROTO_UDPLITE, | 74 | .protonum = IPPROTO_UDPLITE, |
| 75 | .me = THIS_MODULE, | ||
| 76 | .manip_pkt = udplite_manip_pkt, | 75 | .manip_pkt = udplite_manip_pkt, |
| 77 | .in_range = nf_nat_proto_in_range, | 76 | .in_range = nf_nat_proto_in_range, |
| 78 | .unique_tuple = udplite_unique_tuple, | 77 | .unique_tuple = udplite_unique_tuple, |
| 79 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 78 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
| 80 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
| 81 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 79 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, |
| 82 | #endif | 80 | #endif |
| 83 | }; | 81 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/ipv4/netfilter/nf_nat_proto_unknown.c index a50f2bc1c732..e0afe8112b1c 100644 --- a/net/ipv4/netfilter/nf_nat_proto_unknown.c +++ b/net/ipv4/netfilter/nf_nat_proto_unknown.c | |||
| @@ -27,7 +27,7 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple, | |||
| 27 | } | 27 | } |
| 28 | 28 | ||
| 29 | static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple, | 29 | static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple, |
| 30 | const struct nf_nat_range *range, | 30 | const struct nf_nat_ipv4_range *range, |
| 31 | enum nf_nat_manip_type maniptype, | 31 | enum nf_nat_manip_type maniptype, |
| 32 | const struct nf_conn *ct) | 32 | const struct nf_conn *ct) |
| 33 | { | 33 | { |
| @@ -46,7 +46,6 @@ unknown_manip_pkt(struct sk_buff *skb, | |||
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | const struct nf_nat_protocol nf_nat_unknown_protocol = { | 48 | const struct nf_nat_protocol nf_nat_unknown_protocol = { |
| 49 | /* .me isn't set: getting a ref to this cannot fail. */ | ||
| 50 | .manip_pkt = unknown_manip_pkt, | 49 | .manip_pkt = unknown_manip_pkt, |
| 51 | .in_range = unknown_in_range, | 50 | .in_range = unknown_in_range, |
| 52 | .unique_tuple = unknown_unique_tuple, | 51 | .unique_tuple = unknown_unique_tuple, |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c index 733c9abc1cbd..d2a9dc314e0e 100644 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ b/net/ipv4/netfilter/nf_nat_rule.c | |||
| @@ -44,7 +44,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 44 | { | 44 | { |
| 45 | struct nf_conn *ct; | 45 | struct nf_conn *ct; |
| 46 | enum ip_conntrack_info ctinfo; | 46 | enum ip_conntrack_info ctinfo; |
| 47 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 47 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 48 | 48 | ||
| 49 | NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING || | 49 | NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING || |
| 50 | par->hooknum == NF_INET_LOCAL_IN); | 50 | par->hooknum == NF_INET_LOCAL_IN); |
| @@ -56,7 +56,7 @@ ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 56 | ctinfo == IP_CT_RELATED_REPLY)); | 56 | ctinfo == IP_CT_RELATED_REPLY)); |
| 57 | NF_CT_ASSERT(par->out != NULL); | 57 | NF_CT_ASSERT(par->out != NULL); |
| 58 | 58 | ||
| 59 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_SRC); | 59 | return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_SRC); |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static unsigned int | 62 | static unsigned int |
| @@ -64,7 +64,7 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 64 | { | 64 | { |
| 65 | struct nf_conn *ct; | 65 | struct nf_conn *ct; |
| 66 | enum ip_conntrack_info ctinfo; | 66 | enum ip_conntrack_info ctinfo; |
| 67 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 67 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 68 | 68 | ||
| 69 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | 69 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
| 70 | par->hooknum == NF_INET_LOCAL_OUT); | 70 | par->hooknum == NF_INET_LOCAL_OUT); |
| @@ -74,12 +74,12 @@ ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 74 | /* Connection must be valid and new. */ | 74 | /* Connection must be valid and new. */ |
| 75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | 75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); |
| 76 | 76 | ||
| 77 | return nf_nat_setup_info(ct, &mr->range[0], IP_NAT_MANIP_DST); | 77 | return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_DST); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static int ipt_snat_checkentry(const struct xt_tgchk_param *par) | 80 | static int ipt_snat_checkentry(const struct xt_tgchk_param *par) |
| 81 | { | 81 | { |
| 82 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 82 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 83 | 83 | ||
| 84 | /* Must be a valid range */ | 84 | /* Must be a valid range */ |
| 85 | if (mr->rangesize != 1) { | 85 | if (mr->rangesize != 1) { |
| @@ -91,7 +91,7 @@ static int ipt_snat_checkentry(const struct xt_tgchk_param *par) | |||
| 91 | 91 | ||
| 92 | static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) | 92 | static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) |
| 93 | { | 93 | { |
| 94 | const struct nf_nat_multi_range_compat *mr = par->targinfo; | 94 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
| 95 | 95 | ||
| 96 | /* Must be a valid range */ | 96 | /* Must be a valid range */ |
| 97 | if (mr->rangesize != 1) { | 97 | if (mr->rangesize != 1) { |
| @@ -105,13 +105,13 @@ static unsigned int | |||
| 105 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | 105 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) |
| 106 | { | 106 | { |
| 107 | /* Force range to this IP; let proto decide mapping for | 107 | /* Force range to this IP; let proto decide mapping for |
| 108 | per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). | 108 | per-proto parts (hence not NF_NAT_RANGE_PROTO_SPECIFIED). |
| 109 | */ | 109 | */ |
| 110 | struct nf_nat_range range; | 110 | struct nf_nat_ipv4_range range; |
| 111 | 111 | ||
| 112 | range.flags = 0; | 112 | range.flags = 0; |
| 113 | pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, | 113 | pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, |
| 114 | HOOK2MANIP(hooknum) == IP_NAT_MANIP_SRC ? | 114 | HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? |
| 115 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip : | 115 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip : |
| 116 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); | 116 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); |
| 117 | 117 | ||
| @@ -140,7 +140,7 @@ int nf_nat_rule_find(struct sk_buff *skb, | |||
| 140 | static struct xt_target ipt_snat_reg __read_mostly = { | 140 | static struct xt_target ipt_snat_reg __read_mostly = { |
| 141 | .name = "SNAT", | 141 | .name = "SNAT", |
| 142 | .target = ipt_snat_target, | 142 | .target = ipt_snat_target, |
| 143 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 143 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), |
| 144 | .table = "nat", | 144 | .table = "nat", |
| 145 | .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), | 145 | .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), |
| 146 | .checkentry = ipt_snat_checkentry, | 146 | .checkentry = ipt_snat_checkentry, |
| @@ -150,7 +150,7 @@ static struct xt_target ipt_snat_reg __read_mostly = { | |||
| 150 | static struct xt_target ipt_dnat_reg __read_mostly = { | 150 | static struct xt_target ipt_dnat_reg __read_mostly = { |
| 151 | .name = "DNAT", | 151 | .name = "DNAT", |
| 152 | .target = ipt_dnat_target, | 152 | .target = ipt_dnat_target, |
| 153 | .targetsize = sizeof(struct nf_nat_multi_range_compat), | 153 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), |
| 154 | .table = "nat", | 154 | .table = "nat", |
| 155 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | 155 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), |
| 156 | .checkentry = ipt_dnat_checkentry, | 156 | .checkentry = ipt_dnat_checkentry, |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/ipv4/netfilter/nf_nat_sip.c index 78844d9208f1..d0319f96269f 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/ipv4/netfilter/nf_nat_sip.c | |||
| @@ -249,25 +249,25 @@ static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off) | |||
| 249 | static void ip_nat_sip_expected(struct nf_conn *ct, | 249 | static void ip_nat_sip_expected(struct nf_conn *ct, |
| 250 | struct nf_conntrack_expect *exp) | 250 | struct nf_conntrack_expect *exp) |
| 251 | { | 251 | { |
| 252 | struct nf_nat_range range; | 252 | struct nf_nat_ipv4_range range; |
| 253 | 253 | ||
| 254 | /* This must be a fresh one. */ | 254 | /* This must be a fresh one. */ |
| 255 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | 255 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); |
| 256 | 256 | ||
| 257 | /* For DST manip, map port here to where it's expected. */ | 257 | /* For DST manip, map port here to where it's expected. */ |
| 258 | range.flags = (IP_NAT_RANGE_MAP_IPS | IP_NAT_RANGE_PROTO_SPECIFIED); | 258 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
| 259 | range.min = range.max = exp->saved_proto; | 259 | range.min = range.max = exp->saved_proto; |
| 260 | range.min_ip = range.max_ip = exp->saved_ip; | 260 | range.min_ip = range.max_ip = exp->saved_ip; |
| 261 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_DST); | 261 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
| 262 | 262 | ||
| 263 | /* Change src to where master sends to, but only if the connection | 263 | /* Change src to where master sends to, but only if the connection |
| 264 | * actually came from the same source. */ | 264 | * actually came from the same source. */ |
| 265 | if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == | 265 | if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == |
| 266 | ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { | 266 | ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { |
| 267 | range.flags = IP_NAT_RANGE_MAP_IPS; | 267 | range.flags = NF_NAT_RANGE_MAP_IPS; |
| 268 | range.min_ip = range.max_ip | 268 | range.min_ip = range.max_ip |
| 269 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 269 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; |
| 270 | nf_nat_setup_info(ct, &range, IP_NAT_MANIP_SRC); | 270 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
| 271 | } | 271 | } |
| 272 | } | 272 | } |
| 273 | 273 | ||
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index 92900482edea..3828a4229822 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
| @@ -137,7 +137,7 @@ nf_nat_fn(unsigned int hooknum, | |||
| 137 | return ret; | 137 | return ret; |
| 138 | } else | 138 | } else |
| 139 | pr_debug("Already setup manip %s for ct %p\n", | 139 | pr_debug("Already setup manip %s for ct %p\n", |
| 140 | maniptype == IP_NAT_MANIP_SRC ? "SRC" : "DST", | 140 | maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST", |
| 141 | ct); | 141 | ct); |
| 142 | break; | 142 | break; |
| 143 | 143 | ||
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index f792b34cbe9c..9a68fb5b9e77 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
| @@ -125,6 +125,16 @@ config IP6_NF_MATCH_MH | |||
| 125 | 125 | ||
| 126 | To compile it as a module, choose M here. If unsure, say N. | 126 | To compile it as a module, choose M here. If unsure, say N. |
| 127 | 127 | ||
| 128 | config IP6_NF_MATCH_RPFILTER | ||
| 129 | tristate '"rpfilter" reverse path filter match support' | ||
| 130 | depends on NETFILTER_ADVANCED | ||
| 131 | ---help--- | ||
| 132 | This option allows you to match packets whose replies would | ||
| 133 | go out via the interface the packet came in. | ||
| 134 | |||
| 135 | To compile it as a module, choose M here. If unsure, say N. | ||
| 136 | The module will be called ip6t_rpfilter. | ||
| 137 | |||
| 128 | config IP6_NF_MATCH_RT | 138 | config IP6_NF_MATCH_RT |
| 129 | tristate '"rt" Routing header match support' | 139 | tristate '"rt" Routing header match support' |
| 130 | depends on NETFILTER_ADVANCED | 140 | depends on NETFILTER_ADVANCED |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index abfee91ce816..2eaed96db02c 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
| @@ -27,6 +27,7 @@ obj-$(CONFIG_IP6_NF_MATCH_FRAG) += ip6t_frag.o | |||
| 27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o | 27 | obj-$(CONFIG_IP6_NF_MATCH_IPV6HEADER) += ip6t_ipv6header.o |
| 28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o | 28 | obj-$(CONFIG_IP6_NF_MATCH_MH) += ip6t_mh.o |
| 29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o | 29 | obj-$(CONFIG_IP6_NF_MATCH_OPTS) += ip6t_hbh.o |
| 30 | obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | ||
| 30 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 31 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
| 31 | 32 | ||
| 32 | # targets | 33 | # targets |
diff --git a/net/ipv6/netfilter/ip6t_rpfilter.c b/net/ipv6/netfilter/ip6t_rpfilter.c new file mode 100644 index 000000000000..5d1d8b04d694 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_rpfilter.c | |||
| @@ -0,0 +1,133 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Florian Westphal <fw@strlen.de> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/skbuff.h> | ||
| 11 | #include <linux/netdevice.h> | ||
| 12 | #include <linux/route.h> | ||
| 13 | #include <net/ip6_fib.h> | ||
| 14 | #include <net/ip6_route.h> | ||
| 15 | |||
| 16 | #include <linux/netfilter/xt_rpfilter.h> | ||
| 17 | #include <linux/netfilter/x_tables.h> | ||
| 18 | |||
| 19 | MODULE_LICENSE("GPL"); | ||
| 20 | MODULE_AUTHOR("Florian Westphal <fw@strlen.de>"); | ||
| 21 | MODULE_DESCRIPTION("Xtables: IPv6 reverse path filter match"); | ||
| 22 | |||
| 23 | static bool rpfilter_addr_unicast(const struct in6_addr *addr) | ||
| 24 | { | ||
| 25 | int addr_type = ipv6_addr_type(addr); | ||
| 26 | return addr_type & IPV6_ADDR_UNICAST; | ||
| 27 | } | ||
| 28 | |||
| 29 | static bool rpfilter_lookup_reverse6(const struct sk_buff *skb, | ||
| 30 | const struct net_device *dev, u8 flags) | ||
| 31 | { | ||
| 32 | struct rt6_info *rt; | ||
| 33 | struct ipv6hdr *iph = ipv6_hdr(skb); | ||
| 34 | bool ret = false; | ||
| 35 | struct flowi6 fl6 = { | ||
| 36 | .flowlabel = (* (__be32 *) iph) & IPV6_FLOWINFO_MASK, | ||
| 37 | .flowi6_proto = iph->nexthdr, | ||
| 38 | .daddr = iph->saddr, | ||
| 39 | }; | ||
| 40 | int lookup_flags; | ||
| 41 | |||
| 42 | if (rpfilter_addr_unicast(&iph->daddr)) { | ||
| 43 | memcpy(&fl6.saddr, &iph->daddr, sizeof(struct in6_addr)); | ||
| 44 | lookup_flags = RT6_LOOKUP_F_HAS_SADDR; | ||
| 45 | } else { | ||
| 46 | lookup_flags = 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | fl6.flowi6_mark = flags & XT_RPFILTER_VALID_MARK ? skb->mark : 0; | ||
| 50 | if ((flags & XT_RPFILTER_LOOSE) == 0) { | ||
| 51 | fl6.flowi6_oif = dev->ifindex; | ||
| 52 | lookup_flags |= RT6_LOOKUP_F_IFACE; | ||
| 53 | } | ||
| 54 | |||
| 55 | rt = (void *) ip6_route_lookup(dev_net(dev), &fl6, lookup_flags); | ||
| 56 | if (rt->dst.error) | ||
| 57 | goto out; | ||
| 58 | |||
| 59 | if (rt->rt6i_flags & (RTF_REJECT|RTF_ANYCAST)) | ||
| 60 | goto out; | ||
| 61 | |||
| 62 | if (rt->rt6i_flags & RTF_LOCAL) { | ||
| 63 | ret = flags & XT_RPFILTER_ACCEPT_LOCAL; | ||
| 64 | goto out; | ||
| 65 | } | ||
| 66 | |||
| 67 | if (rt->rt6i_idev->dev == dev || (flags & XT_RPFILTER_LOOSE)) | ||
| 68 | ret = true; | ||
| 69 | out: | ||
| 70 | dst_release(&rt->dst); | ||
| 71 | return ret; | ||
| 72 | } | ||
| 73 | |||
| 74 | static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 75 | { | ||
| 76 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
| 77 | int saddrtype; | ||
| 78 | struct ipv6hdr *iph; | ||
| 79 | bool invert = info->flags & XT_RPFILTER_INVERT; | ||
| 80 | |||
| 81 | if (par->in->flags & IFF_LOOPBACK) | ||
| 82 | return true ^ invert; | ||
| 83 | |||
| 84 | iph = ipv6_hdr(skb); | ||
| 85 | saddrtype = ipv6_addr_type(&iph->saddr); | ||
| 86 | if (unlikely(saddrtype == IPV6_ADDR_ANY)) | ||
| 87 | return true ^ invert; /* not routable: forward path will drop it */ | ||
| 88 | |||
| 89 | return rpfilter_lookup_reverse6(skb, par->in, info->flags) ^ invert; | ||
| 90 | } | ||
| 91 | |||
| 92 | static int rpfilter_check(const struct xt_mtchk_param *par) | ||
| 93 | { | ||
| 94 | const struct xt_rpfilter_info *info = par->matchinfo; | ||
| 95 | unsigned int options = ~XT_RPFILTER_OPTION_MASK; | ||
| 96 | |||
| 97 | if (info->flags & options) { | ||
| 98 | pr_info("unknown options encountered"); | ||
| 99 | return -EINVAL; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (strcmp(par->table, "mangle") != 0 && | ||
| 103 | strcmp(par->table, "raw") != 0) { | ||
| 104 | pr_info("match only valid in the \'raw\' " | ||
| 105 | "or \'mangle\' tables, not \'%s\'.\n", par->table); | ||
| 106 | return -EINVAL; | ||
| 107 | } | ||
| 108 | |||
| 109 | return 0; | ||
| 110 | } | ||
| 111 | |||
| 112 | static struct xt_match rpfilter_mt_reg __read_mostly = { | ||
| 113 | .name = "rpfilter", | ||
| 114 | .family = NFPROTO_IPV6, | ||
| 115 | .checkentry = rpfilter_check, | ||
| 116 | .match = rpfilter_mt, | ||
| 117 | .matchsize = sizeof(struct xt_rpfilter_info), | ||
| 118 | .hooks = (1 << NF_INET_PRE_ROUTING), | ||
| 119 | .me = THIS_MODULE | ||
| 120 | }; | ||
| 121 | |||
| 122 | static int __init rpfilter_mt_init(void) | ||
| 123 | { | ||
| 124 | return xt_register_match(&rpfilter_mt_reg); | ||
| 125 | } | ||
| 126 | |||
| 127 | static void __exit rpfilter_mt_exit(void) | ||
| 128 | { | ||
| 129 | xt_unregister_match(&rpfilter_mt_reg); | ||
| 130 | } | ||
| 131 | |||
| 132 | module_init(rpfilter_mt_init); | ||
| 133 | module_exit(rpfilter_mt_exit); | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index ad438546d915..5855e9ede3cb 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -658,6 +658,13 @@ out: | |||
| 658 | 658 | ||
| 659 | } | 659 | } |
| 660 | 660 | ||
| 661 | struct dst_entry * ip6_route_lookup(struct net *net, struct flowi6 *fl6, | ||
| 662 | int flags) | ||
| 663 | { | ||
| 664 | return fib6_rule_lookup(net, fl6, flags, ip6_pol_route_lookup); | ||
| 665 | } | ||
| 666 | EXPORT_SYMBOL_GPL(ip6_route_lookup); | ||
| 667 | |||
| 661 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, | 668 | struct rt6_info *rt6_lookup(struct net *net, const struct in6_addr *daddr, |
| 662 | const struct in6_addr *saddr, int oif, int strict) | 669 | const struct in6_addr *saddr, int oif, int strict) |
| 663 | { | 670 | { |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index d5597b759ba3..bac93ba60778 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
| @@ -4,6 +4,14 @@ menu "Core Netfilter Configuration" | |||
| 4 | config NETFILTER_NETLINK | 4 | config NETFILTER_NETLINK |
| 5 | tristate | 5 | tristate |
| 6 | 6 | ||
| 7 | config NETFILTER_NETLINK_ACCT | ||
| 8 | tristate "Netfilter NFACCT over NFNETLINK interface" | ||
| 9 | depends on NETFILTER_ADVANCED | ||
| 10 | select NETFILTER_NETLINK | ||
| 11 | help | ||
| 12 | If this option is enabled, the kernel will include support | ||
| 13 | for extended accounting via NFNETLINK. | ||
| 14 | |||
| 7 | config NETFILTER_NETLINK_QUEUE | 15 | config NETFILTER_NETLINK_QUEUE |
| 8 | tristate "Netfilter NFQUEUE over NFNETLINK interface" | 16 | tristate "Netfilter NFQUEUE over NFNETLINK interface" |
| 9 | depends on NETFILTER_ADVANCED | 17 | depends on NETFILTER_ADVANCED |
| @@ -879,6 +887,16 @@ config NETFILTER_XT_MATCH_MULTIPORT | |||
| 879 | 887 | ||
| 880 | To compile it as a module, choose M here. If unsure, say N. | 888 | To compile it as a module, choose M here. If unsure, say N. |
| 881 | 889 | ||
| 890 | config NETFILTER_XT_MATCH_NFACCT | ||
| 891 | tristate '"nfacct" match support' | ||
| 892 | default m if NETFILTER_ADVANCED=n | ||
| 893 | select NETFILTER_NETLINK_ACCT | ||
| 894 | help | ||
| 895 | This option allows you to use the extended accounting through | ||
| 896 | nfnetlink_acct. | ||
| 897 | |||
| 898 | To compile it as a module, choose M here. If unsure, say N. | ||
| 899 | |||
| 882 | config NETFILTER_XT_MATCH_OSF | 900 | config NETFILTER_XT_MATCH_OSF |
| 883 | tristate '"osf" Passive OS fingerprint match' | 901 | tristate '"osf" Passive OS fingerprint match' |
| 884 | depends on NETFILTER_ADVANCED && NETFILTER_NETLINK | 902 | depends on NETFILTER_ADVANCED && NETFILTER_NETLINK |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 1a02853df863..b2eee4df8168 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
| @@ -7,6 +7,7 @@ nf_conntrack-$(CONFIG_NF_CONNTRACK_EVENTS) += nf_conntrack_ecache.o | |||
| 7 | obj-$(CONFIG_NETFILTER) = netfilter.o | 7 | obj-$(CONFIG_NETFILTER) = netfilter.o |
| 8 | 8 | ||
| 9 | obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o | 9 | obj-$(CONFIG_NETFILTER_NETLINK) += nfnetlink.o |
| 10 | obj-$(CONFIG_NETFILTER_NETLINK_ACCT) += nfnetlink_acct.o | ||
| 10 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o | 11 | obj-$(CONFIG_NETFILTER_NETLINK_QUEUE) += nfnetlink_queue.o |
| 11 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o | 12 | obj-$(CONFIG_NETFILTER_NETLINK_LOG) += nfnetlink_log.o |
| 12 | 13 | ||
| @@ -90,6 +91,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_LENGTH) += xt_length.o | |||
| 90 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o | 91 | obj-$(CONFIG_NETFILTER_XT_MATCH_LIMIT) += xt_limit.o |
| 91 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o | 92 | obj-$(CONFIG_NETFILTER_XT_MATCH_MAC) += xt_mac.o |
| 92 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o | 93 | obj-$(CONFIG_NETFILTER_XT_MATCH_MULTIPORT) += xt_multiport.o |
| 94 | obj-$(CONFIG_NETFILTER_XT_MATCH_NFACCT) += xt_nfacct.o | ||
| 93 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o | 95 | obj-$(CONFIG_NETFILTER_XT_MATCH_OSF) += xt_osf.o |
| 94 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o | 96 | obj-$(CONFIG_NETFILTER_XT_MATCH_OWNER) += xt_owner.o |
| 95 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o | 97 | obj-$(CONFIG_NETFILTER_XT_MATCH_PHYSDEV) += xt_physdev.o |
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index 70bd1d0774c6..af4c0b8c5275 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
| @@ -232,6 +232,21 @@ config IP_VS_NQ | |||
| 232 | If you want to compile it in kernel, say Y. To compile it as a | 232 | If you want to compile it in kernel, say Y. To compile it as a |
| 233 | module, choose M here. If unsure, say N. | 233 | module, choose M here. If unsure, say N. |
| 234 | 234 | ||
| 235 | comment 'IPVS SH scheduler' | ||
| 236 | |||
| 237 | config IP_VS_SH_TAB_BITS | ||
| 238 | int "IPVS source hashing table size (the Nth power of 2)" | ||
| 239 | range 4 20 | ||
| 240 | default 8 | ||
| 241 | ---help--- | ||
| 242 | The source hashing scheduler maps source IPs to destinations | ||
| 243 | stored in a hash table. This table is tiled by each destination | ||
| 244 | until all slots in the table are filled. When using weights to | ||
| 245 | allow destinations to receive more connections, the table is | ||
| 246 | tiled an amount proportional to the weights specified. The table | ||
| 247 | needs to be large enough to effectively fit all the destinations | ||
| 248 | multiplied by their respective weights. | ||
| 249 | |||
| 235 | comment 'IPVS application helper' | 250 | comment 'IPVS application helper' |
| 236 | 251 | ||
| 237 | config IP_VS_FTP | 252 | config IP_VS_FTP |
diff --git a/net/netfilter/ipvs/ip_vs_sh.c b/net/netfilter/ipvs/ip_vs_sh.c index 33815f4fb451..069e8d4d5c01 100644 --- a/net/netfilter/ipvs/ip_vs_sh.c +++ b/net/netfilter/ipvs/ip_vs_sh.c | |||
| @@ -30,6 +30,11 @@ | |||
| 30 | * server is dead or overloaded, the load balancer can bypass the cache | 30 | * server is dead or overloaded, the load balancer can bypass the cache |
| 31 | * server and send requests to the original server directly. | 31 | * server and send requests to the original server directly. |
| 32 | * | 32 | * |
| 33 | * The weight destination attribute can be used to control the | ||
| 34 | * distribution of connections to the destinations in servernode. The | ||
| 35 | * greater the weight, the more connections the destination | ||
| 36 | * will receive. | ||
| 37 | * | ||
| 33 | */ | 38 | */ |
| 34 | 39 | ||
| 35 | #define KMSG_COMPONENT "IPVS" | 40 | #define KMSG_COMPONENT "IPVS" |
| @@ -99,9 +104,11 @@ ip_vs_sh_assign(struct ip_vs_sh_bucket *tbl, struct ip_vs_service *svc) | |||
| 99 | struct ip_vs_sh_bucket *b; | 104 | struct ip_vs_sh_bucket *b; |
| 100 | struct list_head *p; | 105 | struct list_head *p; |
| 101 | struct ip_vs_dest *dest; | 106 | struct ip_vs_dest *dest; |
| 107 | int d_count; | ||
| 102 | 108 | ||
| 103 | b = tbl; | 109 | b = tbl; |
| 104 | p = &svc->destinations; | 110 | p = &svc->destinations; |
| 111 | d_count = 0; | ||
| 105 | for (i=0; i<IP_VS_SH_TAB_SIZE; i++) { | 112 | for (i=0; i<IP_VS_SH_TAB_SIZE; i++) { |
| 106 | if (list_empty(p)) { | 113 | if (list_empty(p)) { |
| 107 | b->dest = NULL; | 114 | b->dest = NULL; |
| @@ -113,7 +120,16 @@ ip_vs_sh_assign(struct ip_vs_sh_bucket *tbl, struct ip_vs_service *svc) | |||
| 113 | atomic_inc(&dest->refcnt); | 120 | atomic_inc(&dest->refcnt); |
| 114 | b->dest = dest; | 121 | b->dest = dest; |
| 115 | 122 | ||
| 116 | p = p->next; | 123 | IP_VS_DBG_BUF(6, "assigned i: %d dest: %s weight: %d\n", |
| 124 | i, IP_VS_DBG_ADDR(svc->af, &dest->addr), | ||
| 125 | atomic_read(&dest->weight)); | ||
| 126 | |||
| 127 | /* Don't move to next dest until filling weight */ | ||
| 128 | if (++d_count >= atomic_read(&dest->weight)) { | ||
| 129 | p = p->next; | ||
| 130 | d_count = 0; | ||
| 131 | } | ||
| 132 | |||
| 117 | } | 133 | } |
| 118 | b++; | 134 | b++; |
| 119 | } | 135 | } |
diff --git a/net/netfilter/nf_conntrack_acct.c b/net/netfilter/nf_conntrack_acct.c index bffa6b03bb79..f4f8cda05986 100644 --- a/net/netfilter/nf_conntrack_acct.c +++ b/net/netfilter/nf_conntrack_acct.c | |||
| @@ -46,8 +46,8 @@ seq_print_acct(struct seq_file *s, const struct nf_conn *ct, int dir) | |||
| 46 | return 0; | 46 | return 0; |
| 47 | 47 | ||
| 48 | return seq_printf(s, "packets=%llu bytes=%llu ", | 48 | return seq_printf(s, "packets=%llu bytes=%llu ", |
| 49 | (unsigned long long)acct[dir].packets, | 49 | (unsigned long long)atomic64_read(&acct[dir].packets), |
| 50 | (unsigned long long)acct[dir].bytes); | 50 | (unsigned long long)atomic64_read(&acct[dir].bytes)); |
| 51 | }; | 51 | }; |
| 52 | EXPORT_SYMBOL_GPL(seq_print_acct); | 52 | EXPORT_SYMBOL_GPL(seq_print_acct); |
| 53 | 53 | ||
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index deeef74e775f..e875f8902db3 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -67,6 +67,7 @@ DEFINE_PER_CPU(struct nf_conn, nf_conntrack_untracked); | |||
| 67 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); | 67 | EXPORT_PER_CPU_SYMBOL(nf_conntrack_untracked); |
| 68 | 68 | ||
| 69 | unsigned int nf_conntrack_hash_rnd __read_mostly; | 69 | unsigned int nf_conntrack_hash_rnd __read_mostly; |
| 70 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_rnd); | ||
| 70 | 71 | ||
| 71 | static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone) | 72 | static u32 hash_conntrack_raw(const struct nf_conntrack_tuple *tuple, u16 zone) |
| 72 | { | 73 | { |
| @@ -1044,10 +1045,8 @@ acct: | |||
| 1044 | 1045 | ||
| 1045 | acct = nf_conn_acct_find(ct); | 1046 | acct = nf_conn_acct_find(ct); |
| 1046 | if (acct) { | 1047 | if (acct) { |
| 1047 | spin_lock_bh(&ct->lock); | 1048 | atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets); |
| 1048 | acct[CTINFO2DIR(ctinfo)].packets++; | 1049 | atomic64_add(skb->len, &acct[CTINFO2DIR(ctinfo)].bytes); |
| 1049 | acct[CTINFO2DIR(ctinfo)].bytes += skb->len; | ||
| 1050 | spin_unlock_bh(&ct->lock); | ||
| 1051 | } | 1050 | } |
| 1052 | } | 1051 | } |
| 1053 | } | 1052 | } |
| @@ -1063,11 +1062,9 @@ bool __nf_ct_kill_acct(struct nf_conn *ct, | |||
| 1063 | 1062 | ||
| 1064 | acct = nf_conn_acct_find(ct); | 1063 | acct = nf_conn_acct_find(ct); |
| 1065 | if (acct) { | 1064 | if (acct) { |
| 1066 | spin_lock_bh(&ct->lock); | 1065 | atomic64_inc(&acct[CTINFO2DIR(ctinfo)].packets); |
| 1067 | acct[CTINFO2DIR(ctinfo)].packets++; | 1066 | atomic64_add(skb->len - skb_network_offset(skb), |
| 1068 | acct[CTINFO2DIR(ctinfo)].bytes += | 1067 | &acct[CTINFO2DIR(ctinfo)].bytes); |
| 1069 | skb->len - skb_network_offset(skb); | ||
| 1070 | spin_unlock_bh(&ct->lock); | ||
| 1071 | } | 1068 | } |
| 1072 | } | 1069 | } |
| 1073 | 1070 | ||
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 340c80d968d4..bebb1675e6ff 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -38,8 +38,6 @@ unsigned int nf_ct_expect_max __read_mostly; | |||
| 38 | 38 | ||
| 39 | static struct kmem_cache *nf_ct_expect_cachep __read_mostly; | 39 | static struct kmem_cache *nf_ct_expect_cachep __read_mostly; |
| 40 | 40 | ||
| 41 | static HLIST_HEAD(nf_ct_userspace_expect_list); | ||
| 42 | |||
| 43 | /* nf_conntrack_expect helper functions */ | 41 | /* nf_conntrack_expect helper functions */ |
| 44 | void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, | 42 | void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, |
| 45 | u32 pid, int report) | 43 | u32 pid, int report) |
| @@ -47,14 +45,14 @@ void nf_ct_unlink_expect_report(struct nf_conntrack_expect *exp, | |||
| 47 | struct nf_conn_help *master_help = nfct_help(exp->master); | 45 | struct nf_conn_help *master_help = nfct_help(exp->master); |
| 48 | struct net *net = nf_ct_exp_net(exp); | 46 | struct net *net = nf_ct_exp_net(exp); |
| 49 | 47 | ||
| 48 | NF_CT_ASSERT(master_help); | ||
| 50 | NF_CT_ASSERT(!timer_pending(&exp->timeout)); | 49 | NF_CT_ASSERT(!timer_pending(&exp->timeout)); |
| 51 | 50 | ||
| 52 | hlist_del_rcu(&exp->hnode); | 51 | hlist_del_rcu(&exp->hnode); |
| 53 | net->ct.expect_count--; | 52 | net->ct.expect_count--; |
| 54 | 53 | ||
| 55 | hlist_del(&exp->lnode); | 54 | hlist_del(&exp->lnode); |
| 56 | if (!(exp->flags & NF_CT_EXPECT_USERSPACE)) | 55 | master_help->expecting[exp->class]--; |
| 57 | master_help->expecting[exp->class]--; | ||
| 58 | 56 | ||
| 59 | nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report); | 57 | nf_ct_expect_event_report(IPEXP_DESTROY, exp, pid, report); |
| 60 | nf_ct_expect_put(exp); | 58 | nf_ct_expect_put(exp); |
| @@ -314,37 +312,34 @@ void nf_ct_expect_put(struct nf_conntrack_expect *exp) | |||
| 314 | } | 312 | } |
| 315 | EXPORT_SYMBOL_GPL(nf_ct_expect_put); | 313 | EXPORT_SYMBOL_GPL(nf_ct_expect_put); |
| 316 | 314 | ||
| 317 | static void nf_ct_expect_insert(struct nf_conntrack_expect *exp) | 315 | static int nf_ct_expect_insert(struct nf_conntrack_expect *exp) |
| 318 | { | 316 | { |
| 319 | struct nf_conn_help *master_help = nfct_help(exp->master); | 317 | struct nf_conn_help *master_help = nfct_help(exp->master); |
| 318 | struct nf_conntrack_helper *helper; | ||
| 320 | struct net *net = nf_ct_exp_net(exp); | 319 | struct net *net = nf_ct_exp_net(exp); |
| 321 | const struct nf_conntrack_expect_policy *p; | ||
| 322 | unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); | 320 | unsigned int h = nf_ct_expect_dst_hash(&exp->tuple); |
| 323 | 321 | ||
| 324 | /* two references : one for hash insert, one for the timer */ | 322 | /* two references : one for hash insert, one for the timer */ |
| 325 | atomic_add(2, &exp->use); | 323 | atomic_add(2, &exp->use); |
| 326 | 324 | ||
| 327 | if (master_help) { | 325 | hlist_add_head(&exp->lnode, &master_help->expectations); |
| 328 | hlist_add_head(&exp->lnode, &master_help->expectations); | 326 | master_help->expecting[exp->class]++; |
| 329 | master_help->expecting[exp->class]++; | ||
| 330 | } else if (exp->flags & NF_CT_EXPECT_USERSPACE) | ||
| 331 | hlist_add_head(&exp->lnode, &nf_ct_userspace_expect_list); | ||
| 332 | 327 | ||
| 333 | hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]); | 328 | hlist_add_head_rcu(&exp->hnode, &net->ct.expect_hash[h]); |
| 334 | net->ct.expect_count++; | 329 | net->ct.expect_count++; |
| 335 | 330 | ||
| 336 | setup_timer(&exp->timeout, nf_ct_expectation_timed_out, | 331 | setup_timer(&exp->timeout, nf_ct_expectation_timed_out, |
| 337 | (unsigned long)exp); | 332 | (unsigned long)exp); |
| 338 | if (master_help) { | 333 | helper = rcu_dereference_protected(master_help->helper, |
| 339 | p = &rcu_dereference_protected( | 334 | lockdep_is_held(&nf_conntrack_lock)); |
| 340 | master_help->helper, | 335 | if (helper) { |
| 341 | lockdep_is_held(&nf_conntrack_lock) | 336 | exp->timeout.expires = jiffies + |
| 342 | )->expect_policy[exp->class]; | 337 | helper->expect_policy[exp->class].timeout * HZ; |
| 343 | exp->timeout.expires = jiffies + p->timeout * HZ; | ||
| 344 | } | 338 | } |
| 345 | add_timer(&exp->timeout); | 339 | add_timer(&exp->timeout); |
| 346 | 340 | ||
| 347 | NF_CT_STAT_INC(net, expect_create); | 341 | NF_CT_STAT_INC(net, expect_create); |
| 342 | return 0; | ||
| 348 | } | 343 | } |
| 349 | 344 | ||
| 350 | /* Race with expectations being used means we could have none to find; OK. */ | 345 | /* Race with expectations being used means we could have none to find; OK. */ |
| @@ -389,14 +384,13 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
| 389 | struct nf_conntrack_expect *i; | 384 | struct nf_conntrack_expect *i; |
| 390 | struct nf_conn *master = expect->master; | 385 | struct nf_conn *master = expect->master; |
| 391 | struct nf_conn_help *master_help = nfct_help(master); | 386 | struct nf_conn_help *master_help = nfct_help(master); |
| 387 | struct nf_conntrack_helper *helper; | ||
| 392 | struct net *net = nf_ct_exp_net(expect); | 388 | struct net *net = nf_ct_exp_net(expect); |
| 393 | struct hlist_node *n; | 389 | struct hlist_node *n; |
| 394 | unsigned int h; | 390 | unsigned int h; |
| 395 | int ret = 1; | 391 | int ret = 1; |
| 396 | 392 | ||
| 397 | /* Don't allow expectations created from kernel-space with no helper */ | 393 | if (!master_help) { |
| 398 | if (!(expect->flags & NF_CT_EXPECT_USERSPACE) && | ||
| 399 | (!master_help || (master_help && !master_help->helper))) { | ||
| 400 | ret = -ESHUTDOWN; | 394 | ret = -ESHUTDOWN; |
| 401 | goto out; | 395 | goto out; |
| 402 | } | 396 | } |
| @@ -414,11 +408,10 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
| 414 | } | 408 | } |
| 415 | } | 409 | } |
| 416 | /* Will be over limit? */ | 410 | /* Will be over limit? */ |
| 417 | if (master_help) { | 411 | helper = rcu_dereference_protected(master_help->helper, |
| 418 | p = &rcu_dereference_protected( | 412 | lockdep_is_held(&nf_conntrack_lock)); |
| 419 | master_help->helper, | 413 | if (helper) { |
| 420 | lockdep_is_held(&nf_conntrack_lock) | 414 | p = &helper->expect_policy[expect->class]; |
| 421 | )->expect_policy[expect->class]; | ||
| 422 | if (p->max_expected && | 415 | if (p->max_expected && |
| 423 | master_help->expecting[expect->class] >= p->max_expected) { | 416 | master_help->expecting[expect->class] >= p->max_expected) { |
| 424 | evict_oldest_expect(master, expect); | 417 | evict_oldest_expect(master, expect); |
| @@ -450,8 +443,9 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, | |||
| 450 | if (ret <= 0) | 443 | if (ret <= 0) |
| 451 | goto out; | 444 | goto out; |
| 452 | 445 | ||
| 453 | ret = 0; | 446 | ret = nf_ct_expect_insert(expect); |
| 454 | nf_ct_expect_insert(expect); | 447 | if (ret < 0) |
| 448 | goto out; | ||
| 455 | spin_unlock_bh(&nf_conntrack_lock); | 449 | spin_unlock_bh(&nf_conntrack_lock); |
| 456 | nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report); | 450 | nf_ct_expect_event_report(IPEXP_NEW, expect, pid, report); |
| 457 | return ret; | 451 | return ret; |
| @@ -461,21 +455,6 @@ out: | |||
| 461 | } | 455 | } |
| 462 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); | 456 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); |
| 463 | 457 | ||
| 464 | void nf_ct_remove_userspace_expectations(void) | ||
| 465 | { | ||
| 466 | struct nf_conntrack_expect *exp; | ||
| 467 | struct hlist_node *n, *next; | ||
| 468 | |||
| 469 | hlist_for_each_entry_safe(exp, n, next, | ||
| 470 | &nf_ct_userspace_expect_list, lnode) { | ||
| 471 | if (del_timer(&exp->timeout)) { | ||
| 472 | nf_ct_unlink_expect(exp); | ||
| 473 | nf_ct_expect_put(exp); | ||
| 474 | } | ||
| 475 | } | ||
| 476 | } | ||
| 477 | EXPORT_SYMBOL_GPL(nf_ct_remove_userspace_expectations); | ||
| 478 | |||
| 479 | #ifdef CONFIG_PROC_FS | 458 | #ifdef CONFIG_PROC_FS |
| 480 | struct ct_expect_iter_state { | 459 | struct ct_expect_iter_state { |
| 481 | struct seq_net_private p; | 460 | struct seq_net_private p; |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 93c4bdbfc1ae..c9e0de08aa87 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
| @@ -121,6 +121,18 @@ int __nf_ct_try_assign_helper(struct nf_conn *ct, struct nf_conn *tmpl, | |||
| 121 | int ret = 0; | 121 | int ret = 0; |
| 122 | 122 | ||
| 123 | if (tmpl != NULL) { | 123 | if (tmpl != NULL) { |
| 124 | /* we've got a userspace helper. */ | ||
| 125 | if (tmpl->status & IPS_USERSPACE_HELPER) { | ||
| 126 | help = nf_ct_helper_ext_add(ct, flags); | ||
| 127 | if (help == NULL) { | ||
| 128 | ret = -ENOMEM; | ||
| 129 | goto out; | ||
| 130 | } | ||
| 131 | rcu_assign_pointer(help->helper, NULL); | ||
| 132 | __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status); | ||
| 133 | ret = 0; | ||
| 134 | goto out; | ||
| 135 | } | ||
| 124 | help = nfct_help(tmpl); | 136 | help = nfct_help(tmpl); |
| 125 | if (help != NULL) | 137 | if (help != NULL) |
| 126 | helper = help->helper; | 138 | helper = help->helper; |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index ef21b221f036..85033344aed2 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -203,25 +203,18 @@ nla_put_failure: | |||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static int | 205 | static int |
| 206 | ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, | 206 | dump_counters(struct sk_buff *skb, u64 pkts, u64 bytes, |
| 207 | enum ip_conntrack_dir dir) | 207 | enum ip_conntrack_dir dir) |
| 208 | { | 208 | { |
| 209 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; | 209 | enum ctattr_type type = dir ? CTA_COUNTERS_REPLY: CTA_COUNTERS_ORIG; |
| 210 | struct nlattr *nest_count; | 210 | struct nlattr *nest_count; |
| 211 | const struct nf_conn_counter *acct; | ||
| 212 | |||
| 213 | acct = nf_conn_acct_find(ct); | ||
| 214 | if (!acct) | ||
| 215 | return 0; | ||
| 216 | 211 | ||
| 217 | nest_count = nla_nest_start(skb, type | NLA_F_NESTED); | 212 | nest_count = nla_nest_start(skb, type | NLA_F_NESTED); |
| 218 | if (!nest_count) | 213 | if (!nest_count) |
| 219 | goto nla_put_failure; | 214 | goto nla_put_failure; |
| 220 | 215 | ||
| 221 | NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, | 216 | NLA_PUT_BE64(skb, CTA_COUNTERS_PACKETS, cpu_to_be64(pkts)); |
| 222 | cpu_to_be64(acct[dir].packets)); | 217 | NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, cpu_to_be64(bytes)); |
| 223 | NLA_PUT_BE64(skb, CTA_COUNTERS_BYTES, | ||
| 224 | cpu_to_be64(acct[dir].bytes)); | ||
| 225 | 218 | ||
| 226 | nla_nest_end(skb, nest_count); | 219 | nla_nest_end(skb, nest_count); |
| 227 | 220 | ||
| @@ -232,6 +225,27 @@ nla_put_failure: | |||
| 232 | } | 225 | } |
| 233 | 226 | ||
| 234 | static int | 227 | static int |
| 228 | ctnetlink_dump_counters(struct sk_buff *skb, const struct nf_conn *ct, | ||
| 229 | enum ip_conntrack_dir dir, int type) | ||
| 230 | { | ||
| 231 | struct nf_conn_counter *acct; | ||
| 232 | u64 pkts, bytes; | ||
| 233 | |||
| 234 | acct = nf_conn_acct_find(ct); | ||
| 235 | if (!acct) | ||
| 236 | return 0; | ||
| 237 | |||
| 238 | if (type == IPCTNL_MSG_CT_GET_CTRZERO) { | ||
| 239 | pkts = atomic64_xchg(&acct[dir].packets, 0); | ||
| 240 | bytes = atomic64_xchg(&acct[dir].bytes, 0); | ||
| 241 | } else { | ||
| 242 | pkts = atomic64_read(&acct[dir].packets); | ||
| 243 | bytes = atomic64_read(&acct[dir].bytes); | ||
| 244 | } | ||
| 245 | return dump_counters(skb, pkts, bytes, dir); | ||
| 246 | } | ||
| 247 | |||
| 248 | static int | ||
| 235 | ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) | 249 | ctnetlink_dump_timestamp(struct sk_buff *skb, const struct nf_conn *ct) |
| 236 | { | 250 | { |
| 237 | struct nlattr *nest_count; | 251 | struct nlattr *nest_count; |
| @@ -393,15 +407,15 @@ nla_put_failure: | |||
| 393 | } | 407 | } |
| 394 | 408 | ||
| 395 | static int | 409 | static int |
| 396 | ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | 410 | ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, |
| 397 | int event, struct nf_conn *ct) | 411 | struct nf_conn *ct) |
| 398 | { | 412 | { |
| 399 | struct nlmsghdr *nlh; | 413 | struct nlmsghdr *nlh; |
| 400 | struct nfgenmsg *nfmsg; | 414 | struct nfgenmsg *nfmsg; |
| 401 | struct nlattr *nest_parms; | 415 | struct nlattr *nest_parms; |
| 402 | unsigned int flags = pid ? NLM_F_MULTI : 0; | 416 | unsigned int flags = pid ? NLM_F_MULTI : 0, event; |
| 403 | 417 | ||
| 404 | event |= NFNL_SUBSYS_CTNETLINK << 8; | 418 | event = (NFNL_SUBSYS_CTNETLINK << 8 | IPCTNL_MSG_CT_NEW); |
| 405 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | 419 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); |
| 406 | if (nlh == NULL) | 420 | if (nlh == NULL) |
| 407 | goto nlmsg_failure; | 421 | goto nlmsg_failure; |
| @@ -430,8 +444,8 @@ ctnetlink_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | |||
| 430 | 444 | ||
| 431 | if (ctnetlink_dump_status(skb, ct) < 0 || | 445 | if (ctnetlink_dump_status(skb, ct) < 0 || |
| 432 | ctnetlink_dump_timeout(skb, ct) < 0 || | 446 | ctnetlink_dump_timeout(skb, ct) < 0 || |
| 433 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || | 447 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL, type) < 0 || |
| 434 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || | 448 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY, type) < 0 || |
| 435 | ctnetlink_dump_timestamp(skb, ct) < 0 || | 449 | ctnetlink_dump_timestamp(skb, ct) < 0 || |
| 436 | ctnetlink_dump_protoinfo(skb, ct) < 0 || | 450 | ctnetlink_dump_protoinfo(skb, ct) < 0 || |
| 437 | ctnetlink_dump_helpinfo(skb, ct) < 0 || | 451 | ctnetlink_dump_helpinfo(skb, ct) < 0 || |
| @@ -612,8 +626,10 @@ ctnetlink_conntrack_event(unsigned int events, struct nf_ct_event *item) | |||
| 612 | goto nla_put_failure; | 626 | goto nla_put_failure; |
| 613 | 627 | ||
| 614 | if (events & (1 << IPCT_DESTROY)) { | 628 | if (events & (1 << IPCT_DESTROY)) { |
| 615 | if (ctnetlink_dump_counters(skb, ct, IP_CT_DIR_ORIGINAL) < 0 || | 629 | if (ctnetlink_dump_counters(skb, ct, |
| 616 | ctnetlink_dump_counters(skb, ct, IP_CT_DIR_REPLY) < 0 || | 630 | IP_CT_DIR_ORIGINAL, type) < 0 || |
| 631 | ctnetlink_dump_counters(skb, ct, | ||
| 632 | IP_CT_DIR_REPLY, type) < 0 || | ||
| 617 | ctnetlink_dump_timestamp(skb, ct) < 0) | 633 | ctnetlink_dump_timestamp(skb, ct) < 0) |
| 618 | goto nla_put_failure; | 634 | goto nla_put_failure; |
| 619 | } else { | 635 | } else { |
| @@ -709,20 +725,13 @@ restart: | |||
| 709 | } | 725 | } |
| 710 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, | 726 | if (ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).pid, |
| 711 | cb->nlh->nlmsg_seq, | 727 | cb->nlh->nlmsg_seq, |
| 712 | IPCTNL_MSG_CT_NEW, ct) < 0) { | 728 | NFNL_MSG_TYPE( |
| 729 | cb->nlh->nlmsg_type), | ||
| 730 | ct) < 0) { | ||
| 713 | nf_conntrack_get(&ct->ct_general); | 731 | nf_conntrack_get(&ct->ct_general); |
| 714 | cb->args[1] = (unsigned long)ct; | 732 | cb->args[1] = (unsigned long)ct; |
| 715 | goto out; | 733 | goto out; |
| 716 | } | 734 | } |
| 717 | |||
| 718 | if (NFNL_MSG_TYPE(cb->nlh->nlmsg_type) == | ||
| 719 | IPCTNL_MSG_CT_GET_CTRZERO) { | ||
| 720 | struct nf_conn_counter *acct; | ||
| 721 | |||
| 722 | acct = nf_conn_acct_find(ct); | ||
| 723 | if (acct) | ||
| 724 | memset(acct, 0, sizeof(struct nf_conn_counter[IP_CT_DIR_MAX])); | ||
| 725 | } | ||
| 726 | } | 735 | } |
| 727 | if (cb->args[1]) { | 736 | if (cb->args[1]) { |
| 728 | cb->args[1] = 0; | 737 | cb->args[1] = 0; |
| @@ -1001,7 +1010,7 @@ ctnetlink_get_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 1001 | 1010 | ||
| 1002 | rcu_read_lock(); | 1011 | rcu_read_lock(); |
| 1003 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, | 1012 | err = ctnetlink_fill_info(skb2, NETLINK_CB(skb).pid, nlh->nlmsg_seq, |
| 1004 | IPCTNL_MSG_CT_NEW, ct); | 1013 | NFNL_MSG_TYPE(nlh->nlmsg_type), ct); |
| 1005 | rcu_read_unlock(); | 1014 | rcu_read_unlock(); |
| 1006 | nf_ct_put(ct); | 1015 | nf_ct_put(ct); |
| 1007 | if (err <= 0) | 1016 | if (err <= 0) |
| @@ -1087,14 +1096,14 @@ ctnetlink_change_nat(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
| 1087 | 1096 | ||
| 1088 | if (cda[CTA_NAT_DST]) { | 1097 | if (cda[CTA_NAT_DST]) { |
| 1089 | ret = ctnetlink_parse_nat_setup(ct, | 1098 | ret = ctnetlink_parse_nat_setup(ct, |
| 1090 | IP_NAT_MANIP_DST, | 1099 | NF_NAT_MANIP_DST, |
| 1091 | cda[CTA_NAT_DST]); | 1100 | cda[CTA_NAT_DST]); |
| 1092 | if (ret < 0) | 1101 | if (ret < 0) |
| 1093 | return ret; | 1102 | return ret; |
| 1094 | } | 1103 | } |
| 1095 | if (cda[CTA_NAT_SRC]) { | 1104 | if (cda[CTA_NAT_SRC]) { |
| 1096 | ret = ctnetlink_parse_nat_setup(ct, | 1105 | ret = ctnetlink_parse_nat_setup(ct, |
| 1097 | IP_NAT_MANIP_SRC, | 1106 | NF_NAT_MANIP_SRC, |
| 1098 | cda[CTA_NAT_SRC]); | 1107 | cda[CTA_NAT_SRC]); |
| 1099 | if (ret < 0) | 1108 | if (ret < 0) |
| 1100 | return ret; | 1109 | return ret; |
| @@ -1847,7 +1856,9 @@ ctnetlink_get_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 1847 | if (err < 0) | 1856 | if (err < 0) |
| 1848 | return err; | 1857 | return err; |
| 1849 | 1858 | ||
| 1850 | if (cda[CTA_EXPECT_MASTER]) | 1859 | if (cda[CTA_EXPECT_TUPLE]) |
| 1860 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_TUPLE, u3); | ||
| 1861 | else if (cda[CTA_EXPECT_MASTER]) | ||
| 1851 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3); | 1862 | err = ctnetlink_parse_tuple(cda, &tuple, CTA_EXPECT_MASTER, u3); |
| 1852 | else | 1863 | else |
| 1853 | return -EINVAL; | 1864 | return -EINVAL; |
| @@ -2023,6 +2034,10 @@ ctnetlink_create_expect(struct net *net, u16 zone, | |||
| 2023 | } | 2034 | } |
| 2024 | help = nfct_help(ct); | 2035 | help = nfct_help(ct); |
| 2025 | if (!help) { | 2036 | if (!help) { |
| 2037 | err = -EOPNOTSUPP; | ||
| 2038 | goto out; | ||
| 2039 | } | ||
| 2040 | if (test_bit(IPS_USERSPACE_HELPER_BIT, &ct->status)) { | ||
| 2026 | if (!cda[CTA_EXPECT_TIMEOUT]) { | 2041 | if (!cda[CTA_EXPECT_TIMEOUT]) { |
| 2027 | err = -EINVAL; | 2042 | err = -EINVAL; |
| 2028 | goto out; | 2043 | goto out; |
| @@ -2247,7 +2262,6 @@ static void __exit ctnetlink_exit(void) | |||
| 2247 | { | 2262 | { |
| 2248 | pr_info("ctnetlink: unregistering from nfnetlink.\n"); | 2263 | pr_info("ctnetlink: unregistering from nfnetlink.\n"); |
| 2249 | 2264 | ||
| 2250 | nf_ct_remove_userspace_expectations(); | ||
| 2251 | unregister_pernet_subsys(&ctnetlink_net_ops); | 2265 | unregister_pernet_subsys(&ctnetlink_net_ops); |
| 2252 | nfnetlink_subsys_unregister(&ctnl_exp_subsys); | 2266 | nfnetlink_subsys_unregister(&ctnl_exp_subsys); |
| 2253 | nfnetlink_subsys_unregister(&ctnl_subsys); | 2267 | nfnetlink_subsys_unregister(&ctnl_subsys); |
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c new file mode 100644 index 000000000000..362ab6ca3dc1 --- /dev/null +++ b/net/netfilter/nfnetlink_acct.c | |||
| @@ -0,0 +1,352 @@ | |||
| 1 | /* | ||
| 2 | * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org> | ||
| 3 | * (C) 2011 Intra2net AG <http://www.intra2net.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation (or any later at your option). | ||
| 8 | */ | ||
| 9 | #include <linux/init.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/kernel.h> | ||
| 12 | #include <linux/skbuff.h> | ||
| 13 | #include <linux/netlink.h> | ||
| 14 | #include <linux/rculist.h> | ||
| 15 | #include <linux/slab.h> | ||
| 16 | #include <linux/types.h> | ||
| 17 | #include <linux/errno.h> | ||
| 18 | #include <net/netlink.h> | ||
| 19 | #include <net/sock.h> | ||
| 20 | #include <asm/atomic.h> | ||
| 21 | |||
| 22 | #include <linux/netfilter.h> | ||
| 23 | #include <linux/netfilter/nfnetlink.h> | ||
| 24 | #include <linux/netfilter/nfnetlink_acct.h> | ||
| 25 | |||
| 26 | MODULE_LICENSE("GPL"); | ||
| 27 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
| 28 | MODULE_DESCRIPTION("nfacct: Extended Netfilter accounting infrastructure"); | ||
| 29 | |||
| 30 | static LIST_HEAD(nfnl_acct_list); | ||
| 31 | |||
| 32 | struct nf_acct { | ||
| 33 | atomic64_t pkts; | ||
| 34 | atomic64_t bytes; | ||
| 35 | struct list_head head; | ||
| 36 | atomic_t refcnt; | ||
| 37 | char name[NFACCT_NAME_MAX]; | ||
| 38 | struct rcu_head rcu_head; | ||
| 39 | }; | ||
| 40 | |||
| 41 | static int | ||
| 42 | nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | ||
| 43 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | ||
| 44 | { | ||
| 45 | struct nf_acct *nfacct, *matching = NULL; | ||
| 46 | char *acct_name; | ||
| 47 | |||
| 48 | if (!tb[NFACCT_NAME]) | ||
| 49 | return -EINVAL; | ||
| 50 | |||
| 51 | acct_name = nla_data(tb[NFACCT_NAME]); | ||
| 52 | |||
| 53 | list_for_each_entry(nfacct, &nfnl_acct_list, head) { | ||
| 54 | if (strncmp(nfacct->name, acct_name, NFACCT_NAME_MAX) != 0) | ||
| 55 | continue; | ||
| 56 | |||
| 57 | if (nlh->nlmsg_flags & NLM_F_EXCL) | ||
| 58 | return -EEXIST; | ||
| 59 | |||
| 60 | matching = nfacct; | ||
| 61 | break; | ||
| 62 | } | ||
| 63 | |||
| 64 | if (matching) { | ||
| 65 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | ||
| 66 | /* reset counters if you request a replacement. */ | ||
| 67 | atomic64_set(&matching->pkts, 0); | ||
| 68 | atomic64_set(&matching->bytes, 0); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | return -EBUSY; | ||
| 72 | } | ||
| 73 | |||
| 74 | nfacct = kzalloc(sizeof(struct nf_acct), GFP_KERNEL); | ||
| 75 | if (nfacct == NULL) | ||
| 76 | return -ENOMEM; | ||
| 77 | |||
| 78 | strncpy(nfacct->name, nla_data(tb[NFACCT_NAME]), NFACCT_NAME_MAX); | ||
| 79 | |||
| 80 | if (tb[NFACCT_BYTES]) { | ||
| 81 | atomic64_set(&nfacct->bytes, | ||
| 82 | be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES]))); | ||
| 83 | } | ||
| 84 | if (tb[NFACCT_PKTS]) { | ||
| 85 | atomic64_set(&nfacct->pkts, | ||
| 86 | be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS]))); | ||
| 87 | } | ||
| 88 | atomic_set(&nfacct->refcnt, 1); | ||
| 89 | list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | static int | ||
| 94 | nfnl_acct_fill_info(struct sk_buff *skb, u32 pid, u32 seq, u32 type, | ||
| 95 | int event, struct nf_acct *acct) | ||
| 96 | { | ||
| 97 | struct nlmsghdr *nlh; | ||
| 98 | struct nfgenmsg *nfmsg; | ||
| 99 | unsigned int flags = pid ? NLM_F_MULTI : 0; | ||
| 100 | u64 pkts, bytes; | ||
| 101 | |||
| 102 | event |= NFNL_SUBSYS_ACCT << 8; | ||
| 103 | nlh = nlmsg_put(skb, pid, seq, event, sizeof(*nfmsg), flags); | ||
| 104 | if (nlh == NULL) | ||
| 105 | goto nlmsg_failure; | ||
| 106 | |||
| 107 | nfmsg = nlmsg_data(nlh); | ||
| 108 | nfmsg->nfgen_family = AF_UNSPEC; | ||
| 109 | nfmsg->version = NFNETLINK_V0; | ||
| 110 | nfmsg->res_id = 0; | ||
| 111 | |||
| 112 | NLA_PUT_STRING(skb, NFACCT_NAME, acct->name); | ||
| 113 | |||
| 114 | if (type == NFNL_MSG_ACCT_GET_CTRZERO) { | ||
| 115 | pkts = atomic64_xchg(&acct->pkts, 0); | ||
| 116 | bytes = atomic64_xchg(&acct->bytes, 0); | ||
| 117 | } else { | ||
| 118 | pkts = atomic64_read(&acct->pkts); | ||
| 119 | bytes = atomic64_read(&acct->bytes); | ||
| 120 | } | ||
| 121 | NLA_PUT_BE64(skb, NFACCT_PKTS, cpu_to_be64(pkts)); | ||
| 122 | NLA_PUT_BE64(skb, NFACCT_BYTES, cpu_to_be64(bytes)); | ||
| 123 | NLA_PUT_BE32(skb, NFACCT_USE, htonl(atomic_read(&acct->refcnt))); | ||
| 124 | |||
| 125 | nlmsg_end(skb, nlh); | ||
| 126 | return skb->len; | ||
| 127 | |||
| 128 | nlmsg_failure: | ||
| 129 | nla_put_failure: | ||
| 130 | nlmsg_cancel(skb, nlh); | ||
| 131 | return -1; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int | ||
| 135 | nfnl_acct_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 136 | { | ||
| 137 | struct nf_acct *cur, *last; | ||
| 138 | |||
| 139 | if (cb->args[2]) | ||
| 140 | return 0; | ||
| 141 | |||
| 142 | last = (struct nf_acct *)cb->args[1]; | ||
| 143 | if (cb->args[1]) | ||
| 144 | cb->args[1] = 0; | ||
| 145 | |||
| 146 | rcu_read_lock(); | ||
| 147 | list_for_each_entry_rcu(cur, &nfnl_acct_list, head) { | ||
| 148 | if (last && cur != last) | ||
| 149 | continue; | ||
| 150 | |||
| 151 | if (nfnl_acct_fill_info(skb, NETLINK_CB(cb->skb).pid, | ||
| 152 | cb->nlh->nlmsg_seq, | ||
| 153 | NFNL_MSG_TYPE(cb->nlh->nlmsg_type), | ||
| 154 | NFNL_MSG_ACCT_NEW, cur) < 0) { | ||
| 155 | cb->args[1] = (unsigned long)cur; | ||
| 156 | break; | ||
| 157 | } | ||
| 158 | } | ||
| 159 | if (!cb->args[1]) | ||
| 160 | cb->args[2] = 1; | ||
| 161 | rcu_read_unlock(); | ||
| 162 | return skb->len; | ||
| 163 | } | ||
| 164 | |||
| 165 | static int | ||
| 166 | nfnl_acct_get(struct sock *nfnl, struct sk_buff *skb, | ||
| 167 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | ||
| 168 | { | ||
| 169 | int ret = 0; | ||
| 170 | struct nf_acct *cur; | ||
| 171 | char *acct_name; | ||
| 172 | |||
| 173 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | ||
| 174 | return netlink_dump_start(nfnl, skb, nlh, nfnl_acct_dump, | ||
| 175 | NULL, 0); | ||
| 176 | } | ||
| 177 | |||
| 178 | if (!tb[NFACCT_NAME]) | ||
| 179 | return -EINVAL; | ||
| 180 | acct_name = nla_data(tb[NFACCT_NAME]); | ||
| 181 | |||
| 182 | list_for_each_entry(cur, &nfnl_acct_list, head) { | ||
| 183 | struct sk_buff *skb2; | ||
| 184 | |||
| 185 | if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0) | ||
| 186 | continue; | ||
| 187 | |||
| 188 | skb2 = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 189 | if (skb2 == NULL) | ||
| 190 | break; | ||
| 191 | |||
| 192 | ret = nfnl_acct_fill_info(skb2, NETLINK_CB(skb).pid, | ||
| 193 | nlh->nlmsg_seq, | ||
| 194 | NFNL_MSG_TYPE(nlh->nlmsg_type), | ||
| 195 | NFNL_MSG_ACCT_NEW, cur); | ||
| 196 | if (ret <= 0) | ||
| 197 | kfree_skb(skb2); | ||
| 198 | |||
| 199 | break; | ||
| 200 | } | ||
| 201 | return ret; | ||
| 202 | } | ||
| 203 | |||
| 204 | /* try to delete object, fail if it is still in use. */ | ||
| 205 | static int nfnl_acct_try_del(struct nf_acct *cur) | ||
| 206 | { | ||
| 207 | int ret = 0; | ||
| 208 | |||
| 209 | /* we want to avoid races with nfnl_acct_find_get. */ | ||
| 210 | if (atomic_dec_and_test(&cur->refcnt)) { | ||
| 211 | /* We are protected by nfnl mutex. */ | ||
| 212 | list_del_rcu(&cur->head); | ||
| 213 | kfree_rcu(cur, rcu_head); | ||
| 214 | } else { | ||
| 215 | /* still in use, restore reference counter. */ | ||
| 216 | atomic_inc(&cur->refcnt); | ||
| 217 | ret = -EBUSY; | ||
| 218 | } | ||
| 219 | return ret; | ||
| 220 | } | ||
| 221 | |||
| 222 | static int | ||
| 223 | nfnl_acct_del(struct sock *nfnl, struct sk_buff *skb, | ||
| 224 | const struct nlmsghdr *nlh, const struct nlattr * const tb[]) | ||
| 225 | { | ||
| 226 | char *acct_name; | ||
| 227 | struct nf_acct *cur; | ||
| 228 | int ret = -ENOENT; | ||
| 229 | |||
| 230 | if (!tb[NFACCT_NAME]) { | ||
| 231 | list_for_each_entry(cur, &nfnl_acct_list, head) | ||
| 232 | nfnl_acct_try_del(cur); | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | acct_name = nla_data(tb[NFACCT_NAME]); | ||
| 237 | |||
| 238 | list_for_each_entry(cur, &nfnl_acct_list, head) { | ||
| 239 | if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX) != 0) | ||
| 240 | continue; | ||
| 241 | |||
| 242 | ret = nfnl_acct_try_del(cur); | ||
| 243 | if (ret < 0) | ||
| 244 | return ret; | ||
| 245 | |||
| 246 | break; | ||
| 247 | } | ||
| 248 | return ret; | ||
| 249 | } | ||
| 250 | |||
| 251 | static const struct nla_policy nfnl_acct_policy[NFACCT_MAX+1] = { | ||
| 252 | [NFACCT_NAME] = { .type = NLA_NUL_STRING, .len = NFACCT_NAME_MAX-1 }, | ||
| 253 | [NFACCT_BYTES] = { .type = NLA_U64 }, | ||
| 254 | [NFACCT_PKTS] = { .type = NLA_U64 }, | ||
| 255 | }; | ||
| 256 | |||
| 257 | static const struct nfnl_callback nfnl_acct_cb[NFNL_MSG_ACCT_MAX] = { | ||
| 258 | [NFNL_MSG_ACCT_NEW] = { .call = nfnl_acct_new, | ||
| 259 | .attr_count = NFACCT_MAX, | ||
| 260 | .policy = nfnl_acct_policy }, | ||
| 261 | [NFNL_MSG_ACCT_GET] = { .call = nfnl_acct_get, | ||
| 262 | .attr_count = NFACCT_MAX, | ||
| 263 | .policy = nfnl_acct_policy }, | ||
| 264 | [NFNL_MSG_ACCT_GET_CTRZERO] = { .call = nfnl_acct_get, | ||
| 265 | .attr_count = NFACCT_MAX, | ||
| 266 | .policy = nfnl_acct_policy }, | ||
| 267 | [NFNL_MSG_ACCT_DEL] = { .call = nfnl_acct_del, | ||
| 268 | .attr_count = NFACCT_MAX, | ||
| 269 | .policy = nfnl_acct_policy }, | ||
| 270 | }; | ||
| 271 | |||
| 272 | static const struct nfnetlink_subsystem nfnl_acct_subsys = { | ||
| 273 | .name = "acct", | ||
| 274 | .subsys_id = NFNL_SUBSYS_ACCT, | ||
| 275 | .cb_count = NFNL_MSG_ACCT_MAX, | ||
| 276 | .cb = nfnl_acct_cb, | ||
| 277 | }; | ||
| 278 | |||
| 279 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ACCT); | ||
| 280 | |||
| 281 | struct nf_acct *nfnl_acct_find_get(const char *acct_name) | ||
| 282 | { | ||
| 283 | struct nf_acct *cur, *acct = NULL; | ||
| 284 | |||
| 285 | rcu_read_lock(); | ||
| 286 | list_for_each_entry_rcu(cur, &nfnl_acct_list, head) { | ||
| 287 | if (strncmp(cur->name, acct_name, NFACCT_NAME_MAX)!= 0) | ||
| 288 | continue; | ||
| 289 | |||
| 290 | if (!try_module_get(THIS_MODULE)) | ||
| 291 | goto err; | ||
| 292 | |||
| 293 | if (!atomic_inc_not_zero(&cur->refcnt)) { | ||
| 294 | module_put(THIS_MODULE); | ||
| 295 | goto err; | ||
| 296 | } | ||
| 297 | |||
| 298 | acct = cur; | ||
| 299 | break; | ||
| 300 | } | ||
| 301 | err: | ||
| 302 | rcu_read_unlock(); | ||
| 303 | return acct; | ||
| 304 | } | ||
| 305 | EXPORT_SYMBOL_GPL(nfnl_acct_find_get); | ||
| 306 | |||
| 307 | void nfnl_acct_put(struct nf_acct *acct) | ||
| 308 | { | ||
| 309 | atomic_dec(&acct->refcnt); | ||
| 310 | module_put(THIS_MODULE); | ||
| 311 | } | ||
| 312 | EXPORT_SYMBOL_GPL(nfnl_acct_put); | ||
| 313 | |||
| 314 | void nfnl_acct_update(const struct sk_buff *skb, struct nf_acct *nfacct) | ||
| 315 | { | ||
| 316 | atomic64_inc(&nfacct->pkts); | ||
| 317 | atomic64_add(skb->len, &nfacct->bytes); | ||
| 318 | } | ||
| 319 | EXPORT_SYMBOL_GPL(nfnl_acct_update); | ||
| 320 | |||
| 321 | static int __init nfnl_acct_init(void) | ||
| 322 | { | ||
| 323 | int ret; | ||
| 324 | |||
| 325 | pr_info("nfnl_acct: registering with nfnetlink.\n"); | ||
| 326 | ret = nfnetlink_subsys_register(&nfnl_acct_subsys); | ||
| 327 | if (ret < 0) { | ||
| 328 | pr_err("nfnl_acct_init: cannot register with nfnetlink.\n"); | ||
| 329 | goto err_out; | ||
| 330 | } | ||
| 331 | return 0; | ||
| 332 | err_out: | ||
| 333 | return ret; | ||
| 334 | } | ||
| 335 | |||
| 336 | static void __exit nfnl_acct_exit(void) | ||
| 337 | { | ||
| 338 | struct nf_acct *cur, *tmp; | ||
| 339 | |||
| 340 | pr_info("nfnl_acct: unregistering from nfnetlink.\n"); | ||
| 341 | nfnetlink_subsys_unregister(&nfnl_acct_subsys); | ||
| 342 | |||
| 343 | list_for_each_entry_safe(cur, tmp, &nfnl_acct_list, head) { | ||
| 344 | list_del_rcu(&cur->head); | ||
| 345 | /* We are sure that our objects have no clients at this point, | ||
| 346 | * it's safe to release them all without checking refcnt. */ | ||
| 347 | kfree_rcu(cur, rcu_head); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | |||
| 351 | module_init(nfnl_acct_init); | ||
| 352 | module_exit(nfnl_acct_exit); | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 0221d10de75a..8e87123f1373 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
| @@ -62,8 +62,8 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par) | |||
| 62 | int ret = 0; | 62 | int ret = 0; |
| 63 | u8 proto; | 63 | u8 proto; |
| 64 | 64 | ||
| 65 | if (info->flags & ~XT_CT_NOTRACK) | 65 | if (info->flags & ~(XT_CT_NOTRACK | XT_CT_USERSPACE_HELPER)) |
| 66 | return -EINVAL; | 66 | return -EOPNOTSUPP; |
| 67 | 67 | ||
| 68 | if (info->flags & XT_CT_NOTRACK) { | 68 | if (info->flags & XT_CT_NOTRACK) { |
| 69 | ct = nf_ct_untracked_get(); | 69 | ct = nf_ct_untracked_get(); |
| @@ -92,7 +92,9 @@ static int xt_ct_tg_check(const struct xt_tgchk_param *par) | |||
| 92 | GFP_KERNEL)) | 92 | GFP_KERNEL)) |
| 93 | goto err3; | 93 | goto err3; |
| 94 | 94 | ||
| 95 | if (info->helper[0]) { | 95 | if (info->flags & XT_CT_USERSPACE_HELPER) { |
| 96 | __set_bit(IPS_USERSPACE_HELPER_BIT, &ct->status); | ||
| 97 | } else if (info->helper[0]) { | ||
| 96 | ret = -ENOENT; | 98 | ret = -ENOENT; |
| 97 | proto = xt_ct_find_proto(par); | 99 | proto = xt_ct_find_proto(par); |
| 98 | if (!proto) { | 100 | if (!proto) { |
diff --git a/net/netfilter/xt_connbytes.c b/net/netfilter/xt_connbytes.c index 9ddf1c3bfb39..e595e07a759b 100644 --- a/net/netfilter/xt_connbytes.c +++ b/net/netfilter/xt_connbytes.c | |||
| @@ -40,46 +40,46 @@ connbytes_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 40 | case XT_CONNBYTES_PKTS: | 40 | case XT_CONNBYTES_PKTS: |
| 41 | switch (sinfo->direction) { | 41 | switch (sinfo->direction) { |
| 42 | case XT_CONNBYTES_DIR_ORIGINAL: | 42 | case XT_CONNBYTES_DIR_ORIGINAL: |
| 43 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 43 | what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); |
| 44 | break; | 44 | break; |
| 45 | case XT_CONNBYTES_DIR_REPLY: | 45 | case XT_CONNBYTES_DIR_REPLY: |
| 46 | what = counters[IP_CT_DIR_REPLY].packets; | 46 | what = atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
| 47 | break; | 47 | break; |
| 48 | case XT_CONNBYTES_DIR_BOTH: | 48 | case XT_CONNBYTES_DIR_BOTH: |
| 49 | what = counters[IP_CT_DIR_ORIGINAL].packets; | 49 | what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); |
| 50 | what += counters[IP_CT_DIR_REPLY].packets; | 50 | what += atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
| 51 | break; | 51 | break; |
| 52 | } | 52 | } |
| 53 | break; | 53 | break; |
| 54 | case XT_CONNBYTES_BYTES: | 54 | case XT_CONNBYTES_BYTES: |
| 55 | switch (sinfo->direction) { | 55 | switch (sinfo->direction) { |
| 56 | case XT_CONNBYTES_DIR_ORIGINAL: | 56 | case XT_CONNBYTES_DIR_ORIGINAL: |
| 57 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 57 | what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); |
| 58 | break; | 58 | break; |
| 59 | case XT_CONNBYTES_DIR_REPLY: | 59 | case XT_CONNBYTES_DIR_REPLY: |
| 60 | what = counters[IP_CT_DIR_REPLY].bytes; | 60 | what = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
| 61 | break; | 61 | break; |
| 62 | case XT_CONNBYTES_DIR_BOTH: | 62 | case XT_CONNBYTES_DIR_BOTH: |
| 63 | what = counters[IP_CT_DIR_ORIGINAL].bytes; | 63 | what = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); |
| 64 | what += counters[IP_CT_DIR_REPLY].bytes; | 64 | what += atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
| 65 | break; | 65 | break; |
| 66 | } | 66 | } |
| 67 | break; | 67 | break; |
| 68 | case XT_CONNBYTES_AVGPKT: | 68 | case XT_CONNBYTES_AVGPKT: |
| 69 | switch (sinfo->direction) { | 69 | switch (sinfo->direction) { |
| 70 | case XT_CONNBYTES_DIR_ORIGINAL: | 70 | case XT_CONNBYTES_DIR_ORIGINAL: |
| 71 | bytes = counters[IP_CT_DIR_ORIGINAL].bytes; | 71 | bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes); |
| 72 | pkts = counters[IP_CT_DIR_ORIGINAL].packets; | 72 | pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets); |
| 73 | break; | 73 | break; |
| 74 | case XT_CONNBYTES_DIR_REPLY: | 74 | case XT_CONNBYTES_DIR_REPLY: |
| 75 | bytes = counters[IP_CT_DIR_REPLY].bytes; | 75 | bytes = atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
| 76 | pkts = counters[IP_CT_DIR_REPLY].packets; | 76 | pkts = atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
| 77 | break; | 77 | break; |
| 78 | case XT_CONNBYTES_DIR_BOTH: | 78 | case XT_CONNBYTES_DIR_BOTH: |
| 79 | bytes = counters[IP_CT_DIR_ORIGINAL].bytes + | 79 | bytes = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].bytes) + |
| 80 | counters[IP_CT_DIR_REPLY].bytes; | 80 | atomic64_read(&counters[IP_CT_DIR_REPLY].bytes); |
| 81 | pkts = counters[IP_CT_DIR_ORIGINAL].packets + | 81 | pkts = atomic64_read(&counters[IP_CT_DIR_ORIGINAL].packets) + |
| 82 | counters[IP_CT_DIR_REPLY].packets; | 82 | atomic64_read(&counters[IP_CT_DIR_REPLY].packets); |
| 83 | break; | 83 | break; |
| 84 | } | 84 | } |
| 85 | if (pkts != 0) | 85 | if (pkts != 0) |
diff --git a/net/netfilter/xt_nfacct.c b/net/netfilter/xt_nfacct.c new file mode 100644 index 000000000000..b3be0ef21f19 --- /dev/null +++ b/net/netfilter/xt_nfacct.c | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | /* | ||
| 2 | * (C) 2011 Pablo Neira Ayuso <pablo@netfilter.org> | ||
| 3 | * (C) 2011 Intra2net AG <http://www.intra2net.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 (or any | ||
| 7 | * later at your option) as published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | #include <linux/module.h> | ||
| 10 | #include <linux/skbuff.h> | ||
| 11 | |||
| 12 | #include <linux/netfilter/x_tables.h> | ||
| 13 | #include <linux/netfilter/nfnetlink_acct.h> | ||
| 14 | #include <linux/netfilter/xt_nfacct.h> | ||
| 15 | |||
| 16 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
| 17 | MODULE_DESCRIPTION("Xtables: match for the extended accounting infrastructure"); | ||
| 18 | MODULE_LICENSE("GPL"); | ||
| 19 | MODULE_ALIAS("ipt_nfacct"); | ||
| 20 | MODULE_ALIAS("ip6t_nfacct"); | ||
| 21 | |||
| 22 | static bool nfacct_mt(const struct sk_buff *skb, struct xt_action_param *par) | ||
| 23 | { | ||
| 24 | const struct xt_nfacct_match_info *info = par->targinfo; | ||
| 25 | |||
| 26 | nfnl_acct_update(skb, info->nfacct); | ||
| 27 | |||
| 28 | return true; | ||
| 29 | } | ||
| 30 | |||
| 31 | static int | ||
| 32 | nfacct_mt_checkentry(const struct xt_mtchk_param *par) | ||
| 33 | { | ||
| 34 | struct xt_nfacct_match_info *info = par->matchinfo; | ||
| 35 | struct nf_acct *nfacct; | ||
| 36 | |||
| 37 | nfacct = nfnl_acct_find_get(info->name); | ||
| 38 | if (nfacct == NULL) { | ||
| 39 | pr_info("xt_nfacct: accounting object with name `%s' " | ||
| 40 | "does not exists\n", info->name); | ||
| 41 | return -ENOENT; | ||
| 42 | } | ||
| 43 | info->nfacct = nfacct; | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 47 | static void | ||
| 48 | nfacct_mt_destroy(const struct xt_mtdtor_param *par) | ||
| 49 | { | ||
| 50 | const struct xt_nfacct_match_info *info = par->matchinfo; | ||
| 51 | |||
| 52 | nfnl_acct_put(info->nfacct); | ||
| 53 | } | ||
| 54 | |||
| 55 | static struct xt_match nfacct_mt_reg __read_mostly = { | ||
| 56 | .name = "nfacct", | ||
| 57 | .family = NFPROTO_UNSPEC, | ||
| 58 | .checkentry = nfacct_mt_checkentry, | ||
| 59 | .match = nfacct_mt, | ||
| 60 | .destroy = nfacct_mt_destroy, | ||
| 61 | .matchsize = sizeof(struct xt_nfacct_match_info), | ||
| 62 | .me = THIS_MODULE, | ||
| 63 | }; | ||
| 64 | |||
| 65 | static int __init nfacct_mt_init(void) | ||
| 66 | { | ||
| 67 | return xt_register_match(&nfacct_mt_reg); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void __exit nfacct_mt_exit(void) | ||
| 71 | { | ||
| 72 | xt_unregister_match(&nfacct_mt_reg); | ||
| 73 | } | ||
| 74 | |||
| 75 | module_init(nfacct_mt_init); | ||
| 76 | module_exit(nfacct_mt_exit); | ||
