1 | // SPDX-License-Identifier: GPL-2.0 |
2 | /* |
3 | * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com) |
4 | */ |
5 | |
6 | #include <linux/if_arp.h> |
7 | #include <linux/init.h> |
8 | #include <linux/netdevice.h> |
9 | #include <linux/string.h> |
10 | #include <net_kern.h> |
11 | #include <net_user.h> |
12 | #include "slirp.h" |
13 | |
14 | struct slirp_init { |
15 | struct arg_list_dummy_wrapper argw; /* XXX should be simpler... */ |
16 | }; |
17 | |
18 | static void slirp_init(struct net_device *dev, void *data) |
19 | { |
20 | struct uml_net_private *private; |
21 | struct slirp_data *spri; |
22 | struct slirp_init *init = data; |
23 | int i; |
24 | |
25 | private = netdev_priv(dev); |
26 | spri = (struct slirp_data *) private->user; |
27 | |
28 | spri->argw = init->argw; |
29 | spri->pid = -1; |
30 | spri->slave = -1; |
31 | spri->dev = dev; |
32 | |
33 | slip_proto_init(slip: &spri->slip); |
34 | |
35 | dev->hard_header_len = 0; |
36 | dev->header_ops = NULL; |
37 | dev->addr_len = 0; |
38 | dev->type = ARPHRD_SLIP; |
39 | dev->tx_queue_len = 256; |
40 | dev->flags = IFF_NOARP; |
41 | printk("SLIRP backend - command line:" ); |
42 | for (i = 0; spri->argw.argv[i] != NULL; i++) |
43 | printk(" '%s'" ,spri->argw.argv[i]); |
44 | printk("\n" ); |
45 | } |
46 | |
47 | static unsigned short slirp_protocol(struct sk_buff *skbuff) |
48 | { |
49 | return htons(ETH_P_IP); |
50 | } |
51 | |
52 | static int slirp_read(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
53 | { |
54 | return slirp_user_read(fd, buf: skb_mac_header(skb), len: skb->dev->mtu, |
55 | pri: (struct slirp_data *) &lp->user); |
56 | } |
57 | |
58 | static int slirp_write(int fd, struct sk_buff *skb, struct uml_net_private *lp) |
59 | { |
60 | return slirp_user_write(fd, buf: skb->data, len: skb->len, |
61 | pri: (struct slirp_data *) &lp->user); |
62 | } |
63 | |
64 | const struct net_kern_info slirp_kern_info = { |
65 | .init = slirp_init, |
66 | .protocol = slirp_protocol, |
67 | .read = slirp_read, |
68 | .write = slirp_write, |
69 | }; |
70 | |
71 | static int slirp_setup(char *str, char **mac_out, void *data) |
72 | { |
73 | struct slirp_init *init = data; |
74 | int i=0; |
75 | |
76 | *init = ((struct slirp_init) { .argw = { { "slirp" , NULL } } }); |
77 | |
78 | str = split_if_spec(str, mac_out, NULL); |
79 | |
80 | if (str == NULL) /* no command line given after MAC addr */ |
81 | return 1; |
82 | |
83 | do { |
84 | if (i >= SLIRP_MAX_ARGS - 1) { |
85 | printk(KERN_WARNING "slirp_setup: truncating slirp " |
86 | "arguments\n" ); |
87 | break; |
88 | } |
89 | init->argw.argv[i++] = str; |
90 | while(*str && *str!=',') { |
91 | if (*str == '_') |
92 | *str=' '; |
93 | str++; |
94 | } |
95 | if (*str != ',') |
96 | break; |
97 | *str++ = '\0'; |
98 | } while (1); |
99 | |
100 | init->argw.argv[i] = NULL; |
101 | return 1; |
102 | } |
103 | |
104 | static struct transport slirp_transport = { |
105 | .list = LIST_HEAD_INIT(slirp_transport.list), |
106 | .name = "slirp" , |
107 | .setup = slirp_setup, |
108 | .user = &slirp_user_info, |
109 | .kern = &slirp_kern_info, |
110 | .private_size = sizeof(struct slirp_data), |
111 | .setup_size = sizeof(struct slirp_init), |
112 | }; |
113 | |
114 | static int register_slirp(void) |
115 | { |
116 | register_transport(&slirp_transport); |
117 | return 0; |
118 | } |
119 | |
120 | late_initcall(register_slirp); |
121 | |