Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux] / net / netfilter / nf_nat_proto.c
1 /* (C) 1999-2001 Paul `Rusty' Russell
2  * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License version 2 as
6  * published by the Free Software Foundation.
7  */
8
9 #include <linux/types.h>
10 #include <linux/export.h>
11 #include <linux/init.h>
12 #include <linux/udp.h>
13 #include <linux/tcp.h>
14 #include <linux/icmp.h>
15 #include <linux/icmpv6.h>
16
17 #include <linux/dccp.h>
18 #include <linux/sctp.h>
19 #include <net/sctp/checksum.h>
20
21 #include <linux/netfilter.h>
22 #include <net/netfilter/nf_nat.h>
23 #include <net/netfilter/nf_nat_core.h>
24 #include <net/netfilter/nf_nat_l3proto.h>
25 #include <net/netfilter/nf_nat_l4proto.h>
26
27 static void
28 __udp_manip_pkt(struct sk_buff *skb,
29                 const struct nf_nat_l3proto *l3proto,
30                 unsigned int iphdroff, struct udphdr *hdr,
31                 const struct nf_conntrack_tuple *tuple,
32                 enum nf_nat_manip_type maniptype, bool do_csum)
33 {
34         __be16 *portptr, newport;
35
36         if (maniptype == NF_NAT_MANIP_SRC) {
37                 /* Get rid of src port */
38                 newport = tuple->src.u.udp.port;
39                 portptr = &hdr->source;
40         } else {
41                 /* Get rid of dst port */
42                 newport = tuple->dst.u.udp.port;
43                 portptr = &hdr->dest;
44         }
45         if (do_csum) {
46                 l3proto->csum_update(skb, iphdroff, &hdr->check,
47                                      tuple, maniptype);
48                 inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport,
49                                          false);
50                 if (!hdr->check)
51                         hdr->check = CSUM_MANGLED_0;
52         }
53         *portptr = newport;
54 }
55
56 static bool udp_manip_pkt(struct sk_buff *skb,
57                           const struct nf_nat_l3proto *l3proto,
58                           unsigned int iphdroff, unsigned int hdroff,
59                           const struct nf_conntrack_tuple *tuple,
60                           enum nf_nat_manip_type maniptype)
61 {
62         struct udphdr *hdr;
63         bool do_csum;
64
65         if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
66                 return false;
67
68         hdr = (struct udphdr *)(skb->data + hdroff);
69         do_csum = hdr->check || skb->ip_summed == CHECKSUM_PARTIAL;
70
71         __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, do_csum);
72         return true;
73 }
74
75 static bool udplite_manip_pkt(struct sk_buff *skb,
76                               const struct nf_nat_l3proto *l3proto,
77                               unsigned int iphdroff, unsigned int hdroff,
78                               const struct nf_conntrack_tuple *tuple,
79                               enum nf_nat_manip_type maniptype)
80 {
81 #ifdef CONFIG_NF_CT_PROTO_UDPLITE
82         struct udphdr *hdr;
83
84         if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
85                 return false;
86
87         hdr = (struct udphdr *)(skb->data + hdroff);
88         __udp_manip_pkt(skb, l3proto, iphdroff, hdr, tuple, maniptype, true);
89 #endif
90         return true;
91 }
92
93 static bool
94 sctp_manip_pkt(struct sk_buff *skb,
95                const struct nf_nat_l3proto *l3proto,
96                unsigned int iphdroff, unsigned int hdroff,
97                const struct nf_conntrack_tuple *tuple,
98                enum nf_nat_manip_type maniptype)
99 {
100 #ifdef CONFIG_NF_CT_PROTO_SCTP
101         struct sctphdr *hdr;
102         int hdrsize = 8;
103
104         /* This could be an inner header returned in imcp packet; in such
105          * cases we cannot update the checksum field since it is outside
106          * of the 8 bytes of transport layer headers we are guaranteed.
107          */
108         if (skb->len >= hdroff + sizeof(*hdr))
109                 hdrsize = sizeof(*hdr);
110
111         if (!skb_make_writable(skb, hdroff + hdrsize))
112                 return false;
113
114         hdr = (struct sctphdr *)(skb->data + hdroff);
115
116         if (maniptype == NF_NAT_MANIP_SRC) {
117                 /* Get rid of src port */
118                 hdr->source = tuple->src.u.sctp.port;
119         } else {
120                 /* Get rid of dst port */
121                 hdr->dest = tuple->dst.u.sctp.port;
122         }
123
124         if (hdrsize < sizeof(*hdr))
125                 return true;
126
127         if (skb->ip_summed != CHECKSUM_PARTIAL) {
128                 hdr->checksum = sctp_compute_cksum(skb, hdroff);
129                 skb->ip_summed = CHECKSUM_NONE;
130         }
131
132 #endif
133         return true;
134 }
135
136 static bool
137 tcp_manip_pkt(struct sk_buff *skb,
138               const struct nf_nat_l3proto *l3proto,
139               unsigned int iphdroff, unsigned int hdroff,
140               const struct nf_conntrack_tuple *tuple,
141               enum nf_nat_manip_type maniptype)
142 {
143         struct tcphdr *hdr;
144         __be16 *portptr, newport, oldport;
145         int hdrsize = 8; /* TCP connection tracking guarantees this much */
146
147         /* this could be a inner header returned in icmp packet; in such
148            cases we cannot update the checksum field since it is outside of
149            the 8 bytes of transport layer headers we are guaranteed */
150         if (skb->len >= hdroff + sizeof(struct tcphdr))
151                 hdrsize = sizeof(struct tcphdr);
152
153         if (!skb_make_writable(skb, hdroff + hdrsize))
154                 return false;
155
156         hdr = (struct tcphdr *)(skb->data + hdroff);
157
158         if (maniptype == NF_NAT_MANIP_SRC) {
159                 /* Get rid of src port */
160                 newport = tuple->src.u.tcp.port;
161                 portptr = &hdr->source;
162         } else {
163                 /* Get rid of dst port */
164                 newport = tuple->dst.u.tcp.port;
165                 portptr = &hdr->dest;
166         }
167
168         oldport = *portptr;
169         *portptr = newport;
170
171         if (hdrsize < sizeof(*hdr))
172                 return true;
173
174         l3proto->csum_update(skb, iphdroff, &hdr->check, tuple, maniptype);
175         inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, false);
176         return true;
177 }
178
179 static bool
180 dccp_manip_pkt(struct sk_buff *skb,
181                const struct nf_nat_l3proto *l3proto,
182                unsigned int iphdroff, unsigned int hdroff,
183                const struct nf_conntrack_tuple *tuple,
184                enum nf_nat_manip_type maniptype)
185 {
186 #ifdef CONFIG_NF_CT_PROTO_DCCP
187         struct dccp_hdr *hdr;
188         __be16 *portptr, oldport, newport;
189         int hdrsize = 8; /* DCCP connection tracking guarantees this much */
190
191         if (skb->len >= hdroff + sizeof(struct dccp_hdr))
192                 hdrsize = sizeof(struct dccp_hdr);
193
194         if (!skb_make_writable(skb, hdroff + hdrsize))
195                 return false;
196
197         hdr = (struct dccp_hdr *)(skb->data + hdroff);
198
199         if (maniptype == NF_NAT_MANIP_SRC) {
200                 newport = tuple->src.u.dccp.port;
201                 portptr = &hdr->dccph_sport;
202         } else {
203                 newport = tuple->dst.u.dccp.port;
204                 portptr = &hdr->dccph_dport;
205         }
206
207         oldport = *portptr;
208         *portptr = newport;
209
210         if (hdrsize < sizeof(*hdr))
211                 return true;
212
213         l3proto->csum_update(skb, iphdroff, &hdr->dccph_checksum,
214                              tuple, maniptype);
215         inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport,
216                                  false);
217 #endif
218         return true;
219 }
220
221 static bool
222 icmp_manip_pkt(struct sk_buff *skb,
223                const struct nf_nat_l3proto *l3proto,
224                unsigned int iphdroff, unsigned int hdroff,
225                const struct nf_conntrack_tuple *tuple,
226                enum nf_nat_manip_type maniptype)
227 {
228         struct icmphdr *hdr;
229
230         if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
231                 return false;
232
233         hdr = (struct icmphdr *)(skb->data + hdroff);
234         inet_proto_csum_replace2(&hdr->checksum, skb,
235                                  hdr->un.echo.id, tuple->src.u.icmp.id, false);
236         hdr->un.echo.id = tuple->src.u.icmp.id;
237         return true;
238 }
239
240 static bool
241 icmpv6_manip_pkt(struct sk_buff *skb,
242                  const struct nf_nat_l3proto *l3proto,
243                  unsigned int iphdroff, unsigned int hdroff,
244                  const struct nf_conntrack_tuple *tuple,
245                  enum nf_nat_manip_type maniptype)
246 {
247         struct icmp6hdr *hdr;
248
249         if (!skb_make_writable(skb, hdroff + sizeof(*hdr)))
250                 return false;
251
252         hdr = (struct icmp6hdr *)(skb->data + hdroff);
253         l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum,
254                              tuple, maniptype);
255         if (hdr->icmp6_type == ICMPV6_ECHO_REQUEST ||
256             hdr->icmp6_type == ICMPV6_ECHO_REPLY) {
257                 inet_proto_csum_replace2(&hdr->icmp6_cksum, skb,
258                                          hdr->icmp6_identifier,
259                                          tuple->src.u.icmp.id, false);
260                 hdr->icmp6_identifier = tuple->src.u.icmp.id;
261         }
262         return true;
263 }
264
265 /* manipulate a GRE packet according to maniptype */
266 static bool
267 gre_manip_pkt(struct sk_buff *skb,
268               const struct nf_nat_l3proto *l3proto,
269               unsigned int iphdroff, unsigned int hdroff,
270               const struct nf_conntrack_tuple *tuple,
271               enum nf_nat_manip_type maniptype)
272 {
273 #if IS_ENABLED(CONFIG_NF_CT_PROTO_GRE)
274         const struct gre_base_hdr *greh;
275         struct pptp_gre_header *pgreh;
276
277         /* pgreh includes two optional 32bit fields which are not required
278          * to be there.  That's where the magic '8' comes from */
279         if (!skb_make_writable(skb, hdroff + sizeof(*pgreh) - 8))
280                 return false;
281
282         greh = (void *)skb->data + hdroff;
283         pgreh = (struct pptp_gre_header *)greh;
284
285         /* we only have destination manip of a packet, since 'source key'
286          * is not present in the packet itself */
287         if (maniptype != NF_NAT_MANIP_DST)
288                 return true;
289
290         switch (greh->flags & GRE_VERSION) {
291         case GRE_VERSION_0:
292                 /* We do not currently NAT any GREv0 packets.
293                  * Try to behave like "nf_nat_proto_unknown" */
294                 break;
295         case GRE_VERSION_1:
296                 pr_debug("call_id -> 0x%04x\n", ntohs(tuple->dst.u.gre.key));
297                 pgreh->call_id = tuple->dst.u.gre.key;
298                 break;
299         default:
300                 pr_debug("can't nat unknown GRE version\n");
301                 return false;
302         }
303 #endif
304         return true;
305 }
306
307 bool nf_nat_l4proto_manip_pkt(struct sk_buff *skb,
308                               const struct nf_nat_l3proto *l3proto,
309                               unsigned int iphdroff, unsigned int hdroff,
310                               const struct nf_conntrack_tuple *tuple,
311                               enum nf_nat_manip_type maniptype)
312 {
313         switch (tuple->dst.protonum) {
314         case IPPROTO_TCP:
315                 return tcp_manip_pkt(skb, l3proto, iphdroff, hdroff,
316                                      tuple, maniptype);
317         case IPPROTO_UDP:
318                 return udp_manip_pkt(skb, l3proto, iphdroff, hdroff,
319                                      tuple, maniptype);
320         case IPPROTO_UDPLITE:
321                 return udplite_manip_pkt(skb, l3proto, iphdroff, hdroff,
322                                          tuple, maniptype);
323         case IPPROTO_SCTP:
324                 return sctp_manip_pkt(skb, l3proto, iphdroff, hdroff,
325                                       tuple, maniptype);
326         case IPPROTO_ICMP:
327                 return icmp_manip_pkt(skb, l3proto, iphdroff, hdroff,
328                                       tuple, maniptype);
329         case IPPROTO_ICMPV6:
330                 return icmpv6_manip_pkt(skb, l3proto, iphdroff, hdroff,
331                                         tuple, maniptype);
332         case IPPROTO_DCCP:
333                 return dccp_manip_pkt(skb, l3proto, iphdroff, hdroff,
334                                       tuple, maniptype);
335         case IPPROTO_GRE:
336                 return gre_manip_pkt(skb, l3proto, iphdroff, hdroff,
337                                      tuple, maniptype);
338         }
339
340         /* If we don't know protocol -- no error, pass it unmodified. */
341         return true;
342 }
343 EXPORT_SYMBOL_GPL(nf_nat_l4proto_manip_pkt);