1 /* 2 * Copyright (C) 2001 Lennert Buytenhek (buytenh@gnu.org) and 3 * James Leu (jleu@mindspring.net). 4 * Copyright (C) 2001 by various other people who didn't put their name here. 5 * Licensed under the GPL. 6 */ 7 8 #include "linux/init.h" 9 #include "linux/netdevice.h" 10 #include "linux/etherdevice.h" 11 #include "net_kern.h" 12 #include "net_user.h" 13 #include "etap.h" 14 15 struct ethertap_init { 16 char *dev_name; 17 char *gate_addr; 18 }; 19 20 static void etap_init(struct net_device *dev, void *data) 21 { 22 struct uml_net_private *pri; 23 struct ethertap_data *epri; 24 struct ethertap_init *init = data; 25 26 pri = dev->priv; 27 epri = (struct ethertap_data *) pri->user; 28 epri->dev_name = init->dev_name; 29 epri->gate_addr = init->gate_addr; 30 epri->data_fd = -1; 31 epri->control_fd = -1; 32 epri->dev = dev; 33 34 printk("ethertap backend - %s", epri->dev_name); 35 if (epri->gate_addr != NULL) 36 printk(", IP = %s", epri->gate_addr); 37 printk("\n"); 38 } 39 40 static int etap_read(int fd, struct sk_buff **skb, struct uml_net_private *lp) 41 { 42 int len; 43 44 *skb = ether_adjust_skb(*skb, ETH_HEADER_ETHERTAP); 45 if(*skb == NULL) return(-ENOMEM); 46 len = net_recvfrom(fd, (*skb)->mac.raw, 47 (*skb)->dev->mtu + 2 * ETH_HEADER_ETHERTAP); 48 if(len <= 0) return(len); 49 skb_pull(*skb, 2); 50 len -= 2; 51 return(len); 52 } 53 54 static int etap_write(int fd, struct sk_buff **skb, struct uml_net_private *lp) 55 { 56 if(skb_headroom(*skb) < 2){ 57 struct sk_buff *skb2; 58 59 skb2 = skb_realloc_headroom(*skb, 2); 60 dev_kfree_skb(*skb); 61 if (skb2 == NULL) return(-ENOMEM); 62 *skb = skb2; 63 } 64 skb_push(*skb, 2); 65 return(net_send(fd, (*skb)->data, (*skb)->len)); 66 } 67 68 struct net_kern_info ethertap_kern_info = { 69 .init = etap_init, 70 .protocol = eth_protocol, 71 .read = etap_read, 72 .write = etap_write, 73 }; 74 75 int ethertap_setup(char *str, char **mac_out, void *data) 76 { 77 struct ethertap_init *init = data; 78 79 *init = ((struct ethertap_init) 80 { .dev_name = NULL, 81 .gate_addr = NULL }); 82 if(tap_setup_common(str, "ethertap", &init->dev_name, mac_out, 83 &init->gate_addr)) 84 return(0); 85 if(init->dev_name == NULL){ 86 printk("ethertap_setup : Missing tap device name\n"); 87 return(0); 88 } 89 90 return(1); 91 } 92 93 static struct transport ethertap_transport = { 94 .list = LIST_HEAD_INIT(ethertap_transport.list), 95 .name = "ethertap", 96 .setup = ethertap_setup, 97 .user = ðertap_user_info, 98 .kern = ðertap_kern_info, 99 .private_size = sizeof(struct ethertap_data), 100 }; 101 102 static int register_ethertap(void) 103 { 104 register_transport(ðertap_transport); 105 return(1); 106 } 107 108 __initcall(register_ethertap); 109 110 /* 111 * Overrides for Emacs so that we follow Linus's tabbing style. 112 * Emacs will notice this stuff at the end of the file and automatically 113 * adjust the settings for this buffer only. This must remain at the end 114 * of the file. 115 * --------------------------------------------------------------------------- 116 * Local variables: 117 * c-file-style: "linux" 118 * End: 119 */ 120