aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/drivers/slirp_kern.c
blob: c9d6b52a831de0c5836222bb14cf27bb3c760b0a (plain) (blame)
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
#include "linux/kernel.h"
#include "linux/stddef.h"
#include "linux/init.h"
#include "linux/netdevice.h"
#include "linux/if_arp.h"
#include "net_kern.h"
#include "net_user.h"
#include "kern.h"
#include "slirp.h"

struct slirp_init {
	struct arg_list_dummy_wrapper argw;  /* XXX should be simpler... */
};

void slirp_init(struct net_device *dev, void *data)
{
	struct uml_net_private *private;
	struct slirp_data *spri;
	struct slirp_init *init = data;
	int i;

	private = dev->priv;
	spri = (struct slirp_data *) private->user;
	*spri = ((struct slirp_data)
		{ .argw 	= init->argw,
		  .pid  	= -1,
		  .slave  	= -1,
		  .ibuf  	= { '\0' },
		  .obuf  	= { '\0' },
		  .pos 		= 0,
		  .esc 		= 0,
		  .dev 		= dev });

	dev->init = NULL;
	dev->hard_header_len = 0;
	dev->header_cache_update = NULL;
	dev->hard_header_cache = NULL;
	dev->hard_header = NULL;
	dev->addr_len = 0;
	dev->type = ARPHRD_SLIP;
	dev->tx_queue_len = 256;
	dev->flags = IFF_NOARP;
	printk("SLIRP backend - command line:");
	for(i=0;spri->argw.argv[i]!=NULL;i++) {
		printk(" '%s'",spri->argw.argv[i]);
	}
	printk("\n");
}

static unsigned short slirp_protocol(struct sk_buff *skbuff)
{
	return(htons(ETH_P_IP));
}

static int slirp_read(int fd, struct sk_buff **skb, 
		       struct uml_net_private *lp)
{
	return(slirp_user_read(fd, (*skb)->mac.raw, (*skb)->dev->mtu, 
			      (struct slirp_data *) &lp->user));
}

static int slirp_write(int fd, struct sk_buff **skb,
		      struct uml_net_private *lp)
{
	return(slirp_user_write(fd, (*skb)->data, (*skb)->len, 
			       (struct slirp_data *) &lp->user));
}

struct net_kern_info slirp_kern_info = {
	.init			= slirp_init,
	.protocol		= slirp_protocol,
	.read			= slirp_read,
	.write			= slirp_write,
};

static int slirp_setup(char *str, char **mac_out, void *data)
{
	struct slirp_init *init = data;
	int i=0;

	*init = ((struct slirp_init)
		{ argw :		{ { "slirp", NULL  } } });

	str = split_if_spec(str, mac_out, NULL);

	if(str == NULL) { /* no command line given after MAC addr */
		return(1);
	}

	do {
		if(i>=SLIRP_MAX_ARGS-1) {
			printk("slirp_setup: truncating slirp arguments\n");
			break;
		}
		init->argw.argv[i++] = str;
		while(*str && *str!=',') {
			if(*str=='_') *str=' ';
			str++;
		}
		if(*str!=',')
			break;
		*str++='\0';
	} while(1);
	init->argw.argv[i]=NULL;
	return(1);
}

static struct transport slirp_transport = {
	.list 		= LIST_HEAD_INIT(slirp_transport.list),
	.name 		= "slirp",
	.setup  	= slirp_setup,
	.user 		= &slirp_user_info,
	.kern 		= &slirp_kern_info,
	.private_size 	= sizeof(struct slirp_data),
	.setup_size 	= sizeof(struct slirp_init),
};

static int register_slirp(void)
{
	register_transport(&slirp_transport);
	return(1);
}

__initcall(register_slirp);

/*
 * Overrides for Emacs so that we follow Linus's tabbing style.
 * Emacs will notice this stuff at the end of the file and automatically
 * adjust the settings for this buffer only.  This must remain at the end
 * of the file.
 * ---------------------------------------------------------------------------
 * Local variables:
 * c-file-style: "linux"
 * End:
 */