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