update to 2.6.39.1
[openwrt/openwrt.git] / target / linux / lantiq / patches-2.6.39 / 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
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
283 if (len > 0xFFFF)
284 @@ -818,7 +822,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 if (up->pending) {
298 /*
299 @@ -1608,6 +1618,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 @@ -1640,7 +1651,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 @@ -1937,7 +1957,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"