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 | |
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>
-rw-r--r-- | Documentation/feature-removal-schedule.txt | 15 | ||||
-rw-r--r-- | drivers/net/Space.c | 1 | ||||
-rw-r--r-- | include/linux/Kbuild | 1 | ||||
-rw-r--r-- | include/linux/divert.h | 132 | ||||
-rw-r--r-- | include/linux/netdevice.h | 6 | ||||
-rw-r--r-- | include/linux/sockios.h | 4 | ||||
-rw-r--r-- | net/Kconfig | 27 | ||||
-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 | ||||
-rw-r--r-- | net/socket.c | 6 |
12 files changed, 6 insertions, 767 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index d52c4aaaf17f..b3949cd3d013 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt | |||
@@ -227,21 +227,6 @@ Who: Patrick McHardy <kaber@trash.net> | |||
227 | 227 | ||
228 | --------------------------- | 228 | --------------------------- |
229 | 229 | ||
230 | What: frame diverter | ||
231 | When: November 2006 | ||
232 | Why: The frame diverter is included in most distribution kernels, but is | ||
233 | broken. It does not correctly handle many things: | ||
234 | - IPV6 | ||
235 | - non-linear skb's | ||
236 | - network device RCU on removal | ||
237 | - input frames not correctly checked for protocol errors | ||
238 | It also adds allocation overhead even if not enabled. | ||
239 | It is not clear if anyone is still using it. | ||
240 | Who: Stephen Hemminger <shemminger@osdl.org> | ||
241 | |||
242 | --------------------------- | ||
243 | |||
244 | |||
245 | What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment | 230 | What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment |
246 | When: October 2008 | 231 | When: October 2008 |
247 | Why: The stacking of class devices makes these values misleading and | 232 | Why: The stacking of class devices makes these values misleading and |
diff --git a/drivers/net/Space.c b/drivers/net/Space.c index a67f5efc983f..602ed31a5dd9 100644 --- a/drivers/net/Space.c +++ b/drivers/net/Space.c | |||
@@ -33,7 +33,6 @@ | |||
33 | #include <linux/errno.h> | 33 | #include <linux/errno.h> |
34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
35 | #include <linux/netlink.h> | 35 | #include <linux/netlink.h> |
36 | #include <linux/divert.h> | ||
37 | 36 | ||
38 | /* A unified ethernet device probe. This is the easiest way to have every | 37 | /* A unified ethernet device probe. This is the easiest way to have every |
39 | ethernet adaptor have the name "eth[0123...]". | 38 | ethernet adaptor have the name "eth[0123...]". |
diff --git a/include/linux/Kbuild b/include/linux/Kbuild index a1155a2beb32..d7e04689304c 100644 --- a/include/linux/Kbuild +++ b/include/linux/Kbuild | |||
@@ -193,7 +193,6 @@ unifdef-y += cuda.h | |||
193 | unifdef-y += cyclades.h | 193 | unifdef-y += cyclades.h |
194 | unifdef-y += dccp.h | 194 | unifdef-y += dccp.h |
195 | unifdef-y += dirent.h | 195 | unifdef-y += dirent.h |
196 | unifdef-y += divert.h | ||
197 | unifdef-y += dlm.h | 196 | unifdef-y += dlm.h |
198 | unifdef-y += elfcore.h | 197 | unifdef-y += elfcore.h |
199 | unifdef-y += errno.h | 198 | unifdef-y += errno.h |
diff --git a/include/linux/divert.h b/include/linux/divert.h deleted file mode 100644 index 8fb4e9de6843..000000000000 --- a/include/linux/divert.h +++ /dev/null | |||
@@ -1,132 +0,0 @@ | |||
1 | /* | ||
2 | * Frame Diversion, Benoit Locher <Benoit.Locher@skf.com> | ||
3 | * | ||
4 | * Changes: | ||
5 | * 06/09/2000 BL: initial version | ||
6 | * | ||
7 | */ | ||
8 | |||
9 | #ifndef _LINUX_DIVERT_H | ||
10 | #define _LINUX_DIVERT_H | ||
11 | |||
12 | #include <asm/types.h> | ||
13 | |||
14 | #define MAX_DIVERT_PORTS 8 /* Max number of ports to divert (tcp, udp) */ | ||
15 | |||
16 | /* Divertable protocols */ | ||
17 | #define DIVERT_PROTO_NONE 0x0000 | ||
18 | #define DIVERT_PROTO_IP 0x0001 | ||
19 | #define DIVERT_PROTO_ICMP 0x0002 | ||
20 | #define DIVERT_PROTO_TCP 0x0004 | ||
21 | #define DIVERT_PROTO_UDP 0x0008 | ||
22 | |||
23 | /* | ||
24 | * This is an Ethernet Frame Diverter option block | ||
25 | */ | ||
26 | struct divert_blk | ||
27 | { | ||
28 | int divert; /* are we active */ | ||
29 | unsigned int protos; /* protocols */ | ||
30 | __u16 tcp_dst[MAX_DIVERT_PORTS]; /* specific tcp dst ports to divert */ | ||
31 | __u16 tcp_src[MAX_DIVERT_PORTS]; /* specific tcp src ports to divert */ | ||
32 | __u16 udp_dst[MAX_DIVERT_PORTS]; /* specific udp dst ports to divert */ | ||
33 | __u16 udp_src[MAX_DIVERT_PORTS]; /* specific udp src ports to divert */ | ||
34 | }; | ||
35 | |||
36 | /* | ||
37 | * Diversion control block, for configuration with the userspace tool | ||
38 | * divert | ||
39 | */ | ||
40 | |||
41 | typedef union _divert_cf_arg | ||
42 | { | ||
43 | __s16 int16; | ||
44 | __u16 uint16; | ||
45 | __s32 int32; | ||
46 | __u32 uint32; | ||
47 | __s64 int64; | ||
48 | __u64 uint64; | ||
49 | void __user *ptr; | ||
50 | } divert_cf_arg; | ||
51 | |||
52 | |||
53 | struct divert_cf | ||
54 | { | ||
55 | int cmd; /* Command */ | ||
56 | divert_cf_arg arg1, | ||
57 | arg2, | ||
58 | arg3; | ||
59 | int dev_index; /* device index (eth0=0, etc...) */ | ||
60 | }; | ||
61 | |||
62 | |||
63 | /* Diversion commands */ | ||
64 | #define DIVCMD_DIVERT 1 /* ENABLE/DISABLE diversion */ | ||
65 | #define DIVCMD_IP 2 /* ENABLE/DISABLE whold IP diversion */ | ||
66 | #define DIVCMD_TCP 3 /* ENABLE/DISABLE whold TCP diversion */ | ||
67 | #define DIVCMD_TCPDST 4 /* ADD/REMOVE TCP DST port for diversion */ | ||
68 | #define DIVCMD_TCPSRC 5 /* ADD/REMOVE TCP SRC port for diversion */ | ||
69 | #define DIVCMD_UDP 6 /* ENABLE/DISABLE whole UDP diversion */ | ||
70 | #define DIVCMD_UDPDST 7 /* ADD/REMOVE UDP DST port for diversion */ | ||
71 | #define DIVCMD_UDPSRC 8 /* ADD/REMOVE UDP SRC port for diversion */ | ||
72 | #define DIVCMD_ICMP 9 /* ENABLE/DISABLE whole ICMP diversion */ | ||
73 | #define DIVCMD_GETSTATUS 10 /* GET the status of the diverter */ | ||
74 | #define DIVCMD_RESET 11 /* Reset the diverter on the specified dev */ | ||
75 | #define DIVCMD_GETVERSION 12 /* Retrieve the diverter code version (char[32]) */ | ||
76 | |||
77 | /* General syntax of the commands: | ||
78 | * | ||
79 | * DIVCMD_xxxxxx(arg1, arg2, arg3, dev_index) | ||
80 | * | ||
81 | * SIOCSIFDIVERT: | ||
82 | * DIVCMD_DIVERT(DIVARG1_ENABLE|DIVARG1_DISABLE, , ,ifindex) | ||
83 | * DIVCMD_IP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) | ||
84 | * DIVCMD_TCP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) | ||
85 | * DIVCMD_TCPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) | ||
86 | * DIVCMD_TCPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) | ||
87 | * DIVCMD_UDP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) | ||
88 | * DIVCMD_UDPDST(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) | ||
89 | * DIVCMD_UDPSRC(DIVARG1_ADD|DIVARG1_REMOVE, port, , ifindex) | ||
90 | * DIVCMD_ICMP(DIVARG1_ENABLE|DIVARG1_DISABLE, , , ifindex) | ||
91 | * DIVCMD_RESET(, , , ifindex) | ||
92 | * | ||
93 | * SIOGIFDIVERT: | ||
94 | * DIVCMD_GETSTATUS(divert_blk, , , ifindex) | ||
95 | * DIVCMD_GETVERSION(string[3]) | ||
96 | */ | ||
97 | |||
98 | |||
99 | /* Possible values for arg1 */ | ||
100 | #define DIVARG1_ENABLE 0 /* ENABLE something */ | ||
101 | #define DIVARG1_DISABLE 1 /* DISABLE something */ | ||
102 | #define DIVARG1_ADD 2 /* ADD something */ | ||
103 | #define DIVARG1_REMOVE 3 /* REMOVE something */ | ||
104 | |||
105 | |||
106 | #ifdef __KERNEL__ | ||
107 | |||
108 | /* diverter functions */ | ||
109 | #include <linux/skbuff.h> | ||
110 | |||
111 | #ifdef CONFIG_NET_DIVERT | ||
112 | #include <linux/netdevice.h> | ||
113 | |||
114 | int alloc_divert_blk(struct net_device *); | ||
115 | void free_divert_blk(struct net_device *); | ||
116 | int divert_ioctl(unsigned int cmd, struct divert_cf __user *arg); | ||
117 | void divert_frame(struct sk_buff *skb); | ||
118 | static inline void handle_diverter(struct sk_buff *skb) | ||
119 | { | ||
120 | /* if diversion is supported on device, then divert */ | ||
121 | if (skb->dev->divert && skb->dev->divert->divert) | ||
122 | divert_frame(skb); | ||
123 | } | ||
124 | |||
125 | #else | ||
126 | # define alloc_divert_blk(dev) (0) | ||
127 | # define free_divert_blk(dev) do {} while (0) | ||
128 | # define divert_ioctl(cmd, arg) (-ENOPKG) | ||
129 | # define handle_diverter(skb) do {} while (0) | ||
130 | #endif | ||
131 | #endif | ||
132 | #endif /* _LINUX_DIVERT_H */ | ||
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h index 83b8c4f1d69d..4e967b2e22cc 100644 --- a/include/linux/netdevice.h +++ b/include/linux/netdevice.h | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/percpu.h> | 38 | #include <linux/percpu.h> |
39 | #include <linux/dmaengine.h> | 39 | #include <linux/dmaengine.h> |
40 | 40 | ||
41 | struct divert_blk; | ||
42 | struct vlan_group; | 41 | struct vlan_group; |
43 | struct ethtool_ops; | 42 | struct ethtool_ops; |
44 | struct netpoll_info; | 43 | struct netpoll_info; |
@@ -517,11 +516,6 @@ struct net_device | |||
517 | /* bridge stuff */ | 516 | /* bridge stuff */ |
518 | struct net_bridge_port *br_port; | 517 | struct net_bridge_port *br_port; |
519 | 518 | ||
520 | #ifdef CONFIG_NET_DIVERT | ||
521 | /* this will get initialized at each interface type init routine */ | ||
522 | struct divert_blk *divert; | ||
523 | #endif /* CONFIG_NET_DIVERT */ | ||
524 | |||
525 | /* class/net/name entry */ | 519 | /* class/net/name entry */ |
526 | struct class_device class_dev; | 520 | struct class_device class_dev; |
527 | /* space for optional statistics and wireless sysfs groups */ | 521 | /* space for optional statistics and wireless sysfs groups */ |
diff --git a/include/linux/sockios.h b/include/linux/sockios.h index e6b9d1d36ea2..abef7596655a 100644 --- a/include/linux/sockios.h +++ b/include/linux/sockios.h | |||
@@ -72,8 +72,8 @@ | |||
72 | #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ | 72 | #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ |
73 | #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ | 73 | #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ |
74 | 74 | ||
75 | #define SIOCGIFDIVERT 0x8944 /* Frame diversion support */ | 75 | /* SIOCGIFDIVERT was: 0x8944 Frame diversion support */ |
76 | #define SIOCSIFDIVERT 0x8945 /* Set frame diversion options */ | 76 | /* SIOCSIFDIVERT was: 0x8945 Set frame diversion options */ |
77 | 77 | ||
78 | #define SIOCETHTOOL 0x8946 /* Ethtool interface */ | 78 | #define SIOCETHTOOL 0x8946 /* Ethtool interface */ |
79 | 79 | ||
diff --git a/net/Kconfig b/net/Kconfig index 67e39ad8b8b6..867f95032513 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -175,33 +175,6 @@ source "net/ipx/Kconfig" | |||
175 | source "drivers/net/appletalk/Kconfig" | 175 | source "drivers/net/appletalk/Kconfig" |
176 | source "net/x25/Kconfig" | 176 | source "net/x25/Kconfig" |
177 | source "net/lapb/Kconfig" | 177 | source "net/lapb/Kconfig" |
178 | |||
179 | config NET_DIVERT | ||
180 | bool "Frame Diverter (EXPERIMENTAL)" | ||
181 | depends on EXPERIMENTAL && BROKEN | ||
182 | ---help--- | ||
183 | The Frame Diverter allows you to divert packets from the | ||
184 | network, that are not aimed at the interface receiving it (in | ||
185 | promisc. mode). Typically, a Linux box setup as an Ethernet bridge | ||
186 | with the Frames Diverter on, can do some *really* transparent www | ||
187 | caching using a Squid proxy for example. | ||
188 | |||
189 | This is very useful when you don't want to change your router's | ||
190 | config (or if you simply don't have access to it). | ||
191 | |||
192 | The other possible usages of diverting Ethernet Frames are | ||
193 | numberous: | ||
194 | - reroute smtp traffic to another interface | ||
195 | - traffic-shape certain network streams | ||
196 | - transparently proxy smtp connections | ||
197 | - etc... | ||
198 | |||
199 | For more informations, please refer to: | ||
200 | <http://diverter.sourceforge.net/> | ||
201 | <http://perso.wanadoo.fr/magpie/EtherDivert.html> | ||
202 | |||
203 | If unsure, say N. | ||
204 | |||
205 | source "net/econet/Kconfig" | 178 | source "net/econet/Kconfig" |
206 | source "net/wanrouter/Kconfig" | 179 | source "net/wanrouter/Kconfig" |
207 | source "net/sched/Kconfig" | 180 | source "net/sched/Kconfig" |
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, |
diff --git a/net/socket.c b/net/socket.c index 6c9b9b326d76..e8db54702a69 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -77,7 +77,6 @@ | |||
77 | #include <linux/cache.h> | 77 | #include <linux/cache.h> |
78 | #include <linux/module.h> | 78 | #include <linux/module.h> |
79 | #include <linux/highmem.h> | 79 | #include <linux/highmem.h> |
80 | #include <linux/divert.h> | ||
81 | #include <linux/mount.h> | 80 | #include <linux/mount.h> |
82 | #include <linux/security.h> | 81 | #include <linux/security.h> |
83 | #include <linux/syscalls.h> | 82 | #include <linux/syscalls.h> |
@@ -852,11 +851,6 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | |||
852 | err = vlan_ioctl_hook(argp); | 851 | err = vlan_ioctl_hook(argp); |
853 | mutex_unlock(&vlan_ioctl_mutex); | 852 | mutex_unlock(&vlan_ioctl_mutex); |
854 | break; | 853 | break; |
855 | case SIOCGIFDIVERT: | ||
856 | case SIOCSIFDIVERT: | ||
857 | /* Convert this to call through a hook */ | ||
858 | err = divert_ioctl(cmd, argp); | ||
859 | break; | ||
860 | case SIOCADDDLCI: | 854 | case SIOCADDDLCI: |
861 | case SIOCDELDLCI: | 855 | case SIOCDELDLCI: |
862 | err = -ENOPKG; | 856 | err = -ENOPKG; |