1cd1ae0e4SJeff Dike /* 2cd1ae0e4SJeff Dike * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) 3cd1ae0e4SJeff Dike * Licensed under the GPL. 4cd1ae0e4SJeff Dike */ 5cd1ae0e4SJeff Dike 6cd1ae0e4SJeff Dike #include <linux/if_arp.h> 71da177e4SLinus Torvalds #include "linux/init.h" 8cd1ae0e4SJeff Dike #include <linux/netdevice.h> 9cd1ae0e4SJeff Dike #include <linux/string.h> 101da177e4SLinus Torvalds #include "net_kern.h" 111da177e4SLinus Torvalds #include "net_user.h" 121da177e4SLinus Torvalds #include "slirp.h" 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds struct slirp_init { 151da177e4SLinus Torvalds struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ 161da177e4SLinus Torvalds }; 171da177e4SLinus Torvalds 181da177e4SLinus Torvalds void slirp_init(struct net_device *dev, void *data) 191da177e4SLinus Torvalds { 201da177e4SLinus Torvalds struct uml_net_private *private; 211da177e4SLinus Torvalds struct slirp_data *spri; 221da177e4SLinus Torvalds struct slirp_init *init = data; 231da177e4SLinus Torvalds int i; 241da177e4SLinus Torvalds 251da177e4SLinus Torvalds private = dev->priv; 261da177e4SLinus Torvalds spri = (struct slirp_data *) private->user; 27854e981cSPaolo 'Blaisorblade' Giarrusso 28854e981cSPaolo 'Blaisorblade' Giarrusso spri->argw = init->argw; 29854e981cSPaolo 'Blaisorblade' Giarrusso spri->pid = -1; 30854e981cSPaolo 'Blaisorblade' Giarrusso spri->slave = -1; 31854e981cSPaolo 'Blaisorblade' Giarrusso spri->dev = dev; 32854e981cSPaolo 'Blaisorblade' Giarrusso 33854e981cSPaolo 'Blaisorblade' Giarrusso slip_proto_init(&spri->slip); 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds dev->init = NULL; 361da177e4SLinus Torvalds dev->hard_header_len = 0; 37*be8ad5a4SJeff Dike dev->header_ops = NULL; 381da177e4SLinus Torvalds dev->addr_len = 0; 391da177e4SLinus Torvalds dev->type = ARPHRD_SLIP; 401da177e4SLinus Torvalds dev->tx_queue_len = 256; 411da177e4SLinus Torvalds dev->flags = IFF_NOARP; 421da177e4SLinus Torvalds printk("SLIRP backend - command line:"); 43cd1ae0e4SJeff Dike for (i = 0; spri->argw.argv[i] != NULL; i++) 441da177e4SLinus Torvalds printk(" '%s'",spri->argw.argv[i]); 451da177e4SLinus Torvalds printk("\n"); 461da177e4SLinus Torvalds } 471da177e4SLinus Torvalds 481da177e4SLinus Torvalds static unsigned short slirp_protocol(struct sk_buff *skbuff) 491da177e4SLinus Torvalds { 50cd1ae0e4SJeff Dike return htons(ETH_P_IP); 511da177e4SLinus Torvalds } 521da177e4SLinus Torvalds 53b53f35a8SJeff Dike static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 541da177e4SLinus Torvalds { 55b53f35a8SJeff Dike return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu, 56cd1ae0e4SJeff Dike (struct slirp_data *) &lp->user); 571da177e4SLinus Torvalds } 581da177e4SLinus Torvalds 59b53f35a8SJeff Dike static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 601da177e4SLinus Torvalds { 61b53f35a8SJeff Dike return slirp_user_write(fd, skb->data, skb->len, 62cd1ae0e4SJeff Dike (struct slirp_data *) &lp->user); 631da177e4SLinus Torvalds } 641da177e4SLinus Torvalds 655e7672ecSJeff Dike const struct net_kern_info slirp_kern_info = { 661da177e4SLinus Torvalds .init = slirp_init, 671da177e4SLinus Torvalds .protocol = slirp_protocol, 681da177e4SLinus Torvalds .read = slirp_read, 691da177e4SLinus Torvalds .write = slirp_write, 701da177e4SLinus Torvalds }; 711da177e4SLinus Torvalds 721da177e4SLinus Torvalds static int slirp_setup(char *str, char **mac_out, void *data) 731da177e4SLinus Torvalds { 741da177e4SLinus Torvalds struct slirp_init *init = data; 751da177e4SLinus Torvalds int i=0; 761da177e4SLinus Torvalds 77cd1ae0e4SJeff Dike *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } }); 781da177e4SLinus Torvalds 791da177e4SLinus Torvalds str = split_if_spec(str, mac_out, NULL); 801da177e4SLinus Torvalds 81cd1ae0e4SJeff Dike if (str == NULL) /* no command line given after MAC addr */ 82cd1ae0e4SJeff Dike return 1; 831da177e4SLinus Torvalds 841da177e4SLinus Torvalds do { 851da177e4SLinus Torvalds if (i >= SLIRP_MAX_ARGS - 1) { 86cd1ae0e4SJeff Dike printk(KERN_WARNING "slirp_setup: truncating slirp " 87cd1ae0e4SJeff Dike "arguments\n"); 881da177e4SLinus Torvalds break; 891da177e4SLinus Torvalds } 901da177e4SLinus Torvalds init->argw.argv[i++] = str; 911da177e4SLinus Torvalds while(*str && *str!=',') { 92cd1ae0e4SJeff Dike if (*str == '_') 93cd1ae0e4SJeff Dike *str=' '; 941da177e4SLinus Torvalds str++; 951da177e4SLinus Torvalds } 961da177e4SLinus Torvalds if (*str != ',') 971da177e4SLinus Torvalds break; 981da177e4SLinus Torvalds *str++ = '\0'; 991da177e4SLinus Torvalds } while (1); 100cd1ae0e4SJeff Dike 1011da177e4SLinus Torvalds init->argw.argv[i] = NULL; 102cd1ae0e4SJeff Dike return 1; 1031da177e4SLinus Torvalds } 1041da177e4SLinus Torvalds 1051da177e4SLinus Torvalds static struct transport slirp_transport = { 1061da177e4SLinus Torvalds .list = LIST_HEAD_INIT(slirp_transport.list), 1071da177e4SLinus Torvalds .name = "slirp", 1081da177e4SLinus Torvalds .setup = slirp_setup, 1091da177e4SLinus Torvalds .user = &slirp_user_info, 1101da177e4SLinus Torvalds .kern = &slirp_kern_info, 1111da177e4SLinus Torvalds .private_size = sizeof(struct slirp_data), 1121da177e4SLinus Torvalds .setup_size = sizeof(struct slirp_init), 1131da177e4SLinus Torvalds }; 1141da177e4SLinus Torvalds 1151da177e4SLinus Torvalds static int register_slirp(void) 1161da177e4SLinus Torvalds { 1171da177e4SLinus Torvalds register_transport(&slirp_transport); 118f4c57a78SJeff Dike return 0; 1191da177e4SLinus Torvalds } 1201da177e4SLinus Torvalds 1218210fd2aSJeff Dike late_initcall(register_slirp); 122