Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/um/drivers/slip_user.c
10817 views
1
/*
2
* Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3
* Licensed under the GPL.
4
*/
5
6
#include <stdio.h>
7
#include <stdlib.h>
8
#include <unistd.h>
9
#include <errno.h>
10
#include <fcntl.h>
11
#include <string.h>
12
#include <sys/termios.h>
13
#include <sys/wait.h>
14
#include "kern_constants.h"
15
#include "net_user.h"
16
#include "os.h"
17
#include "slip.h"
18
#include "um_malloc.h"
19
#include "user.h"
20
21
static int slip_user_init(void *data, void *dev)
22
{
23
struct slip_data *pri = data;
24
25
pri->dev = dev;
26
return 0;
27
}
28
29
static int set_up_tty(int fd)
30
{
31
int i;
32
struct termios tios;
33
34
if (tcgetattr(fd, &tios) < 0) {
35
printk(UM_KERN_ERR "could not get initial terminal "
36
"attributes\n");
37
return -1;
38
}
39
40
tios.c_cflag = CS8 | CREAD | HUPCL | CLOCAL;
41
tios.c_iflag = IGNBRK | IGNPAR;
42
tios.c_oflag = 0;
43
tios.c_lflag = 0;
44
for (i = 0; i < NCCS; i++)
45
tios.c_cc[i] = 0;
46
tios.c_cc[VMIN] = 1;
47
tios.c_cc[VTIME] = 0;
48
49
cfsetospeed(&tios, B38400);
50
cfsetispeed(&tios, B38400);
51
52
if (tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
53
printk(UM_KERN_ERR "failed to set terminal attributes\n");
54
return -1;
55
}
56
return 0;
57
}
58
59
struct slip_pre_exec_data {
60
int stdin;
61
int stdout;
62
int close_me;
63
};
64
65
static void slip_pre_exec(void *arg)
66
{
67
struct slip_pre_exec_data *data = arg;
68
69
if (data->stdin >= 0)
70
dup2(data->stdin, 0);
71
dup2(data->stdout, 1);
72
if (data->close_me >= 0)
73
close(data->close_me);
74
}
75
76
static int slip_tramp(char **argv, int fd)
77
{
78
struct slip_pre_exec_data pe_data;
79
char *output;
80
int pid, fds[2], err, output_len;
81
82
err = os_pipe(fds, 1, 0);
83
if (err < 0) {
84
printk(UM_KERN_ERR "slip_tramp : pipe failed, err = %d\n",
85
-err);
86
goto out;
87
}
88
89
err = 0;
90
pe_data.stdin = fd;
91
pe_data.stdout = fds[1];
92
pe_data.close_me = fds[0];
93
err = run_helper(slip_pre_exec, &pe_data, argv);
94
if (err < 0)
95
goto out_close;
96
pid = err;
97
98
output_len = UM_KERN_PAGE_SIZE;
99
output = uml_kmalloc(output_len, UM_GFP_KERNEL);
100
if (output == NULL) {
101
printk(UM_KERN_ERR "slip_tramp : failed to allocate output "
102
"buffer\n");
103
os_kill_process(pid, 1);
104
err = -ENOMEM;
105
goto out_free;
106
}
107
108
close(fds[1]);
109
read_output(fds[0], output, output_len);
110
printk("%s", output);
111
112
err = helper_wait(pid);
113
close(fds[0]);
114
115
out_free:
116
kfree(output);
117
return err;
118
119
out_close:
120
close(fds[0]);
121
close(fds[1]);
122
out:
123
return err;
124
}
125
126
static int slip_open(void *data)
127
{
128
struct slip_data *pri = data;
129
char version_buf[sizeof("nnnnn\0")];
130
char gate_buf[sizeof("nnn.nnn.nnn.nnn\0")];
131
char *argv[] = { "uml_net", version_buf, "slip", "up", gate_buf,
132
NULL };
133
int sfd, mfd, err;
134
135
err = get_pty();
136
if (err < 0) {
137
printk(UM_KERN_ERR "slip-open : Failed to open pty, err = %d\n",
138
-err);
139
goto out;
140
}
141
mfd = err;
142
143
err = open(ptsname(mfd), O_RDWR, 0);
144
if (err < 0) {
145
printk(UM_KERN_ERR "Couldn't open tty for slip line, "
146
"err = %d\n", -err);
147
goto out_close;
148
}
149
sfd = err;
150
151
if (set_up_tty(sfd))
152
goto out_close2;
153
154
pri->slave = sfd;
155
pri->slip.pos = 0;
156
pri->slip.esc = 0;
157
if (pri->gate_addr != NULL) {
158
sprintf(version_buf, "%d", UML_NET_VERSION);
159
strcpy(gate_buf, pri->gate_addr);
160
161
err = slip_tramp(argv, sfd);
162
163
if (err < 0) {
164
printk(UM_KERN_ERR "slip_tramp failed - err = %d\n",
165
-err);
166
goto out_close2;
167
}
168
err = os_get_ifname(pri->slave, pri->name);
169
if (err < 0) {
170
printk(UM_KERN_ERR "get_ifname failed, err = %d\n",
171
-err);
172
goto out_close2;
173
}
174
iter_addresses(pri->dev, open_addr, pri->name);
175
}
176
else {
177
err = os_set_slip(sfd);
178
if (err < 0) {
179
printk(UM_KERN_ERR "Failed to set slip discipline "
180
"encapsulation - err = %d\n", -err);
181
goto out_close2;
182
}
183
}
184
return mfd;
185
out_close2:
186
close(sfd);
187
out_close:
188
close(mfd);
189
out:
190
return err;
191
}
192
193
static void slip_close(int fd, void *data)
194
{
195
struct slip_data *pri = data;
196
char version_buf[sizeof("nnnnn\0")];
197
char *argv[] = { "uml_net", version_buf, "slip", "down", pri->name,
198
NULL };
199
int err;
200
201
if (pri->gate_addr != NULL)
202
iter_addresses(pri->dev, close_addr, pri->name);
203
204
sprintf(version_buf, "%d", UML_NET_VERSION);
205
206
err = slip_tramp(argv, pri->slave);
207
208
if (err != 0)
209
printk(UM_KERN_ERR "slip_tramp failed - errno = %d\n", -err);
210
close(fd);
211
close(pri->slave);
212
pri->slave = -1;
213
}
214
215
int slip_user_read(int fd, void *buf, int len, struct slip_data *pri)
216
{
217
return slip_proto_read(fd, buf, len, &pri->slip);
218
}
219
220
int slip_user_write(int fd, void *buf, int len, struct slip_data *pri)
221
{
222
return slip_proto_write(fd, buf, len, &pri->slip);
223
}
224
225
static void slip_add_addr(unsigned char *addr, unsigned char *netmask,
226
void *data)
227
{
228
struct slip_data *pri = data;
229
230
if (pri->slave < 0)
231
return;
232
open_addr(addr, netmask, pri->name);
233
}
234
235
static void slip_del_addr(unsigned char *addr, unsigned char *netmask,
236
void *data)
237
{
238
struct slip_data *pri = data;
239
240
if (pri->slave < 0)
241
return;
242
close_addr(addr, netmask, pri->name);
243
}
244
245
const struct net_user_info slip_user_info = {
246
.init = slip_user_init,
247
.open = slip_open,
248
.close = slip_close,
249
.remove = NULL,
250
.add_address = slip_add_addr,
251
.delete_address = slip_del_addr,
252
.mtu = BUF_SIZE,
253
.max_packet = BUF_SIZE,
254
};
255
256