Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 | /* * Ethertap: A network device for bouncing packets via user space * * This is a very simple ethernet driver. It bounces ethernet frames * to user space on /dev/tap0->/dev/tap15 and expects ethernet frames * to be written back to it. By default it does not ARP. If you turn ARP * on it will attempt to ARP the user space and reply to ARPS from the * user space. * * As this is an ethernet device you can use it for appletalk, IPX etc * even for building bridging tunnels. */ #include <linux/config.h> #include <linux/module.h> #include <linux/kernel.h> #include <linux/sched.h> #include <linux/malloc.h> #include <linux/string.h> #include <linux/errno.h> #include <linux/netdevice.h> #include <linux/inetdevice.h> #include <linux/etherdevice.h> #include <linux/skbuff.h> #include <linux/init.h> #include <net/sock.h> #include <linux/netlink.h> /* * Index to functions. */ int ethertap_probe(struct net_device *dev); static int ethertap_open(struct net_device *dev); static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev); static int ethertap_close(struct net_device *dev); static struct net_device_stats *ethertap_get_stats(struct net_device *dev); static void ethertap_rx(struct sock *sk, int len); #ifdef CONFIG_ETHERTAP_MC static void set_multicast_list(struct net_device *dev); #endif static int ethertap_debug = 0; static struct net_device *tap_map[32]; /* Returns the tap device for a given netlink */ /* * Board-specific info in dev->priv. */ struct net_local { struct sock *nl; #ifdef CONFIG_ETHERTAP_MC __u32 groups; #endif struct net_device_stats stats; }; /* * To call this a probe is a bit misleading, however for real * hardware it would have to check what was present. */ int __init ethertap_probe(struct net_device *dev) { memcpy(dev->dev_addr, "\xFE\xFD\x00\x00\x00\x00", 6); if (dev->mem_start & 0xf) ethertap_debug = dev->mem_start & 0x7; /* * Initialize the device structure. */ dev->priv = kmalloc(sizeof(struct net_local), GFP_KERNEL); if (dev->priv == NULL) return -ENOMEM; memset(dev->priv, 0, sizeof(struct net_local)); /* * The tap specific entries in the device structure. */ dev->open = ethertap_open; dev->hard_start_xmit = ethertap_start_xmit; dev->stop = ethertap_close; dev->get_stats = ethertap_get_stats; #ifdef CONFIG_ETHERTAP_MC dev->set_multicast_list = set_multicast_list; #endif /* * Setup the generic properties */ ether_setup(dev); dev->tx_queue_len = 0; dev->flags|=IFF_NOARP; tap_map[dev->base_addr]=dev; return 0; } /* * Open/initialize the board. */ static int ethertap_open(struct net_device *dev) { struct net_local *lp = (struct net_local*)dev->priv; if (ethertap_debug > 2) printk("%s: Doing ethertap_open()...", dev->name); MOD_INC_USE_COUNT; lp->nl = netlink_kernel_create(dev->base_addr, ethertap_rx); if (lp->nl == NULL) { MOD_DEC_USE_COUNT; return -ENOBUFS; } netif_start_queue(dev); return 0; } #ifdef CONFIG_ETHERTAP_MC static unsigned ethertap_mc_hash(__u8 *dest) { unsigned idx = 0; idx ^= dest[0]; idx ^= dest[1]; idx ^= dest[2]; idx ^= dest[3]; idx ^= dest[4]; idx ^= dest[5]; return 1U << (idx&0x1F); } static void set_multicast_list(struct net_device *dev) { unsigned groups = ~0; struct net_local *lp = (struct net_local *)dev->priv; if (!(dev->flags&(IFF_NOARP|IFF_PROMISC|IFF_ALLMULTI))) { struct dev_mc_list *dmi; groups = ethertap_mc_hash(dev->broadcast); for (dmi=dev->mc_list; dmi; dmi=dmi->next) { if (dmi->dmi_addrlen != 6) continue; groups |= ethertap_mc_hash(dmi->dmi_addr); } } lp->groups = groups; if (lp->nl) lp->nl->protinfo.af_netlink.groups = groups; } #endif /* * We transmit by throwing the packet at netlink. We have to clone * it for 2.0 so that we dev_kfree_skb() the locked original. */ static int ethertap_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; #ifdef CONFIG_ETHERTAP_MC struct ethhdr *eth = (struct ethhdr*)skb->data; #endif if (skb_headroom(skb) < 2) { static int once; struct sk_buff *skb2; if (!once) { once = 1; printk(KERN_DEBUG "%s: not aligned xmit by protocol %04x\n", dev->name, skb->protocol); } skb2 = skb_realloc_headroom(skb, 2); dev_kfree_skb(skb); if (skb2 == NULL) return 0; skb = skb2; } __skb_push(skb, 2); /* Make the same thing, which loopback does. */ if (skb_shared(skb)) { struct sk_buff *skb2 = skb; skb = skb_clone(skb, GFP_ATOMIC); /* Clone the buffer */ if (skb==NULL) { dev_kfree_skb(skb2); return 0; } dev_kfree_skb(skb2); } /* ... but do not orphan it here, netlink does it in any case. */ lp->stats.tx_bytes+=skb->len; lp->stats.tx_packets++; #ifndef CONFIG_ETHERTAP_MC netlink_broadcast(lp->nl, skb, 0, ~0, GFP_ATOMIC); #else if (dev->flags&IFF_NOARP) { netlink_broadcast(lp->nl, skb, 0, ~0, GFP_ATOMIC); return 0; } if (!(eth->h_dest[0]&1)) { /* Unicast packet */ __u32 pid; memcpy(&pid, eth->h_dest+2, 4); netlink_unicast(lp->nl, skb, ntohl(pid), MSG_DONTWAIT); } else netlink_broadcast(lp->nl, skb, 0, ethertap_mc_hash(eth->h_dest), GFP_ATOMIC); #endif return 0; } static __inline__ int ethertap_rx_skb(struct sk_buff *skb, struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; #ifdef CONFIG_ETHERTAP_MC struct ethhdr *eth = (struct ethhdr*)(skb->data + 2); #endif int len = skb->len; if (len < 16) { printk(KERN_DEBUG "%s : rx len = %d\n", dev->name, len); kfree_skb(skb); return -EINVAL; } if (NETLINK_CREDS(skb)->uid) { printk(KERN_INFO "%s : user %d\n", dev->name, NETLINK_CREDS(skb)->uid); kfree_skb(skb); return -EPERM; } #ifdef CONFIG_ETHERTAP_MC if (!(dev->flags&(IFF_NOARP|IFF_PROMISC))) { int drop = 0; if (eth->h_dest[0]&1) { if (!(ethertap_mc_hash(eth->h_dest)&lp->groups)) drop = 1; } else if (memcmp(eth->h_dest, dev->dev_addr, 6) != 0) drop = 1; if (drop) { if (ethertap_debug > 3) printk(KERN_DEBUG "%s : not for us\n", dev->name); kfree_skb(skb); return -EINVAL; } } #endif if (skb_shared(skb)) { struct sk_buff *skb2 = skb; skb = skb_clone(skb, GFP_KERNEL); /* Clone the buffer */ if (skb==NULL) { kfree_skb(skb2); return -ENOBUFS; } kfree_skb(skb2); } else skb_orphan(skb); skb_pull(skb, 2); skb->dev = dev; skb->protocol=eth_type_trans(skb,dev); memset(skb->cb, 0, sizeof(skb->cb)); lp->stats.rx_packets++; lp->stats.rx_bytes+=len; netif_rx(skb); return len; } /* * The typical workload of the driver: * Handle the ether interface interrupts. * * (In this case handle the packets posted from user space..) */ static void ethertap_rx(struct sock *sk, int len) { struct net_device *dev = tap_map[sk->protocol]; struct sk_buff *skb; if (dev==NULL) { printk(KERN_CRIT "ethertap: bad unit!\n"); skb_queue_purge(&sk->receive_queue); return; } if (ethertap_debug > 3) printk("%s: ethertap_rx()\n", dev->name); while ((skb = skb_dequeue(&sk->receive_queue)) != NULL) ethertap_rx_skb(skb, dev); } static int ethertap_close(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; struct sock *sk = lp->nl; if (ethertap_debug > 2) printk("%s: Shutting down.\n", dev->name); netif_stop_queue(dev); if (sk) { lp->nl = NULL; sock_release(sk->socket); } MOD_DEC_USE_COUNT; return 0; } static struct net_device_stats *ethertap_get_stats(struct net_device *dev) { struct net_local *lp = (struct net_local *)dev->priv; return &lp->stats; } #ifdef MODULE static int unit; MODULE_PARM(unit,"i"); static char devicename[9] = { 0, }; static struct net_device dev_ethertap = { devicename, 0, 0, 0, 0, 1, 5, 0, 0, 0, NULL, ethertap_probe }; int init_module(void) { dev_ethertap.base_addr=unit+NETLINK_TAPBASE; sprintf(devicename,"tap%d",unit); if (dev_get(devicename)) { printk(KERN_INFO "%s already loaded.\n", devicename); return -EBUSY; } if (register_netdev(&dev_ethertap) != 0) return -EIO; return 0; } void cleanup_module(void) { tap_map[dev_ethertap.base_addr]=NULL; unregister_netdev(&dev_ethertap); /* * Free up the private structure. */ kfree(dev_ethertap.priv); dev_ethertap.priv = NULL; /* gets re-allocated by ethertap_probe */ } #endif /* MODULE */ |