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 void 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 nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, 32 &dccp_port_rover); 33} 34 35static bool 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 const struct iphdr *iph = (const void *)(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 false; 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 true; 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 true; 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"); 109