Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Adrian Bunk and committed by
David S. Miller
90833aa4 d7f7365f

+6 -767
-15
Documentation/feature-removal-schedule.txt
··· 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 230 What: PHYSDEVPATH, PHYSDEVBUS, PHYSDEVDRIVER in the uevent environment 246 231 When: October 2008 247 232 Why: The stacking of class devices makes these values misleading and
-1
drivers/net/Space.c
··· 33 33 #include <linux/errno.h> 34 34 #include <linux/init.h> 35 35 #include <linux/netlink.h> 36 - #include <linux/divert.h> 37 36 38 37 /* A unified ethernet device probe. This is the easiest way to have every 39 38 ethernet adaptor have the name "eth[0123...]".
-1
include/linux/Kbuild
··· 193 193 unifdef-y += cyclades.h 194 194 unifdef-y += dccp.h 195 195 unifdef-y += dirent.h 196 - unifdef-y += divert.h 197 196 unifdef-y += dlm.h 198 197 unifdef-y += elfcore.h 199 198 unifdef-y += errno.h
-132
include/linux/divert.h
··· 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 */
-6
include/linux/netdevice.h
··· 38 38 #include <linux/percpu.h> 39 39 #include <linux/dmaengine.h> 40 40 41 - struct divert_blk; 42 41 struct vlan_group; 43 42 struct ethtool_ops; 44 43 struct netpoll_info; ··· 515 516 516 517 /* bridge stuff */ 517 518 struct net_bridge_port *br_port; 518 - 519 - #ifdef CONFIG_NET_DIVERT 520 - /* this will get initialized at each interface type init routine */ 521 - struct divert_blk *divert; 522 - #endif /* CONFIG_NET_DIVERT */ 523 519 524 520 /* class/net/name entry */ 525 521 struct class_device class_dev;
+2 -2
include/linux/sockios.h
··· 72 72 #define SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */ 73 73 #define SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */ 74 74 75 - #define SIOCGIFDIVERT 0x8944 /* Frame diversion support */ 76 - #define SIOCSIFDIVERT 0x8945 /* Set frame diversion options */ 75 + /* SIOCGIFDIVERT was: 0x8944 Frame diversion support */ 76 + /* SIOCSIFDIVERT was: 0x8945 Set frame diversion options */ 77 77 78 78 #define SIOCETHTOOL 0x8946 /* Ethtool interface */ 79 79
-27
net/Kconfig
··· 175 175 source "drivers/net/appletalk/Kconfig" 176 176 source "net/x25/Kconfig" 177 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 178 source "net/econet/Kconfig" 206 179 source "net/wanrouter/Kconfig" 207 180 source "net/sched/Kconfig"
-1
net/core/Makefile
··· 12 12 13 13 obj-$(CONFIG_XFRM) += flow.o 14 14 obj-$(CONFIG_SYSFS) += net-sysfs.o 15 - obj-$(CONFIG_NET_DIVERT) += dv.o 16 15 obj-$(CONFIG_NET_PKTGEN) += pktgen.o 17 16 obj-$(CONFIG_WIRELESS_EXT) += wireless.o 18 17 obj-$(CONFIG_NETPOLL) += netpoll.o
+4 -16
net/core/dev.c
··· 98 98 #include <linux/seq_file.h> 99 99 #include <linux/stat.h> 100 100 #include <linux/if_bridge.h> 101 - #include <linux/divert.h> 102 101 #include <net/dst.h> 103 102 #include <net/pkt_sched.h> 104 103 #include <net/checksum.h> ··· 1826 1827 ncls: 1827 1828 #endif 1828 1829 1829 - handle_diverter(skb); 1830 - 1831 1830 if (handle_bridge(&skb, &pt_prev, &ret, orig_dev)) 1832 1831 goto out; 1833 1832 ··· 2895 2898 spin_lock_init(&dev->ingress_lock); 2896 2899 #endif 2897 2900 2898 - ret = alloc_divert_blk(dev); 2899 - if (ret) 2900 - goto out; 2901 - 2902 2901 dev->iflink = -1; 2903 2902 2904 2903 /* Init, if this function is available */ ··· 2903 2910 if (ret) { 2904 2911 if (ret > 0) 2905 2912 ret = -EIO; 2906 - goto out_err; 2913 + goto out; 2907 2914 } 2908 2915 } 2909 2916 2910 2917 if (!dev_valid_name(dev->name)) { 2911 2918 ret = -EINVAL; 2912 - goto out_err; 2919 + goto out; 2913 2920 } 2914 2921 2915 2922 dev->ifindex = dev_new_index(); ··· 2923 2930 = hlist_entry(p, struct net_device, name_hlist); 2924 2931 if (!strncmp(d->name, dev->name, IFNAMSIZ)) { 2925 2932 ret = -EEXIST; 2926 - goto out_err; 2933 + goto out; 2927 2934 } 2928 2935 } 2929 2936 ··· 2967 2974 2968 2975 ret = netdev_register_sysfs(dev); 2969 2976 if (ret) 2970 - goto out_err; 2977 + goto out; 2971 2978 dev->reg_state = NETREG_REGISTERED; 2972 2979 2973 2980 /* ··· 2994 3001 2995 3002 out: 2996 3003 return ret; 2997 - out_err: 2998 - free_divert_blk(dev); 2999 - goto out; 3000 3004 } 3001 3005 3002 3006 /** ··· 3309 3319 3310 3320 /* Notifier chain MUST detach us from master device. */ 3311 3321 BUG_TRAP(!dev->master); 3312 - 3313 - free_divert_blk(dev); 3314 3322 3315 3323 /* Finish processing unregister after unlock */ 3316 3324 net_set_todo(dev);
-546
net/core/dv.c
··· 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 - }
-14
net/core/sysctl_net_core.c
··· 21 21 22 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 24 #ifdef CONFIG_XFRM 29 25 extern u32 sysctl_xfrm_aevent_etime; 30 26 extern u32 sysctl_xfrm_aevent_rseqth; ··· 101 105 .mode = 0644, 102 106 .proc_handler = &proc_dointvec 103 107 }, 104 - #ifdef CONFIG_NET_DIVERT 105 - { 106 - .ctl_name = NET_CORE_DIVERT_VERSION, 107 - .procname = "divert_version", 108 - .data = (void *)sysctl_divert_version, 109 - .maxlen = 32, 110 - .mode = 0444, 111 - .proc_handler = &proc_dostring 112 - }, 113 - #endif /* CONFIG_NET_DIVERT */ 114 108 #ifdef CONFIG_XFRM 115 109 { 116 110 .ctl_name = NET_CORE_AEVENT_ETIME,
-6
net/socket.c
··· 77 77 #include <linux/cache.h> 78 78 #include <linux/module.h> 79 79 #include <linux/highmem.h> 80 - #include <linux/divert.h> 81 80 #include <linux/mount.h> 82 81 #include <linux/security.h> 83 82 #include <linux/syscalls.h> ··· 850 851 if (vlan_ioctl_hook) 851 852 err = vlan_ioctl_hook(argp); 852 853 mutex_unlock(&vlan_ioctl_mutex); 853 - break; 854 - case SIOCGIFDIVERT: 855 - case SIOCSIFDIVERT: 856 - /* Convert this to call through a hook */ 857 - err = divert_ioctl(cmd, argp); 858 854 break; 859 855 case SIOCADDDLCI: 860 856 case SIOCDELDLCI: