pxa: remove 2.6.37 support
[openwrt.git] / target / linux / lantiq / patches-3.3 / 0055-MIPS-lantiq-udp-in-kernel-redirect.patch
1 From 186a2683b8fc1730dff28b2201d7508501a1dee4 Mon Sep 17 00:00:00 2001
2 From: John Crispin <blogic@openwrt.org>
3 Date: Thu, 29 Sep 2011 20:29:54 +0200
4 Subject: [PATCH 55/70] MIPS: lantiq: udp in-kernel redirect
5
6 ---
7  include/linux/udp_redirect.h |   57 +++++++++++++
8  net/Kconfig                  |    6 ++
9  net/ipv4/Makefile            |    3 +
10  net/ipv4/udp.c               |   28 ++++++-
11  net/ipv4/udp_redirect_symb.c |  186 ++++++++++++++++++++++++++++++++++++++++++
12  5 files changed, 276 insertions(+), 4 deletions(-)
13  create mode 100644 include/linux/udp_redirect.h
14  create mode 100644 net/ipv4/udp_redirect_symb.c
15
16 --- /dev/null
17 +++ b/include/linux/udp_redirect.h
18 @@ -0,0 +1,57 @@
19 +#ifndef _UDP_REDIRECT_H
20 +#define _UDP_REDIRECT_H
21 +
22 +/******************************************************************************
23 +
24 +                               Copyright (c) 2006
25 +                            Infineon Technologies AG
26 +                     Am Campeon 1-12; 81726 Munich, Germany
27 +
28 +  THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
29 +  WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
30 +  SOFTWARE IS FREE OF CHARGE.
31 +
32 +  THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
33 +  ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
34 +  WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
35 +  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
36 +  OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
37 +  PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
38 +  PROPERTY INFRINGEMENT.
39 +
40 +  EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
41 +  FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
42 +  OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
43 +  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
44 +  DEALINGS IN THE SOFTWARE.
45 +
46 +******************************************************************************/
47 +
48 +/* ============================= */
49 +/* Includes                      */
50 +/* ============================= */
51 +#ifndef _LINUX_TYPES_H
52 +#include <linux/types.h>
53 +#endif
54 +
55 +
56 +/* ============================= */
57 +/* Definitions                   */
58 +/* ============================= */
59 +#define UDP_REDIRECT_MAGIC (void*)0x55445052L
60 +
61 +
62 +/* ============================= */
63 +/* Global variable declaration   */
64 +/* ============================= */
65 +extern int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb);
66 +extern int (*udpredirect_getfrag_fn)(void *p, char * to,
67 +                                     int offset, int fraglen, int odd,
68 +                                     struct sk_buff *skb);
69 +/* ============================= */
70 +/* Global function declaration   */
71 +/* ============================= */
72 +
73 +extern int udpredirect_getfrag(void *p, char * to, int offset,
74 +                               int fraglen, int odd, struct sk_buff *skb);
75 +#endif
76 --- a/net/Kconfig
77 +++ b/net/Kconfig
78 @@ -72,6 +72,12 @@ config INET
79  
80           Short answer: say Y.
81  
82 +config IFX_UDP_REDIRECT
83 +       bool "IFX Kernel Packet Interface for UDP redirection"
84 +       help
85 +         You can say Y here if you want to use hooks from kernel for
86 +         UDP redirection.
87 +
88  if INET
89  source "net/ipv4/Kconfig"
90  source "net/ipv6/Kconfig"
91 --- a/net/ipv4/Makefile
92 +++ b/net/ipv4/Makefile
93 @@ -14,6 +14,9 @@ obj-y     := route.o inetpeer.o protocol
94              inet_fragment.o ping.o
95  
96  obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
97 +ifneq ($(CONFIG_IFX_UDP_REDIRECT),)
98 +obj-$(CONFIG_IFX_UDP_REDIRECT) += udp_redirect_symb.o
99 +endif
100  obj-$(CONFIG_PROC_FS) += proc.o
101  obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
102  obj-$(CONFIG_IP_MROUTE) += ipmr.o
103 --- a/net/ipv4/udp.c
104 +++ b/net/ipv4/udp.c
105 @@ -108,6 +108,10 @@
106  #include <trace/events/udp.h>
107  #include "udp_impl.h"
108  
109 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
110 +#include <linux/udp_redirect.h>
111 +#endif
112 +
113  struct udp_table udp_table __read_mostly;
114  EXPORT_SYMBOL(udp_table);
115  
116 @@ -804,7 +808,7 @@ int udp_sendmsg(struct kiocb *iocb, stru
117         u8  tos;
118         int err, is_udplite = IS_UDPLITE(sk);
119         int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
120 -       int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
121 +       int (*getfrag)(void *, char *, int, int, int, struct sk_buff *) = NULL;
122         struct sk_buff *skb;
123         struct ip_options_data opt_copy;
124  
125 @@ -821,7 +825,13 @@ int udp_sendmsg(struct kiocb *iocb, stru
126         ipc.opt = NULL;
127         ipc.tx_flags = 0;
128  
129 -       getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
130 +/* UDPREDIRECT */
131 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
132 +       if(udpredirect_getfrag_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
133 +               getfrag = udpredirect_getfrag_fn;
134 +       else
135 +#endif /* IFX_UDP_REDIRECT */
136 +               getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
137  
138         fl4 = &inet->cork.fl.u.ip4;
139         if (up->pending) {
140 @@ -1625,6 +1635,7 @@ int __udp4_lib_rcv(struct sk_buff *skb,
141         struct rtable *rt = skb_rtable(skb);
142         __be32 saddr, daddr;
143         struct net *net = dev_net(skb->dev);
144 +       int ret = 0;
145  
146         /*
147          *  Validate the packet.
148 @@ -1657,7 +1668,16 @@ int __udp4_lib_rcv(struct sk_buff *skb,
149         sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
150  
151         if (sk != NULL) {
152 -               int ret = udp_queue_rcv_skb(sk, skb);
153 +       /* UDPREDIRECT */
154 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
155 +      if(udp_do_redirect_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
156 +      {
157 +         udp_do_redirect_fn(sk,skb);
158 +         kfree_skb(skb);
159 +         return(0);
160 +      }
161 +#endif
162 +               ret = udp_queue_rcv_skb(sk, skb);
163                 sock_put(sk);
164  
165                 /* a return value > 0 means to resubmit the input, but
166 @@ -1954,7 +1974,7 @@ struct proto udp_prot = {
167         .clear_sk          = sk_prot_clear_portaddr_nulls,
168  };
169  EXPORT_SYMBOL(udp_prot);
170 -
171 +EXPORT_SYMBOL(udp_rcv);
172  /* ------------------------------------------------------------------------ */
173  #ifdef CONFIG_PROC_FS
174  
175 --- /dev/null
176 +++ b/net/ipv4/udp_redirect_symb.c
177 @@ -0,0 +1,186 @@
178 +/******************************************************************************
179 +
180 +                               Copyright (c) 2006
181 +                            Infineon Technologies AG
182 +                     Am Campeon 1-12; 81726 Munich, Germany
183 +
184 +  THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
185 +  WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
186 +  SOFTWARE IS FREE OF CHARGE.
187 +
188 +  THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
189 +  ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
190 +  WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
191 +  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
192 +  OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
193 +  PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
194 +  PROPERTY INFRINGEMENT.
195 +
196 +  EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
197 +  FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
198 +  OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
199 +  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
200 +  DEALINGS IN THE SOFTWARE.
201 +
202 +******************************************************************************/
203 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
204 +/* ============================= */
205 +/* Includes                      */
206 +/* ============================= */
207 +#include <net/checksum.h>
208 +#include <net/udp.h>
209 +#include <linux/module.h>
210 +#include <linux/skbuff.h>
211 +#include <linux/udp_redirect.h>
212 +
213 +/* ============================= */
214 +/* Global variable definition    */
215 +/* ============================= */
216 +int (*udpredirect_getfrag_fn) (void *p, char * to, int offset,
217 +                               int fraglen, int odd, struct sk_buff *skb) = NULL;
218 +int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb) = NULL;
219 +
220 +/* ============================= */
221 +/* Local type definitions        */
222 +/* ============================= */
223 +struct udpfakehdr
224 +{
225 +  struct udphdr uh;
226 +  u32 saddr;
227 +  u32 daddr;
228 +  struct iovec *iov;
229 +  u32 wcheck;
230 +};
231 +
232 +/* ============================= */
233 +/* Local function declaration    */
234 +/* ============================= */
235 +static int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata,
236 +              struct iovec *iov, int offset, unsigned int len, __wsum *csump);
237 +
238 +static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
239 +                        int len);
240 +
241 +/* ============================= */
242 +/* Global function definition    */
243 +/* ============================= */
244 +
245 +/*
246 +   Copy of udp_getfrag() from udp.c
247 +   This function exists because no copy_from_user() is needed for udpredirect.
248 +*/
249 +
250 +int
251 +udpredirect_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
252 +{
253 +   struct iovec *iov = from;
254 +
255 +        if (skb->ip_summed == CHECKSUM_PARTIAL) {
256 +                if (udpredirect_memcpy_fromiovecend(to, iov, offset, len) < 0)
257 +                        return -EFAULT;
258 +        } else {
259 +                __wsum csum = 0;
260 +                if (udpredirect_csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
261 +                        return -EFAULT;
262 +                skb->csum = csum_block_add(skb->csum, csum, odd);
263 +        }
264 +        return 0;
265 +}
266 +
267 +static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
268 +                        int len)
269 +{
270 +        /* Skip over the finished iovecs */
271 +        while (offset >= iov->iov_len) {
272 +                offset -= iov->iov_len;
273 +                iov++;
274 +        }
275 +
276 +        while (len > 0) {
277 +                u8 __user *base = iov->iov_base + offset;
278 +                int copy = min_t(unsigned int, len, iov->iov_len - offset);
279 +
280 +                offset = 0;
281 +                memcpy(kdata, base, copy);
282 +                len -= copy;
283 +                kdata += copy;
284 +                iov++;
285 +        }
286 +
287 +        return 0;
288 +}
289 +
290 +/*
291 +   Copy of csum_partial_copy_fromiovecend() from iovec.c
292 +   This function exists because no copy_from_user() is needed for udpredirect.
293 +*/
294 +
295 +int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
296 +                                int offset, unsigned int len, __wsum *csump)
297 +{
298 +       __wsum csum = *csump;
299 +       int partial_cnt = 0, err = 0;
300 +
301 +       /* Skip over the finished iovecs */
302 +       while (offset >= iov->iov_len) {
303 +               offset -= iov->iov_len;
304 +               iov++;
305 +       }
306 +
307 +       while (len > 0) {
308 +               u8 __user *base = iov->iov_base + offset;
309 +               int copy = min_t(unsigned int, len, iov->iov_len - offset);
310 +
311 +               offset = 0;
312 +
313 +               /* There is a remnant from previous iov. */
314 +               if (partial_cnt) {
315 +                       int par_len = 4 - partial_cnt;
316 +
317 +                       /* iov component is too short ... */
318 +                       if (par_len > copy) {
319 +                               memcpy(kdata, base, copy);
320 +                               kdata += copy;
321 +                               base  += copy;
322 +                               partial_cnt += copy;
323 +                               len   -= copy;
324 +                               iov++;
325 +                               if (len)
326 +                                       continue;
327 +                               *csump = csum_partial(kdata - partial_cnt,
328 +                                                        partial_cnt, csum);
329 +                               goto out;
330 +                       }
331 +                       memcpy(kdata, base, par_len);
332 +                       csum = csum_partial(kdata - partial_cnt, 4, csum);
333 +                       kdata += par_len;
334 +                       base  += par_len;
335 +                       copy  -= par_len;
336 +                       len   -= par_len;
337 +                       partial_cnt = 0;
338 +               }
339 +
340 +               if (len > copy) {
341 +                       partial_cnt = copy % 4;
342 +                       if (partial_cnt) {
343 +                               copy -= partial_cnt;
344 +                               memcpy(kdata + copy, base + copy, partial_cnt);
345 +                       }
346 +               }
347 +
348 +               if (copy) {
349 +                       csum = csum_partial_copy_nocheck(base, kdata, copy, csum);
350 +               }
351 +               len   -= copy + partial_cnt;
352 +               kdata += copy + partial_cnt;
353 +               iov++;
354 +       }
355 +        *csump = csum;
356 +out:
357 +       return err;
358 +}
359 +
360 +EXPORT_SYMBOL(udpredirect_getfrag);
361 +EXPORT_SYMBOL(udp_do_redirect_fn);
362 +EXPORT_SYMBOL(udpredirect_getfrag_fn);
363 +#endif /* CONFIG_IFX_UDP_REDIRECT* */