1 From 14ff975c660696fa636e8d6b58d0abed0ddc72ce 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 22/24] MIPS: lantiq: adds udp in-kernel redirect
7 include/linux/udp_redirect.h | 57 +++++++++++++
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
16 diff --git a/include/linux/udp_redirect.h b/include/linux/udp_redirect.h
18 index 0000000..de1e64f
20 +++ b/include/linux/udp_redirect.h
22 +#ifndef _UDP_REDIRECT_H
23 +#define _UDP_REDIRECT_H
25 +/******************************************************************************
28 + Infineon Technologies AG
29 + Am Campeon 1-12; 81726 Munich, Germany
31 + THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
32 + WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
33 + SOFTWARE IS FREE OF CHARGE.
35 + THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
36 + ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
37 + WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
38 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
39 + OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
40 + PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
41 + PROPERTY INFRINGEMENT.
43 + EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
44 + FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
45 + OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
46 + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
47 + DEALINGS IN THE SOFTWARE.
49 +******************************************************************************/
51 +/* ============================= */
53 +/* ============================= */
54 +#ifndef _LINUX_TYPES_H
55 +#include <linux/types.h>
59 +/* ============================= */
61 +/* ============================= */
62 +#define UDP_REDIRECT_MAGIC (void*)0x55445052L
65 +/* ============================= */
66 +/* Global variable declaration */
67 +/* ============================= */
68 +extern int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb);
69 +extern int (*udpredirect_getfrag_fn)(void *p, char * to,
70 + int offset, int fraglen, int odd,
71 + struct sk_buff *skb);
72 +/* ============================= */
73 +/* Global function declaration */
74 +/* ============================= */
76 +extern int udpredirect_getfrag(void *p, char * to, int offset,
77 + int fraglen, int odd, struct sk_buff *skb);
79 diff --git a/net/Kconfig b/net/Kconfig
80 index a073148..d13e3fa 100644
83 @@ -72,6 +72,12 @@ config INET
87 +config IFX_UDP_REDIRECT
88 + bool "IFX Kernel Packet Interface for UDP redirection"
90 + You can say Y here if you want to use hooks from kernel for
94 source "net/ipv4/Kconfig"
95 source "net/ipv6/Kconfig"
96 diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile
97 index f2dc69c..6badd72 100644
98 --- a/net/ipv4/Makefile
99 +++ b/net/ipv4/Makefile
100 @@ -14,6 +14,9 @@ obj-y := route.o inetpeer.o protocol.o \
101 inet_fragment.o ping.o
103 obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o
104 +ifneq ($(CONFIG_IFX_UDP_REDIRECT),)
105 +obj-$(CONFIG_IFX_UDP_REDIRECT) += udp_redirect_symb.o
107 obj-$(CONFIG_PROC_FS) += proc.o
108 obj-$(CONFIG_IP_MULTIPLE_TABLES) += fib_rules.o
109 obj-$(CONFIG_IP_MROUTE) += ipmr.o
110 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
111 index 1b5a193..4d15cf6 100644
115 #include <trace/events/udp.h>
116 #include "udp_impl.h"
118 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
119 +#include <linux/udp_redirect.h>
122 struct udp_table udp_table __read_mostly;
123 EXPORT_SYMBOL(udp_table);
125 @@ -803,7 +807,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
127 int err, is_udplite = IS_UDPLITE(sk);
128 int corkreq = up->corkflag || msg->msg_flags&MSG_MORE;
129 - int (*getfrag)(void *, char *, int, int, int, struct sk_buff *);
130 + int (*getfrag)(void *, char *, int, int, int, struct sk_buff *) = NULL;
132 struct ip_options_data opt_copy;
134 @@ -820,7 +824,13 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
138 - getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
140 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
141 + if(udpredirect_getfrag_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
142 + getfrag = udpredirect_getfrag_fn;
144 +#endif /* IFX_UDP_REDIRECT */
145 + getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag;
147 fl4 = &inet->cork.fl.u.ip4;
149 @@ -1621,6 +1631,7 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
150 struct rtable *rt = skb_rtable(skb);
152 struct net *net = dev_net(skb->dev);
156 * Validate the packet.
157 @@ -1653,7 +1664,16 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct udp_table *udptable,
158 sk = __udp4_lib_lookup_skb(skb, uh->source, uh->dest, udptable);
161 - int ret = udp_queue_rcv_skb(sk, skb);
163 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
164 + if(udp_do_redirect_fn && sk->sk_user_data == UDP_REDIRECT_MAGIC)
166 + udp_do_redirect_fn(sk,skb);
171 + ret = udp_queue_rcv_skb(sk, skb);
174 /* a return value > 0 means to resubmit the input, but
175 @@ -1950,7 +1970,7 @@ struct proto udp_prot = {
176 .clear_sk = sk_prot_clear_portaddr_nulls,
178 EXPORT_SYMBOL(udp_prot);
180 +EXPORT_SYMBOL(udp_rcv);
181 /* ------------------------------------------------------------------------ */
182 #ifdef CONFIG_PROC_FS
184 diff --git a/net/ipv4/udp_redirect_symb.c b/net/ipv4/udp_redirect_symb.c
186 index 0000000..5617e86
188 +++ b/net/ipv4/udp_redirect_symb.c
190 +/******************************************************************************
193 + Infineon Technologies AG
194 + Am Campeon 1-12; 81726 Munich, Germany
196 + THE DELIVERY OF THIS SOFTWARE AS WELL AS THE HEREBY GRANTED NON-EXCLUSIVE,
197 + WORLDWIDE LICENSE TO USE, COPY, MODIFY, DISTRIBUTE AND SUBLICENSE THIS
198 + SOFTWARE IS FREE OF CHARGE.
200 + THE LICENSED SOFTWARE IS PROVIDED "AS IS" AND INFINEON EXPRESSLY DISCLAIMS
201 + ALL REPRESENTATIONS AND WARRANTIES, WHETHER EXPRESS OR IMPLIED, INCLUDING
202 + WITHOUT LIMITATION, WARRANTIES OR REPRESENTATIONS OF WORKMANSHIP,
203 + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, DURABILITY, THAT THE
204 + OPERATING OF THE LICENSED SOFTWARE WILL BE ERROR FREE OR FREE OF ANY THIRD
205 + PARTY CLAIMS, INCLUDING WITHOUT LIMITATION CLAIMS OF THIRD PARTY INTELLECTUAL
206 + PROPERTY INFRINGEMENT.
208 + EXCEPT FOR ANY LIABILITY DUE TO WILFUL ACTS OR GROSS NEGLIGENCE AND EXCEPT
209 + FOR ANY PERSONAL INJURY INFINEON SHALL IN NO EVENT BE LIABLE FOR ANY CLAIM
210 + OR DAMAGES OF ANY KIND, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
211 + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
212 + DEALINGS IN THE SOFTWARE.
214 +******************************************************************************/
215 +#if defined(CONFIG_IFX_UDP_REDIRECT) || defined(CONFIG_IFX_UDP_REDIRECT_MODULE)
216 +/* ============================= */
218 +/* ============================= */
219 +#include <net/checksum.h>
220 +#include <net/udp.h>
221 +#include <linux/module.h>
222 +#include <linux/skbuff.h>
223 +#include <linux/udp_redirect.h>
225 +/* ============================= */
226 +/* Global variable definition */
227 +/* ============================= */
228 +int (*udpredirect_getfrag_fn) (void *p, char * to, int offset,
229 + int fraglen, int odd, struct sk_buff *skb) = NULL;
230 +int (*udp_do_redirect_fn)(struct sock *sk, struct sk_buff *skb) = NULL;
232 +/* ============================= */
233 +/* Local type definitions */
234 +/* ============================= */
244 +/* ============================= */
245 +/* Local function declaration */
246 +/* ============================= */
247 +static int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata,
248 + struct iovec *iov, int offset, unsigned int len, __wsum *csump);
250 +static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
253 +/* ============================= */
254 +/* Global function definition */
255 +/* ============================= */
258 + Copy of udp_getfrag() from udp.c
259 + This function exists because no copy_from_user() is needed for udpredirect.
263 +udpredirect_getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb)
265 + struct iovec *iov = from;
267 + if (skb->ip_summed == CHECKSUM_PARTIAL) {
268 + if (udpredirect_memcpy_fromiovecend(to, iov, offset, len) < 0)
272 + if (udpredirect_csum_partial_copy_fromiovecend(to, iov, offset, len, &csum) < 0)
274 + skb->csum = csum_block_add(skb->csum, csum, odd);
279 +static int udpredirect_memcpy_fromiovecend(unsigned char *kdata, struct iovec *iov, int offset,
282 + /* Skip over the finished iovecs */
283 + while (offset >= iov->iov_len) {
284 + offset -= iov->iov_len;
289 + u8 __user *base = iov->iov_base + offset;
290 + int copy = min_t(unsigned int, len, iov->iov_len - offset);
293 + memcpy(kdata, base, copy);
303 + Copy of csum_partial_copy_fromiovecend() from iovec.c
304 + This function exists because no copy_from_user() is needed for udpredirect.
307 +int udpredirect_csum_partial_copy_fromiovecend(unsigned char *kdata, struct iovec *iov,
308 + int offset, unsigned int len, __wsum *csump)
310 + __wsum csum = *csump;
311 + int partial_cnt = 0, err = 0;
313 + /* Skip over the finished iovecs */
314 + while (offset >= iov->iov_len) {
315 + offset -= iov->iov_len;
320 + u8 __user *base = iov->iov_base + offset;
321 + int copy = min_t(unsigned int, len, iov->iov_len - offset);
325 + /* There is a remnant from previous iov. */
327 + int par_len = 4 - partial_cnt;
329 + /* iov component is too short ... */
330 + if (par_len > copy) {
331 + memcpy(kdata, base, copy);
334 + partial_cnt += copy;
339 + *csump = csum_partial(kdata - partial_cnt,
340 + partial_cnt, csum);
343 + memcpy(kdata, base, par_len);
344 + csum = csum_partial(kdata - partial_cnt, 4, csum);
353 + partial_cnt = copy % 4;
355 + copy -= partial_cnt;
356 + memcpy(kdata + copy, base + copy, partial_cnt);
361 + csum = csum_partial_copy_nocheck(base, kdata, copy, csum);
363 + len -= copy + partial_cnt;
364 + kdata += copy + partial_cnt;
372 +EXPORT_SYMBOL(udpredirect_getfrag);
373 +EXPORT_SYMBOL(udp_do_redirect_fn);
374 +EXPORT_SYMBOL(udpredirect_getfrag_fn);
375 +#endif /* CONFIG_IFX_UDP_REDIRECT* */