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> 7*37185b33SAl Viro #include <linux/init.h> 8cd1ae0e4SJeff Dike #include <linux/netdevice.h> 9cd1ae0e4SJeff Dike #include <linux/string.h> 10*37185b33SAl Viro #include <net_kern.h> 11*37185b33SAl Viro #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 2517c324faSWang Chen private = netdev_priv(dev); 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->hard_header_len = 0; 36be8ad5a4SJeff Dike dev->header_ops = NULL; 371da177e4SLinus Torvalds dev->addr_len = 0; 381da177e4SLinus Torvalds dev->type = ARPHRD_SLIP; 391da177e4SLinus Torvalds dev->tx_queue_len = 256; 401da177e4SLinus Torvalds dev->flags = IFF_NOARP; 411da177e4SLinus Torvalds printk("SLIRP backend - command line:"); 42cd1ae0e4SJeff Dike for (i = 0; spri->argw.argv[i] != NULL; i++) 431da177e4SLinus Torvalds printk(" '%s'",spri->argw.argv[i]); 441da177e4SLinus Torvalds printk("\n"); 451da177e4SLinus Torvalds } 461da177e4SLinus Torvalds 471da177e4SLinus Torvalds static unsigned short slirp_protocol(struct sk_buff *skbuff) 481da177e4SLinus Torvalds { 49cd1ae0e4SJeff Dike return htons(ETH_P_IP); 501da177e4SLinus Torvalds } 511da177e4SLinus Torvalds 52b53f35a8SJeff Dike static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) 531da177e4SLinus Torvalds { 54b53f35a8SJeff Dike return slirp_user_read(fd, skb_mac_header(skb), skb->dev->mtu, 55cd1ae0e4SJeff Dike (struct slirp_data *) &lp->user); 561da177e4SLinus Torvalds } 571da177e4SLinus Torvalds 58b53f35a8SJeff Dike static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) 591da177e4SLinus Torvalds { 60b53f35a8SJeff Dike return slirp_user_write(fd, skb->data, skb->len, 61cd1ae0e4SJeff Dike (struct slirp_data *) &lp->user); 621da177e4SLinus Torvalds } 631da177e4SLinus Torvalds 645e7672ecSJeff Dike const struct net_kern_info slirp_kern_info = { 651da177e4SLinus Torvalds .init = slirp_init, 661da177e4SLinus Torvalds .protocol = slirp_protocol, 671da177e4SLinus Torvalds .read = slirp_read, 681da177e4SLinus Torvalds .write = slirp_write, 691da177e4SLinus Torvalds }; 701da177e4SLinus Torvalds 711da177e4SLinus Torvalds static int slirp_setup(char *str, char **mac_out, void *data) 721da177e4SLinus Torvalds { 731da177e4SLinus Torvalds struct slirp_init *init = data; 741da177e4SLinus Torvalds int i=0; 751da177e4SLinus Torvalds 76cd1ae0e4SJeff Dike *init = ((struct slirp_init) { .argw = { { "slirp", NULL } } }); 771da177e4SLinus Torvalds 781da177e4SLinus Torvalds str = split_if_spec(str, mac_out, NULL); 791da177e4SLinus Torvalds 80cd1ae0e4SJeff Dike if (str == NULL) /* no command line given after MAC addr */ 81cd1ae0e4SJeff Dike return 1; 821da177e4SLinus Torvalds 831da177e4SLinus Torvalds do { 841da177e4SLinus Torvalds if (i >= SLIRP_MAX_ARGS - 1) { 85cd1ae0e4SJeff Dike printk(KERN_WARNING "slirp_setup: truncating slirp " 86cd1ae0e4SJeff Dike "arguments\n"); 871da177e4SLinus Torvalds break; 881da177e4SLinus Torvalds } 891da177e4SLinus Torvalds init->argw.argv[i++] = str; 901da177e4SLinus Torvalds while(*str && *str!=',') { 91cd1ae0e4SJeff Dike if (*str == '_') 92cd1ae0e4SJeff Dike *str=' '; 931da177e4SLinus Torvalds str++; 941da177e4SLinus Torvalds } 951da177e4SLinus Torvalds if (*str != ',') 961da177e4SLinus Torvalds break; 971da177e4SLinus Torvalds *str++ = '\0'; 981da177e4SLinus Torvalds } while (1); 99cd1ae0e4SJeff Dike 1001da177e4SLinus Torvalds init->argw.argv[i] = NULL; 101cd1ae0e4SJeff Dike return 1; 1021da177e4SLinus Torvalds } 1031da177e4SLinus Torvalds 1041da177e4SLinus Torvalds static struct transport slirp_transport = { 1051da177e4SLinus Torvalds .list = LIST_HEAD_INIT(slirp_transport.list), 1061da177e4SLinus Torvalds .name = "slirp", 1071da177e4SLinus Torvalds .setup = slirp_setup, 1081da177e4SLinus Torvalds .user = &slirp_user_info, 1091da177e4SLinus Torvalds .kern = &slirp_kern_info, 1101da177e4SLinus Torvalds .private_size = sizeof(struct slirp_data), 1111da177e4SLinus Torvalds .setup_size = sizeof(struct slirp_init), 1121da177e4SLinus Torvalds }; 1131da177e4SLinus Torvalds 1141da177e4SLinus Torvalds static int register_slirp(void) 1151da177e4SLinus Torvalds { 1161da177e4SLinus Torvalds register_transport(&slirp_transport); 117f4c57a78SJeff Dike return 0; 1181da177e4SLinus Torvalds } 1191da177e4SLinus Torvalds 1208210fd2aSJeff Dike late_initcall(register_slirp); 121