diff options
author | Patrick McHardy <kaber@trash.net> | 2008-03-20 10:15:57 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-04-14 05:15:50 -0400 |
commit | 4910a087996e637adc50f955eccf114307f8fab7 (patch) | |
tree | bf3402198dc4126b24618da1571c835510645be9 /net/ipv4 | |
parent | 2bc780499aa33311ec0f3e42624dfaa7be0ade5e (diff) |
[NETFILTER]: nf_nat: add DCCP protocol support
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/Kconfig | 5 | ||||
-rw-r--r-- | net/ipv4/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_proto_dccp.c | 108 | ||||
-rw-r--r-- | net/ipv4/netfilter/nf_nat_standalone.c | 6 |
4 files changed, 118 insertions, 2 deletions
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index c5bd2840663b..fde3eacd196d 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -241,6 +241,11 @@ config NF_NAT_SNMP_BASIC | |||
241 | # <expr> '&&' <expr> (6) | 241 | # <expr> '&&' <expr> (6) |
242 | # | 242 | # |
243 | # (6) Returns the result of min(/expr/, /expr/). | 243 | # (6) Returns the result of min(/expr/, /expr/). |
244 | config NF_NAT_PROTO_DCCP | ||
245 | tristate | ||
246 | depends on NF_NAT && NF_CT_PROTO_DCCP | ||
247 | default NF_NAT && NF_CT_PROTO_DCCP | ||
248 | |||
244 | config NF_NAT_PROTO_GRE | 249 | config NF_NAT_PROTO_GRE |
245 | tristate | 250 | tristate |
246 | depends on NF_NAT && NF_CT_PROTO_GRE | 251 | depends on NF_NAT && NF_CT_PROTO_GRE |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 332f46fbc756..74d8dbdc1120 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -29,6 +29,7 @@ obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o | |||
29 | obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o | 29 | obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o |
30 | 30 | ||
31 | # NAT protocols (nf_nat) | 31 | # NAT protocols (nf_nat) |
32 | obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o | ||
32 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | 33 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o |
33 | obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o | 34 | obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o |
34 | 35 | ||
diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/ipv4/netfilter/nf_nat_proto_dccp.c new file mode 100644 index 000000000000..12b51b38442e --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_proto_dccp.c | |||
@@ -0,0 +1,108 @@ | |||
1 | /* | ||
2 | * DCCP NAT protocol helper | ||
3 | * | ||
4 | * Copyright (c) 2005, 2006. 2008 Patrick McHardy <kaber@trash.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/ip.h> | ||
17 | #include <linux/dccp.h> | ||
18 | |||
19 | #include <net/netfilter/nf_conntrack.h> | ||
20 | #include <net/netfilter/nf_nat.h> | ||
21 | #include <net/netfilter/nf_nat_protocol.h> | ||
22 | |||
23 | static u_int16_t dccp_port_rover; | ||
24 | |||
25 | static int | ||
26 | dccp_unique_tuple(struct nf_conntrack_tuple *tuple, | ||
27 | const struct nf_nat_range *range, | ||
28 | enum nf_nat_manip_type maniptype, | ||
29 | const struct nf_conn *ct) | ||
30 | { | ||
31 | return nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, | ||
32 | &dccp_port_rover); | ||
33 | } | ||
34 | |||
35 | static int | ||
36 | dccp_manip_pkt(struct sk_buff *skb, | ||
37 | unsigned int iphdroff, | ||
38 | const struct nf_conntrack_tuple *tuple, | ||
39 | enum nf_nat_manip_type maniptype) | ||
40 | { | ||
41 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
42 | struct dccp_hdr *hdr; | ||
43 | unsigned int hdroff = iphdroff + iph->ihl * 4; | ||
44 | __be32 oldip, newip; | ||
45 | __be16 *portptr, oldport, newport; | ||
46 | int hdrsize = 8; /* DCCP connection tracking guarantees this much */ | ||
47 | |||
48 | if (skb->len >= hdroff + sizeof(struct dccp_hdr)) | ||
49 | hdrsize = sizeof(struct dccp_hdr); | ||
50 | |||
51 | if (!skb_make_writable(skb, hdroff + hdrsize)) | ||
52 | return 0; | ||
53 | |||
54 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
55 | hdr = (struct dccp_hdr *)(skb->data + hdroff); | ||
56 | |||
57 | if (maniptype == IP_NAT_MANIP_SRC) { | ||
58 | oldip = iph->saddr; | ||
59 | newip = tuple->src.u3.ip; | ||
60 | newport = tuple->src.u.dccp.port; | ||
61 | portptr = &hdr->dccph_sport; | ||
62 | } else { | ||
63 | oldip = iph->daddr; | ||
64 | newip = tuple->dst.u3.ip; | ||
65 | newport = tuple->dst.u.dccp.port; | ||
66 | portptr = &hdr->dccph_dport; | ||
67 | } | ||
68 | |||
69 | oldport = *portptr; | ||
70 | *portptr = newport; | ||
71 | |||
72 | if (hdrsize < sizeof(*hdr)) | ||
73 | return 1; | ||
74 | |||
75 | inet_proto_csum_replace4(&hdr->dccph_checksum, skb, oldip, newip, 1); | ||
76 | inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport, | ||
77 | 0); | ||
78 | return 1; | ||
79 | } | ||
80 | |||
81 | static const struct nf_nat_protocol nf_nat_protocol_dccp = { | ||
82 | .protonum = IPPROTO_DCCP, | ||
83 | .me = THIS_MODULE, | ||
84 | .manip_pkt = dccp_manip_pkt, | ||
85 | .in_range = nf_nat_proto_in_range, | ||
86 | .unique_tuple = dccp_unique_tuple, | ||
87 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
88 | .range_to_nlattr = nf_nat_proto_range_to_nlattr, | ||
89 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | ||
90 | #endif | ||
91 | }; | ||
92 | |||
93 | static int __init nf_nat_proto_dccp_init(void) | ||
94 | { | ||
95 | return nf_nat_protocol_register(&nf_nat_protocol_dccp); | ||
96 | } | ||
97 | |||
98 | static void __exit nf_nat_proto_dccp_fini(void) | ||
99 | { | ||
100 | nf_nat_protocol_unregister(&nf_nat_protocol_dccp); | ||
101 | } | ||
102 | |||
103 | module_init(nf_nat_proto_dccp_init); | ||
104 | module_exit(nf_nat_proto_dccp_fini); | ||
105 | |||
106 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
107 | MODULE_DESCRIPTION("DCCP NAT protocol helper"); | ||
108 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/nf_nat_standalone.c index dc316b9f9b1d..b759ffa1098d 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/nf_nat_standalone.c | |||
@@ -51,7 +51,8 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | |||
51 | fl->fl4_dst = t->dst.u3.ip; | 51 | fl->fl4_dst = t->dst.u3.ip; |
52 | if (t->dst.protonum == IPPROTO_TCP || | 52 | if (t->dst.protonum == IPPROTO_TCP || |
53 | t->dst.protonum == IPPROTO_UDP || | 53 | t->dst.protonum == IPPROTO_UDP || |
54 | t->dst.protonum == IPPROTO_UDPLITE) | 54 | t->dst.protonum == IPPROTO_UDPLITE || |
55 | t->dst.protonum == IPPROTO_DCCP) | ||
55 | fl->fl_ip_dport = t->dst.u.tcp.port; | 56 | fl->fl_ip_dport = t->dst.u.tcp.port; |
56 | } | 57 | } |
57 | 58 | ||
@@ -61,7 +62,8 @@ static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | |||
61 | fl->fl4_src = t->src.u3.ip; | 62 | fl->fl4_src = t->src.u3.ip; |
62 | if (t->dst.protonum == IPPROTO_TCP || | 63 | if (t->dst.protonum == IPPROTO_TCP || |
63 | t->dst.protonum == IPPROTO_UDP || | 64 | t->dst.protonum == IPPROTO_UDP || |
64 | t->dst.protonum == IPPROTO_UDPLITE) | 65 | t->dst.protonum == IPPROTO_UDPLITE || |
66 | t->dst.protonum == IPPROTO_DCCP) | ||
65 | fl->fl_ip_sport = t->src.u.tcp.port; | 67 | fl->fl_ip_sport = t->src.u.tcp.port; |
66 | } | 68 | } |
67 | } | 69 | } |