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 | } |
