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