aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2008-03-20 10:15:57 -0400
committerPatrick McHardy <kaber@trash.net>2008-04-14 05:15:50 -0400
commit4910a087996e637adc50f955eccf114307f8fab7 (patch)
treebf3402198dc4126b24618da1571c835510645be9 /net
parent2bc780499aa33311ec0f3e42624dfaa7be0ade5e (diff)
[NETFILTER]: nf_nat: add DCCP protocol support
Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/ipv4/netfilter/Kconfig5
-rw-r--r--net/ipv4/netfilter/Makefile1
-rw-r--r--net/ipv4/netfilter/nf_nat_proto_dccp.c108
-rw-r--r--net/ipv4/netfilter/nf_nat_standalone.c6
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/).
244config NF_NAT_PROTO_DCCP
245 tristate
246 depends on NF_NAT && NF_CT_PROTO_DCCP
247 default NF_NAT && NF_CT_PROTO_DCCP
248
244config NF_NAT_PROTO_GRE 249config 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
29obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o 29obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o
30 30
31# NAT protocols (nf_nat) 31# NAT protocols (nf_nat)
32obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o
32obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o 33obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o
33obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o 34obj-$(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
23static u_int16_t dccp_port_rover;
24
25static int
26dccp_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
35static int
36dccp_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
81static 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
93static int __init nf_nat_proto_dccp_init(void)
94{
95 return nf_nat_protocol_register(&nf_nat_protocol_dccp);
96}
97
98static void __exit nf_nat_proto_dccp_fini(void)
99{
100 nf_nat_protocol_unregister(&nf_nat_protocol_dccp);
101}
102
103module_init(nf_nat_proto_dccp_init);
104module_exit(nf_nat_proto_dccp_fini);
105
106MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>");
107MODULE_DESCRIPTION("DCCP NAT protocol helper");
108MODULE_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}