• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/skbuff.h>
14 #include <linux/dccp.h>
15 
16 #include <net/netfilter/nf_conntrack.h>
17 #include <net/netfilter/nf_nat.h>
18 #include <net/netfilter/nf_nat_l3proto.h>
19 #include <net/netfilter/nf_nat_l4proto.h>
20 
21 static u_int16_t dccp_port_rover;
22 
23 static void
dccp_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)24 dccp_unique_tuple(const struct nf_nat_l3proto *l3proto,
25 		  struct nf_conntrack_tuple *tuple,
26 		  const struct nf_nat_range *range,
27 		  enum nf_nat_manip_type maniptype,
28 		  const struct nf_conn *ct)
29 {
30 	nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct,
31 				    &dccp_port_rover);
32 }
33 
34 static bool
dccp_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)35 dccp_manip_pkt(struct sk_buff *skb,
36 	       const struct nf_nat_l3proto *l3proto,
37 	       unsigned int iphdroff, unsigned int hdroff,
38 	       const struct nf_conntrack_tuple *tuple,
39 	       enum nf_nat_manip_type maniptype)
40 {
41 	struct dccp_hdr *hdr;
42 	__be16 *portptr, oldport, newport;
43 	int hdrsize = 8; /* DCCP connection tracking guarantees this much */
44 
45 	if (skb->len >= hdroff + sizeof(struct dccp_hdr))
46 		hdrsize = sizeof(struct dccp_hdr);
47 
48 	if (!skb_make_writable(skb, hdroff + hdrsize))
49 		return false;
50 
51 	hdr = (struct dccp_hdr *)(skb->data + hdroff);
52 
53 	if (maniptype == NF_NAT_MANIP_SRC) {
54 		newport = tuple->src.u.dccp.port;
55 		portptr = &hdr->dccph_sport;
56 	} else {
57 		newport = tuple->dst.u.dccp.port;
58 		portptr = &hdr->dccph_dport;
59 	}
60 
61 	oldport = *portptr;
62 	*portptr = newport;
63 
64 	if (hdrsize < sizeof(*hdr))
65 		return true;
66 
67 	l3proto->csum_update(skb, iphdroff, &hdr->dccph_checksum,
68 			     tuple, maniptype);
69 	inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
70 				 false);
71 	return true;
72 }
73 
74 const struct nf_nat_l4proto nf_nat_l4proto_dccp = {
75 	.l4proto		= IPPROTO_DCCP,
76 	.manip_pkt		= dccp_manip_pkt,
77 	.in_range		= nf_nat_l4proto_in_range,
78 	.unique_tuple		= dccp_unique_tuple,
79 #if IS_ENABLED(CONFIG_NF_CT_NETLINK)
80 	.nlattr_to_range	= nf_nat_l4proto_nlattr_to_range,
81 #endif
82 };
83