mirror of
https://github.com/torvalds/linux.git
synced 2024-11-06 03:51:48 +00:00
Merge branch 'master' of git://1984.lsi.us.es/nf-next
This commit is contained in:
commit
1e9f0207d3
@ -353,14 +353,6 @@ Why: Internal alias support has been present in module-init-tools for some
|
||||
|
||||
Who: Wey-Yi Guy <wey-yi.w.guy@intel.com>
|
||||
|
||||
---------------------------
|
||||
|
||||
What: xt_NOTRACK
|
||||
Files: net/netfilter/xt_NOTRACK.c
|
||||
When: April 2011
|
||||
Why: Superseded by xt_CT
|
||||
Who: Netfilter developer team <netfilter-devel@vger.kernel.org>
|
||||
|
||||
----------------------------
|
||||
|
||||
What: IRQF_DISABLED
|
||||
|
@ -67,7 +67,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -67,7 +67,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -66,7 +66,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -61,7 +61,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -80,7 +80,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -64,7 +64,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -65,7 +65,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -61,7 +61,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -62,7 +62,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -62,7 +62,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -56,7 +56,6 @@ CONFIG_NF_CONNTRACK_MARK=y
|
||||
CONFIG_NF_CONNTRACK_FTP=m
|
||||
CONFIG_NF_CONNTRACK_IRC=m
|
||||
CONFIG_NF_CONNTRACK_TFTP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_LIMIT=m
|
||||
CONFIG_NETFILTER_XT_MATCH_MAC=m
|
||||
|
@ -96,7 +96,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
|
@ -87,7 +87,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
|
@ -60,7 +60,6 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
|
||||
|
@ -86,7 +86,6 @@ CONFIG_NETFILTER_XT_TARGET_CONNMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
|
@ -59,7 +59,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
|
||||
|
@ -108,7 +108,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
|
@ -109,7 +109,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
|
@ -68,7 +68,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_MATCH_COMMENT=m
|
||||
|
@ -55,7 +55,6 @@ CONFIG_NETFILTER_XT_TARGET_CLASSIFY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP=m
|
||||
|
@ -92,7 +92,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
|
@ -66,7 +66,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TCPMSS=m
|
||||
|
@ -167,7 +167,6 @@ CONFIG_NETFILTER_XT_TARGET_DSCP=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_SECMARK=m
|
||||
|
@ -134,7 +134,6 @@ CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TEE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
|
@ -132,7 +132,6 @@ CONFIG_NETFILTER_XT_TARGET_IDLETIMER=m
|
||||
CONFIG_NETFILTER_XT_TARGET_MARK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFLOG=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NFQUEUE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_NOTRACK=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TEE=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TPROXY=m
|
||||
CONFIG_NETFILTER_XT_TARGET_TRACE=m
|
||||
|
@ -256,6 +256,7 @@ struct inet6_skb_parm {
|
||||
#if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
|
||||
__u16 dsthao;
|
||||
#endif
|
||||
__u16 frag_max_size;
|
||||
|
||||
#define IP6SKB_XFRM_TRANSFORMED 1
|
||||
#define IP6SKB_FORWARDED 2
|
||||
|
@ -342,7 +342,7 @@ extern int nf_register_afinfo(const struct nf_afinfo *afinfo);
|
||||
extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
|
||||
|
||||
#include <net/flow.h>
|
||||
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
|
||||
extern void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
|
||||
|
||||
static inline void
|
||||
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
@ -350,13 +350,11 @@ nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
void (*decodefn)(struct sk_buff *, struct flowi *);
|
||||
|
||||
if (family == AF_INET) {
|
||||
rcu_read_lock();
|
||||
decodefn = rcu_dereference(ip_nat_decode_session);
|
||||
if (decodefn)
|
||||
decodefn(skb, fl);
|
||||
rcu_read_unlock();
|
||||
}
|
||||
rcu_read_lock();
|
||||
decodefn = rcu_dereference(nf_nat_decode_session_hook);
|
||||
if (decodefn)
|
||||
decodefn(skb, fl);
|
||||
rcu_read_unlock();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
extern unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
|
@ -34,6 +34,7 @@ struct nf_conntrack_expect;
|
||||
extern unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
enum nf_ct_ftp_type type,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
|
@ -36,12 +36,12 @@ extern void nf_conntrack_h245_expect(struct nf_conn *new,
|
||||
struct nf_conntrack_expect *this);
|
||||
extern void nf_conntrack_q931_expect(struct nf_conn *new,
|
||||
struct nf_conntrack_expect *this);
|
||||
extern int (*set_h245_addr_hook) (struct sk_buff *skb,
|
||||
extern int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
union nf_inet_addr *addr,
|
||||
__be16 port);
|
||||
extern int (*set_h225_addr_hook) (struct sk_buff *skb,
|
||||
extern int (*set_h225_addr_hook) (struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr,
|
||||
union nf_inet_addr *addr,
|
||||
@ -49,40 +49,45 @@ extern int (*set_h225_addr_hook) (struct sk_buff *skb,
|
||||
extern int (*set_sig_addr_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count);
|
||||
extern int (*set_ras_addr_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count);
|
||||
extern int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
__be16 port, __be16 rtp_port,
|
||||
struct nf_conntrack_expect *rtp_exp,
|
||||
struct nf_conntrack_expect *rtcp_exp);
|
||||
extern int (*nat_t120_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp);
|
||||
extern int (*nat_h245_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp);
|
||||
extern int (*nat_callforwarding_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr,
|
||||
__be16 port,
|
||||
struct nf_conntrack_expect *exp);
|
||||
extern int (*nat_q931_hook) (struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, TransportAddress *taddr,
|
||||
int idx, __be16 port,
|
||||
struct nf_conntrack_expect *exp);
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
extern unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
|
@ -303,12 +303,14 @@ struct nf_conntrack_expect;
|
||||
extern int
|
||||
(*nf_nat_pptp_hook_outbound)(struct sk_buff *skb,
|
||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
struct PptpControlHeader *ctlh,
|
||||
union pptp_ctrl_union *pptpReq);
|
||||
|
||||
extern int
|
||||
(*nf_nat_pptp_hook_inbound)(struct sk_buff *skb,
|
||||
struct nf_conn *ct, enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
struct PptpControlHeader *ctlh,
|
||||
union pptp_ctrl_union *pptpReq);
|
||||
|
||||
|
@ -37,10 +37,12 @@ struct sdp_media_type {
|
||||
struct sip_handler {
|
||||
const char *method;
|
||||
unsigned int len;
|
||||
int (*request)(struct sk_buff *skb, unsigned int dataoff,
|
||||
int (*request)(struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr, unsigned int *datalen,
|
||||
unsigned int cseq);
|
||||
int (*response)(struct sk_buff *skb, unsigned int dataoff,
|
||||
int (*response)(struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr, unsigned int *datalen,
|
||||
unsigned int cseq, unsigned int code);
|
||||
};
|
||||
@ -97,19 +99,20 @@ enum sip_header_types {
|
||||
enum sdp_header_types {
|
||||
SDP_HDR_UNSPEC,
|
||||
SDP_HDR_VERSION,
|
||||
SDP_HDR_OWNER_IP4,
|
||||
SDP_HDR_CONNECTION_IP4,
|
||||
SDP_HDR_OWNER_IP6,
|
||||
SDP_HDR_CONNECTION_IP6,
|
||||
SDP_HDR_OWNER,
|
||||
SDP_HDR_CONNECTION,
|
||||
SDP_HDR_MEDIA,
|
||||
};
|
||||
|
||||
extern unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen);
|
||||
extern void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off);
|
||||
extern void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff, s16 off);
|
||||
extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
@ -117,6 +120,7 @@ extern unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen);
|
||||
extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
@ -125,6 +129,7 @@ extern unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb,
|
||||
enum sdp_header_types term,
|
||||
const union nf_inet_addr *addr);
|
||||
extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
@ -132,12 +137,14 @@ extern unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb,
|
||||
unsigned int matchlen,
|
||||
u_int16_t port);
|
||||
extern unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
unsigned int sdpoff,
|
||||
const union nf_inet_addr *addr);
|
||||
extern unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb,
|
||||
unsigned int protoff,
|
||||
unsigned int dataoff,
|
||||
const char **dptr,
|
||||
unsigned int *datalen,
|
||||
|
@ -22,4 +22,12 @@ struct nf_nat_ipv4_multi_range_compat {
|
||||
struct nf_nat_ipv4_range range[1];
|
||||
};
|
||||
|
||||
struct nf_nat_range {
|
||||
unsigned int flags;
|
||||
union nf_inet_addr min_addr;
|
||||
union nf_inet_addr max_addr;
|
||||
union nf_conntrack_man_proto min_proto;
|
||||
union nf_conntrack_man_proto max_proto;
|
||||
};
|
||||
|
||||
#endif /* _NETFILTER_NF_NAT_H */
|
||||
|
@ -142,9 +142,13 @@ enum ctattr_tstamp {
|
||||
|
||||
enum ctattr_nat {
|
||||
CTA_NAT_UNSPEC,
|
||||
CTA_NAT_MINIP,
|
||||
CTA_NAT_MAXIP,
|
||||
CTA_NAT_V4_MINIP,
|
||||
#define CTA_NAT_MINIP CTA_NAT_V4_MINIP
|
||||
CTA_NAT_V4_MAXIP,
|
||||
#define CTA_NAT_MAXIP CTA_NAT_V4_MAXIP
|
||||
CTA_NAT_PROTO,
|
||||
CTA_NAT_V6_MINIP,
|
||||
CTA_NAT_V6_MAXIP,
|
||||
__CTA_NAT_MAX
|
||||
};
|
||||
#define CTA_NAT_MAX (__CTA_NAT_MAX - 1)
|
||||
|
@ -79,7 +79,6 @@ enum nf_ip_hook_priorities {
|
||||
|
||||
#ifdef __KERNEL__
|
||||
extern int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type);
|
||||
extern int ip_xfrm_me_harder(struct sk_buff *skb);
|
||||
extern __sum16 nf_ip_checksum(struct sk_buff *skb, unsigned int hook,
|
||||
unsigned int dataoff, u_int8_t protocol);
|
||||
#endif /*__KERNEL__*/
|
||||
|
@ -1,6 +1,7 @@
|
||||
header-y += ip6_tables.h
|
||||
header-y += ip6t_HL.h
|
||||
header-y += ip6t_LOG.h
|
||||
header-y += ip6t_NPT.h
|
||||
header-y += ip6t_REJECT.h
|
||||
header-y += ip6t_ah.h
|
||||
header-y += ip6t_frag.h
|
||||
|
16
include/linux/netfilter_ipv6/ip6t_NPT.h
Normal file
16
include/linux/netfilter_ipv6/ip6t_NPT.h
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef __NETFILTER_IP6T_NPT
|
||||
#define __NETFILTER_IP6T_NPT
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/netfilter.h>
|
||||
|
||||
struct ip6t_npt_tginfo {
|
||||
union nf_inet_addr src_pfx;
|
||||
union nf_inet_addr dst_pfx;
|
||||
__u8 src_pfx_len;
|
||||
__u8 dst_pfx_len;
|
||||
/* Used internally by the kernel */
|
||||
__sum16 adjustment;
|
||||
};
|
||||
|
||||
#endif /* __NETFILTER_IP6T_NPT */
|
@ -78,7 +78,7 @@ extern struct inet6_ifaddr *ipv6_get_ifaddr(struct net *net,
|
||||
int strict);
|
||||
|
||||
extern int ipv6_dev_get_saddr(struct net *net,
|
||||
struct net_device *dev,
|
||||
const struct net_device *dev,
|
||||
const struct in6_addr *daddr,
|
||||
unsigned int srcprefs,
|
||||
struct in6_addr *saddr);
|
||||
|
@ -109,6 +109,9 @@ static inline void csum_replace2(__sum16 *sum, __be16 from, __be16 to)
|
||||
struct sk_buff;
|
||||
extern void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
|
||||
__be32 from, __be32 to, int pseudohdr);
|
||||
extern void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
||||
const __be32 *from, const __be32 *to,
|
||||
int pseudohdr);
|
||||
|
||||
static inline void inet_proto_csum_replace2(__sum16 *sum, struct sk_buff *skb,
|
||||
__be16 from, __be16 to,
|
||||
|
@ -29,6 +29,8 @@ struct inet_frag_queue {
|
||||
#define INET_FRAG_COMPLETE 4
|
||||
#define INET_FRAG_FIRST_IN 2
|
||||
#define INET_FRAG_LAST_IN 1
|
||||
|
||||
u16 max_size;
|
||||
};
|
||||
|
||||
#define INETFRAGS_HASHSZ 64
|
||||
|
@ -42,6 +42,8 @@ struct inet_skb_parm {
|
||||
#define IPSKB_XFRM_TRANSFORMED 4
|
||||
#define IPSKB_FRAG_COMPLETE 8
|
||||
#define IPSKB_REROUTED 16
|
||||
|
||||
u16 frag_max_size;
|
||||
};
|
||||
|
||||
static inline unsigned int ip_hdrlen(const struct sk_buff *skb)
|
||||
|
@ -43,7 +43,7 @@ struct nf_conntrack_expect {
|
||||
unsigned int class;
|
||||
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
__be32 saved_ip;
|
||||
union nf_inet_addr saved_addr;
|
||||
/* This is the original per-proto part, used to map the
|
||||
* expected connection the way the recipient expects. */
|
||||
union nf_conntrack_man_proto saved_proto;
|
||||
|
@ -55,6 +55,26 @@ struct nf_conn_timeout *nf_ct_timeout_ext_add(struct nf_conn *ct,
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline unsigned int *
|
||||
nf_ct_timeout_lookup(struct net *net, struct nf_conn *ct,
|
||||
struct nf_conntrack_l4proto *l4proto)
|
||||
{
|
||||
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
|
||||
struct nf_conn_timeout *timeout_ext;
|
||||
unsigned int *timeouts;
|
||||
|
||||
timeout_ext = nf_ct_timeout_find(ct);
|
||||
if (timeout_ext)
|
||||
timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
|
||||
else
|
||||
timeouts = l4proto->get_timeouts(net);
|
||||
|
||||
return timeouts;
|
||||
#else
|
||||
return l4proto->get_timeouts(net);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_NF_CONNTRACK_TIMEOUT
|
||||
extern int nf_conntrack_timeout_init(struct net *net);
|
||||
extern void nf_conntrack_timeout_fini(struct net *net);
|
||||
|
@ -43,14 +43,16 @@ struct nf_conn_nat {
|
||||
struct nf_conn *ct;
|
||||
union nf_conntrack_nat_help help;
|
||||
#if defined(CONFIG_IP_NF_TARGET_MASQUERADE) || \
|
||||
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE)
|
||||
defined(CONFIG_IP_NF_TARGET_MASQUERADE_MODULE) || \
|
||||
defined(CONFIG_IP6_NF_TARGET_MASQUERADE) || \
|
||||
defined(CONFIG_IP6_NF_TARGET_MASQUERADE_MODULE)
|
||||
int masq_index;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Set up the info structure to map into this range. */
|
||||
extern unsigned int nf_nat_setup_info(struct nf_conn *ct,
|
||||
const struct nf_nat_ipv4_range *range,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype);
|
||||
|
||||
/* Is this tuple already taken? (not by us)*/
|
||||
|
@ -12,10 +12,7 @@ extern unsigned int nf_nat_packet(struct nf_conn *ct,
|
||||
unsigned int hooknum,
|
||||
struct sk_buff *skb);
|
||||
|
||||
extern int nf_nat_icmp_reply_translation(struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int hooknum,
|
||||
struct sk_buff *skb);
|
||||
extern int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family);
|
||||
|
||||
static inline int nf_nat_initialized(struct nf_conn *ct,
|
||||
enum nf_nat_manip_type manip)
|
||||
|
@ -10,6 +10,7 @@ struct sk_buff;
|
||||
extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int match_offset,
|
||||
unsigned int match_len,
|
||||
const char *rep_buffer,
|
||||
@ -18,12 +19,13 @@ extern int __nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||
static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int match_offset,
|
||||
unsigned int match_len,
|
||||
const char *rep_buffer,
|
||||
unsigned int rep_len)
|
||||
{
|
||||
return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
return __nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
match_offset, match_len,
|
||||
rep_buffer, rep_len, true);
|
||||
}
|
||||
@ -31,6 +33,7 @@ static inline int nf_nat_mangle_tcp_packet(struct sk_buff *skb,
|
||||
extern int nf_nat_mangle_udp_packet(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int match_offset,
|
||||
unsigned int match_len,
|
||||
const char *rep_buffer,
|
||||
@ -41,10 +44,12 @@ extern void nf_nat_set_seq_adjust(struct nf_conn *ct,
|
||||
__be32 seq, s16 off);
|
||||
extern int nf_nat_seq_adjust(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff);
|
||||
extern int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff);
|
||||
|
||||
/* Setup NAT on this expected conntrack so it follows master, but goes
|
||||
* to port ct->master->saved_proto. */
|
||||
|
52
include/net/netfilter/nf_nat_l3proto.h
Normal file
52
include/net/netfilter/nf_nat_l3proto.h
Normal file
@ -0,0 +1,52 @@
|
||||
#ifndef _NF_NAT_L3PROTO_H
|
||||
#define _NF_NAT_L3PROTO_H
|
||||
|
||||
struct nf_nat_l4proto;
|
||||
struct nf_nat_l3proto {
|
||||
u8 l3proto;
|
||||
|
||||
bool (*in_range)(const struct nf_conntrack_tuple *t,
|
||||
const struct nf_nat_range *range);
|
||||
|
||||
u32 (*secure_port)(const struct nf_conntrack_tuple *t, __be16);
|
||||
|
||||
bool (*manip_pkt)(struct sk_buff *skb,
|
||||
unsigned int iphdroff,
|
||||
const struct nf_nat_l4proto *l4proto,
|
||||
const struct nf_conntrack_tuple *target,
|
||||
enum nf_nat_manip_type maniptype);
|
||||
|
||||
void (*csum_update)(struct sk_buff *skb, unsigned int iphdroff,
|
||||
__sum16 *check,
|
||||
const struct nf_conntrack_tuple *t,
|
||||
enum nf_nat_manip_type maniptype);
|
||||
|
||||
void (*csum_recalc)(struct sk_buff *skb, u8 proto,
|
||||
void *data, __sum16 *check,
|
||||
int datalen, int oldlen);
|
||||
|
||||
void (*decode_session)(struct sk_buff *skb,
|
||||
const struct nf_conn *ct,
|
||||
enum ip_conntrack_dir dir,
|
||||
unsigned long statusbit,
|
||||
struct flowi *fl);
|
||||
|
||||
int (*nlattr_to_range)(struct nlattr *tb[],
|
||||
struct nf_nat_range *range);
|
||||
};
|
||||
|
||||
extern int nf_nat_l3proto_register(const struct nf_nat_l3proto *);
|
||||
extern void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *);
|
||||
extern const struct nf_nat_l3proto *__nf_nat_l3proto_find(u8 l3proto);
|
||||
|
||||
extern int nf_nat_icmp_reply_translation(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int hooknum);
|
||||
extern int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int hooknum,
|
||||
unsigned int hdrlen);
|
||||
|
||||
#endif /* _NF_NAT_L3PROTO_H */
|
72
include/net/netfilter/nf_nat_l4proto.h
Normal file
72
include/net/netfilter/nf_nat_l4proto.h
Normal file
@ -0,0 +1,72 @@
|
||||
/* Header for use in defining a given protocol. */
|
||||
#ifndef _NF_NAT_L4PROTO_H
|
||||
#define _NF_NAT_L4PROTO_H
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
struct nf_nat_range;
|
||||
struct nf_nat_l3proto;
|
||||
|
||||
struct nf_nat_l4proto {
|
||||
/* Protocol number. */
|
||||
u8 l4proto;
|
||||
|
||||
/* Translate a packet to the target according to manip type.
|
||||
* Return true if succeeded.
|
||||
*/
|
||||
bool (*manip_pkt)(struct sk_buff *skb,
|
||||
const struct nf_nat_l3proto *l3proto,
|
||||
unsigned int iphdroff, unsigned int hdroff,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype);
|
||||
|
||||
/* Is the manipable part of the tuple between min and max incl? */
|
||||
bool (*in_range)(const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const union nf_conntrack_man_proto *min,
|
||||
const union nf_conntrack_man_proto *max);
|
||||
|
||||
/* Alter the per-proto part of the tuple (depending on
|
||||
* maniptype), to give a unique tuple in the given range if
|
||||
* possible. Per-protocol part of tuple is initialized to the
|
||||
* incoming packet.
|
||||
*/
|
||||
void (*unique_tuple)(const struct nf_nat_l3proto *l3proto,
|
||||
struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct);
|
||||
|
||||
int (*nlattr_to_range)(struct nlattr *tb[],
|
||||
struct nf_nat_range *range);
|
||||
};
|
||||
|
||||
/* Protocol registration. */
|
||||
extern int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto);
|
||||
extern void nf_nat_l4proto_unregister(u8 l3proto, const struct nf_nat_l4proto *l4proto);
|
||||
|
||||
extern const struct nf_nat_l4proto *__nf_nat_l4proto_find(u8 l3proto, u8 l4proto);
|
||||
|
||||
/* Built-in protocols. */
|
||||
extern const struct nf_nat_l4proto nf_nat_l4proto_tcp;
|
||||
extern const struct nf_nat_l4proto nf_nat_l4proto_udp;
|
||||
extern const struct nf_nat_l4proto nf_nat_l4proto_icmp;
|
||||
extern const struct nf_nat_l4proto nf_nat_l4proto_icmpv6;
|
||||
extern const struct nf_nat_l4proto nf_nat_l4proto_unknown;
|
||||
|
||||
extern bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const union nf_conntrack_man_proto *min,
|
||||
const union nf_conntrack_man_proto *max);
|
||||
|
||||
extern void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct,
|
||||
u16 *rover);
|
||||
|
||||
extern int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[],
|
||||
struct nf_nat_range *range);
|
||||
|
||||
#endif /*_NF_NAT_L4PROTO_H*/
|
@ -1,67 +0,0 @@
|
||||
/* Header for use in defining a given protocol. */
|
||||
#ifndef _NF_NAT_PROTOCOL_H
|
||||
#define _NF_NAT_PROTOCOL_H
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <linux/netfilter/nfnetlink_conntrack.h>
|
||||
|
||||
struct nf_nat_ipv4_range;
|
||||
|
||||
struct nf_nat_protocol {
|
||||
/* Protocol number. */
|
||||
unsigned int protonum;
|
||||
|
||||
/* Translate a packet to the target according to manip type.
|
||||
Return true if succeeded. */
|
||||
bool (*manip_pkt)(struct sk_buff *skb,
|
||||
unsigned int iphdroff,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype);
|
||||
|
||||
/* Is the manipable part of the tuple between min and max incl? */
|
||||
bool (*in_range)(const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const union nf_conntrack_man_proto *min,
|
||||
const union nf_conntrack_man_proto *max);
|
||||
|
||||
/* Alter the per-proto part of the tuple (depending on
|
||||
maniptype), to give a unique tuple in the given range if
|
||||
possible. Per-protocol part of tuple is initialized to the
|
||||
incoming packet. */
|
||||
void (*unique_tuple)(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_ipv4_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct);
|
||||
|
||||
int (*nlattr_to_range)(struct nlattr *tb[],
|
||||
struct nf_nat_ipv4_range *range);
|
||||
};
|
||||
|
||||
/* Protocol registration. */
|
||||
extern int nf_nat_protocol_register(const struct nf_nat_protocol *proto);
|
||||
extern void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto);
|
||||
|
||||
/* Built-in protocols. */
|
||||
extern const struct nf_nat_protocol nf_nat_protocol_tcp;
|
||||
extern const struct nf_nat_protocol nf_nat_protocol_udp;
|
||||
extern const struct nf_nat_protocol nf_nat_protocol_icmp;
|
||||
extern const struct nf_nat_protocol nf_nat_unknown_protocol;
|
||||
|
||||
extern int init_protocols(void) __init;
|
||||
extern void cleanup_protocols(void);
|
||||
extern const struct nf_nat_protocol *find_nat_proto(u_int16_t protonum);
|
||||
|
||||
extern bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const union nf_conntrack_man_proto *min,
|
||||
const union nf_conntrack_man_proto *max);
|
||||
|
||||
extern void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_ipv4_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct,
|
||||
u_int16_t *rover);
|
||||
|
||||
extern int nf_nat_proto_nlattr_to_range(struct nlattr *tb[],
|
||||
struct nf_nat_ipv4_range *range);
|
||||
|
||||
#endif /*_NF_NAT_PROTO_H*/
|
@ -1,15 +0,0 @@
|
||||
#ifndef _NF_NAT_RULE_H
|
||||
#define _NF_NAT_RULE_H
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
|
||||
extern int nf_nat_rule_init(void) __init;
|
||||
extern void nf_nat_rule_cleanup(void);
|
||||
extern int nf_nat_rule_find(struct sk_buff *skb,
|
||||
unsigned int hooknum,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
struct nf_conn *ct);
|
||||
|
||||
#endif /* _NF_NAT_RULE_H */
|
@ -83,6 +83,10 @@ struct netns_ct {
|
||||
int sysctl_auto_assign_helper;
|
||||
bool auto_assign_helper_warned;
|
||||
struct nf_ip_net nf_ct_proto;
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
struct hlist_head *nat_bysource;
|
||||
unsigned int nat_htable_size;
|
||||
#endif
|
||||
#ifdef CONFIG_SYSCTL
|
||||
struct ctl_table_header *sysctl_header;
|
||||
struct ctl_table_header *acct_sysctl_header;
|
||||
|
@ -52,8 +52,6 @@ struct netns_ipv4 {
|
||||
struct xt_table *iptable_security;
|
||||
#endif
|
||||
struct xt_table *nat_table;
|
||||
struct hlist_head *nat_bysource;
|
||||
unsigned int nat_htable_size;
|
||||
#endif
|
||||
|
||||
int sysctl_icmp_echo_ignore_all;
|
||||
|
@ -42,6 +42,7 @@ struct netns_ipv6 {
|
||||
#ifdef CONFIG_SECURITY
|
||||
struct xt_table *ip6table_security;
|
||||
#endif
|
||||
struct xt_table *ip6table_nat;
|
||||
#endif
|
||||
struct rt6_info *ip6_null_entry;
|
||||
struct rt6_statistics *rt6_stats;
|
||||
|
@ -76,6 +76,7 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr,
|
||||
|
||||
return hash[0];
|
||||
}
|
||||
EXPORT_SYMBOL(secure_ipv6_port_ephemeral);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_INET
|
||||
|
@ -294,6 +294,26 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb,
|
||||
}
|
||||
EXPORT_SYMBOL(inet_proto_csum_replace4);
|
||||
|
||||
void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
|
||||
const __be32 *from, const __be32 *to,
|
||||
int pseudohdr)
|
||||
{
|
||||
__be32 diff[] = {
|
||||
~from[0], ~from[1], ~from[2], ~from[3],
|
||||
to[0], to[1], to[2], to[3],
|
||||
};
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
*sum = csum_fold(csum_partial(diff, sizeof(diff),
|
||||
~csum_unfold(*sum)));
|
||||
if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr)
|
||||
skb->csum = ~csum_partial(diff, sizeof(diff),
|
||||
~skb->csum);
|
||||
} else if (pseudohdr)
|
||||
*sum = ~csum_fold(csum_partial(diff, sizeof(diff),
|
||||
csum_unfold(*sum)));
|
||||
}
|
||||
EXPORT_SYMBOL(inet_proto_csum_replace16);
|
||||
|
||||
int mac_pton(const char *s, u8 *mac)
|
||||
{
|
||||
int i;
|
||||
|
@ -523,6 +523,10 @@ found:
|
||||
if (offset == 0)
|
||||
qp->q.last_in |= INET_FRAG_FIRST_IN;
|
||||
|
||||
if (ip_hdr(skb)->frag_off & htons(IP_DF) &&
|
||||
skb->len + ihl > qp->q.max_size)
|
||||
qp->q.max_size = skb->len + ihl;
|
||||
|
||||
if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) &&
|
||||
qp->q.meat == qp->q.len)
|
||||
return ip_frag_reasm(qp, prev, dev);
|
||||
@ -646,9 +650,11 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev,
|
||||
head->next = NULL;
|
||||
head->dev = dev;
|
||||
head->tstamp = qp->q.stamp;
|
||||
IPCB(head)->frag_max_size = qp->q.max_size;
|
||||
|
||||
iph = ip_hdr(head);
|
||||
iph->frag_off = 0;
|
||||
/* max_size != 0 implies at least one fragment had IP_DF set */
|
||||
iph->frag_off = qp->q.max_size ? htons(IP_DF) : 0;
|
||||
iph->tot_len = htons(len);
|
||||
iph->tos |= ecn;
|
||||
IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS);
|
||||
|
@ -467,7 +467,9 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
||||
|
||||
iph = ip_hdr(skb);
|
||||
|
||||
if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) {
|
||||
if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->local_df) ||
|
||||
(IPCB(skb)->frag_max_size &&
|
||||
IPCB(skb)->frag_max_size > dst_mtu(&rt->dst)))) {
|
||||
IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS);
|
||||
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED,
|
||||
htonl(ip_skb_dst_mtu(skb)));
|
||||
|
@ -72,43 +72,6 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type)
|
||||
}
|
||||
EXPORT_SYMBOL(ip_route_me_harder);
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
int ip_xfrm_me_harder(struct sk_buff *skb)
|
||||
{
|
||||
struct flowi fl;
|
||||
unsigned int hh_len;
|
||||
struct dst_entry *dst;
|
||||
|
||||
if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED)
|
||||
return 0;
|
||||
if (xfrm_decode_session(skb, &fl, AF_INET) < 0)
|
||||
return -1;
|
||||
|
||||
dst = skb_dst(skb);
|
||||
if (dst->xfrm)
|
||||
dst = ((struct xfrm_dst *)dst)->route;
|
||||
dst_hold(dst);
|
||||
|
||||
dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0);
|
||||
if (IS_ERR(dst))
|
||||
return -1;
|
||||
|
||||
skb_dst_drop(skb);
|
||||
skb_dst_set(skb, dst);
|
||||
|
||||
/* Change in oif may mean change in hh_len. */
|
||||
hh_len = skb_dst(skb)->dev->hard_header_len;
|
||||
if (skb_headroom(skb) < hh_len &&
|
||||
pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ip_xfrm_me_harder);
|
||||
#endif
|
||||
|
||||
void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);
|
||||
EXPORT_SYMBOL(ip_nat_decode_session);
|
||||
|
||||
/*
|
||||
* Extra routing may needed on local out, as the QUEUE target never
|
||||
* returns control to the table.
|
||||
@ -225,12 +188,12 @@ static const struct nf_afinfo nf_ip_afinfo = {
|
||||
.route_key_size = sizeof(struct ip_rt_info),
|
||||
};
|
||||
|
||||
static int ipv4_netfilter_init(void)
|
||||
static int __init ipv4_netfilter_init(void)
|
||||
{
|
||||
return nf_register_afinfo(&nf_ip_afinfo);
|
||||
}
|
||||
|
||||
static void ipv4_netfilter_fini(void)
|
||||
static void __exit ipv4_netfilter_fini(void)
|
||||
{
|
||||
nf_unregister_afinfo(&nf_ip_afinfo);
|
||||
}
|
||||
|
@ -143,25 +143,22 @@ config IP_NF_TARGET_ULOG
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
# NAT + specific targets: nf_conntrack
|
||||
config NF_NAT
|
||||
tristate "Full NAT"
|
||||
config NF_NAT_IPV4
|
||||
tristate "IPv4 NAT"
|
||||
depends on NF_CONNTRACK_IPV4
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
select NF_NAT
|
||||
help
|
||||
The Full NAT option allows masquerading, port forwarding and other
|
||||
The IPv4 NAT option allows masquerading, port forwarding and other
|
||||
forms of full Network Address Port Translation. It is controlled by
|
||||
the `nat' table in iptables: see the man page for iptables(8).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NF_NAT_NEEDED
|
||||
bool
|
||||
depends on NF_NAT
|
||||
default y
|
||||
if NF_NAT_IPV4
|
||||
|
||||
config IP_NF_TARGET_MASQUERADE
|
||||
tristate "MASQUERADE target support"
|
||||
depends on NF_NAT
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
help
|
||||
Masquerading is a special case of NAT: all outgoing connections are
|
||||
@ -174,7 +171,6 @@ config IP_NF_TARGET_MASQUERADE
|
||||
|
||||
config IP_NF_TARGET_NETMAP
|
||||
tristate "NETMAP target support"
|
||||
depends on NF_NAT
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
NETMAP is an implementation of static 1:1 NAT mapping of network
|
||||
@ -185,7 +181,6 @@ config IP_NF_TARGET_NETMAP
|
||||
|
||||
config IP_NF_TARGET_REDIRECT
|
||||
tristate "REDIRECT target support"
|
||||
depends on NF_NAT
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
REDIRECT is a special case of NAT: all incoming connections are
|
||||
@ -195,9 +190,11 @@ config IP_NF_TARGET_REDIRECT
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
endif
|
||||
|
||||
config NF_NAT_SNMP_BASIC
|
||||
tristate "Basic SNMP-ALG support"
|
||||
depends on NF_CONNTRACK_SNMP && NF_NAT
|
||||
depends on NF_CONNTRACK_SNMP && NF_NAT_IPV4
|
||||
depends on NETFILTER_ADVANCED
|
||||
default NF_NAT && NF_CONNTRACK_SNMP
|
||||
---help---
|
||||
@ -219,61 +216,21 @@ config NF_NAT_SNMP_BASIC
|
||||
# <expr> '&&' <expr> (6)
|
||||
#
|
||||
# (6) Returns the result of min(/expr/, /expr/).
|
||||
config NF_NAT_PROTO_DCCP
|
||||
tristate
|
||||
depends on NF_NAT && NF_CT_PROTO_DCCP
|
||||
default NF_NAT && NF_CT_PROTO_DCCP
|
||||
|
||||
config NF_NAT_PROTO_GRE
|
||||
tristate
|
||||
depends on NF_NAT && NF_CT_PROTO_GRE
|
||||
|
||||
config NF_NAT_PROTO_UDPLITE
|
||||
tristate
|
||||
depends on NF_NAT && NF_CT_PROTO_UDPLITE
|
||||
default NF_NAT && NF_CT_PROTO_UDPLITE
|
||||
|
||||
config NF_NAT_PROTO_SCTP
|
||||
tristate
|
||||
default NF_NAT && NF_CT_PROTO_SCTP
|
||||
depends on NF_NAT && NF_CT_PROTO_SCTP
|
||||
select LIBCRC32C
|
||||
|
||||
config NF_NAT_FTP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_FTP
|
||||
|
||||
config NF_NAT_IRC
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_IRC
|
||||
|
||||
config NF_NAT_TFTP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_TFTP
|
||||
|
||||
config NF_NAT_AMANDA
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_AMANDA
|
||||
depends on NF_NAT_IPV4 && NF_CT_PROTO_GRE
|
||||
|
||||
config NF_NAT_PPTP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_PPTP
|
||||
depends on NF_CONNTRACK && NF_NAT_IPV4
|
||||
default NF_NAT_IPV4 && NF_CONNTRACK_PPTP
|
||||
select NF_NAT_PROTO_GRE
|
||||
|
||||
config NF_NAT_H323
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_H323
|
||||
|
||||
config NF_NAT_SIP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_SIP
|
||||
depends on NF_CONNTRACK && NF_NAT_IPV4
|
||||
default NF_NAT_IPV4 && NF_CONNTRACK_H323
|
||||
|
||||
# mangle + specific targets
|
||||
config IP_NF_MANGLE
|
||||
|
@ -10,32 +10,22 @@ nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o
|
||||
endif
|
||||
endif
|
||||
|
||||
nf_nat-y := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_common.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o
|
||||
iptable_nat-y := nf_nat_rule.o nf_nat_standalone.o
|
||||
|
||||
# connection tracking
|
||||
obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
|
||||
|
||||
obj-$(CONFIG_NF_NAT) += nf_nat.o
|
||||
nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o
|
||||
obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o
|
||||
|
||||
# defrag
|
||||
obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
|
||||
|
||||
# NAT helpers (nf_conntrack)
|
||||
obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
|
||||
obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
|
||||
obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o
|
||||
obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
|
||||
obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o
|
||||
obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o
|
||||
obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o
|
||||
obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
|
||||
|
||||
# NAT protocols (nf_nat)
|
||||
obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
|
||||
obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
|
||||
obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
|
||||
obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
|
||||
|
||||
# generic IP tables
|
||||
obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
|
||||
@ -43,7 +33,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o
|
||||
# the three instances of ip_tables
|
||||
obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o
|
||||
obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o
|
||||
obj-$(CONFIG_NF_NAT) += iptable_nat.o
|
||||
obj-$(CONFIG_NF_NAT_IPV4) += iptable_nat.o
|
||||
obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o
|
||||
obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o
|
||||
|
||||
|
@ -19,9 +19,9 @@
|
||||
#include <net/ip.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/route.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
@ -49,7 +49,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
struct nf_conn *ct;
|
||||
struct nf_conn_nat *nat;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_nat_ipv4_range newrange;
|
||||
struct nf_nat_range newrange;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr;
|
||||
const struct rtable *rt;
|
||||
__be32 newsrc, nh;
|
||||
@ -80,10 +80,13 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
nat->masq_index = par->out->ifindex;
|
||||
|
||||
/* Transfer from original range. */
|
||||
newrange = ((struct nf_nat_ipv4_range)
|
||||
{ mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
|
||||
newsrc, newsrc,
|
||||
mr->range[0].min, mr->range[0].max });
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = newsrc;
|
||||
newrange.max_addr.ip = newsrc;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
|
||||
@ -96,7 +99,8 @@ device_cmp(struct nf_conn *i, void *ifindex)
|
||||
|
||||
if (!nat)
|
||||
return 0;
|
||||
|
||||
if (nf_ct_l3num(i) != NFPROTO_IPV4)
|
||||
return 0;
|
||||
return nat->masq_index == (int)(long)ifindex;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>");
|
||||
@ -44,7 +44,7 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 new_ip, netmask;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_ipv4_range newrange;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_POST_ROUTING ||
|
||||
@ -61,10 +61,13 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
new_ip = ip_hdr(skb)->saddr & ~netmask;
|
||||
new_ip |= mr->range[0].min_ip & netmask;
|
||||
|
||||
newrange = ((struct nf_nat_ipv4_range)
|
||||
{ mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
|
||||
new_ip, new_ip,
|
||||
mr->range[0].min, mr->range[0].max });
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = new_ip;
|
||||
newrange.max_addr.ip = new_ip;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include <net/checksum.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>");
|
||||
@ -48,7 +48,7 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
enum ip_conntrack_info ctinfo;
|
||||
__be32 newdst;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
struct nf_nat_ipv4_range newrange;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT);
|
||||
@ -76,10 +76,13 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
}
|
||||
|
||||
/* Transfer from original range. */
|
||||
newrange = ((struct nf_nat_ipv4_range)
|
||||
{ mr->range[0].flags | NF_NAT_RANGE_MAP_IPS,
|
||||
newdst, newdst,
|
||||
mr->range[0].min, mr->range[0].max });
|
||||
memset(&newrange.min_addr, 0, sizeof(newrange.min_addr));
|
||||
memset(&newrange.max_addr, 0, sizeof(newrange.max_addr));
|
||||
newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.ip = newdst;
|
||||
newrange.max_addr.ip = newdst;
|
||||
newrange.min_proto = mr->range[0].min;
|
||||
newrange.max_proto = mr->range[0].max;
|
||||
|
||||
/* Hand modified range to generic setup. */
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
|
@ -1,84 +1,71 @@
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
* (C) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/ip.h>
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <net/ip.h>
|
||||
#include <net/checksum.h>
|
||||
#include <linux/spinlock.h>
|
||||
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_extend.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_nat_protocol.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <linux/ip.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
static void nat_decode_session(struct sk_buff *skb, struct flowi *fl)
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_l3proto.h>
|
||||
|
||||
static const struct xt_table nf_nat_ipv4_table = {
|
||||
.name = "nat",
|
||||
.valid_hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.me = THIS_MODULE,
|
||||
.af = NFPROTO_IPV4,
|
||||
};
|
||||
|
||||
static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
{
|
||||
struct flowi4 *fl4 = &fl->u.ip4;
|
||||
const struct nf_conn *ct;
|
||||
const struct nf_conntrack_tuple *t;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
enum ip_conntrack_dir dir;
|
||||
unsigned long statusbit;
|
||||
/* Force range to this IP; let proto decide mapping for
|
||||
* per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
|
||||
*/
|
||||
struct nf_nat_range range;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (ct == NULL)
|
||||
return;
|
||||
dir = CTINFO2DIR(ctinfo);
|
||||
t = &ct->tuplehash[dir].tuple;
|
||||
range.flags = 0;
|
||||
pr_debug("Allocating NULL binding for %p (%pI4)\n", ct,
|
||||
HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
|
||||
|
||||
if (dir == IP_CT_DIR_ORIGINAL)
|
||||
statusbit = IPS_DST_NAT;
|
||||
else
|
||||
statusbit = IPS_SRC_NAT;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl4->daddr = t->dst.u3.ip;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl4->fl4_dport = t->dst.u.tcp.port;
|
||||
}
|
||||
|
||||
statusbit ^= IPS_NAT_MASK;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl4->saddr = t->src.u3.ip;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl4->fl4_sport = t->src.u.tcp.port;
|
||||
}
|
||||
return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
|
||||
}
|
||||
|
||||
static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
struct nf_conn *ct)
|
||||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
unsigned int ret;
|
||||
|
||||
ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
|
||||
if (ret == NF_ACCEPT) {
|
||||
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
|
||||
ret = alloc_null_binding(ct, hooknum);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
static unsigned int
|
||||
nf_nat_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
nf_nat_ipv4_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
@ -87,14 +74,16 @@ nf_nat_fn(unsigned int hooknum,
|
||||
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
|
||||
|
||||
/* We never see fragments: conntrack defrags on pre-routing
|
||||
and local-out, and nf_nat_out protects post-routing. */
|
||||
* and local-out, and nf_nat_out protects post-routing.
|
||||
*/
|
||||
NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb)));
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
/* Can't track? It's not due to stress, or conntrack would
|
||||
have dropped it. Hence it's the user's responsibilty to
|
||||
packet filter it out, or implement conntrack/NAT for that
|
||||
protocol. 8) --RR */
|
||||
* have dropped it. Hence it's the user's responsibilty to
|
||||
* packet filter it out, or implement conntrack/NAT for that
|
||||
* protocol. 8) --RR
|
||||
*/
|
||||
if (!ct)
|
||||
return NF_ACCEPT;
|
||||
|
||||
@ -118,17 +107,17 @@ nf_nat_fn(unsigned int hooknum,
|
||||
case IP_CT_RELATED:
|
||||
case IP_CT_RELATED_REPLY:
|
||||
if (ip_hdr(skb)->protocol == IPPROTO_ICMP) {
|
||||
if (!nf_nat_icmp_reply_translation(ct, ctinfo,
|
||||
hooknum, skb))
|
||||
if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo,
|
||||
hooknum))
|
||||
return NF_DROP;
|
||||
else
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
|
||||
case IP_CT_NEW:
|
||||
|
||||
/* Seen it before? This can happen for loopback, retrans,
|
||||
or local packets.. */
|
||||
* or local packets.
|
||||
*/
|
||||
if (!nf_nat_initialized(ct, maniptype)) {
|
||||
unsigned int ret;
|
||||
|
||||
@ -151,16 +140,16 @@ nf_nat_fn(unsigned int hooknum,
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_in(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
nf_nat_ipv4_in(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
unsigned int ret;
|
||||
__be32 daddr = ip_hdr(skb)->daddr;
|
||||
|
||||
ret = nf_nat_fn(hooknum, skb, in, out, okfn);
|
||||
ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn);
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
daddr != ip_hdr(skb)->daddr)
|
||||
skb_dst_drop(skb);
|
||||
@ -169,11 +158,11 @@ nf_nat_in(unsigned int hooknum,
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_out(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
nf_nat_ipv4_out(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
#ifdef CONFIG_XFRM
|
||||
const struct nf_conn *ct;
|
||||
@ -186,29 +175,30 @@ nf_nat_out(unsigned int hooknum,
|
||||
ip_hdrlen(skb) < sizeof(struct iphdr))
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_nat_fn(hooknum, skb, in, out, okfn);
|
||||
ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn);
|
||||
#ifdef CONFIG_XFRM
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
||||
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
|
||||
if ((ct->tuplehash[dir].tuple.src.u3.ip !=
|
||||
ct->tuplehash[!dir].tuple.dst.u3.ip) ||
|
||||
(ct->tuplehash[dir].tuple.src.u.all !=
|
||||
ct->tuplehash[!dir].tuple.dst.u.all)
|
||||
)
|
||||
return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP;
|
||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
||||
ret = NF_DROP;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_local_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
nf_nat_ipv4_local_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
@ -219,7 +209,7 @@ nf_nat_local_fn(unsigned int hooknum,
|
||||
ip_hdrlen(skb) < sizeof(struct iphdr))
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_nat_fn(hooknum, skb, in, out, okfn);
|
||||
ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn);
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
@ -230,21 +220,20 @@ nf_nat_local_fn(unsigned int hooknum,
|
||||
ret = NF_DROP;
|
||||
}
|
||||
#ifdef CONFIG_XFRM
|
||||
else if (ct->tuplehash[dir].tuple.dst.u.all !=
|
||||
else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) &&
|
||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||
ct->tuplehash[!dir].tuple.src.u.all)
|
||||
if (ip_xfrm_me_harder(skb))
|
||||
if (nf_xfrm_me_harder(skb, AF_INET) < 0)
|
||||
ret = NF_DROP;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* We must be after connection tracking and before packet filtering. */
|
||||
|
||||
static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
|
||||
static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = {
|
||||
/* Before packet filtering, change destination */
|
||||
{
|
||||
.hook = nf_nat_in,
|
||||
.hook = nf_nat_ipv4_in,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_PRE_ROUTING,
|
||||
@ -252,7 +241,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
|
||||
},
|
||||
/* After packet filtering, change source */
|
||||
{
|
||||
.hook = nf_nat_out,
|
||||
.hook = nf_nat_ipv4_out,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_POST_ROUTING,
|
||||
@ -260,7 +249,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
|
||||
},
|
||||
/* Before packet filtering, change destination */
|
||||
{
|
||||
.hook = nf_nat_local_fn,
|
||||
.hook = nf_nat_ipv4_local_fn,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
@ -268,7 +257,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
|
||||
},
|
||||
/* After packet filtering, change source */
|
||||
{
|
||||
.hook = nf_nat_fn,
|
||||
.hook = nf_nat_ipv4_fn,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV4,
|
||||
.hooknum = NF_INET_LOCAL_IN,
|
||||
@ -276,51 +265,56 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = {
|
||||
},
|
||||
};
|
||||
|
||||
static int __init nf_nat_standalone_init(void)
|
||||
static int __net_init iptable_nat_net_init(struct net *net)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ipt_replace *repl;
|
||||
|
||||
need_ipv4_conntrack();
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
BUG_ON(ip_nat_decode_session != NULL);
|
||||
RCU_INIT_POINTER(ip_nat_decode_session, nat_decode_session);
|
||||
#endif
|
||||
ret = nf_nat_rule_init();
|
||||
if (ret < 0) {
|
||||
pr_err("nf_nat_init: can't setup rules.\n");
|
||||
goto cleanup_decode_session;
|
||||
}
|
||||
ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
|
||||
if (ret < 0) {
|
||||
pr_err("nf_nat_init: can't register hooks.\n");
|
||||
goto cleanup_rule_init;
|
||||
}
|
||||
return ret;
|
||||
|
||||
cleanup_rule_init:
|
||||
nf_nat_rule_cleanup();
|
||||
cleanup_decode_session:
|
||||
#ifdef CONFIG_XFRM
|
||||
RCU_INIT_POINTER(ip_nat_decode_session, NULL);
|
||||
synchronize_net();
|
||||
#endif
|
||||
return ret;
|
||||
repl = ipt_alloc_initial_table(&nf_nat_ipv4_table);
|
||||
if (repl == NULL)
|
||||
return -ENOMEM;
|
||||
net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
|
||||
kfree(repl);
|
||||
if (IS_ERR(net->ipv4.nat_table))
|
||||
return PTR_ERR(net->ipv4.nat_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit nf_nat_standalone_fini(void)
|
||||
static void __net_exit iptable_nat_net_exit(struct net *net)
|
||||
{
|
||||
nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops));
|
||||
nf_nat_rule_cleanup();
|
||||
#ifdef CONFIG_XFRM
|
||||
RCU_INIT_POINTER(ip_nat_decode_session, NULL);
|
||||
synchronize_net();
|
||||
#endif
|
||||
/* Conntrack caches are unregistered in nf_conntrack_cleanup */
|
||||
ipt_unregister_table(net, net->ipv4.nat_table);
|
||||
}
|
||||
|
||||
module_init(nf_nat_standalone_init);
|
||||
module_exit(nf_nat_standalone_fini);
|
||||
static struct pernet_operations iptable_nat_net_ops = {
|
||||
.init = iptable_nat_net_init,
|
||||
.exit = iptable_nat_net_exit,
|
||||
};
|
||||
|
||||
static int __init iptable_nat_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = register_pernet_subsys(&iptable_nat_net_ops);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
unregister_pernet_subsys(&iptable_nat_net_ops);
|
||||
err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit iptable_nat_exit(void)
|
||||
{
|
||||
nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops));
|
||||
unregister_pernet_subsys(&iptable_nat_net_ops);
|
||||
}
|
||||
|
||||
module_init(iptable_nat_init);
|
||||
module_exit(iptable_nat_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ip_nat");
|
@ -29,11 +29,6 @@
|
||||
#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo);
|
||||
EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
|
||||
|
||||
static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff,
|
||||
struct nf_conntrack_tuple *tuple)
|
||||
{
|
||||
@ -149,7 +144,8 @@ static unsigned int ipv4_confirm(unsigned int hooknum,
|
||||
typeof(nf_nat_seq_adjust_hook) seq_adjust;
|
||||
|
||||
seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
|
||||
if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) {
|
||||
if (!seq_adjust ||
|
||||
!seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) {
|
||||
NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
|
||||
return NF_DROP;
|
||||
}
|
||||
|
@ -15,13 +15,12 @@
|
||||
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_expect.h>
|
||||
#include <linux/netfilter/nf_conntrack_h323.h>
|
||||
|
||||
/****************************************************************************/
|
||||
static int set_addr(struct sk_buff *skb,
|
||||
static int set_addr(struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int addroff, __be32 ip, __be16 port)
|
||||
{
|
||||
@ -40,7 +39,7 @@ static int set_addr(struct sk_buff *skb,
|
||||
|
||||
if (ip_hdr(skb)->protocol == IPPROTO_TCP) {
|
||||
if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
addroff, sizeof(buf),
|
||||
protoff, addroff, sizeof(buf),
|
||||
(char *) &buf, sizeof(buf))) {
|
||||
net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n");
|
||||
return -1;
|
||||
@ -54,7 +53,7 @@ static int set_addr(struct sk_buff *skb,
|
||||
*data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff;
|
||||
} else {
|
||||
if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo,
|
||||
addroff, sizeof(buf),
|
||||
protoff, addroff, sizeof(buf),
|
||||
(char *) &buf, sizeof(buf))) {
|
||||
net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n");
|
||||
return -1;
|
||||
@ -69,22 +68,22 @@ static int set_addr(struct sk_buff *skb,
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int set_h225_addr(struct sk_buff *skb,
|
||||
static int set_h225_addr(struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr,
|
||||
union nf_inet_addr *addr, __be16 port)
|
||||
{
|
||||
return set_addr(skb, data, dataoff, taddr->ipAddress.ip,
|
||||
return set_addr(skb, protoff, data, dataoff, taddr->ipAddress.ip,
|
||||
addr->ip, port);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int set_h245_addr(struct sk_buff *skb,
|
||||
static int set_h245_addr(struct sk_buff *skb, unsigned protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
union nf_inet_addr *addr, __be16 port)
|
||||
{
|
||||
return set_addr(skb, data, dataoff,
|
||||
return set_addr(skb, protoff, data, dataoff,
|
||||
taddr->unicastAddress.iPAddress.network,
|
||||
addr->ip, port);
|
||||
}
|
||||
@ -92,7 +91,7 @@ static int set_h245_addr(struct sk_buff *skb,
|
||||
/****************************************************************************/
|
||||
static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count)
|
||||
{
|
||||
const struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -118,7 +117,8 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&addr.ip, port,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3.ip,
|
||||
info->sig_port[!dir]);
|
||||
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||
return set_h225_addr(skb, protoff, data, 0,
|
||||
&taddr[i],
|
||||
&ct->tuplehash[!dir].
|
||||
tuple.dst.u3,
|
||||
info->sig_port[!dir]);
|
||||
@ -129,7 +129,8 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&addr.ip, port,
|
||||
&ct->tuplehash[!dir].tuple.src.u3.ip,
|
||||
info->sig_port[!dir]);
|
||||
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||
return set_h225_addr(skb, protoff, data, 0,
|
||||
&taddr[i],
|
||||
&ct->tuplehash[!dir].
|
||||
tuple.src.u3,
|
||||
info->sig_port[!dir]);
|
||||
@ -143,7 +144,7 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count)
|
||||
{
|
||||
int dir = CTINFO2DIR(ctinfo);
|
||||
@ -159,7 +160,7 @@ static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&addr.ip, ntohs(port),
|
||||
&ct->tuplehash[!dir].tuple.dst.u3.ip,
|
||||
ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port));
|
||||
return set_h225_addr(skb, data, 0, &taddr[i],
|
||||
return set_h225_addr(skb, protoff, data, 0, &taddr[i],
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
ct->tuplehash[!dir].tuple.
|
||||
dst.u.udp.port);
|
||||
@ -172,7 +173,7 @@ static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
__be16 port, __be16 rtp_port,
|
||||
struct nf_conntrack_expect *rtp_exp,
|
||||
@ -244,7 +245,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
/* Modify signal */
|
||||
if (set_h245_addr(skb, data, dataoff, taddr,
|
||||
if (set_h245_addr(skb, protoff, data, dataoff, taddr,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
htons((port & htons(1)) ? nated_port + 1 :
|
||||
nated_port)) == 0) {
|
||||
@ -275,7 +276,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp)
|
||||
{
|
||||
@ -307,7 +308,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
/* Modify signal */
|
||||
if (set_h245_addr(skb, data, dataoff, taddr,
|
||||
if (set_h245_addr(skb, protoff, data, dataoff, taddr,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
htons(nated_port)) < 0) {
|
||||
nf_ct_unexpect_related(exp);
|
||||
@ -326,7 +327,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp)
|
||||
{
|
||||
@ -363,7 +364,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
/* Modify signal */
|
||||
if (set_h225_addr(skb, data, dataoff, taddr,
|
||||
if (set_h225_addr(skb, protoff, data, dataoff, taddr,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
htons(nated_port)) == 0) {
|
||||
/* Save ports */
|
||||
@ -390,7 +391,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
static void ip_nat_q931_expect(struct nf_conn *new,
|
||||
struct nf_conntrack_expect *this)
|
||||
{
|
||||
struct nf_nat_ipv4_range range;
|
||||
struct nf_nat_range range;
|
||||
|
||||
if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */
|
||||
nf_nat_follow_master(new, this);
|
||||
@ -402,21 +403,23 @@ static void ip_nat_q931_expect(struct nf_conn *new,
|
||||
|
||||
/* Change src to where master sends to */
|
||||
range.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
|
||||
range.min_addr = range.max_addr =
|
||||
new->tuplehash[!this->dir].tuple.src.u3;
|
||||
nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
|
||||
|
||||
/* For DST manip, map port here to where it's expected. */
|
||||
range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
|
||||
range.min = range.max = this->saved_proto;
|
||||
range.min_ip = range.max_ip =
|
||||
new->master->tuplehash[!this->dir].tuple.src.u3.ip;
|
||||
range.min_proto = range.max_proto = this->saved_proto;
|
||||
range.min_addr = range.max_addr =
|
||||
new->master->tuplehash[!this->dir].tuple.src.u3;
|
||||
nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, TransportAddress *taddr, int idx,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int idx,
|
||||
__be16 port, struct nf_conntrack_expect *exp)
|
||||
{
|
||||
struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -453,7 +456,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
/* Modify signal */
|
||||
if (set_h225_addr(skb, data, 0, &taddr[idx],
|
||||
if (set_h225_addr(skb, protoff, data, 0, &taddr[idx],
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
htons(nated_port)) == 0) {
|
||||
/* Save ports */
|
||||
@ -464,7 +467,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if (idx > 0 &&
|
||||
get_h225_addr(ct, *data, &taddr[0], &addr, &port) &&
|
||||
(ntohl(addr.ip) & 0xff000000) == 0x7f000000) {
|
||||
set_h225_addr(skb, data, 0, &taddr[0],
|
||||
set_h225_addr(skb, protoff, data, 0, &taddr[0],
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
info->sig_port[!dir]);
|
||||
}
|
||||
@ -487,26 +490,28 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
static void ip_nat_callforwarding_expect(struct nf_conn *new,
|
||||
struct nf_conntrack_expect *this)
|
||||
{
|
||||
struct nf_nat_ipv4_range range;
|
||||
struct nf_nat_range range;
|
||||
|
||||
/* This must be a fresh one. */
|
||||
BUG_ON(new->status & IPS_NAT_DONE_MASK);
|
||||
|
||||
/* Change src to where master sends to */
|
||||
range.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip;
|
||||
range.min_addr = range.max_addr =
|
||||
new->tuplehash[!this->dir].tuple.src.u3;
|
||||
nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC);
|
||||
|
||||
/* For DST manip, map port here to where it's expected. */
|
||||
range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED);
|
||||
range.min = range.max = this->saved_proto;
|
||||
range.min_ip = range.max_ip = this->saved_ip;
|
||||
range.min_proto = range.max_proto = this->saved_proto;
|
||||
range.min_addr = range.max_addr = this->saved_addr;
|
||||
nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
/****************************************************************************/
|
||||
static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp)
|
||||
@ -515,7 +520,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
|
||||
u_int16_t nated_port;
|
||||
|
||||
/* Set expectations for NAT */
|
||||
exp->saved_ip = exp->tuple.dst.u3.ip;
|
||||
exp->saved_addr = exp->tuple.dst.u3;
|
||||
exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip;
|
||||
exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port;
|
||||
exp->expectfn = ip_nat_callforwarding_expect;
|
||||
@ -541,7 +546,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
/* Modify signal */
|
||||
if (!set_h225_addr(skb, data, dataoff, taddr,
|
||||
if (!set_h225_addr(skb, protoff, data, dataoff, taddr,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
htons(nated_port)) == 0) {
|
||||
nf_ct_unexpect_related(exp);
|
||||
|
281
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
Normal file
281
net/ipv4/netfilter/nf_nat_l3proto_ipv4.c
Normal file
@ -0,0 +1,281 @@
|
||||
/*
|
||||
* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
* (C) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/icmp.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <net/secure_seq.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/route.h>
|
||||
#include <net/ip.h>
|
||||
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_l3proto.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
|
||||
static const struct nf_nat_l3proto nf_nat_l3proto_ipv4;
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
static void nf_nat_ipv4_decode_session(struct sk_buff *skb,
|
||||
const struct nf_conn *ct,
|
||||
enum ip_conntrack_dir dir,
|
||||
unsigned long statusbit,
|
||||
struct flowi *fl)
|
||||
{
|
||||
const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
|
||||
struct flowi4 *fl4 = &fl->u.ip4;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl4->daddr = t->dst.u3.ip;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl4->fl4_dport = t->dst.u.all;
|
||||
}
|
||||
|
||||
statusbit ^= IPS_NAT_MASK;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl4->saddr = t->src.u3.ip;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl4->fl4_sport = t->src.u.all;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_XFRM */
|
||||
|
||||
static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t,
|
||||
const struct nf_nat_range *range)
|
||||
{
|
||||
return ntohl(t->src.u3.ip) >= ntohl(range->min_addr.ip) &&
|
||||
ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip);
|
||||
}
|
||||
|
||||
static u32 nf_nat_ipv4_secure_port(const struct nf_conntrack_tuple *t,
|
||||
__be16 dport)
|
||||
{
|
||||
return secure_ipv4_port_ephemeral(t->src.u3.ip, t->dst.u3.ip, dport);
|
||||
}
|
||||
|
||||
static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb,
|
||||
unsigned int iphdroff,
|
||||
const struct nf_nat_l4proto *l4proto,
|
||||
const struct nf_conntrack_tuple *target,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
struct iphdr *iph;
|
||||
unsigned int hdroff;
|
||||
|
||||
if (!skb_make_writable(skb, iphdroff + sizeof(*iph)))
|
||||
return false;
|
||||
|
||||
iph = (void *)skb->data + iphdroff;
|
||||
hdroff = iphdroff + iph->ihl * 4;
|
||||
|
||||
if (!l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv4, iphdroff, hdroff,
|
||||
target, maniptype))
|
||||
return false;
|
||||
iph = (void *)skb->data + iphdroff;
|
||||
|
||||
if (maniptype == NF_NAT_MANIP_SRC) {
|
||||
csum_replace4(&iph->check, iph->saddr, target->src.u3.ip);
|
||||
iph->saddr = target->src.u3.ip;
|
||||
} else {
|
||||
csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip);
|
||||
iph->daddr = target->dst.u3.ip;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nf_nat_ipv4_csum_update(struct sk_buff *skb,
|
||||
unsigned int iphdroff, __sum16 *check,
|
||||
const struct nf_conntrack_tuple *t,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||
__be32 oldip, newip;
|
||||
|
||||
if (maniptype == NF_NAT_MANIP_SRC) {
|
||||
oldip = iph->saddr;
|
||||
newip = t->src.u3.ip;
|
||||
} else {
|
||||
oldip = iph->daddr;
|
||||
newip = t->dst.u3.ip;
|
||||
}
|
||||
inet_proto_csum_replace4(check, skb, oldip, newip, 1);
|
||||
}
|
||||
|
||||
static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb,
|
||||
u8 proto, void *data, __sum16 *check,
|
||||
int datalen, int oldlen)
|
||||
{
|
||||
const struct iphdr *iph = ip_hdr(skb);
|
||||
struct rtable *rt = skb_rtable(skb);
|
||||
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
if (!(rt->rt_flags & RTCF_LOCAL) &&
|
||||
(!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) {
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->csum_start = skb_headroom(skb) +
|
||||
skb_network_offset(skb) +
|
||||
ip_hdrlen(skb);
|
||||
skb->csum_offset = (void *)check - data;
|
||||
*check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||
datalen, proto, 0);
|
||||
} else {
|
||||
*check = 0;
|
||||
*check = csum_tcpudp_magic(iph->saddr, iph->daddr,
|
||||
datalen, proto,
|
||||
csum_partial(data, datalen,
|
||||
0));
|
||||
if (proto == IPPROTO_UDP && !*check)
|
||||
*check = CSUM_MANGLED_0;
|
||||
}
|
||||
} else
|
||||
inet_proto_csum_replace2(check, skb,
|
||||
htons(oldlen), htons(datalen), 1);
|
||||
}
|
||||
|
||||
static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[],
|
||||
struct nf_nat_range *range)
|
||||
{
|
||||
if (tb[CTA_NAT_V4_MINIP]) {
|
||||
range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]);
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
}
|
||||
|
||||
if (tb[CTA_NAT_V4_MAXIP])
|
||||
range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]);
|
||||
else
|
||||
range->max_addr.ip = range->min_addr.ip;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = {
|
||||
.l3proto = NFPROTO_IPV4,
|
||||
.in_range = nf_nat_ipv4_in_range,
|
||||
.secure_port = nf_nat_ipv4_secure_port,
|
||||
.manip_pkt = nf_nat_ipv4_manip_pkt,
|
||||
.csum_update = nf_nat_ipv4_csum_update,
|
||||
.csum_recalc = nf_nat_ipv4_csum_recalc,
|
||||
.nlattr_to_range = nf_nat_ipv4_nlattr_to_range,
|
||||
#ifdef CONFIG_XFRM
|
||||
.decode_session = nf_nat_ipv4_decode_session,
|
||||
#endif
|
||||
};
|
||||
|
||||
int nf_nat_icmp_reply_translation(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int hooknum)
|
||||
{
|
||||
struct {
|
||||
struct icmphdr icmp;
|
||||
struct iphdr ip;
|
||||
} *inside;
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
|
||||
unsigned int hdrlen = ip_hdrlen(skb);
|
||||
const struct nf_nat_l4proto *l4proto;
|
||||
struct nf_conntrack_tuple target;
|
||||
unsigned long statusbit;
|
||||
|
||||
NF_CT_ASSERT(ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY);
|
||||
|
||||
if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
|
||||
return 0;
|
||||
if (nf_ip_checksum(skb, hooknum, hdrlen, 0))
|
||||
return 0;
|
||||
|
||||
inside = (void *)skb->data + hdrlen;
|
||||
if (inside->icmp.type == ICMP_REDIRECT) {
|
||||
if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
|
||||
return 0;
|
||||
if (ct->status & IPS_NAT_MASK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (manip == NF_NAT_MANIP_SRC)
|
||||
statusbit = IPS_SRC_NAT;
|
||||
else
|
||||
statusbit = IPS_DST_NAT;
|
||||
|
||||
/* Invert if this is reply direction */
|
||||
if (dir == IP_CT_DIR_REPLY)
|
||||
statusbit ^= IPS_NAT_MASK;
|
||||
|
||||
if (!(ct->status & statusbit))
|
||||
return 1;
|
||||
|
||||
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, inside->ip.protocol);
|
||||
if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp),
|
||||
l4proto, &ct->tuplehash[!dir].tuple, !manip))
|
||||
return 0;
|
||||
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
/* Reloading "inside" here since manip_pkt may reallocate */
|
||||
inside = (void *)skb->data + hdrlen;
|
||||
inside->icmp.checksum = 0;
|
||||
inside->icmp.checksum =
|
||||
csum_fold(skb_checksum(skb, hdrlen,
|
||||
skb->len - hdrlen, 0));
|
||||
}
|
||||
|
||||
/* Change outer to look like the reply to an incoming packet */
|
||||
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
||||
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, 0);
|
||||
if (!nf_nat_ipv4_manip_pkt(skb, 0, l4proto, &target, manip))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation);
|
||||
|
||||
static int __init nf_nat_l3proto_ipv4_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_icmp);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
err = nf_nat_l3proto_register(&nf_nat_l3proto_ipv4);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
return err;
|
||||
|
||||
err2:
|
||||
nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_icmp);
|
||||
err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit nf_nat_l3proto_ipv4_exit(void)
|
||||
{
|
||||
nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv4);
|
||||
nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_icmp);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("nf-nat-" __stringify(AF_INET));
|
||||
|
||||
module_init(nf_nat_l3proto_ipv4_init);
|
||||
module_exit(nf_nat_l3proto_ipv4_exit);
|
@ -22,7 +22,6 @@
|
||||
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_conntrack_helper.h>
|
||||
#include <net/netfilter/nf_conntrack_expect.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
@ -47,7 +46,7 @@ static void pptp_nat_expected(struct nf_conn *ct,
|
||||
struct nf_conntrack_tuple t;
|
||||
const struct nf_ct_pptp_master *ct_pptp_info;
|
||||
const struct nf_nat_pptp *nat_pptp_info;
|
||||
struct nf_nat_ipv4_range range;
|
||||
struct nf_nat_range range;
|
||||
|
||||
ct_pptp_info = nfct_help_data(master);
|
||||
nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info;
|
||||
@ -89,21 +88,21 @@ static void pptp_nat_expected(struct nf_conn *ct,
|
||||
|
||||
/* Change src to where master sends to */
|
||||
range.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
range.min_ip = range.max_ip
|
||||
= ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip;
|
||||
range.min_addr = range.max_addr
|
||||
= ct->master->tuplehash[!exp->dir].tuple.dst.u3;
|
||||
if (exp->dir == IP_CT_DIR_ORIGINAL) {
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
range.min = range.max = exp->saved_proto;
|
||||
range.min_proto = range.max_proto = exp->saved_proto;
|
||||
}
|
||||
nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC);
|
||||
|
||||
/* For DST manip, map port here to where it's expected. */
|
||||
range.flags = NF_NAT_RANGE_MAP_IPS;
|
||||
range.min_ip = range.max_ip
|
||||
= ct->master->tuplehash[!exp->dir].tuple.src.u3.ip;
|
||||
range.min_addr = range.max_addr
|
||||
= ct->master->tuplehash[!exp->dir].tuple.src.u3;
|
||||
if (exp->dir == IP_CT_DIR_REPLY) {
|
||||
range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED;
|
||||
range.min = range.max = exp->saved_proto;
|
||||
range.min_proto = range.max_proto = exp->saved_proto;
|
||||
}
|
||||
nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST);
|
||||
}
|
||||
@ -113,6 +112,7 @@ static int
|
||||
pptp_outbound_pkt(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
struct PptpControlHeader *ctlh,
|
||||
union pptp_ctrl_union *pptpReq)
|
||||
|
||||
@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff *skb,
|
||||
ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid));
|
||||
|
||||
/* mangle packet */
|
||||
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
cid_off + sizeof(struct pptp_pkt_hdr) +
|
||||
sizeof(struct PptpControlHeader),
|
||||
sizeof(new_callid), (char *)&new_callid,
|
||||
@ -216,6 +216,7 @@ static int
|
||||
pptp_inbound_pkt(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
struct PptpControlHeader *ctlh,
|
||||
union pptp_ctrl_union *pptpReq)
|
||||
{
|
||||
@ -268,7 +269,7 @@ pptp_inbound_pkt(struct sk_buff *skb,
|
||||
pr_debug("altering peer call id from 0x%04x to 0x%04x\n",
|
||||
ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid));
|
||||
|
||||
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff,
|
||||
pcid_off + sizeof(struct pptp_pkt_hdr) +
|
||||
sizeof(struct PptpControlHeader),
|
||||
sizeof(new_pcid), (char *)&new_pcid,
|
||||
|
@ -28,8 +28,7 @@
|
||||
#include <linux/ip.h>
|
||||
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_nat_protocol.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
#include <linux/netfilter/nf_conntrack_proto_gre.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@ -38,8 +37,9 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE");
|
||||
|
||||
/* generate unique tuple ... */
|
||||
static void
|
||||
gre_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_ipv4_range *range,
|
||||
gre_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct)
|
||||
{
|
||||
@ -62,8 +62,8 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
min = 1;
|
||||
range_size = 0xffff;
|
||||
} else {
|
||||
min = ntohs(range->min.gre.key);
|
||||
range_size = ntohs(range->max.gre.key) - min + 1;
|
||||
min = ntohs(range->min_proto.gre.key);
|
||||
range_size = ntohs(range->max_proto.gre.key) - min + 1;
|
||||
}
|
||||
|
||||
pr_debug("min = %u, range_size = %u\n", min, range_size);
|
||||
@ -80,14 +80,14 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
|
||||
/* manipulate a GRE packet according to maniptype */
|
||||
static bool
|
||||
gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
|
||||
gre_manip_pkt(struct sk_buff *skb,
|
||||
const struct nf_nat_l3proto *l3proto,
|
||||
unsigned int iphdroff, unsigned int hdroff,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
const struct gre_hdr *greh;
|
||||
struct gre_hdr_pptp *pgreh;
|
||||
const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||
unsigned int hdroff = iphdroff + iph->ihl * 4;
|
||||
|
||||
/* pgreh includes two optional 32bit fields which are not required
|
||||
* to be there. That's where the magic '8' comes from */
|
||||
@ -117,24 +117,24 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff,
|
||||
return true;
|
||||
}
|
||||
|
||||
static const struct nf_nat_protocol gre = {
|
||||
.protonum = IPPROTO_GRE,
|
||||
static const struct nf_nat_l4proto gre = {
|
||||
.l4proto = IPPROTO_GRE,
|
||||
.manip_pkt = gre_manip_pkt,
|
||||
.in_range = nf_nat_proto_in_range,
|
||||
.in_range = nf_nat_l4proto_in_range,
|
||||
.unique_tuple = gre_unique_tuple,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.nlattr_to_range = nf_nat_proto_nlattr_to_range,
|
||||
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
|
||||
#endif
|
||||
};
|
||||
|
||||
static int __init nf_nat_proto_gre_init(void)
|
||||
{
|
||||
return nf_nat_protocol_register(&gre);
|
||||
return nf_nat_l4proto_register(NFPROTO_IPV4, &gre);
|
||||
}
|
||||
|
||||
static void __exit nf_nat_proto_gre_fini(void)
|
||||
{
|
||||
nf_nat_protocol_unregister(&gre);
|
||||
nf_nat_l4proto_unregister(NFPROTO_IPV4, &gre);
|
||||
}
|
||||
|
||||
module_init(nf_nat_proto_gre_init);
|
||||
|
@ -15,8 +15,7 @@
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
#include <net/netfilter/nf_nat_protocol.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
|
||||
static bool
|
||||
icmp_in_range(const struct nf_conntrack_tuple *tuple,
|
||||
@ -29,8 +28,9 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple,
|
||||
}
|
||||
|
||||
static void
|
||||
icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_ipv4_range *range,
|
||||
icmp_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct)
|
||||
{
|
||||
@ -38,13 +38,14 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
unsigned int range_size;
|
||||
unsigned int i;
|
||||
|
||||
range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1;
|
||||
range_size = ntohs(range->max_proto.icmp.id) -
|
||||
ntohs(range->min_proto.icmp.id) + 1;
|
||||
/* If no range specified... */
|
||||
if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED))
|
||||
range_size = 0xFFFF;
|
||||
|
||||
for (i = 0; ; ++id) {
|
||||
tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) +
|
||||
tuple->src.u.icmp.id = htons(ntohs(range->min_proto.icmp.id) +
|
||||
(id % range_size));
|
||||
if (++i == range_size || !nf_nat_used_tuple(tuple, ct))
|
||||
return;
|
||||
@ -54,13 +55,12 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple,
|
||||
|
||||
static bool
|
||||
icmp_manip_pkt(struct sk_buff *skb,
|
||||
unsigned int iphdroff,
|
||||
const struct nf_nat_l3proto *l3proto,
|
||||
unsigned int iphdroff, unsigned int hdroff,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff);
|
||||
struct icmphdr *hdr;
|
||||
unsigned int hdroff = iphdroff + iph->ihl*4;
|
||||
|
||||
if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
|
||||
return false;
|
||||
@ -72,12 +72,12 @@ icmp_manip_pkt(struct sk_buff *skb,
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct nf_nat_protocol nf_nat_protocol_icmp = {
|
||||
.protonum = IPPROTO_ICMP,
|
||||
const struct nf_nat_l4proto nf_nat_l4proto_icmp = {
|
||||
.l4proto = IPPROTO_ICMP,
|
||||
.manip_pkt = icmp_manip_pkt,
|
||||
.in_range = icmp_in_range,
|
||||
.unique_tuple = icmp_unique_tuple,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.nlattr_to_range = nf_nat_proto_nlattr_to_range,
|
||||
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
|
||||
#endif
|
||||
};
|
||||
|
@ -1,214 +0,0 @@
|
||||
/* (C) 1999-2001 Paul `Rusty' Russell
|
||||
* (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
/* Everything about the rules for NAT. */
|
||||
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
||||
#include <linux/types.h>
|
||||
#include <linux/ip.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv4.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/kmod.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/proc_fs.h>
|
||||
#include <linux/slab.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/route.h>
|
||||
#include <linux/bitops.h>
|
||||
|
||||
#include <linux/netfilter_ipv4/ip_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_rule.h>
|
||||
|
||||
#define NAT_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \
|
||||
(1 << NF_INET_POST_ROUTING) | \
|
||||
(1 << NF_INET_LOCAL_OUT) | \
|
||||
(1 << NF_INET_LOCAL_IN))
|
||||
|
||||
static const struct xt_table nat_table = {
|
||||
.name = "nat",
|
||||
.valid_hooks = NAT_VALID_HOOKS,
|
||||
.me = THIS_MODULE,
|
||||
.af = NFPROTO_IPV4,
|
||||
};
|
||||
|
||||
/* Source NAT */
|
||||
static unsigned int
|
||||
ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_IN);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
/* Connection must be valid and new. */
|
||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
|
||||
ctinfo == IP_CT_RELATED_REPLY));
|
||||
NF_CT_ASSERT(par->out != NULL);
|
||||
|
||||
return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_SRC);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT);
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
|
||||
/* Connection must be valid and new. */
|
||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED));
|
||||
|
||||
return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static int ipt_snat_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
/* Must be a valid range */
|
||||
if (mr->rangesize != 1) {
|
||||
pr_info("SNAT: multiple ranges no longer supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ipt_dnat_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo;
|
||||
|
||||
/* Must be a valid range */
|
||||
if (mr->rangesize != 1) {
|
||||
pr_info("DNAT: multiple ranges no longer supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
{
|
||||
/* Force range to this IP; let proto decide mapping for
|
||||
per-proto parts (hence not NF_NAT_RANGE_PROTO_SPECIFIED).
|
||||
*/
|
||||
struct nf_nat_ipv4_range range;
|
||||
|
||||
range.flags = 0;
|
||||
pr_debug("Allocating NULL binding for %p (%pI4)\n", ct,
|
||||
HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip :
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip);
|
||||
|
||||
return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
|
||||
}
|
||||
|
||||
int nf_nat_rule_find(struct sk_buff *skb,
|
||||
unsigned int hooknum,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
struct nf_conn *ct)
|
||||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
int ret;
|
||||
|
||||
ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table);
|
||||
|
||||
if (ret == NF_ACCEPT) {
|
||||
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
|
||||
/* NUL mapping */
|
||||
ret = alloc_null_binding(ct, hooknum);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct xt_target ipt_snat_reg __read_mostly = {
|
||||
.name = "SNAT",
|
||||
.target = ipt_snat_target,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = ipt_snat_checkentry,
|
||||
.family = AF_INET,
|
||||
};
|
||||
|
||||
static struct xt_target ipt_dnat_reg __read_mostly = {
|
||||
.name = "DNAT",
|
||||
.target = ipt_dnat_target,
|
||||
.targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
|
||||
.checkentry = ipt_dnat_checkentry,
|
||||
.family = AF_INET,
|
||||
};
|
||||
|
||||
static int __net_init nf_nat_rule_net_init(struct net *net)
|
||||
{
|
||||
struct ipt_replace *repl;
|
||||
|
||||
repl = ipt_alloc_initial_table(&nat_table);
|
||||
if (repl == NULL)
|
||||
return -ENOMEM;
|
||||
net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl);
|
||||
kfree(repl);
|
||||
if (IS_ERR(net->ipv4.nat_table))
|
||||
return PTR_ERR(net->ipv4.nat_table);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit nf_nat_rule_net_exit(struct net *net)
|
||||
{
|
||||
ipt_unregister_table(net, net->ipv4.nat_table);
|
||||
}
|
||||
|
||||
static struct pernet_operations nf_nat_rule_net_ops = {
|
||||
.init = nf_nat_rule_net_init,
|
||||
.exit = nf_nat_rule_net_exit,
|
||||
};
|
||||
|
||||
int __init nf_nat_rule_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = register_pernet_subsys(&nf_nat_rule_net_ops);
|
||||
if (ret != 0)
|
||||
goto out;
|
||||
ret = xt_register_target(&ipt_snat_reg);
|
||||
if (ret != 0)
|
||||
goto unregister_table;
|
||||
|
||||
ret = xt_register_target(&ipt_dnat_reg);
|
||||
if (ret != 0)
|
||||
goto unregister_snat;
|
||||
|
||||
return ret;
|
||||
|
||||
unregister_snat:
|
||||
xt_unregister_target(&ipt_snat_reg);
|
||||
unregister_table:
|
||||
unregister_pernet_subsys(&nf_nat_rule_net_ops);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void nf_nat_rule_cleanup(void)
|
||||
{
|
||||
xt_unregister_target(&ipt_dnat_reg);
|
||||
xt_unregister_target(&ipt_snat_reg);
|
||||
unregister_pernet_subsys(&nf_nat_rule_net_ops);
|
||||
}
|
@ -1084,7 +1084,7 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev,
|
||||
int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev,
|
||||
const struct in6_addr *daddr, unsigned int prefs,
|
||||
struct in6_addr *saddr)
|
||||
{
|
||||
|
@ -493,7 +493,8 @@ int ip6_forward(struct sk_buff *skb)
|
||||
if (mtu < IPV6_MIN_MTU)
|
||||
mtu = IPV6_MIN_MTU;
|
||||
|
||||
if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) ||
|
||||
(IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) {
|
||||
/* Again, force OUTPUT device used as source address */
|
||||
skb->dev = dst->dev;
|
||||
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu);
|
||||
@ -636,7 +637,9 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
|
||||
/* We must not fragment if the socket is set to force MTU discovery
|
||||
* or if the skb it not generated by a local socket.
|
||||
*/
|
||||
if (unlikely(!skb->local_df && skb->len > mtu)) {
|
||||
if (unlikely(!skb->local_df && skb->len > mtu) ||
|
||||
(IP6CB(skb)->frag_max_size &&
|
||||
IP6CB(skb)->frag_max_size > mtu)) {
|
||||
if (skb->sk && dst_allfrag(skb_dst(skb)))
|
||||
sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK);
|
||||
|
||||
|
@ -15,6 +15,7 @@ int ip6_route_me_harder(struct sk_buff *skb)
|
||||
{
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
const struct ipv6hdr *iph = ipv6_hdr(skb);
|
||||
unsigned int hh_len;
|
||||
struct dst_entry *dst;
|
||||
struct flowi6 fl6 = {
|
||||
.flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0,
|
||||
@ -47,6 +48,13 @@ int ip6_route_me_harder(struct sk_buff *skb)
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Change in oif may mean change in hh_len. */
|
||||
hh_len = skb_dst(skb)->dev->hard_header_len;
|
||||
if (skb_headroom(skb) < hh_len &&
|
||||
pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)),
|
||||
0, GFP_ATOMIC))
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ip6_route_me_harder);
|
||||
|
@ -25,6 +25,18 @@ config NF_CONNTRACK_IPV6
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NF_NAT_IPV6
|
||||
tristate "IPv6 NAT"
|
||||
depends on NF_CONNTRACK_IPV6
|
||||
depends on NETFILTER_ADVANCED
|
||||
select NF_NAT
|
||||
help
|
||||
The IPv6 NAT option allows masquerading, port forwarding and other
|
||||
forms of full Network Address Port Translation. It is controlled by
|
||||
the `nat' table in ip6tables, see the man page for ip6tables(8).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_IPTABLES
|
||||
tristate "IP6 tables support (required for filtering)"
|
||||
depends on INET && IPV6
|
||||
@ -132,6 +144,48 @@ config IP6_NF_TARGET_HL
|
||||
(e.g. when running oldconfig). It selects
|
||||
CONFIG_NETFILTER_XT_TARGET_HL.
|
||||
|
||||
config IP6_NF_TARGET_MASQUERADE
|
||||
tristate "MASQUERADE target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
Masquerading is a special case of NAT: all outgoing connections are
|
||||
changed to seem to come from a particular interface's address, and
|
||||
if the interface goes down, those connections are lost. This is
|
||||
only useful for dialup accounts with dynamic IP address (ie. your IP
|
||||
address will be different on next dialup).
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_NETMAP
|
||||
tristate "NETMAP target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
NETMAP is an implementation of static 1:1 NAT mapping of network
|
||||
addresses. It maps the network address part, while keeping the host
|
||||
address part intact.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_REDIRECT
|
||||
tristate "REDIRECT target support"
|
||||
depends on NF_NAT_IPV6
|
||||
help
|
||||
REDIRECT is a special case of NAT: all incoming connections are
|
||||
mapped onto the incoming interface's address, causing the packets to
|
||||
come to the local machine instead of passing through. This is
|
||||
useful for transparent proxies.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_TARGET_NPT
|
||||
tristate "NPT (Network Prefix translation) target support"
|
||||
depends on NETFILTER_ADVANCED
|
||||
help
|
||||
This option adds the `SNPT' and `DNPT' target, which perform
|
||||
stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296.
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config IP6_NF_FILTER
|
||||
tristate "Packet filtering"
|
||||
default m if NETFILTER_ADVANCED=n
|
||||
|
@ -8,6 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o
|
||||
obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o
|
||||
obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o
|
||||
obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o
|
||||
obj-$(CONFIG_NF_NAT_IPV6) += ip6table_nat.o
|
||||
|
||||
# objects for l3 independent conntrack
|
||||
nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
|
||||
@ -15,6 +16,9 @@ nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o
|
||||
# l3 independent conntrack
|
||||
obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o
|
||||
|
||||
nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o
|
||||
obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o
|
||||
|
||||
# defrag
|
||||
nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o
|
||||
obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o
|
||||
@ -30,4 +34,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o
|
||||
obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o
|
||||
|
||||
# targets
|
||||
obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o
|
||||
obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o
|
||||
|
135
net/ipv6/netfilter/ip6t_MASQUERADE.c
Normal file
135
net/ipv6/netfilter/ip6t_MASQUERADE.c
Normal file
@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
static unsigned int
|
||||
masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct in6_addr src;
|
||||
struct nf_conn *ct;
|
||||
struct nf_nat_range newrange;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED ||
|
||||
ctinfo == IP_CT_RELATED_REPLY));
|
||||
|
||||
if (ipv6_dev_get_saddr(dev_net(par->out), par->out,
|
||||
&ipv6_hdr(skb)->daddr, 0, &src) < 0)
|
||||
return NF_DROP;
|
||||
|
||||
nfct_nat(ct)->masq_index = par->out->ifindex;
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.in6 = src;
|
||||
newrange.max_addr.in6 = src;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC);
|
||||
}
|
||||
|
||||
static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int device_cmp(struct nf_conn *ct, void *ifindex)
|
||||
{
|
||||
const struct nf_conn_nat *nat = nfct_nat(ct);
|
||||
|
||||
if (!nat)
|
||||
return 0;
|
||||
if (nf_ct_l3num(ct) != NFPROTO_IPV6)
|
||||
return 0;
|
||||
return nat->masq_index == (int)(long)ifindex;
|
||||
}
|
||||
|
||||
static int masq_device_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
const struct net_device *dev = ptr;
|
||||
struct net *net = dev_net(dev);
|
||||
|
||||
if (event == NETDEV_DOWN)
|
||||
nf_ct_iterate_cleanup(net, device_cmp,
|
||||
(void *)(long)dev->ifindex);
|
||||
|
||||
return NOTIFY_DONE;
|
||||
}
|
||||
|
||||
static struct notifier_block masq_dev_notifier = {
|
||||
.notifier_call = masq_device_event,
|
||||
};
|
||||
|
||||
static int masq_inet_event(struct notifier_block *this,
|
||||
unsigned long event, void *ptr)
|
||||
{
|
||||
struct inet6_ifaddr *ifa = ptr;
|
||||
|
||||
return masq_device_event(this, event, ifa->idev->dev);
|
||||
}
|
||||
|
||||
static struct notifier_block masq_inet_notifier = {
|
||||
.notifier_call = masq_inet_event,
|
||||
};
|
||||
|
||||
static struct xt_target masquerade_tg6_reg __read_mostly = {
|
||||
.name = "MASQUERADE",
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = masquerade_tg6_checkentry,
|
||||
.target = masquerade_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = 1 << NF_INET_POST_ROUTING,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init masquerade_tg6_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = xt_register_target(&masquerade_tg6_reg);
|
||||
if (err == 0) {
|
||||
register_netdevice_notifier(&masq_dev_notifier);
|
||||
register_inet6addr_notifier(&masq_inet_notifier);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
static void __exit masquerade_tg6_exit(void)
|
||||
{
|
||||
unregister_inet6addr_notifier(&masq_inet_notifier);
|
||||
unregister_netdevice_notifier(&masq_dev_notifier);
|
||||
xt_unregister_target(&masquerade_tg6_reg);
|
||||
}
|
||||
|
||||
module_init(masquerade_tg6_init);
|
||||
module_exit(masquerade_tg6_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_DESCRIPTION("Xtables: automatic address SNAT");
|
94
net/ipv6/netfilter/ip6t_NETMAP.c
Normal file
94
net/ipv6/netfilter/ip6t_NETMAP.c
Normal file
@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static unsigned int
|
||||
netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
union nf_inet_addr new_addr, netmask;
|
||||
unsigned int i;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++)
|
||||
netmask.ip6[i] = ~(range->min_addr.ip6[i] ^
|
||||
range->max_addr.ip6[i]);
|
||||
|
||||
if (par->hooknum == NF_INET_PRE_ROUTING ||
|
||||
par->hooknum == NF_INET_LOCAL_OUT)
|
||||
new_addr.in6 = ipv6_hdr(skb)->daddr;
|
||||
else
|
||||
new_addr.in6 = ipv6_hdr(skb)->saddr;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) {
|
||||
new_addr.ip6[i] &= ~netmask.ip6[i];
|
||||
new_addr.ip6[i] |= range->min_addr.ip6[i] &
|
||||
netmask.ip6[i];
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr = new_addr;
|
||||
newrange.max_addr = new_addr;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum));
|
||||
}
|
||||
|
||||
static int netmap_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (!(range->flags & NF_NAT_RANGE_MAP_IPS))
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target netmap_tg6_reg __read_mostly = {
|
||||
.name = "NETMAP",
|
||||
.family = NFPROTO_IPV6,
|
||||
.target = netmap_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.checkentry = netmap_tg6_checkentry,
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init netmap_tg6_init(void)
|
||||
{
|
||||
return xt_register_target(&netmap_tg6_reg);
|
||||
}
|
||||
|
||||
static void netmap_tg6_exit(void)
|
||||
{
|
||||
xt_unregister_target(&netmap_tg6_reg);
|
||||
}
|
||||
|
||||
module_init(netmap_tg6_init);
|
||||
module_exit(netmap_tg6_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
165
net/ipv6/netfilter/ip6t_NPT.c
Normal file
165
net/ipv6/netfilter/ip6t_NPT.c
Normal file
@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2012 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter_ipv6/ip6t_NPT.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
|
||||
static __sum16 csum16_complement(__sum16 a)
|
||||
{
|
||||
return (__force __sum16)(0xffff - (__force u16)a);
|
||||
}
|
||||
|
||||
static __sum16 csum16_add(__sum16 a, __sum16 b)
|
||||
{
|
||||
u16 sum;
|
||||
|
||||
sum = (__force u16)a + (__force u16)b;
|
||||
sum += (__force u16)a < (__force u16)b;
|
||||
return (__force __sum16)sum;
|
||||
}
|
||||
|
||||
static __sum16 csum16_sub(__sum16 a, __sum16 b)
|
||||
{
|
||||
return csum16_add(a, csum16_complement(b));
|
||||
}
|
||||
|
||||
static int ip6t_npt_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
struct ip6t_npt_tginfo *npt = par->targinfo;
|
||||
__sum16 src_sum = 0, dst_sum = 0;
|
||||
unsigned int i;
|
||||
|
||||
if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64)
|
||||
return -EINVAL;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) {
|
||||
src_sum = csum16_add(src_sum,
|
||||
(__force __sum16)npt->src_pfx.in6.s6_addr16[i]);
|
||||
dst_sum = csum16_add(dst_sum,
|
||||
(__force __sum16)npt->dst_pfx.in6.s6_addr16[i]);
|
||||
}
|
||||
|
||||
npt->adjustment = csum16_sub(src_sum, dst_sum);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt,
|
||||
struct in6_addr *addr)
|
||||
{
|
||||
unsigned int pfx_len;
|
||||
unsigned int i, idx;
|
||||
__be32 mask;
|
||||
__sum16 sum;
|
||||
|
||||
pfx_len = max(npt->src_pfx_len, npt->dst_pfx_len);
|
||||
for (i = 0; i < pfx_len; i += 32) {
|
||||
if (pfx_len - i >= 32)
|
||||
mask = 0;
|
||||
else
|
||||
mask = htonl(~((1 << (pfx_len - i)) - 1));
|
||||
|
||||
idx = i / 32;
|
||||
addr->s6_addr32[idx] &= mask;
|
||||
addr->s6_addr32[idx] |= npt->dst_pfx.in6.s6_addr32[idx];
|
||||
}
|
||||
|
||||
if (pfx_len <= 48)
|
||||
idx = 3;
|
||||
else {
|
||||
for (idx = 4; idx < ARRAY_SIZE(addr->s6_addr16); idx++) {
|
||||
if ((__force __sum16)addr->s6_addr16[idx] !=
|
||||
CSUM_MANGLED_0)
|
||||
break;
|
||||
}
|
||||
if (idx == ARRAY_SIZE(addr->s6_addr16))
|
||||
return false;
|
||||
}
|
||||
|
||||
sum = csum16_add((__force __sum16)addr->s6_addr16[idx],
|
||||
npt->adjustment);
|
||||
if (sum == CSUM_MANGLED_0)
|
||||
sum = 0;
|
||||
*(__force __sum16 *)&addr->s6_addr16[idx] = sum;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ip6t_snpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = par->targinfo;
|
||||
|
||||
if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->saddr)) {
|
||||
icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
|
||||
offsetof(struct ipv6hdr, saddr));
|
||||
return NF_DROP;
|
||||
}
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct ip6t_npt_tginfo *npt = par->targinfo;
|
||||
|
||||
if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->daddr)) {
|
||||
icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD,
|
||||
offsetof(struct ipv6hdr, daddr));
|
||||
return NF_DROP;
|
||||
}
|
||||
return XT_CONTINUE;
|
||||
}
|
||||
|
||||
static struct xt_target ip6t_npt_target_reg[] __read_mostly = {
|
||||
{
|
||||
.name = "SNPT",
|
||||
.target = ip6t_snpt_tg,
|
||||
.targetsize = sizeof(struct ip6t_npt_tginfo),
|
||||
.checkentry = ip6t_npt_checkentry,
|
||||
.family = NFPROTO_IPV6,
|
||||
.hooks = (1 << NF_INET_LOCAL_IN) |
|
||||
(1 << NF_INET_POST_ROUTING),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
{
|
||||
.name = "DNPT",
|
||||
.target = ip6t_dnpt_tg,
|
||||
.targetsize = sizeof(struct ip6t_npt_tginfo),
|
||||
.checkentry = ip6t_npt_checkentry,
|
||||
.family = NFPROTO_IPV6,
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init ip6t_npt_init(void)
|
||||
{
|
||||
return xt_register_targets(ip6t_npt_target_reg,
|
||||
ARRAY_SIZE(ip6t_npt_target_reg));
|
||||
}
|
||||
|
||||
static void __exit ip6t_npt_exit(void)
|
||||
{
|
||||
xt_unregister_targets(ip6t_npt_target_reg,
|
||||
ARRAY_SIZE(ip6t_npt_target_reg));
|
||||
}
|
||||
|
||||
module_init(ip6t_npt_init);
|
||||
module_exit(ip6t_npt_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_DESCRIPTION("IPv6-to-IPv6 Network Prefix Translation (RFC 6296)");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_ALIAS("ip6t_SNPT");
|
||||
MODULE_ALIAS("ip6t_DNPT");
|
98
net/ipv6/netfilter/ip6t_REDIRECT.c
Normal file
98
net/ipv6/netfilter/ip6t_REDIRECT.c
Normal file
@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter/x_tables.h>
|
||||
#include <net/addrconf.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
|
||||
static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT;
|
||||
|
||||
static unsigned int
|
||||
redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
struct nf_nat_range newrange;
|
||||
struct in6_addr newdst;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn *ct;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (par->hooknum == NF_INET_LOCAL_OUT)
|
||||
newdst = loopback_addr;
|
||||
else {
|
||||
struct inet6_dev *idev;
|
||||
struct inet6_ifaddr *ifa;
|
||||
bool addr = false;
|
||||
|
||||
rcu_read_lock();
|
||||
idev = __in6_dev_get(skb->dev);
|
||||
if (idev != NULL) {
|
||||
list_for_each_entry(ifa, &idev->addr_list, if_list) {
|
||||
newdst = ifa->addr;
|
||||
addr = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
rcu_read_unlock();
|
||||
|
||||
if (!addr)
|
||||
return NF_DROP;
|
||||
}
|
||||
|
||||
newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS;
|
||||
newrange.min_addr.in6 = newdst;
|
||||
newrange.max_addr.in6 = newdst;
|
||||
newrange.min_proto = range->min_proto;
|
||||
newrange.max_proto = range->max_proto;
|
||||
|
||||
return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST);
|
||||
}
|
||||
|
||||
static int redirect_tg6_checkentry(const struct xt_tgchk_param *par)
|
||||
{
|
||||
const struct nf_nat_range *range = par->targinfo;
|
||||
|
||||
if (range->flags & NF_NAT_RANGE_MAP_IPS)
|
||||
return -EINVAL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct xt_target redirect_tg6_reg __read_mostly = {
|
||||
.name = "REDIRECT",
|
||||
.family = NFPROTO_IPV6,
|
||||
.checkentry = redirect_tg6_checkentry,
|
||||
.target = redirect_tg6,
|
||||
.targetsize = sizeof(struct nf_nat_range),
|
||||
.table = "nat",
|
||||
.hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT),
|
||||
.me = THIS_MODULE,
|
||||
};
|
||||
|
||||
static int __init redirect_tg6_init(void)
|
||||
{
|
||||
return xt_register_target(&redirect_tg6_reg);
|
||||
}
|
||||
|
||||
static void __exit redirect_tg6_exit(void)
|
||||
{
|
||||
xt_unregister_target(&redirect_tg6_reg);
|
||||
}
|
||||
|
||||
module_init(redirect_tg6_init);
|
||||
module_exit(redirect_tg6_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
|
||||
MODULE_DESCRIPTION("Xtables: Connection redirection to localhost");
|
321
net/ipv6/netfilter/ip6table_nat.c
Normal file
321
net/ipv6/netfilter/ip6table_nat.c
Normal file
@ -0,0 +1,321 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 NAT code. Development of IPv6 NAT
|
||||
* funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <linux/netfilter_ipv6/ip6_tables.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_l3proto.h>
|
||||
|
||||
static const struct xt_table nf_nat_ipv6_table = {
|
||||
.name = "nat",
|
||||
.valid_hooks = (1 << NF_INET_PRE_ROUTING) |
|
||||
(1 << NF_INET_POST_ROUTING) |
|
||||
(1 << NF_INET_LOCAL_OUT) |
|
||||
(1 << NF_INET_LOCAL_IN),
|
||||
.me = THIS_MODULE,
|
||||
.af = NFPROTO_IPV6,
|
||||
};
|
||||
|
||||
static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum)
|
||||
{
|
||||
/* Force range to this IP; let proto decide mapping for
|
||||
* per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED).
|
||||
*/
|
||||
struct nf_nat_range range;
|
||||
|
||||
range.flags = 0;
|
||||
pr_debug("Allocating NULL binding for %p (%pI6)\n", ct,
|
||||
HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ?
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6 :
|
||||
&ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6);
|
||||
|
||||
return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum));
|
||||
}
|
||||
|
||||
static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
struct nf_conn *ct)
|
||||
{
|
||||
struct net *net = nf_ct_net(ct);
|
||||
unsigned int ret;
|
||||
|
||||
ret = ip6t_do_table(skb, hooknum, in, out, net->ipv6.ip6table_nat);
|
||||
if (ret == NF_ACCEPT) {
|
||||
if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum)))
|
||||
ret = alloc_null_binding(ct, hooknum);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_ipv6_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conn_nat *nat;
|
||||
enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum);
|
||||
__be16 frag_off;
|
||||
int hdrlen;
|
||||
u8 nexthdr;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
/* Can't track? It's not due to stress, or conntrack would
|
||||
* have dropped it. Hence it's the user's responsibilty to
|
||||
* packet filter it out, or implement conntrack/NAT for that
|
||||
* protocol. 8) --RR
|
||||
*/
|
||||
if (!ct)
|
||||
return NF_ACCEPT;
|
||||
|
||||
/* Don't try to NAT if this packet is not conntracked */
|
||||
if (nf_ct_is_untracked(ct))
|
||||
return NF_ACCEPT;
|
||||
|
||||
nat = nfct_nat(ct);
|
||||
if (!nat) {
|
||||
/* NAT module was loaded late. */
|
||||
if (nf_ct_is_confirmed(ct))
|
||||
return NF_ACCEPT;
|
||||
nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC);
|
||||
if (nat == NULL) {
|
||||
pr_debug("failed to add NAT extension\n");
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ctinfo) {
|
||||
case IP_CT_RELATED:
|
||||
case IP_CT_RELATED_REPLY:
|
||||
nexthdr = ipv6_hdr(skb)->nexthdr;
|
||||
hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr),
|
||||
&nexthdr, &frag_off);
|
||||
|
||||
if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) {
|
||||
if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo,
|
||||
hooknum, hdrlen))
|
||||
return NF_DROP;
|
||||
else
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
/* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */
|
||||
case IP_CT_NEW:
|
||||
/* Seen it before? This can happen for loopback, retrans,
|
||||
* or local packets.
|
||||
*/
|
||||
if (!nf_nat_initialized(ct, maniptype)) {
|
||||
unsigned int ret;
|
||||
|
||||
ret = nf_nat_rule_find(skb, hooknum, in, out, ct);
|
||||
if (ret != NF_ACCEPT)
|
||||
return ret;
|
||||
} else
|
||||
pr_debug("Already setup manip %s for ct %p\n",
|
||||
maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST",
|
||||
ct);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* ESTABLISHED */
|
||||
NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED ||
|
||||
ctinfo == IP_CT_ESTABLISHED_REPLY);
|
||||
}
|
||||
|
||||
return nf_nat_packet(ct, ctinfo, hooknum, skb);
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_ipv6_in(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
unsigned int ret;
|
||||
struct in6_addr daddr = ipv6_hdr(skb)->daddr;
|
||||
|
||||
ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn);
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr))
|
||||
skb_dst_drop(skb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_ipv6_out(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
#ifdef CONFIG_XFRM
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
#endif
|
||||
unsigned int ret;
|
||||
|
||||
/* root is playing with raw sockets. */
|
||||
if (skb->len < sizeof(struct ipv6hdr))
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn);
|
||||
#ifdef CONFIG_XFRM
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
|
||||
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
|
||||
if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3) ||
|
||||
(ct->tuplehash[dir].tuple.src.u.all !=
|
||||
ct->tuplehash[!dir].tuple.dst.u.all))
|
||||
if (nf_xfrm_me_harder(skb, AF_INET6) < 0)
|
||||
ret = NF_DROP;
|
||||
}
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
nf_nat_ipv6_local_fn(unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
const struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned int ret;
|
||||
|
||||
/* root is playing with raw sockets. */
|
||||
if (skb->len < sizeof(struct ipv6hdr))
|
||||
return NF_ACCEPT;
|
||||
|
||||
ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn);
|
||||
if (ret != NF_DROP && ret != NF_STOLEN &&
|
||||
(ct = nf_ct_get(skb, &ctinfo)) != NULL) {
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
|
||||
if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3,
|
||||
&ct->tuplehash[!dir].tuple.src.u3)) {
|
||||
if (ip6_route_me_harder(skb))
|
||||
ret = NF_DROP;
|
||||
}
|
||||
#ifdef CONFIG_XFRM
|
||||
else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) &&
|
||||
ct->tuplehash[dir].tuple.dst.u.all !=
|
||||
ct->tuplehash[!dir].tuple.src.u.all)
|
||||
if (nf_xfrm_me_harder(skb, AF_INET6))
|
||||
ret = NF_DROP;
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = {
|
||||
/* Before packet filtering, change destination */
|
||||
{
|
||||
.hook = nf_nat_ipv6_in,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_PRE_ROUTING,
|
||||
.priority = NF_IP6_PRI_NAT_DST,
|
||||
},
|
||||
/* After packet filtering, change source */
|
||||
{
|
||||
.hook = nf_nat_ipv6_out,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_POST_ROUTING,
|
||||
.priority = NF_IP6_PRI_NAT_SRC,
|
||||
},
|
||||
/* Before packet filtering, change destination */
|
||||
{
|
||||
.hook = nf_nat_ipv6_local_fn,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_OUT,
|
||||
.priority = NF_IP6_PRI_NAT_DST,
|
||||
},
|
||||
/* After packet filtering, change source */
|
||||
{
|
||||
.hook = nf_nat_ipv6_fn,
|
||||
.owner = THIS_MODULE,
|
||||
.pf = NFPROTO_IPV6,
|
||||
.hooknum = NF_INET_LOCAL_IN,
|
||||
.priority = NF_IP6_PRI_NAT_SRC,
|
||||
},
|
||||
};
|
||||
|
||||
static int __net_init ip6table_nat_net_init(struct net *net)
|
||||
{
|
||||
struct ip6t_replace *repl;
|
||||
|
||||
repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table);
|
||||
if (repl == NULL)
|
||||
return -ENOMEM;
|
||||
net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
|
||||
kfree(repl);
|
||||
if (IS_ERR(net->ipv6.ip6table_nat))
|
||||
return PTR_ERR(net->ipv6.ip6table_nat);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __net_exit ip6table_nat_net_exit(struct net *net)
|
||||
{
|
||||
ip6t_unregister_table(net, net->ipv6.ip6table_nat);
|
||||
}
|
||||
|
||||
static struct pernet_operations ip6table_nat_net_ops = {
|
||||
.init = ip6table_nat_net_init,
|
||||
.exit = ip6table_nat_net_exit,
|
||||
};
|
||||
|
||||
static int __init ip6table_nat_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = register_pernet_subsys(&ip6table_nat_net_ops);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
|
||||
err = nf_register_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
return 0;
|
||||
|
||||
err2:
|
||||
unregister_pernet_subsys(&ip6table_nat_net_ops);
|
||||
err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit ip6table_nat_exit(void)
|
||||
{
|
||||
nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops));
|
||||
unregister_pernet_subsys(&ip6table_nat_net_ops);
|
||||
}
|
||||
|
||||
module_init(ip6table_nat_init);
|
||||
module_exit(ip6table_nat_exit);
|
||||
|
||||
MODULE_LICENSE("GPL");
|
@ -28,6 +28,7 @@
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack_zones.h>
|
||||
#include <net/netfilter/ipv6/nf_conntrack_ipv6.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
|
||||
#include <net/netfilter/nf_log.h>
|
||||
|
||||
@ -64,82 +65,31 @@ static int ipv6_print_tuple(struct seq_file *s,
|
||||
tuple->src.u3.ip6, tuple->dst.u3.ip6);
|
||||
}
|
||||
|
||||
/*
|
||||
* Based on ipv6_skip_exthdr() in net/ipv6/exthdr.c
|
||||
*
|
||||
* This function parses (probably truncated) exthdr set "hdr"
|
||||
* of length "len". "nexthdrp" initially points to some place,
|
||||
* where type of the first header can be found.
|
||||
*
|
||||
* It skips all well-known exthdrs, and returns pointer to the start
|
||||
* of unparsable area i.e. the first header with unknown type.
|
||||
* if success, *nexthdr is updated by type/protocol of this header.
|
||||
*
|
||||
* NOTES: - it may return pointer pointing beyond end of packet,
|
||||
* if the last recognized header is truncated in the middle.
|
||||
* - if packet is truncated, so that all parsed headers are skipped,
|
||||
* it returns -1.
|
||||
* - if packet is fragmented, return pointer of the fragment header.
|
||||
* - ESP is unparsable for now and considered like
|
||||
* normal payload protocol.
|
||||
* - Note also special handling of AUTH header. Thanks to IPsec wizards.
|
||||
*/
|
||||
|
||||
static int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start,
|
||||
u8 *nexthdrp, int len)
|
||||
{
|
||||
u8 nexthdr = *nexthdrp;
|
||||
|
||||
while (ipv6_ext_hdr(nexthdr)) {
|
||||
struct ipv6_opt_hdr hdr;
|
||||
int hdrlen;
|
||||
|
||||
if (len < (int)sizeof(struct ipv6_opt_hdr))
|
||||
return -1;
|
||||
if (nexthdr == NEXTHDR_NONE)
|
||||
break;
|
||||
if (nexthdr == NEXTHDR_FRAGMENT)
|
||||
break;
|
||||
if (skb_copy_bits(skb, start, &hdr, sizeof(hdr)))
|
||||
BUG();
|
||||
if (nexthdr == NEXTHDR_AUTH)
|
||||
hdrlen = (hdr.hdrlen+2)<<2;
|
||||
else
|
||||
hdrlen = ipv6_optlen(&hdr);
|
||||
|
||||
nexthdr = hdr.nexthdr;
|
||||
len -= hdrlen;
|
||||
start += hdrlen;
|
||||
}
|
||||
|
||||
*nexthdrp = nexthdr;
|
||||
return start;
|
||||
}
|
||||
|
||||
static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
|
||||
unsigned int *dataoff, u_int8_t *protonum)
|
||||
{
|
||||
unsigned int extoff = nhoff + sizeof(struct ipv6hdr);
|
||||
unsigned char pnum;
|
||||
__be16 frag_off;
|
||||
int protoff;
|
||||
u8 nexthdr;
|
||||
|
||||
if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr),
|
||||
&pnum, sizeof(pnum)) != 0) {
|
||||
&nexthdr, sizeof(nexthdr)) != 0) {
|
||||
pr_debug("ip6_conntrack_core: can't get nexthdr\n");
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff);
|
||||
protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off);
|
||||
/*
|
||||
* (protoff == skb->len) mean that the packet doesn't have no data
|
||||
* except of IPv6 & ext headers. but it's tracked anyway. - YK
|
||||
*/
|
||||
if ((protoff < 0) || (protoff > skb->len)) {
|
||||
if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
|
||||
pr_debug("ip6_conntrack_core: can't find proto in pkt\n");
|
||||
return -NF_ACCEPT;
|
||||
}
|
||||
|
||||
*dataoff = protoff;
|
||||
*protonum = pnum;
|
||||
*protonum = nexthdr;
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
@ -153,10 +103,10 @@ static unsigned int ipv6_helper(unsigned int hooknum,
|
||||
const struct nf_conn_help *help;
|
||||
const struct nf_conntrack_helper *helper;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned int ret, protoff;
|
||||
unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data;
|
||||
unsigned char pnum = ipv6_hdr(skb)->nexthdr;
|
||||
|
||||
unsigned int ret;
|
||||
__be16 frag_off;
|
||||
int protoff;
|
||||
u8 nexthdr;
|
||||
|
||||
/* This is where we call the helper: as the packet goes out. */
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
@ -171,9 +121,10 @@ static unsigned int ipv6_helper(unsigned int hooknum,
|
||||
if (!helper)
|
||||
return NF_ACCEPT;
|
||||
|
||||
protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum,
|
||||
skb->len - extoff);
|
||||
if (protoff > skb->len || pnum == NEXTHDR_FRAGMENT) {
|
||||
nexthdr = ipv6_hdr(skb)->nexthdr;
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr,
|
||||
&frag_off);
|
||||
if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
|
||||
pr_debug("proto header not found\n");
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
@ -192,6 +143,36 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
unsigned char pnum = ipv6_hdr(skb)->nexthdr;
|
||||
int protoff;
|
||||
__be16 frag_off;
|
||||
|
||||
ct = nf_ct_get(skb, &ctinfo);
|
||||
if (!ct || ctinfo == IP_CT_RELATED_REPLY)
|
||||
goto out;
|
||||
|
||||
protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum,
|
||||
&frag_off);
|
||||
if (protoff < 0 || (frag_off & htons(~0x7)) != 0) {
|
||||
pr_debug("proto header not found\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* adjust seqs for loopback traffic only in outgoing direction */
|
||||
if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) &&
|
||||
!nf_is_loopback_packet(skb)) {
|
||||
typeof(nf_nat_seq_adjust_hook) seq_adjust;
|
||||
|
||||
seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook);
|
||||
if (!seq_adjust ||
|
||||
!seq_adjust(skb, ct, ctinfo, protoff)) {
|
||||
NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop);
|
||||
return NF_DROP;
|
||||
}
|
||||
}
|
||||
out:
|
||||
/* We've seen it coming out the other side: confirm it */
|
||||
return nf_conntrack_confirm(skb);
|
||||
}
|
||||
@ -199,9 +180,14 @@ static unsigned int ipv6_confirm(unsigned int hooknum,
|
||||
static unsigned int __ipv6_conntrack_in(struct net *net,
|
||||
unsigned int hooknum,
|
||||
struct sk_buff *skb,
|
||||
const struct net_device *in,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct sk_buff *reasm = skb->nfct_reasm;
|
||||
const struct nf_conn_help *help;
|
||||
struct nf_conn *ct;
|
||||
enum ip_conntrack_info ctinfo;
|
||||
|
||||
/* This packet is fragmented and has reassembled packet. */
|
||||
if (reasm) {
|
||||
@ -213,6 +199,25 @@ static unsigned int __ipv6_conntrack_in(struct net *net,
|
||||
if (ret != NF_ACCEPT)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Conntrack helpers need the entire reassembled packet in the
|
||||
* POST_ROUTING hook. In case of unconfirmed connections NAT
|
||||
* might reassign a helper, so the entire packet is also
|
||||
* required.
|
||||
*/
|
||||
ct = nf_ct_get(reasm, &ctinfo);
|
||||
if (ct != NULL && !nf_ct_is_untracked(ct)) {
|
||||
help = nfct_help(ct);
|
||||
if ((help && help->helper) || !nf_ct_is_confirmed(ct)) {
|
||||
nf_conntrack_get_reasm(skb);
|
||||
NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm,
|
||||
(struct net_device *)in,
|
||||
(struct net_device *)out,
|
||||
okfn, NF_IP6_PRI_CONNTRACK + 1);
|
||||
return NF_DROP_ERR(-ECANCELED);
|
||||
}
|
||||
}
|
||||
|
||||
nf_conntrack_get(reasm->nfct);
|
||||
skb->nfct = reasm->nfct;
|
||||
skb->nfctinfo = reasm->nfctinfo;
|
||||
@ -228,7 +233,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum,
|
||||
const struct net_device *out,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
return __ipv6_conntrack_in(dev_net(in), hooknum, skb, okfn);
|
||||
return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn);
|
||||
}
|
||||
|
||||
static unsigned int ipv6_conntrack_local(unsigned int hooknum,
|
||||
@ -242,7 +247,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum,
|
||||
net_notice_ratelimited("ipv6_conntrack_local: packet too short\n");
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn);
|
||||
return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn);
|
||||
}
|
||||
|
||||
static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = {
|
||||
|
@ -190,6 +190,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
|
||||
const struct frag_hdr *fhdr, int nhoff)
|
||||
{
|
||||
struct sk_buff *prev, *next;
|
||||
unsigned int payload_len;
|
||||
int offset, end;
|
||||
|
||||
if (fq->q.last_in & INET_FRAG_COMPLETE) {
|
||||
@ -197,8 +198,10 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb,
|
||||
goto err;
|
||||
}
|
||||
|
||||
payload_len = ntohs(ipv6_hdr(skb)->payload_len);
|
||||
|
||||
offset = ntohs(fhdr->frag_off) & ~0x7;
|
||||
end = offset + (ntohs(ipv6_hdr(skb)->payload_len) -
|
||||
end = offset + (payload_len -
|
||||
((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1)));
|
||||
|
||||
if ((unsigned int)end > IPV6_MAXPLEN) {
|
||||
@ -307,6 +310,8 @@ found:
|
||||
skb->dev = NULL;
|
||||
fq->q.stamp = skb->tstamp;
|
||||
fq->q.meat += skb->len;
|
||||
if (payload_len > fq->q.max_size)
|
||||
fq->q.max_size = payload_len;
|
||||
atomic_add(skb->truesize, &nf_init_frags.mem);
|
||||
|
||||
/* The first fragment.
|
||||
@ -412,10 +417,12 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev)
|
||||
}
|
||||
atomic_sub(head->truesize, &nf_init_frags.mem);
|
||||
|
||||
head->local_df = 1;
|
||||
head->next = NULL;
|
||||
head->dev = dev;
|
||||
head->tstamp = fq->q.stamp;
|
||||
ipv6_hdr(head)->payload_len = htons(payload_len);
|
||||
IP6CB(head)->frag_max_size = sizeof(struct ipv6hdr) + fq->q.max_size;
|
||||
|
||||
/* Yes, and fold redundant checksum back. 8) */
|
||||
if (head->ip_summed == CHECKSUM_COMPLETE)
|
||||
@ -592,6 +599,7 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
|
||||
int (*okfn)(struct sk_buff *))
|
||||
{
|
||||
struct sk_buff *s, *s2;
|
||||
unsigned int ret = 0;
|
||||
|
||||
for (s = NFCT_FRAG6_CB(skb)->orig; s;) {
|
||||
nf_conntrack_put_reasm(s->nfct_reasm);
|
||||
@ -601,8 +609,13 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb,
|
||||
s2 = s->next;
|
||||
s->next = NULL;
|
||||
|
||||
NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, in, out, okfn,
|
||||
NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
|
||||
if (ret != -ECANCELED)
|
||||
ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s,
|
||||
in, out, okfn,
|
||||
NF_IP6_PRI_CONNTRACK_DEFRAG + 1);
|
||||
else
|
||||
kfree_skb(s);
|
||||
|
||||
s = s2;
|
||||
}
|
||||
nf_conntrack_put_reasm(skb);
|
||||
|
287
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
Normal file
287
net/ipv6/netfilter/nf_nat_l3proto_ipv6.c
Normal file
@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick McHardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Development of IPv6 NAT funded by Astaro.
|
||||
*/
|
||||
#include <linux/types.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/skbuff.h>
|
||||
#include <linux/ipv6.h>
|
||||
#include <linux/netfilter.h>
|
||||
#include <linux/netfilter_ipv6.h>
|
||||
#include <net/secure_seq.h>
|
||||
#include <net/checksum.h>
|
||||
#include <net/ip6_route.h>
|
||||
#include <net/ipv6.h>
|
||||
|
||||
#include <net/netfilter/nf_conntrack_core.h>
|
||||
#include <net/netfilter/nf_conntrack.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_l3proto.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
|
||||
static const struct nf_nat_l3proto nf_nat_l3proto_ipv6;
|
||||
|
||||
#ifdef CONFIG_XFRM
|
||||
static void nf_nat_ipv6_decode_session(struct sk_buff *skb,
|
||||
const struct nf_conn *ct,
|
||||
enum ip_conntrack_dir dir,
|
||||
unsigned long statusbit,
|
||||
struct flowi *fl)
|
||||
{
|
||||
const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple;
|
||||
struct flowi6 *fl6 = &fl->u.ip6;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl6->daddr = t->dst.u3.in6;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl6->fl6_dport = t->dst.u.all;
|
||||
}
|
||||
|
||||
statusbit ^= IPS_NAT_MASK;
|
||||
|
||||
if (ct->status & statusbit) {
|
||||
fl6->saddr = t->src.u3.in6;
|
||||
if (t->dst.protonum == IPPROTO_TCP ||
|
||||
t->dst.protonum == IPPROTO_UDP ||
|
||||
t->dst.protonum == IPPROTO_UDPLITE ||
|
||||
t->dst.protonum == IPPROTO_DCCP ||
|
||||
t->dst.protonum == IPPROTO_SCTP)
|
||||
fl6->fl6_sport = t->src.u.all;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t,
|
||||
const struct nf_nat_range *range)
|
||||
{
|
||||
return ipv6_addr_cmp(&t->src.u3.in6, &range->min_addr.in6) >= 0 &&
|
||||
ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0;
|
||||
}
|
||||
|
||||
static u32 nf_nat_ipv6_secure_port(const struct nf_conntrack_tuple *t,
|
||||
__be16 dport)
|
||||
{
|
||||
return secure_ipv6_port_ephemeral(t->src.u3.ip6, t->dst.u3.ip6, dport);
|
||||
}
|
||||
|
||||
static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb,
|
||||
unsigned int iphdroff,
|
||||
const struct nf_nat_l4proto *l4proto,
|
||||
const struct nf_conntrack_tuple *target,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
struct ipv6hdr *ipv6h;
|
||||
__be16 frag_off;
|
||||
int hdroff;
|
||||
u8 nexthdr;
|
||||
|
||||
if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h)))
|
||||
return false;
|
||||
|
||||
ipv6h = (void *)skb->data + iphdroff;
|
||||
nexthdr = ipv6h->nexthdr;
|
||||
hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h),
|
||||
&nexthdr, &frag_off);
|
||||
if (hdroff < 0)
|
||||
goto manip_addr;
|
||||
|
||||
if ((frag_off & htons(~0x7)) == 0 &&
|
||||
!l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv6, iphdroff, hdroff,
|
||||
target, maniptype))
|
||||
return false;
|
||||
manip_addr:
|
||||
if (maniptype == NF_NAT_MANIP_SRC)
|
||||
ipv6h->saddr = target->src.u3.in6;
|
||||
else
|
||||
ipv6h->daddr = target->dst.u3.in6;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nf_nat_ipv6_csum_update(struct sk_buff *skb,
|
||||
unsigned int iphdroff, __sum16 *check,
|
||||
const struct nf_conntrack_tuple *t,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff);
|
||||
const struct in6_addr *oldip, *newip;
|
||||
|
||||
if (maniptype == NF_NAT_MANIP_SRC) {
|
||||
oldip = &ipv6h->saddr;
|
||||
newip = &t->src.u3.in6;
|
||||
} else {
|
||||
oldip = &ipv6h->daddr;
|
||||
newip = &t->dst.u3.in6;
|
||||
}
|
||||
inet_proto_csum_replace16(check, skb, oldip->s6_addr32,
|
||||
newip->s6_addr32, 1);
|
||||
}
|
||||
|
||||
static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb,
|
||||
u8 proto, void *data, __sum16 *check,
|
||||
int datalen, int oldlen)
|
||||
{
|
||||
const struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
|
||||
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
if (!(rt->rt6i_flags & RTF_LOCAL) &&
|
||||
(!skb->dev || skb->dev->features & NETIF_F_V6_CSUM)) {
|
||||
skb->ip_summed = CHECKSUM_PARTIAL;
|
||||
skb->csum_start = skb_headroom(skb) +
|
||||
skb_network_offset(skb) +
|
||||
(data - (void *)skb->data);
|
||||
skb->csum_offset = (void *)check - data;
|
||||
*check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
|
||||
datalen, proto, 0);
|
||||
} else {
|
||||
*check = 0;
|
||||
*check = csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
|
||||
datalen, proto,
|
||||
csum_partial(data, datalen,
|
||||
0));
|
||||
if (proto == IPPROTO_UDP && !*check)
|
||||
*check = CSUM_MANGLED_0;
|
||||
}
|
||||
} else
|
||||
inet_proto_csum_replace2(check, skb,
|
||||
htons(oldlen), htons(datalen), 1);
|
||||
}
|
||||
|
||||
static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[],
|
||||
struct nf_nat_range *range)
|
||||
{
|
||||
if (tb[CTA_NAT_V6_MINIP]) {
|
||||
nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP],
|
||||
sizeof(struct in6_addr));
|
||||
range->flags |= NF_NAT_RANGE_MAP_IPS;
|
||||
}
|
||||
|
||||
if (tb[CTA_NAT_V6_MAXIP])
|
||||
nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP],
|
||||
sizeof(struct in6_addr));
|
||||
else
|
||||
range->max_addr = range->min_addr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = {
|
||||
.l3proto = NFPROTO_IPV6,
|
||||
.secure_port = nf_nat_ipv6_secure_port,
|
||||
.in_range = nf_nat_ipv6_in_range,
|
||||
.manip_pkt = nf_nat_ipv6_manip_pkt,
|
||||
.csum_update = nf_nat_ipv6_csum_update,
|
||||
.csum_recalc = nf_nat_ipv6_csum_recalc,
|
||||
.nlattr_to_range = nf_nat_ipv6_nlattr_to_range,
|
||||
#ifdef CONFIG_XFRM
|
||||
.decode_session = nf_nat_ipv6_decode_session,
|
||||
#endif
|
||||
};
|
||||
|
||||
int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int hooknum,
|
||||
unsigned int hdrlen)
|
||||
{
|
||||
struct {
|
||||
struct icmp6hdr icmp6;
|
||||
struct ipv6hdr ip6;
|
||||
} *inside;
|
||||
enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo);
|
||||
enum nf_nat_manip_type manip = HOOK2MANIP(hooknum);
|
||||
const struct nf_nat_l4proto *l4proto;
|
||||
struct nf_conntrack_tuple target;
|
||||
unsigned long statusbit;
|
||||
|
||||
NF_CT_ASSERT(ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY);
|
||||
|
||||
if (!skb_make_writable(skb, hdrlen + sizeof(*inside)))
|
||||
return 0;
|
||||
if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6))
|
||||
return 0;
|
||||
|
||||
inside = (void *)skb->data + hdrlen;
|
||||
if (inside->icmp6.icmp6_type == NDISC_REDIRECT) {
|
||||
if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK)
|
||||
return 0;
|
||||
if (ct->status & IPS_NAT_MASK)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (manip == NF_NAT_MANIP_SRC)
|
||||
statusbit = IPS_SRC_NAT;
|
||||
else
|
||||
statusbit = IPS_DST_NAT;
|
||||
|
||||
/* Invert if this is reply direction */
|
||||
if (dir == IP_CT_DIR_REPLY)
|
||||
statusbit ^= IPS_NAT_MASK;
|
||||
|
||||
if (!(ct->status & statusbit))
|
||||
return 1;
|
||||
|
||||
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, inside->ip6.nexthdr);
|
||||
if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6),
|
||||
l4proto, &ct->tuplehash[!dir].tuple, !manip))
|
||||
return 0;
|
||||
|
||||
if (skb->ip_summed != CHECKSUM_PARTIAL) {
|
||||
struct ipv6hdr *ipv6h = ipv6_hdr(skb);
|
||||
inside = (void *)skb->data + hdrlen;
|
||||
inside->icmp6.icmp6_cksum = 0;
|
||||
inside->icmp6.icmp6_cksum =
|
||||
csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr,
|
||||
skb->len - hdrlen, IPPROTO_ICMPV6,
|
||||
csum_partial(&inside->icmp6,
|
||||
skb->len - hdrlen, 0));
|
||||
}
|
||||
|
||||
nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
|
||||
l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, IPPROTO_ICMPV6);
|
||||
if (!nf_nat_ipv6_manip_pkt(skb, 0, l4proto, &target, manip))
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation);
|
||||
|
||||
static int __init nf_nat_l3proto_ipv6_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6);
|
||||
if (err < 0)
|
||||
goto err1;
|
||||
err = nf_nat_l3proto_register(&nf_nat_l3proto_ipv6);
|
||||
if (err < 0)
|
||||
goto err2;
|
||||
return err;
|
||||
|
||||
err2:
|
||||
nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6);
|
||||
err1:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit nf_nat_l3proto_ipv6_exit(void)
|
||||
{
|
||||
nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv6);
|
||||
nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6);
|
||||
}
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("nf-nat-" __stringify(AF_INET6));
|
||||
|
||||
module_init(nf_nat_l3proto_ipv6_init);
|
||||
module_exit(nf_nat_l3proto_ipv6_exit);
|
90
net/ipv6/netfilter/nf_nat_proto_icmpv6.c
Normal file
90
net/ipv6/netfilter/nf_nat_proto_icmpv6.c
Normal file
@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright (c) 2011 Patrick Mchardy <kaber@trash.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Based on Rusty Russell's IPv4 ICMP NAT code. Development of IPv6
|
||||
* NAT funded by Astaro.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/icmpv6.h>
|
||||
|
||||
#include <linux/netfilter.h>
|
||||
#include <net/netfilter/nf_nat.h>
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_l3proto.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
|
||||
static bool
|
||||
icmpv6_in_range(const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const union nf_conntrack_man_proto *min,
|
||||
const union nf_conntrack_man_proto *max)
|
||||
{
|
||||
return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) &&
|
||||
ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id);
|
||||
}
|
||||
|
||||
static void
|
||||
icmpv6_unique_tuple(const struct nf_nat_l3proto *l3proto,
|
||||
struct nf_conntrack_tuple *tuple,
|
||||
const struct nf_nat_range *range,
|
||||
enum nf_nat_manip_type maniptype,
|
||||
const struct nf_conn *ct)
|
||||
{
|
||||
static u16 id;
|
||||
unsigned int range_size;
|
||||
unsigned int i;
|
||||
|
||||
range_size = ntohs(range->max_proto.icmp.id) -
|
||||
ntohs(range->min_proto.icmp.id) + 1;
|
||||
|
||||
if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED))
|
||||
range_size = 0xffff;
|
||||
|
||||
for (i = 0; ; ++id) {
|
||||
tuple->src.u.icmp.id = htons(ntohs(range->min_proto.icmp.id) +
|
||||
(id % range_size));
|
||||
if (++i == range_size || !nf_nat_used_tuple(tuple, ct))
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static bool
|
||||
icmpv6_manip_pkt(struct sk_buff *skb,
|
||||
const struct nf_nat_l3proto *l3proto,
|
||||
unsigned int iphdroff, unsigned int hdroff,
|
||||
const struct nf_conntrack_tuple *tuple,
|
||||
enum nf_nat_manip_type maniptype)
|
||||
{
|
||||
struct icmp6hdr *hdr;
|
||||
|
||||
if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
|
||||
return false;
|
||||
|
||||
hdr = (struct icmp6hdr *)(skb->data + hdroff);
|
||||
l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum,
|
||||
tuple, maniptype);
|
||||
if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST ||
|
||||
hdr->icmp6_code == ICMPV6_ECHO_REPLY) {
|
||||
inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
|
||||
hdr->icmp6_identifier,
|
||||
tuple->src.u.icmp.id, 0);
|
||||
hdr->icmp6_identifier = tuple->src.u.icmp.id;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = {
|
||||
.l4proto = IPPROTO_ICMPV6,
|
||||
.manip_pkt = icmpv6_manip_pkt,
|
||||
.in_range = icmpv6_in_range,
|
||||
.unique_tuple = icmpv6_unique_tuple,
|
||||
#if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE)
|
||||
.nlattr_to_range = nf_nat_l4proto_nlattr_to_range,
|
||||
#endif
|
||||
};
|
@ -356,6 +356,55 @@ config NETFILTER_NETLINK_QUEUE_CT
|
||||
If this option is enabled, NFQUEUE can include Connection Tracking
|
||||
information together with the packet is the enqueued via NFNETLINK.
|
||||
|
||||
config NF_NAT
|
||||
tristate
|
||||
|
||||
config NF_NAT_NEEDED
|
||||
bool
|
||||
depends on NF_NAT
|
||||
default y
|
||||
|
||||
config NF_NAT_PROTO_DCCP
|
||||
tristate
|
||||
depends on NF_NAT && NF_CT_PROTO_DCCP
|
||||
default NF_NAT && NF_CT_PROTO_DCCP
|
||||
|
||||
config NF_NAT_PROTO_UDPLITE
|
||||
tristate
|
||||
depends on NF_NAT && NF_CT_PROTO_UDPLITE
|
||||
default NF_NAT && NF_CT_PROTO_UDPLITE
|
||||
|
||||
config NF_NAT_PROTO_SCTP
|
||||
tristate
|
||||
default NF_NAT && NF_CT_PROTO_SCTP
|
||||
depends on NF_NAT && NF_CT_PROTO_SCTP
|
||||
select LIBCRC32C
|
||||
|
||||
config NF_NAT_AMANDA
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_AMANDA
|
||||
|
||||
config NF_NAT_FTP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_FTP
|
||||
|
||||
config NF_NAT_IRC
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_IRC
|
||||
|
||||
config NF_NAT_SIP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_SIP
|
||||
|
||||
config NF_NAT_TFTP
|
||||
tristate
|
||||
depends on NF_CONNTRACK && NF_NAT
|
||||
default NF_NAT && NF_CONNTRACK_TFTP
|
||||
|
||||
endif # NF_CONNTRACK
|
||||
|
||||
# transparent proxy support
|
||||
@ -621,19 +670,6 @@ config NETFILTER_XT_TARGET_NFQUEUE
|
||||
|
||||
To compile it as a module, choose M here. If unsure, say N.
|
||||
|
||||
config NETFILTER_XT_TARGET_NOTRACK
|
||||
tristate '"NOTRACK" target support'
|
||||
depends on IP_NF_RAW || IP6_NF_RAW
|
||||
depends on NF_CONNTRACK
|
||||
help
|
||||
The NOTRACK target allows a select rule to specify
|
||||
which packets *not* to enter the conntrack/NAT
|
||||
subsystem with all the consequences (no ICMP error tracking,
|
||||
no protocol helpers for the selected packets).
|
||||
|
||||
If you want to compile it as a module, say M here and read
|
||||
<file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
|
||||
|
||||
config NETFILTER_XT_TARGET_RATEEST
|
||||
tristate '"RATEEST" target support'
|
||||
depends on NETFILTER_ADVANCED
|
||||
|
@ -43,6 +43,24 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
|
||||
obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
|
||||
obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
|
||||
|
||||
nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \
|
||||
nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o
|
||||
|
||||
obj-$(CONFIG_NF_NAT) += nf_nat.o
|
||||
obj-$(CONFIG_NF_NAT) += xt_nat.o
|
||||
|
||||
# NAT protocols (nf_nat)
|
||||
obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
|
||||
obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o
|
||||
obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o
|
||||
|
||||
# NAT helpers
|
||||
obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
|
||||
obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
|
||||
obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o
|
||||
obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o
|
||||
obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
|
||||
|
||||
# transparent proxy support
|
||||
obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
|
||||
|
||||
@ -67,7 +85,6 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
|
||||
obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
|
||||
|
@ -126,42 +126,38 @@ unsigned int nf_iterate(struct list_head *head,
|
||||
unsigned int hook,
|
||||
const struct net_device *indev,
|
||||
const struct net_device *outdev,
|
||||
struct list_head **i,
|
||||
struct nf_hook_ops **elemp,
|
||||
int (*okfn)(struct sk_buff *),
|
||||
int hook_thresh)
|
||||
{
|
||||
unsigned int verdict;
|
||||
struct nf_hook_ops *elem = list_entry_rcu(*i, struct nf_hook_ops, list);
|
||||
|
||||
/*
|
||||
* The caller must not block between calls to this
|
||||
* function because of risk of continuing from deleted element.
|
||||
*/
|
||||
list_for_each_entry_continue_rcu(elem, head, list) {
|
||||
if (hook_thresh > elem->priority)
|
||||
list_for_each_entry_continue_rcu((*elemp), head, list) {
|
||||
if (hook_thresh > (*elemp)->priority)
|
||||
continue;
|
||||
|
||||
/* Optimization: we don't need to hold module
|
||||
reference here, since function can't sleep. --RR */
|
||||
repeat:
|
||||
verdict = elem->hook(hook, skb, indev, outdev, okfn);
|
||||
verdict = (*elemp)->hook(hook, skb, indev, outdev, okfn);
|
||||
if (verdict != NF_ACCEPT) {
|
||||
#ifdef CONFIG_NETFILTER_DEBUG
|
||||
if (unlikely((verdict & NF_VERDICT_MASK)
|
||||
> NF_MAX_VERDICT)) {
|
||||
NFDEBUG("Evil return from %p(%u).\n",
|
||||
elem->hook, hook);
|
||||
(*elemp)->hook, hook);
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
if (verdict != NF_REPEAT) {
|
||||
*i = &elem->list;
|
||||
if (verdict != NF_REPEAT)
|
||||
return verdict;
|
||||
}
|
||||
goto repeat;
|
||||
}
|
||||
}
|
||||
*i = &elem->list;
|
||||
return NF_ACCEPT;
|
||||
}
|
||||
|
||||
@ -174,14 +170,14 @@ int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
|
||||
int (*okfn)(struct sk_buff *),
|
||||
int hook_thresh)
|
||||
{
|
||||
struct list_head *elem;
|
||||
struct nf_hook_ops *elem;
|
||||
unsigned int verdict;
|
||||
int ret = 0;
|
||||
|
||||
/* We may already have this, but read-locks nest anyway */
|
||||
rcu_read_lock();
|
||||
|
||||
elem = &nf_hooks[pf][hook];
|
||||
elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list);
|
||||
next_hook:
|
||||
verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,
|
||||
outdev, &elem, okfn, hook_thresh);
|
||||
@ -275,6 +271,11 @@ EXPORT_SYMBOL_GPL(nfq_ct_nat_hook);
|
||||
|
||||
#endif /* CONFIG_NF_CONNTRACK */
|
||||
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *);
|
||||
EXPORT_SYMBOL(nf_nat_decode_session_hook);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_PROC_FS
|
||||
struct proc_dir_entry *proc_net_netfilter;
|
||||
EXPORT_SYMBOL(proc_net_netfilter);
|
||||
|
@ -268,6 +268,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp,
|
||||
* packet.
|
||||
*/
|
||||
ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo,
|
||||
iph->ihl * 4,
|
||||
start-data, end-start,
|
||||
buf, buf_len);
|
||||
if (ret) {
|
||||
|
@ -85,6 +85,22 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos)
|
||||
return dst;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
__mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu)
|
||||
{
|
||||
if (IP6CB(skb)->frag_max_size) {
|
||||
/* frag_max_size tell us that, this packet have been
|
||||
* defragmented by netfilter IPv6 conntrack module.
|
||||
*/
|
||||
if (IP6CB(skb)->frag_max_size > mtu)
|
||||
return true; /* largest fragment violate MTU */
|
||||
}
|
||||
else if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
return true; /* Packet size violate MTU size */
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Get route to daddr, update *saddr, optionally bind route to saddr */
|
||||
static struct rtable *do_output_route4(struct net *net, __be32 daddr,
|
||||
u32 rtos, int rt_mode, __be32 *saddr)
|
||||
@ -491,7 +507,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
|
||||
/* MTU checking */
|
||||
mtu = dst_mtu(&rt->dst);
|
||||
if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
if (__mtu_check_toobig_v6(skb, mtu)) {
|
||||
if (!skb->dev) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
|
||||
@ -712,7 +728,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
|
||||
/* MTU checking */
|
||||
mtu = dst_mtu(&rt->dst);
|
||||
if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
if (__mtu_check_toobig_v6(skb, mtu)) {
|
||||
if (!skb->dev) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
|
||||
@ -946,8 +962,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
if (skb_dst(skb))
|
||||
skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu);
|
||||
|
||||
if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr) &&
|
||||
!skb_is_gso(skb)) {
|
||||
/* MTU checking: Notice that 'mtu' have been adjusted before hand */
|
||||
if (__mtu_check_toobig_v6(skb, mtu)) {
|
||||
if (!skb->dev) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
|
||||
@ -1113,7 +1129,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
|
||||
/* MTU checking */
|
||||
mtu = dst_mtu(&rt->dst);
|
||||
if (skb->len > mtu) {
|
||||
if (__mtu_check_toobig_v6(skb, mtu)) {
|
||||
if (!skb->dev) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
|
||||
@ -1349,7 +1365,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp,
|
||||
|
||||
/* MTU checking */
|
||||
mtu = dst_mtu(&rt->dst);
|
||||
if (skb->len > mtu && !skb_is_gso(skb)) {
|
||||
if (__mtu_check_toobig_v6(skb, mtu)) {
|
||||
if (!skb->dev) {
|
||||
struct net *net = dev_net(skb_dst(skb)->dev);
|
||||
|
||||
|
@ -40,6 +40,7 @@ MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)");
|
||||
|
||||
unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp)
|
||||
@ -155,8 +156,8 @@ static int amanda_help(struct sk_buff *skb,
|
||||
|
||||
nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook);
|
||||
if (nf_nat_amanda && ct->status & IPS_NAT_MASK)
|
||||
ret = nf_nat_amanda(skb, ctinfo, off - dataoff,
|
||||
len, exp);
|
||||
ret = nf_nat_amanda(skb, ctinfo, protoff,
|
||||
off - dataoff, len, exp);
|
||||
else if (nf_ct_expect_related(exp) != 0)
|
||||
ret = NF_DROP;
|
||||
nf_ct_expect_put(exp);
|
||||
|
@ -55,6 +55,12 @@ int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct,
|
||||
const struct nlattr *attr) __read_mostly;
|
||||
EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook);
|
||||
|
||||
int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff);
|
||||
EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook);
|
||||
|
||||
DEFINE_SPINLOCK(nf_conntrack_lock);
|
||||
EXPORT_SYMBOL_GPL(nf_conntrack_lock);
|
||||
|
||||
@ -930,7 +936,6 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
enum ip_conntrack_info ctinfo;
|
||||
struct nf_conntrack_l3proto *l3proto;
|
||||
struct nf_conntrack_l4proto *l4proto;
|
||||
struct nf_conn_timeout *timeout_ext;
|
||||
unsigned int *timeouts;
|
||||
unsigned int dataoff;
|
||||
u_int8_t protonum;
|
||||
@ -997,11 +1002,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum,
|
||||
NF_CT_ASSERT(skb->nfct);
|
||||
|
||||
/* Decide what timeout policy we want to apply to this flow. */
|
||||
timeout_ext = nf_ct_timeout_find(ct);
|
||||
if (timeout_ext)
|
||||
timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext);
|
||||
else
|
||||
timeouts = l4proto->get_timeouts(net);
|
||||
timeouts = nf_ct_timeout_lookup(net, ct, l4proto);
|
||||
|
||||
ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts);
|
||||
if (ret <= 0) {
|
||||
|
@ -48,6 +48,7 @@ module_param(loose, bool, 0600);
|
||||
unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
enum nf_ct_ftp_type type,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp);
|
||||
@ -489,7 +490,7 @@ static int help(struct sk_buff *skb,
|
||||
nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook);
|
||||
if (nf_nat_ftp && ct->status & IPS_NAT_MASK)
|
||||
ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype,
|
||||
matchoff, matchlen, exp);
|
||||
protoff, matchoff, matchlen, exp);
|
||||
else {
|
||||
/* Can't expect this? Best to drop packet now. */
|
||||
if (nf_ct_expect_related(exp) != 0)
|
||||
|
@ -49,12 +49,12 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations "
|
||||
"(determined by routing information)");
|
||||
|
||||
/* Hooks for NAT */
|
||||
int (*set_h245_addr_hook) (struct sk_buff *skb,
|
||||
int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
union nf_inet_addr *addr, __be16 port)
|
||||
__read_mostly;
|
||||
int (*set_h225_addr_hook) (struct sk_buff *skb,
|
||||
int (*set_h225_addr_hook) (struct sk_buff *skb, unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr,
|
||||
union nf_inet_addr *addr, __be16 port)
|
||||
@ -62,16 +62,17 @@ int (*set_h225_addr_hook) (struct sk_buff *skb,
|
||||
int (*set_sig_addr_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count) __read_mostly;
|
||||
int (*set_ras_addr_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count) __read_mostly;
|
||||
int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr,
|
||||
__be16 port, __be16 rtp_port,
|
||||
@ -80,24 +81,28 @@ int (*nat_rtp_rtcp_hook) (struct sk_buff *skb,
|
||||
int (*nat_t120_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
int (*nat_h245_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
int (*nat_callforwarding_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr, __be16 port,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
int (*nat_q931_hook) (struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, TransportAddress *taddr, int idx,
|
||||
__be16 port, struct nf_conntrack_expect *exp)
|
||||
__read_mostly;
|
||||
@ -251,6 +256,7 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data,
|
||||
/****************************************************************************/
|
||||
static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr)
|
||||
{
|
||||
@ -295,9 +301,10 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
|
||||
(nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) &&
|
||||
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
/* NAT needed */
|
||||
ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
|
||||
ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
taddr, port, rtp_port, rtp_exp, rtcp_exp);
|
||||
} else { /* Conntrack only */
|
||||
if (nf_ct_expect_related(rtp_exp) == 0) {
|
||||
@ -324,6 +331,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct,
|
||||
static int expect_t120(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H245_TransportAddress *taddr)
|
||||
{
|
||||
@ -353,9 +361,10 @@ static int expect_t120(struct sk_buff *skb,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
|
||||
(nat_t120 = rcu_dereference(nat_t120_hook)) &&
|
||||
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
/* NAT needed */
|
||||
ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr,
|
||||
ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr,
|
||||
port, exp);
|
||||
} else { /* Conntrack only */
|
||||
if (nf_ct_expect_related(exp) == 0) {
|
||||
@ -374,6 +383,7 @@ static int expect_t120(struct sk_buff *skb,
|
||||
static int process_h245_channel(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
H2250LogicalChannelParameters *channel)
|
||||
{
|
||||
@ -381,7 +391,7 @@ static int process_h245_channel(struct sk_buff *skb,
|
||||
|
||||
if (channel->options & eH2250LogicalChannelParameters_mediaChannel) {
|
||||
/* RTP */
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&channel->mediaChannel);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -390,7 +400,7 @@ static int process_h245_channel(struct sk_buff *skb,
|
||||
if (channel->
|
||||
options & eH2250LogicalChannelParameters_mediaControlChannel) {
|
||||
/* RTCP */
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&channel->mediaControlChannel);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -402,6 +412,7 @@ static int process_h245_channel(struct sk_buff *skb,
|
||||
/****************************************************************************/
|
||||
static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
OpenLogicalChannel *olc)
|
||||
{
|
||||
@ -412,7 +423,8 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if (olc->forwardLogicalChannelParameters.multiplexParameters.choice ==
|
||||
eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)
|
||||
{
|
||||
ret = process_h245_channel(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_h245_channel(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&olc->
|
||||
forwardLogicalChannelParameters.
|
||||
multiplexParameters.
|
||||
@ -430,7 +442,8 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
|
||||
eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
|
||||
{
|
||||
ret =
|
||||
process_h245_channel(skb, ct, ctinfo, data, dataoff,
|
||||
process_h245_channel(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&olc->
|
||||
reverseLogicalChannelParameters.
|
||||
multiplexParameters.
|
||||
@ -448,7 +461,7 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
|
||||
t120.choice == eDataProtocolCapability_separateLANStack &&
|
||||
olc->separateStack.networkAddress.choice ==
|
||||
eNetworkAccessParameters_networkAddress_localAreaAddress) {
|
||||
ret = expect_t120(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&olc->separateStack.networkAddress.
|
||||
localAreaAddress);
|
||||
if (ret < 0)
|
||||
@ -461,7 +474,7 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
OpenLogicalChannelAck *olca)
|
||||
{
|
||||
H2250LogicalChannelAckParameters *ack;
|
||||
@ -477,7 +490,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
choice ==
|
||||
eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters))
|
||||
{
|
||||
ret = process_h245_channel(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_h245_channel(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&olca->
|
||||
reverseLogicalChannelParameters.
|
||||
multiplexParameters.
|
||||
@ -496,7 +510,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if (ack->options &
|
||||
eH2250LogicalChannelAckParameters_mediaChannel) {
|
||||
/* RTP */
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&ack->mediaChannel);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -505,7 +520,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if (ack->options &
|
||||
eH2250LogicalChannelAckParameters_mediaControlChannel) {
|
||||
/* RTCP */
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_rtp_rtcp(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&ack->mediaControlChannel);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -515,7 +531,7 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if ((olca->options & eOpenLogicalChannelAck_separateStack) &&
|
||||
olca->separateStack.networkAddress.choice ==
|
||||
eNetworkAccessParameters_networkAddress_localAreaAddress) {
|
||||
ret = expect_t120(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&olca->separateStack.networkAddress.
|
||||
localAreaAddress);
|
||||
if (ret < 0)
|
||||
@ -528,14 +544,15 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
MultimediaSystemControlMessage *mscm)
|
||||
{
|
||||
switch (mscm->choice) {
|
||||
case eMultimediaSystemControlMessage_request:
|
||||
if (mscm->request.choice ==
|
||||
eRequestMessage_openLogicalChannel) {
|
||||
return process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
return process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&mscm->request.openLogicalChannel);
|
||||
}
|
||||
pr_debug("nf_ct_h323: H.245 Request %d\n",
|
||||
@ -544,7 +561,8 @@ static int process_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
case eMultimediaSystemControlMessage_response:
|
||||
if (mscm->response.choice ==
|
||||
eResponseMessage_openLogicalChannelAck) {
|
||||
return process_olca(skb, ct, ctinfo, data, dataoff,
|
||||
return process_olca(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&mscm->response.
|
||||
openLogicalChannelAck);
|
||||
}
|
||||
@ -595,7 +613,8 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff,
|
||||
}
|
||||
|
||||
/* Process H.245 signal */
|
||||
if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0)
|
||||
if (process_h245(skb, ct, ctinfo, protoff,
|
||||
&data, dataoff, &mscm) < 0)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@ -659,7 +678,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data,
|
||||
/****************************************************************************/
|
||||
static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff,
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr)
|
||||
{
|
||||
int dir = CTINFO2DIR(ctinfo);
|
||||
@ -688,9 +707,10 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
|
||||
(nat_h245 = rcu_dereference(nat_h245_hook)) &&
|
||||
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
/* NAT needed */
|
||||
ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr,
|
||||
ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr,
|
||||
port, exp);
|
||||
} else { /* Conntrack only */
|
||||
if (nf_ct_expect_related(exp) == 0) {
|
||||
@ -776,6 +796,7 @@ static int callforward_do_filter(const union nf_inet_addr *src,
|
||||
static int expect_callforwarding(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
TransportAddress *taddr)
|
||||
{
|
||||
@ -811,9 +832,11 @@ static int expect_callforwarding(struct sk_buff *skb,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
sizeof(ct->tuplehash[dir].tuple.src.u3)) &&
|
||||
(nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) &&
|
||||
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
/* Need NAT */
|
||||
ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff,
|
||||
ret = nat_callforwarding(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
taddr, port, exp);
|
||||
} else { /* Conntrack only */
|
||||
if (nf_ct_expect_related(exp) == 0) {
|
||||
@ -831,6 +854,7 @@ static int expect_callforwarding(struct sk_buff *skb,
|
||||
/****************************************************************************/
|
||||
static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
Setup_UUIE *setup)
|
||||
{
|
||||
@ -844,7 +868,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_q931: Setup\n");
|
||||
|
||||
if (setup->options & eSetup_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&setup->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -852,14 +876,15 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
set_h225_addr = rcu_dereference(set_h225_addr_hook);
|
||||
if ((setup->options & eSetup_UUIE_destCallSignalAddress) &&
|
||||
(set_h225_addr) && ct->status & IPS_NAT_MASK &&
|
||||
(set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK &&
|
||||
get_h225_addr(ct, *data, &setup->destCallSignalAddress,
|
||||
&addr, &port) &&
|
||||
memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) {
|
||||
pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n",
|
||||
&addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3,
|
||||
ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port));
|
||||
ret = set_h225_addr(skb, data, dataoff,
|
||||
ret = set_h225_addr(skb, protoff, data, dataoff,
|
||||
&setup->destCallSignalAddress,
|
||||
&ct->tuplehash[!dir].tuple.src.u3,
|
||||
ct->tuplehash[!dir].tuple.src.u.tcp.port);
|
||||
@ -868,14 +893,15 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
}
|
||||
|
||||
if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) &&
|
||||
(set_h225_addr) && ct->status & IPS_NAT_MASK &&
|
||||
(set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK &&
|
||||
get_h225_addr(ct, *data, &setup->sourceCallSignalAddress,
|
||||
&addr, &port) &&
|
||||
memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) {
|
||||
pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n",
|
||||
&addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3,
|
||||
ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port));
|
||||
ret = set_h225_addr(skb, data, dataoff,
|
||||
ret = set_h225_addr(skb, protoff, data, dataoff,
|
||||
&setup->sourceCallSignalAddress,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
ct->tuplehash[!dir].tuple.dst.u.tcp.port);
|
||||
@ -885,7 +911,8 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (setup->options & eSetup_UUIE_fastStart) {
|
||||
for (i = 0; i < setup->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&setup->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -899,6 +926,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct,
|
||||
static int process_callproceeding(struct sk_buff *skb,
|
||||
struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
CallProceeding_UUIE *callproc)
|
||||
{
|
||||
@ -908,7 +936,7 @@ static int process_callproceeding(struct sk_buff *skb,
|
||||
pr_debug("nf_ct_q931: CallProceeding\n");
|
||||
|
||||
if (callproc->options & eCallProceeding_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&callproc->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -916,7 +944,8 @@ static int process_callproceeding(struct sk_buff *skb,
|
||||
|
||||
if (callproc->options & eCallProceeding_UUIE_fastStart) {
|
||||
for (i = 0; i < callproc->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&callproc->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -929,6 +958,7 @@ static int process_callproceeding(struct sk_buff *skb,
|
||||
/****************************************************************************/
|
||||
static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
Connect_UUIE *connect)
|
||||
{
|
||||
@ -938,7 +968,7 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_q931: Connect\n");
|
||||
|
||||
if (connect->options & eConnect_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&connect->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -946,7 +976,8 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (connect->options & eConnect_UUIE_fastStart) {
|
||||
for (i = 0; i < connect->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&connect->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -959,6 +990,7 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
Alerting_UUIE *alert)
|
||||
{
|
||||
@ -968,7 +1000,7 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_q931: Alerting\n");
|
||||
|
||||
if (alert->options & eAlerting_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&alert->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -976,7 +1008,8 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (alert->options & eAlerting_UUIE_fastStart) {
|
||||
for (i = 0; i < alert->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&alert->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -989,6 +1022,7 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
Facility_UUIE *facility)
|
||||
{
|
||||
@ -999,15 +1033,15 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (facility->reason.choice == eFacilityReason_callForwarded) {
|
||||
if (facility->options & eFacility_UUIE_alternativeAddress)
|
||||
return expect_callforwarding(skb, ct, ctinfo, data,
|
||||
dataoff,
|
||||
return expect_callforwarding(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&facility->
|
||||
alternativeAddress);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (facility->options & eFacility_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&facility->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -1015,7 +1049,8 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (facility->options & eFacility_UUIE_fastStart) {
|
||||
for (i = 0; i < facility->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&facility->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -1028,6 +1063,7 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, int dataoff,
|
||||
Progress_UUIE *progress)
|
||||
{
|
||||
@ -1037,7 +1073,7 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_q931: Progress\n");
|
||||
|
||||
if (progress->options & eProgress_UUIE_h245Address) {
|
||||
ret = expect_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&progress->h245Address);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -1045,7 +1081,8 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (progress->options & eProgress_UUIE_fastStart) {
|
||||
for (i = 0; i < progress->fastStart.count; i++) {
|
||||
ret = process_olc(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_olc(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&progress->fastStart.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -1058,7 +1095,8 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data, int dataoff, Q931 *q931)
|
||||
unsigned int protoff, unsigned char **data, int dataoff,
|
||||
Q931 *q931)
|
||||
{
|
||||
H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu;
|
||||
int i;
|
||||
@ -1066,28 +1104,29 @@ static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
switch (pdu->h323_message_body.choice) {
|
||||
case eH323_UU_PDU_h323_message_body_setup:
|
||||
ret = process_setup(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_setup(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&pdu->h323_message_body.setup);
|
||||
break;
|
||||
case eH323_UU_PDU_h323_message_body_callProceeding:
|
||||
ret = process_callproceeding(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_callproceeding(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&pdu->h323_message_body.
|
||||
callProceeding);
|
||||
break;
|
||||
case eH323_UU_PDU_h323_message_body_connect:
|
||||
ret = process_connect(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_connect(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&pdu->h323_message_body.connect);
|
||||
break;
|
||||
case eH323_UU_PDU_h323_message_body_alerting:
|
||||
ret = process_alerting(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_alerting(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&pdu->h323_message_body.alerting);
|
||||
break;
|
||||
case eH323_UU_PDU_h323_message_body_facility:
|
||||
ret = process_facility(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_facility(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&pdu->h323_message_body.facility);
|
||||
break;
|
||||
case eH323_UU_PDU_h323_message_body_progress:
|
||||
ret = process_progress(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_progress(skb, ct, ctinfo, protoff, data, dataoff,
|
||||
&pdu->h323_message_body.progress);
|
||||
break;
|
||||
default:
|
||||
@ -1101,7 +1140,8 @@ static int process_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
if (pdu->options & eH323_UU_PDU_h245Control) {
|
||||
for (i = 0; i < pdu->h245Control.count; i++) {
|
||||
ret = process_h245(skb, ct, ctinfo, data, dataoff,
|
||||
ret = process_h245(skb, ct, ctinfo,
|
||||
protoff, data, dataoff,
|
||||
&pdu->h245Control.item[i]);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
@ -1146,7 +1186,8 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff,
|
||||
}
|
||||
|
||||
/* Process Q.931 signal */
|
||||
if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0)
|
||||
if (process_q931(skb, ct, ctinfo, protoff,
|
||||
&data, dataoff, &q931) < 0)
|
||||
goto drop;
|
||||
}
|
||||
|
||||
@ -1243,7 +1284,7 @@ static int set_expect_timeout(struct nf_conntrack_expect *exp,
|
||||
/****************************************************************************/
|
||||
static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned char **data,
|
||||
unsigned int protoff, unsigned char **data,
|
||||
TransportAddress *taddr, int count)
|
||||
{
|
||||
struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -1278,8 +1319,10 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */
|
||||
|
||||
nat_q931 = rcu_dereference(nat_q931_hook);
|
||||
if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */
|
||||
ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp);
|
||||
if (nat_q931 && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) { /* Need NAT */
|
||||
ret = nat_q931(skb, ct, ctinfo, protoff, data,
|
||||
taddr, i, port, exp);
|
||||
} else { /* Conntrack only */
|
||||
if (nf_ct_expect_related(exp) == 0) {
|
||||
pr_debug("nf_ct_ras: expect Q.931 ");
|
||||
@ -1299,6 +1342,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, GatekeeperRequest *grq)
|
||||
{
|
||||
typeof(set_ras_addr_hook) set_ras_addr;
|
||||
@ -1306,8 +1350,9 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_ras: GRQ\n");
|
||||
|
||||
set_ras_addr = rcu_dereference(set_ras_addr_hook);
|
||||
if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */
|
||||
return set_ras_addr(skb, ct, ctinfo, data,
|
||||
if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) /* NATed */
|
||||
return set_ras_addr(skb, ct, ctinfo, protoff, data,
|
||||
&grq->rasAddress, 1);
|
||||
return 0;
|
||||
}
|
||||
@ -1315,6 +1360,7 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, GatekeeperConfirm *gcf)
|
||||
{
|
||||
int dir = CTINFO2DIR(ctinfo);
|
||||
@ -1359,6 +1405,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, RegistrationRequest *rrq)
|
||||
{
|
||||
struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -1367,15 +1414,16 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
|
||||
pr_debug("nf_ct_ras: RRQ\n");
|
||||
|
||||
ret = expect_q931(skb, ct, ctinfo, data,
|
||||
ret = expect_q931(skb, ct, ctinfo, protoff, data,
|
||||
rrq->callSignalAddress.item,
|
||||
rrq->callSignalAddress.count);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
|
||||
set_ras_addr = rcu_dereference(set_ras_addr_hook);
|
||||
if (set_ras_addr && ct->status & IPS_NAT_MASK) {
|
||||
ret = set_ras_addr(skb, ct, ctinfo, data,
|
||||
if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
ret = set_ras_addr(skb, ct, ctinfo, protoff, data,
|
||||
rrq->rasAddress.item,
|
||||
rrq->rasAddress.count);
|
||||
if (ret < 0)
|
||||
@ -1394,6 +1442,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, RegistrationConfirm *rcf)
|
||||
{
|
||||
struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -1405,8 +1454,9 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_ras: RCF\n");
|
||||
|
||||
set_sig_addr = rcu_dereference(set_sig_addr_hook);
|
||||
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, data,
|
||||
if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
|
||||
rcf->callSignalAddress.item,
|
||||
rcf->callSignalAddress.count);
|
||||
if (ret < 0)
|
||||
@ -1443,6 +1493,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, UnregistrationRequest *urq)
|
||||
{
|
||||
struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -1453,8 +1504,9 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_ras: URQ\n");
|
||||
|
||||
set_sig_addr = rcu_dereference(set_sig_addr_hook);
|
||||
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, data,
|
||||
if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
|
||||
urq->callSignalAddress.item,
|
||||
urq->callSignalAddress.count);
|
||||
if (ret < 0)
|
||||
@ -1475,6 +1527,7 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, AdmissionRequest *arq)
|
||||
{
|
||||
const struct nf_ct_h323_master *info = nfct_help_data(ct);
|
||||
@ -1491,9 +1544,10 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
&addr, &port) &&
|
||||
!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
|
||||
port == info->sig_port[dir] &&
|
||||
nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
set_h225_addr && ct->status & IPS_NAT_MASK) {
|
||||
/* Answering ARQ */
|
||||
return set_h225_addr(skb, data, 0,
|
||||
return set_h225_addr(skb, protoff, data, 0,
|
||||
&arq->destCallSignalAddress,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
info->sig_port[!dir]);
|
||||
@ -1503,9 +1557,10 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
get_h225_addr(ct, *data, &arq->srcCallSignalAddress,
|
||||
&addr, &port) &&
|
||||
!memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) &&
|
||||
set_h225_addr && ct->status & IPS_NAT_MASK) {
|
||||
set_h225_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
/* Calling ARQ */
|
||||
return set_h225_addr(skb, data, 0,
|
||||
return set_h225_addr(skb, protoff, data, 0,
|
||||
&arq->srcCallSignalAddress,
|
||||
&ct->tuplehash[!dir].tuple.dst.u3,
|
||||
port);
|
||||
@ -1517,6 +1572,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, AdmissionConfirm *acf)
|
||||
{
|
||||
int dir = CTINFO2DIR(ctinfo);
|
||||
@ -1535,8 +1591,9 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) {
|
||||
/* Answering ACF */
|
||||
set_sig_addr = rcu_dereference(set_sig_addr_hook);
|
||||
if (set_sig_addr && ct->status & IPS_NAT_MASK)
|
||||
return set_sig_addr(skb, ct, ctinfo, data,
|
||||
if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK)
|
||||
return set_sig_addr(skb, ct, ctinfo, protoff, data,
|
||||
&acf->destCallSignalAddress, 1);
|
||||
return 0;
|
||||
}
|
||||
@ -1564,6 +1621,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, LocationRequest *lrq)
|
||||
{
|
||||
typeof(set_ras_addr_hook) set_ras_addr;
|
||||
@ -1571,8 +1629,9 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_ras: LRQ\n");
|
||||
|
||||
set_ras_addr = rcu_dereference(set_ras_addr_hook);
|
||||
if (set_ras_addr && ct->status & IPS_NAT_MASK)
|
||||
return set_ras_addr(skb, ct, ctinfo, data,
|
||||
if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK)
|
||||
return set_ras_addr(skb, ct, ctinfo, protoff, data,
|
||||
&lrq->replyAddress, 1);
|
||||
return 0;
|
||||
}
|
||||
@ -1580,6 +1639,7 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, LocationConfirm *lcf)
|
||||
{
|
||||
int dir = CTINFO2DIR(ctinfo);
|
||||
@ -1619,6 +1679,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, InfoRequestResponse *irr)
|
||||
{
|
||||
int ret;
|
||||
@ -1628,16 +1689,18 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
pr_debug("nf_ct_ras: IRR\n");
|
||||
|
||||
set_ras_addr = rcu_dereference(set_ras_addr_hook);
|
||||
if (set_ras_addr && ct->status & IPS_NAT_MASK) {
|
||||
ret = set_ras_addr(skb, ct, ctinfo, data,
|
||||
if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
ret = set_ras_addr(skb, ct, ctinfo, protoff, data,
|
||||
&irr->rasAddress, 1);
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
set_sig_addr = rcu_dereference(set_sig_addr_hook);
|
||||
if (set_sig_addr && ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, data,
|
||||
if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 &&
|
||||
ct->status & IPS_NAT_MASK) {
|
||||
ret = set_sig_addr(skb, ct, ctinfo, protoff, data,
|
||||
irr->callSignalAddress.item,
|
||||
irr->callSignalAddress.count);
|
||||
if (ret < 0)
|
||||
@ -1650,38 +1713,39 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct,
|
||||
/****************************************************************************/
|
||||
static int process_ras(struct sk_buff *skb, struct nf_conn *ct,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned char **data, RasMessage *ras)
|
||||
{
|
||||
switch (ras->choice) {
|
||||
case eRasMessage_gatekeeperRequest:
|
||||
return process_grq(skb, ct, ctinfo, data,
|
||||
return process_grq(skb, ct, ctinfo, protoff, data,
|
||||
&ras->gatekeeperRequest);
|
||||
case eRasMessage_gatekeeperConfirm:
|
||||
return process_gcf(skb, ct, ctinfo, data,
|
||||
return process_gcf(skb, ct, ctinfo, protoff, data,
|
||||
&ras->gatekeeperConfirm);
|
||||
case eRasMessage_registrationRequest:
|
||||
return process_rrq(skb, ct, ctinfo, data,
|
||||
return process_rrq(skb, ct, ctinfo, protoff, data,
|
||||
&ras->registrationRequest);
|
||||
case eRasMessage_registrationConfirm:
|
||||
return process_rcf(skb, ct, ctinfo, data,
|
||||
return process_rcf(skb, ct, ctinfo, protoff, data,
|
||||
&ras->registrationConfirm);
|
||||
case eRasMessage_unregistrationRequest:
|
||||
return process_urq(skb, ct, ctinfo, data,
|
||||
return process_urq(skb, ct, ctinfo, protoff, data,
|
||||
&ras->unregistrationRequest);
|
||||
case eRasMessage_admissionRequest:
|
||||
return process_arq(skb, ct, ctinfo, data,
|
||||
return process_arq(skb, ct, ctinfo, protoff, data,
|
||||
&ras->admissionRequest);
|
||||
case eRasMessage_admissionConfirm:
|
||||
return process_acf(skb, ct, ctinfo, data,
|
||||
return process_acf(skb, ct, ctinfo, protoff, data,
|
||||
&ras->admissionConfirm);
|
||||
case eRasMessage_locationRequest:
|
||||
return process_lrq(skb, ct, ctinfo, data,
|
||||
return process_lrq(skb, ct, ctinfo, protoff, data,
|
||||
&ras->locationRequest);
|
||||
case eRasMessage_locationConfirm:
|
||||
return process_lcf(skb, ct, ctinfo, data,
|
||||
return process_lcf(skb, ct, ctinfo, protoff, data,
|
||||
&ras->locationConfirm);
|
||||
case eRasMessage_infoRequestResponse:
|
||||
return process_irr(skb, ct, ctinfo, data,
|
||||
return process_irr(skb, ct, ctinfo, protoff, data,
|
||||
&ras->infoRequestResponse);
|
||||
default:
|
||||
pr_debug("nf_ct_ras: RAS message %d\n", ras->choice);
|
||||
@ -1721,7 +1785,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff,
|
||||
}
|
||||
|
||||
/* Process RAS message */
|
||||
if (process_ras(skb, ct, ctinfo, &data, &ras) < 0)
|
||||
if (process_ras(skb, ct, ctinfo, protoff, &data, &ras) < 0)
|
||||
goto drop;
|
||||
|
||||
accept:
|
||||
|
@ -33,6 +33,7 @@ static DEFINE_SPINLOCK(irc_buffer_lock);
|
||||
|
||||
unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb,
|
||||
enum ip_conntrack_info ctinfo,
|
||||
unsigned int protoff,
|
||||
unsigned int matchoff,
|
||||
unsigned int matchlen,
|
||||
struct nf_conntrack_expect *exp) __read_mostly;
|
||||
@ -205,7 +206,7 @@ static int help(struct sk_buff *skb, unsigned int protoff,
|
||||
|
||||
nf_nat_irc = rcu_dereference(nf_nat_irc_hook);
|
||||
if (nf_nat_irc && ct->status & IPS_NAT_MASK)
|
||||
ret = nf_nat_irc(skb, ctinfo,
|
||||
ret = nf_nat_irc(skb, ctinfo, protoff,
|
||||
addr_beg_p - ib_ptr,
|
||||
addr_end_p - addr_beg_p,
|
||||
exp);
|
||||
|
@ -45,7 +45,7 @@
|
||||
#include <net/netfilter/nf_conntrack_timestamp.h>
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
#include <net/netfilter/nf_nat_core.h>
|
||||
#include <net/netfilter/nf_nat_protocol.h>
|
||||
#include <net/netfilter/nf_nat_l4proto.h>
|
||||
#include <net/netfilter/nf_nat_helper.h>
|
||||
#endif
|
||||
|
||||
@ -1096,13 +1096,14 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
|
||||
const struct nlattr *attr)
|
||||
{
|
||||
typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup;
|
||||
int err;
|
||||
|
||||
parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook);
|
||||
if (!parse_nat_setup) {
|
||||
#ifdef CONFIG_MODULES
|
||||
rcu_read_unlock();
|
||||
nfnl_unlock();
|
||||
if (request_module("nf-nat-ipv4") < 0) {
|
||||
if (request_module("nf-nat") < 0) {
|
||||
nfnl_lock();
|
||||
rcu_read_lock();
|
||||
return -EOPNOTSUPP;
|
||||
@ -1115,7 +1116,26 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct,
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
|
||||
return parse_nat_setup(ct, manip, attr);
|
||||
err = parse_nat_setup(ct, manip, attr);
|
||||
if (err == -EAGAIN) {
|
||||
#ifdef CONFIG_MODULES
|
||||
rcu_read_unlock();
|
||||
spin_unlock_bh(&nf_conntrack_lock);
|
||||
nfnl_unlock();
|
||||
if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) {
|
||||
nfnl_lock();
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
rcu_read_lock();
|
||||
return -EOPNOTSUPP;
|
||||
}
|
||||
nfnl_lock();
|
||||
spin_lock_bh(&nf_conntrack_lock);
|
||||
rcu_read_lock();
|
||||
#else
|
||||
err = -EOPNOTSUPP;
|
||||
#endif
|
||||
}
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
@ -1979,6 +1999,8 @@ nla_put_failure:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const union nf_inet_addr any_addr;
|
||||
|
||||
static int
|
||||
ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||
const struct nf_conntrack_expect *exp)
|
||||
@ -2005,7 +2027,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||
goto nla_put_failure;
|
||||
|
||||
#ifdef CONFIG_NF_NAT_NEEDED
|
||||
if (exp->saved_ip || exp->saved_proto.all) {
|
||||
if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) ||
|
||||
exp->saved_proto.all) {
|
||||
nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED);
|
||||
if (!nest_parms)
|
||||
goto nla_put_failure;
|
||||
@ -2014,7 +2037,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb,
|
||||
goto nla_put_failure;
|
||||
|
||||
nat_tuple.src.l3num = nf_ct_l3num(master);
|
||||
nat_tuple.src.u3.ip = exp->saved_ip;
|
||||
nat_tuple.src.u3 = exp->saved_addr;
|
||||
nat_tuple.dst.protonum = nf_ct_protonum(master);
|
||||
nat_tuple.src.u = exp->saved_proto;
|
||||
|
||||
@ -2410,7 +2433,7 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr,
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
exp->saved_ip = nat_tuple.src.u3.ip;
|
||||
exp->saved_addr = nat_tuple.src.u3;
|
||||
exp->saved_proto = nat_tuple.src.u;
|
||||
exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR]));
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user