diff options
author | Adrian Bunk <bunk@stusta.de> | 2006-11-13 19:02:22 -0500 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2006-12-03 00:22:23 -0500 |
commit | 90833aa4f496d69ca374af6acef7d1614c8693ff (patch) | |
tree | dbac818cc40ab12d493c45778febf6b7a768f757 /net/core | |
parent | d7f7365f5776723da6df73540d855069c2daaa5c (diff) |
[NET]: The scheduled removal of the frame diverter.
This patch contains the scheduled removal of the frame diverter.
Signed-off-by: Adrian Bunk <bunk@stusta.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r-- | net/core/Makefile | 1 | ||||
-rw-r--r-- | net/core/dev.c | 20 | ||||
-rw-r--r-- | net/core/dv.c | 546 | ||||
-rw-r--r-- | net/core/sysctl_net_core.c | 14 |
4 files changed, 4 insertions, 577 deletions
diff --git a/net/core/Makefile b/net/core/Makefile index 119568077dab..73272d506e93 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
@@ -12,7 +12,6 @@ obj-y += dev.o ethtool.o dev_mcast.o dst.o netevent.o \ | |||
12 | 12 | ||
13 | obj-$(CONFIG_XFRM) += flow.o | 13 | obj-$(CONFIG_XFRM) += flow.o |
14 | obj-$(CONFIG_SYSFS) += net-sysfs.o | 14 | obj-$(CONFIG_SYSFS) += net-sysfs.o |
15 | obj-$(CONFIG_NET_DIVERT) += dv.o | ||
16 | obj-$(CONFIG_NET_PKTGEN) += pktgen.o | 15 | obj-$(CONFIG_NET_PKTGEN) += pktgen.o |
17 | obj-$(CONFIG_WIRELESS_EXT) += wireless.o | 16 | obj-$(CONFIG_WIRELESS_EXT) += wireless.o |
18 | obj-$(CONFIG_NETPOLL) += netpoll.o | 17 | obj-$(CONFIG_NETPOLL) += netpoll.o |
diff --git a/net/core/dev.c b/net/core/dev.c index 411c2428d268..5bf13b132dd7 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -98,7 +98,6 @@ | |||
98 | #include <linux/seq_file.h> | 98 | #include <linux/seq_file.h> |
99 | #include <linux/stat.h> | 99 | #include <linux/stat.h> |
100 | #include <linux/if_bridge.h> | 100 | #include <linux/if_bridge.h> |
101 | #include <linux/divert.h> | ||
102 | #include <net/dst.h> | 101 | #include <net/dst.h> |
103 | #include <net/pkt_sched.h> | 102 | #include <net/pkt_sched.h> |
104 | #include <net/checksum.h> | 103 | #include <net/checksum.h> |
@@ -1827,8 +1826,6 @@ int netif_receive_skb(struct sk_buff *skb) | |||
1827 | ncls: | 1826 | ncls: |
1828 | #endif | 1827 | #endif |
1829 | 1828 | ||
1830 | handle_diverter(skb); | ||
1831 | |||
1832 | if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) | 1829 | if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) |
1833 | goto out; | 1830 | goto out; |
1834 | 1831 | ||
@@ -2898,10 +2895,6 @@ int register_netdevice(struct net_device *dev) | |||
2898 | spin_lock_init(&dev->ingress_lock); | 2895 | spin_lock_init(&dev->ingress_lock); |
2899 | #endif | 2896 | #endif |
2900 | 2897 | ||
2901 | ret = alloc_divert_blk(dev); | ||
2902 | if (ret) | ||
2903 | goto out; | ||
2904 | |||
2905 | dev->iflink = -1; | 2898 | dev->iflink = -1; |
2906 | 2899 | ||
2907 | /* Init, if this function is available */ | 2900 | /* Init, if this function is available */ |
@@ -2910,13 +2903,13 @@ int register_netdevice(struct net_device *dev) | |||
2910 | if (ret) { | 2903 | if (ret) { |
2911 | if (ret > 0) | 2904 | if (ret > 0) |
2912 | ret = -EIO; | 2905 | ret = -EIO; |
2913 | goto out_err; | 2906 | goto out; |
2914 | } | 2907 | } |
2915 | } | 2908 | } |
2916 | 2909 | ||
2917 | if (!dev_valid_name(dev->name)) { | 2910 | if (!dev_valid_name(dev->name)) { |
2918 | ret = -EINVAL; | 2911 | ret = -EINVAL; |
2919 | goto out_err; | 2912 | goto out; |
2920 | } | 2913 | } |
2921 | 2914 | ||
2922 | dev->ifindex = dev_new_index(); | 2915 | dev->ifindex = dev_new_index(); |
@@ -2930,7 +2923,7 @@ int register_netdevice(struct net_device *dev) | |||
2930 | = hlist_entry(p, struct net_device, name_hlist); | 2923 | = hlist_entry(p, struct net_device, name_hlist); |
2931 | if (!strncmp(d->name, dev->name, IFNAMSIZ)) { | 2924 | if (!strncmp(d->name, dev->name, IFNAMSIZ)) { |
2932 | ret = -EEXIST; | 2925 | ret = -EEXIST; |
2933 | goto out_err; | 2926 | goto out; |
2934 | } | 2927 | } |
2935 | } | 2928 | } |
2936 | 2929 | ||
@@ -2974,7 +2967,7 @@ int register_netdevice(struct net_device *dev) | |||
2974 | 2967 | ||
2975 | ret = netdev_register_sysfs(dev); | 2968 | ret = netdev_register_sysfs(dev); |
2976 | if (ret) | 2969 | if (ret) |
2977 | goto out_err; | 2970 | goto out; |
2978 | dev->reg_state = NETREG_REGISTERED; | 2971 | dev->reg_state = NETREG_REGISTERED; |
2979 | 2972 | ||
2980 | /* | 2973 | /* |
@@ -3001,9 +2994,6 @@ int register_netdevice(struct net_device *dev) | |||
3001 | 2994 | ||
3002 | out: | 2995 | out: |
3003 | return ret; | 2996 | return ret; |
3004 | out_err: | ||
3005 | free_divert_blk(dev); | ||
3006 | goto out; | ||
3007 | } | 2997 | } |
3008 | 2998 | ||
3009 | /** | 2999 | /** |
@@ -3320,8 +3310,6 @@ int unregister_netdevice(struct net_device *dev) | |||
3320 | /* Notifier chain MUST detach us from master device. */ | 3310 | /* Notifier chain MUST detach us from master device. */ |
3321 | BUG_TRAP(!dev->master); | 3311 | BUG_TRAP(!dev->master); |
3322 | 3312 | ||
3323 | free_divert_blk(dev); | ||
3324 | |||
3325 | /* Finish processing unregister after unlock */ | 3313 | /* Finish processing unregister after unlock */ |
3326 | net_set_todo(dev); | 3314 | net_set_todo(dev); |
3327 | 3315 | ||
diff --git a/net/core/dv.c b/net/core/dv.c deleted file mode 100644 index 29ee77f15932..000000000000 --- a/net/core/dv.c +++ /dev/null | |||
@@ -1,546 +0,0 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * Generic frame diversion | ||
7 | * | ||
8 | * Authors: | ||
9 | * Benoit LOCHER: initial integration within the kernel with support for ethernet | ||
10 | * Dave Miller: improvement on the code (correctness, performance and source files) | ||
11 | * | ||
12 | */ | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/types.h> | ||
15 | #include <linux/kernel.h> | ||
16 | #include <linux/sched.h> | ||
17 | #include <linux/string.h> | ||
18 | #include <linux/mm.h> | ||
19 | #include <linux/socket.h> | ||
20 | #include <linux/in.h> | ||
21 | #include <linux/inet.h> | ||
22 | #include <linux/ip.h> | ||
23 | #include <linux/udp.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/etherdevice.h> | ||
26 | #include <linux/skbuff.h> | ||
27 | #include <linux/capability.h> | ||
28 | #include <linux/errno.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <net/dst.h> | ||
31 | #include <net/arp.h> | ||
32 | #include <net/sock.h> | ||
33 | #include <net/ipv6.h> | ||
34 | #include <net/ip.h> | ||
35 | #include <asm/uaccess.h> | ||
36 | #include <asm/system.h> | ||
37 | #include <asm/checksum.h> | ||
38 | #include <linux/divert.h> | ||
39 | #include <linux/sockios.h> | ||
40 | |||
41 | const char sysctl_divert_version[32]="0.46"; /* Current version */ | ||
42 | |||
43 | static int __init dv_init(void) | ||
44 | { | ||
45 | return 0; | ||
46 | } | ||
47 | module_init(dv_init); | ||
48 | |||
49 | /* | ||
50 | * Allocate a divert_blk for a device. This must be an ethernet nic. | ||
51 | */ | ||
52 | int alloc_divert_blk(struct net_device *dev) | ||
53 | { | ||
54 | int alloc_size = (sizeof(struct divert_blk) + 3) & ~3; | ||
55 | |||
56 | dev->divert = NULL; | ||
57 | if (dev->type == ARPHRD_ETHER) { | ||
58 | dev->divert = kzalloc(alloc_size, GFP_KERNEL); | ||
59 | if (dev->divert == NULL) { | ||
60 | printk(KERN_INFO "divert: unable to allocate divert_blk for %s\n", | ||
61 | dev->name); | ||
62 | return -ENOMEM; | ||
63 | } | ||
64 | dev_hold(dev); | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | * Free a divert_blk allocated by the above function, if it was | ||
72 | * allocated on that device. | ||
73 | */ | ||
74 | void free_divert_blk(struct net_device *dev) | ||
75 | { | ||
76 | if (dev->divert) { | ||
77 | kfree(dev->divert); | ||
78 | dev->divert=NULL; | ||
79 | dev_put(dev); | ||
80 | } | ||
81 | } | ||
82 | |||
83 | /* | ||
84 | * Adds a tcp/udp (source or dest) port to an array | ||
85 | */ | ||
86 | static int add_port(u16 ports[], u16 port) | ||
87 | { | ||
88 | int i; | ||
89 | |||
90 | if (port == 0) | ||
91 | return -EINVAL; | ||
92 | |||
93 | /* Storing directly in network format for performance, | ||
94 | * thanks Dave :) | ||
95 | */ | ||
96 | port = htons(port); | ||
97 | |||
98 | for (i = 0; i < MAX_DIVERT_PORTS; i++) { | ||
99 | if (ports[i] == port) | ||
100 | return -EALREADY; | ||
101 | } | ||
102 | |||
103 | for (i = 0; i < MAX_DIVERT_PORTS; i++) { | ||
104 | if (ports[i] == 0) { | ||
105 | ports[i] = port; | ||
106 | return 0; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | return -ENOBUFS; | ||
111 | } | ||
112 | |||
113 | /* | ||
114 | * Removes a port from an array tcp/udp (source or dest) | ||
115 | */ | ||
116 | static int remove_port(u16 ports[], u16 port) | ||
117 | { | ||
118 | int i; | ||
119 | |||
120 | if (port == 0) | ||
121 | return -EINVAL; | ||
122 | |||
123 | /* Storing directly in network format for performance, | ||
124 | * thanks Dave ! | ||
125 | */ | ||
126 | port = htons(port); | ||
127 | |||
128 | for (i = 0; i < MAX_DIVERT_PORTS; i++) { | ||
129 | if (ports[i] == port) { | ||
130 | ports[i] = 0; | ||
131 | return 0; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | return -EINVAL; | ||
136 | } | ||
137 | |||
138 | /* Some basic sanity checks on the arguments passed to divert_ioctl() */ | ||
139 | static int check_args(struct divert_cf *div_cf, struct net_device **dev) | ||
140 | { | ||
141 | char devname[32]; | ||
142 | int ret; | ||
143 | |||
144 | if (dev == NULL) | ||
145 | return -EFAULT; | ||
146 | |||
147 | /* GETVERSION: all other args are unused */ | ||
148 | if (div_cf->cmd == DIVCMD_GETVERSION) | ||
149 | return 0; | ||
150 | |||
151 | /* Network device index should reasonably be between 0 and 1000 :) */ | ||
152 | if (div_cf->dev_index < 0 || div_cf->dev_index > 1000) | ||
153 | return -EINVAL; | ||
154 | |||
155 | /* Let's try to find the ifname */ | ||
156 | sprintf(devname, "eth%d", div_cf->dev_index); | ||
157 | *dev = dev_get_by_name(devname); | ||
158 | |||
159 | /* dev should NOT be null */ | ||
160 | if (*dev == NULL) | ||
161 | return -EINVAL; | ||
162 | |||
163 | ret = 0; | ||
164 | |||
165 | /* user issuing the ioctl must be a super one :) */ | ||
166 | if (!capable(CAP_SYS_ADMIN)) { | ||
167 | ret = -EPERM; | ||
168 | goto out; | ||
169 | } | ||
170 | |||
171 | /* Device must have a divert_blk member NOT null */ | ||
172 | if ((*dev)->divert == NULL) | ||
173 | ret = -EINVAL; | ||
174 | out: | ||
175 | dev_put(*dev); | ||
176 | return ret; | ||
177 | } | ||
178 | |||
179 | /* | ||
180 | * control function of the diverter | ||
181 | */ | ||
182 | #if 0 | ||
183 | #define DVDBG(a) \ | ||
184 | printk(KERN_DEBUG "divert_ioctl() line %d %s\n", __LINE__, (a)) | ||
185 | #else | ||
186 | #define DVDBG(a) | ||
187 | #endif | ||
188 | |||
189 | int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg) | ||
190 | { | ||
191 | struct divert_cf div_cf; | ||
192 | struct divert_blk *div_blk; | ||
193 | struct net_device *dev; | ||
194 | int ret; | ||
195 | |||
196 | switch (cmd) { | ||
197 | case SIOCGIFDIVERT: | ||
198 | DVDBG("SIOCGIFDIVERT, copy_from_user"); | ||
199 | if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) | ||
200 | return -EFAULT; | ||
201 | DVDBG("before check_args"); | ||
202 | ret = check_args(&div_cf, &dev); | ||
203 | if (ret) | ||
204 | return ret; | ||
205 | DVDBG("after checkargs"); | ||
206 | div_blk = dev->divert; | ||
207 | |||
208 | DVDBG("befre switch()"); | ||
209 | switch (div_cf.cmd) { | ||
210 | case DIVCMD_GETSTATUS: | ||
211 | /* Now, just give the user the raw divert block | ||
212 | * for him to play with :) | ||
213 | */ | ||
214 | if (copy_to_user(div_cf.arg1.ptr, dev->divert, | ||
215 | sizeof(struct divert_blk))) | ||
216 | return -EFAULT; | ||
217 | break; | ||
218 | |||
219 | case DIVCMD_GETVERSION: | ||
220 | DVDBG("GETVERSION: checking ptr"); | ||
221 | if (div_cf.arg1.ptr == NULL) | ||
222 | return -EINVAL; | ||
223 | DVDBG("GETVERSION: copying data to userland"); | ||
224 | if (copy_to_user(div_cf.arg1.ptr, | ||
225 | sysctl_divert_version, 32)) | ||
226 | return -EFAULT; | ||
227 | DVDBG("GETVERSION: data copied"); | ||
228 | break; | ||
229 | |||
230 | default: | ||
231 | return -EINVAL; | ||
232 | } | ||
233 | |||
234 | break; | ||
235 | |||
236 | case SIOCSIFDIVERT: | ||
237 | if (copy_from_user(&div_cf, arg, sizeof(struct divert_cf))) | ||
238 | return -EFAULT; | ||
239 | |||
240 | ret = check_args(&div_cf, &dev); | ||
241 | if (ret) | ||
242 | return ret; | ||
243 | |||
244 | div_blk = dev->divert; | ||
245 | |||
246 | switch(div_cf.cmd) { | ||
247 | case DIVCMD_RESET: | ||
248 | div_blk->divert = 0; | ||
249 | div_blk->protos = DIVERT_PROTO_NONE; | ||
250 | memset(div_blk->tcp_dst, 0, | ||
251 | MAX_DIVERT_PORTS * sizeof(u16)); | ||
252 | memset(div_blk->tcp_src, 0, | ||
253 | MAX_DIVERT_PORTS * sizeof(u16)); | ||
254 | memset(div_blk->udp_dst, 0, | ||
255 | MAX_DIVERT_PORTS * sizeof(u16)); | ||
256 | memset(div_blk->udp_src, 0, | ||
257 | MAX_DIVERT_PORTS * sizeof(u16)); | ||
258 | return 0; | ||
259 | |||
260 | case DIVCMD_DIVERT: | ||
261 | switch(div_cf.arg1.int32) { | ||
262 | case DIVARG1_ENABLE: | ||
263 | if (div_blk->divert) | ||
264 | return -EALREADY; | ||
265 | div_blk->divert = 1; | ||
266 | break; | ||
267 | |||
268 | case DIVARG1_DISABLE: | ||
269 | if (!div_blk->divert) | ||
270 | return -EALREADY; | ||
271 | div_blk->divert = 0; | ||
272 | break; | ||
273 | |||
274 | default: | ||
275 | return -EINVAL; | ||
276 | } | ||
277 | |||
278 | break; | ||
279 | |||
280 | case DIVCMD_IP: | ||
281 | switch(div_cf.arg1.int32) { | ||
282 | case DIVARG1_ENABLE: | ||
283 | if (div_blk->protos & DIVERT_PROTO_IP) | ||
284 | return -EALREADY; | ||
285 | div_blk->protos |= DIVERT_PROTO_IP; | ||
286 | break; | ||
287 | |||
288 | case DIVARG1_DISABLE: | ||
289 | if (!(div_blk->protos & DIVERT_PROTO_IP)) | ||
290 | return -EALREADY; | ||
291 | div_blk->protos &= ~DIVERT_PROTO_IP; | ||
292 | break; | ||
293 | |||
294 | default: | ||
295 | return -EINVAL; | ||
296 | } | ||
297 | |||
298 | break; | ||
299 | |||
300 | case DIVCMD_TCP: | ||
301 | switch(div_cf.arg1.int32) { | ||
302 | case DIVARG1_ENABLE: | ||
303 | if (div_blk->protos & DIVERT_PROTO_TCP) | ||
304 | return -EALREADY; | ||
305 | div_blk->protos |= DIVERT_PROTO_TCP; | ||
306 | break; | ||
307 | |||
308 | case DIVARG1_DISABLE: | ||
309 | if (!(div_blk->protos & DIVERT_PROTO_TCP)) | ||
310 | return -EALREADY; | ||
311 | div_blk->protos &= ~DIVERT_PROTO_TCP; | ||
312 | break; | ||
313 | |||
314 | default: | ||
315 | return -EINVAL; | ||
316 | } | ||
317 | |||
318 | break; | ||
319 | |||
320 | case DIVCMD_TCPDST: | ||
321 | switch(div_cf.arg1.int32) { | ||
322 | case DIVARG1_ADD: | ||
323 | return add_port(div_blk->tcp_dst, | ||
324 | div_cf.arg2.uint16); | ||
325 | |||
326 | case DIVARG1_REMOVE: | ||
327 | return remove_port(div_blk->tcp_dst, | ||
328 | div_cf.arg2.uint16); | ||
329 | |||
330 | default: | ||
331 | return -EINVAL; | ||
332 | } | ||
333 | |||
334 | break; | ||
335 | |||
336 | case DIVCMD_TCPSRC: | ||
337 | switch(div_cf.arg1.int32) { | ||
338 | case DIVARG1_ADD: | ||
339 | return add_port(div_blk->tcp_src, | ||
340 | div_cf.arg2.uint16); | ||
341 | |||
342 | case DIVARG1_REMOVE: | ||
343 | return remove_port(div_blk->tcp_src, | ||
344 | div_cf.arg2.uint16); | ||
345 | |||
346 | default: | ||
347 | return -EINVAL; | ||
348 | } | ||
349 | |||
350 | break; | ||
351 | |||
352 | case DIVCMD_UDP: | ||
353 | switch(div_cf.arg1.int32) { | ||
354 | case DIVARG1_ENABLE: | ||
355 | if (div_blk->protos & DIVERT_PROTO_UDP) | ||
356 | return -EALREADY; | ||
357 | div_blk->protos |= DIVERT_PROTO_UDP; | ||
358 | break; | ||
359 | |||
360 | case DIVARG1_DISABLE: | ||
361 | if (!(div_blk->protos & DIVERT_PROTO_UDP)) | ||
362 | return -EALREADY; | ||
363 | div_blk->protos &= ~DIVERT_PROTO_UDP; | ||
364 | break; | ||
365 | |||
366 | default: | ||
367 | return -EINVAL; | ||
368 | } | ||
369 | |||
370 | break; | ||
371 | |||
372 | case DIVCMD_UDPDST: | ||
373 | switch(div_cf.arg1.int32) { | ||
374 | case DIVARG1_ADD: | ||
375 | return add_port(div_blk->udp_dst, | ||
376 | div_cf.arg2.uint16); | ||
377 | |||
378 | case DIVARG1_REMOVE: | ||
379 | return remove_port(div_blk->udp_dst, | ||
380 | div_cf.arg2.uint16); | ||
381 | |||
382 | default: | ||
383 | return -EINVAL; | ||
384 | } | ||
385 | |||
386 | break; | ||
387 | |||
388 | case DIVCMD_UDPSRC: | ||
389 | switch(div_cf.arg1.int32) { | ||
390 | case DIVARG1_ADD: | ||
391 | return add_port(div_blk->udp_src, | ||
392 | div_cf.arg2.uint16); | ||
393 | |||
394 | case DIVARG1_REMOVE: | ||
395 | return remove_port(div_blk->udp_src, | ||
396 | div_cf.arg2.uint16); | ||
397 | |||
398 | default: | ||
399 | return -EINVAL; | ||
400 | } | ||
401 | |||
402 | break; | ||
403 | |||
404 | case DIVCMD_ICMP: | ||
405 | switch(div_cf.arg1.int32) { | ||
406 | case DIVARG1_ENABLE: | ||
407 | if (div_blk->protos & DIVERT_PROTO_ICMP) | ||
408 | return -EALREADY; | ||
409 | div_blk->protos |= DIVERT_PROTO_ICMP; | ||
410 | break; | ||
411 | |||
412 | case DIVARG1_DISABLE: | ||
413 | if (!(div_blk->protos & DIVERT_PROTO_ICMP)) | ||
414 | return -EALREADY; | ||
415 | div_blk->protos &= ~DIVERT_PROTO_ICMP; | ||
416 | break; | ||
417 | |||
418 | default: | ||
419 | return -EINVAL; | ||
420 | } | ||
421 | |||
422 | break; | ||
423 | |||
424 | default: | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | break; | ||
429 | |||
430 | default: | ||
431 | return -EINVAL; | ||
432 | } | ||
433 | |||
434 | return 0; | ||
435 | } | ||
436 | |||
437 | |||
438 | /* | ||
439 | * Check if packet should have its dest mac address set to the box itself | ||
440 | * for diversion | ||
441 | */ | ||
442 | |||
443 | #define ETH_DIVERT_FRAME(skb) \ | ||
444 | memcpy(eth_hdr(skb), skb->dev->dev_addr, ETH_ALEN); \ | ||
445 | skb->pkt_type=PACKET_HOST | ||
446 | |||
447 | void divert_frame(struct sk_buff *skb) | ||
448 | { | ||
449 | struct ethhdr *eth = eth_hdr(skb); | ||
450 | struct iphdr *iph; | ||
451 | struct tcphdr *tcph; | ||
452 | struct udphdr *udph; | ||
453 | struct divert_blk *divert = skb->dev->divert; | ||
454 | int i, src, dst; | ||
455 | unsigned char *skb_data_end = skb->data + skb->len; | ||
456 | |||
457 | /* Packet is already aimed at us, return */ | ||
458 | if (!compare_ether_addr(eth->h_dest, skb->dev->dev_addr)) | ||
459 | return; | ||
460 | |||
461 | /* proto is not IP, do nothing */ | ||
462 | if (eth->h_proto != htons(ETH_P_IP)) | ||
463 | return; | ||
464 | |||
465 | /* Divert all IP frames ? */ | ||
466 | if (divert->protos & DIVERT_PROTO_IP) { | ||
467 | ETH_DIVERT_FRAME(skb); | ||
468 | return; | ||
469 | } | ||
470 | |||
471 | /* Check for possible (maliciously) malformed IP frame (thanks Dave) */ | ||
472 | iph = (struct iphdr *) skb->data; | ||
473 | if (((iph->ihl<<2)+(unsigned char*)(iph)) >= skb_data_end) { | ||
474 | printk(KERN_INFO "divert: malformed IP packet !\n"); | ||
475 | return; | ||
476 | } | ||
477 | |||
478 | switch (iph->protocol) { | ||
479 | /* Divert all ICMP frames ? */ | ||
480 | case IPPROTO_ICMP: | ||
481 | if (divert->protos & DIVERT_PROTO_ICMP) { | ||
482 | ETH_DIVERT_FRAME(skb); | ||
483 | return; | ||
484 | } | ||
485 | break; | ||
486 | |||
487 | /* Divert all TCP frames ? */ | ||
488 | case IPPROTO_TCP: | ||
489 | if (divert->protos & DIVERT_PROTO_TCP) { | ||
490 | ETH_DIVERT_FRAME(skb); | ||
491 | return; | ||
492 | } | ||
493 | |||
494 | /* Check for possible (maliciously) malformed IP | ||
495 | * frame (thanx Dave) | ||
496 | */ | ||
497 | tcph = (struct tcphdr *) | ||
498 | (((unsigned char *)iph) + (iph->ihl<<2)); | ||
499 | if (((unsigned char *)(tcph+1)) >= skb_data_end) { | ||
500 | printk(KERN_INFO "divert: malformed TCP packet !\n"); | ||
501 | return; | ||
502 | } | ||
503 | |||
504 | /* Divert some tcp dst/src ports only ?*/ | ||
505 | for (i = 0; i < MAX_DIVERT_PORTS; i++) { | ||
506 | dst = divert->tcp_dst[i]; | ||
507 | src = divert->tcp_src[i]; | ||
508 | if ((dst && dst == tcph->dest) || | ||
509 | (src && src == tcph->source)) { | ||
510 | ETH_DIVERT_FRAME(skb); | ||
511 | return; | ||
512 | } | ||
513 | } | ||
514 | break; | ||
515 | |||
516 | /* Divert all UDP frames ? */ | ||
517 | case IPPROTO_UDP: | ||
518 | if (divert->protos & DIVERT_PROTO_UDP) { | ||
519 | ETH_DIVERT_FRAME(skb); | ||
520 | return; | ||
521 | } | ||
522 | |||
523 | /* Check for possible (maliciously) malformed IP | ||
524 | * packet (thanks Dave) | ||
525 | */ | ||
526 | udph = (struct udphdr *) | ||
527 | (((unsigned char *)iph) + (iph->ihl<<2)); | ||
528 | if (((unsigned char *)(udph+1)) >= skb_data_end) { | ||
529 | printk(KERN_INFO | ||
530 | "divert: malformed UDP packet !\n"); | ||
531 | return; | ||
532 | } | ||
533 | |||
534 | /* Divert some udp dst/src ports only ? */ | ||
535 | for (i = 0; i < MAX_DIVERT_PORTS; i++) { | ||
536 | dst = divert->udp_dst[i]; | ||
537 | src = divert->udp_src[i]; | ||
538 | if ((dst && dst == udph->dest) || | ||
539 | (src && src == udph->source)) { | ||
540 | ETH_DIVERT_FRAME(skb); | ||
541 | return; | ||
542 | } | ||
543 | } | ||
544 | break; | ||
545 | } | ||
546 | } | ||
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 02534131d88e..1e75b1585460 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -21,10 +21,6 @@ extern __u32 sysctl_rmem_max; | |||
21 | 21 | ||
22 | extern int sysctl_core_destroy_delay; | 22 | extern int sysctl_core_destroy_delay; |
23 | 23 | ||
24 | #ifdef CONFIG_NET_DIVERT | ||
25 | extern char sysctl_divert_version[]; | ||
26 | #endif /* CONFIG_NET_DIVERT */ | ||
27 | |||
28 | #ifdef CONFIG_XFRM | 24 | #ifdef CONFIG_XFRM |
29 | extern u32 sysctl_xfrm_aevent_etime; | 25 | extern u32 sysctl_xfrm_aevent_etime; |
30 | extern u32 sysctl_xfrm_aevent_rseqth; | 26 | extern u32 sysctl_xfrm_aevent_rseqth; |
@@ -105,16 +101,6 @@ ctl_table core_table[] = { | |||
105 | .mode = 0644, | 101 | .mode = 0644, |
106 | .proc_handler = &proc_dointvec | 102 | .proc_handler = &proc_dointvec |
107 | }, | 103 | }, |
108 | #ifdef CONFIG_NET_DIVERT | ||
109 | { | ||
110 | .ctl_name = NET_CORE_DIVERT_VERSION, | ||
111 | .procname = "divert_version", | ||
112 | .data = (void *)sysctl_divert_version, | ||
113 | .maxlen = 32, | ||
114 | .mode = 0444, | ||
115 | .proc_handler = &proc_dostring | ||
116 | }, | ||
117 | #endif /* CONFIG_NET_DIVERT */ | ||
118 | #ifdef CONFIG_XFRM | 104 | #ifdef CONFIG_XFRM |
119 | { | 105 | { |
120 | .ctl_name = NET_CORE_AEVENT_ETIME, | 106 | .ctl_name = NET_CORE_AEVENT_ETIME, |