2 * Copyright (C) 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
3 * Licensed under the GPL.
12 #include <sys/termios.h>
14 #include "kern_constants.h"
18 #include "um_malloc.h"
21 static int slip_user_init(void *data
, void *dev
)
23 struct slip_data
*pri
= data
;
29 static int set_up_tty(int fd
)
34 if (tcgetattr(fd
, &tios
) < 0) {
35 printk(UM_KERN_ERR
"could not get initial terminal "
40 tios
.c_cflag
= CS8
| CREAD
| HUPCL
| CLOCAL
;
41 tios
.c_iflag
= IGNBRK
| IGNPAR
;
44 for (i
= 0; i
< NCCS
; i
++)
49 cfsetospeed(&tios
, B38400
);
50 cfsetispeed(&tios
, B38400
);
52 if (tcsetattr(fd
, TCSAFLUSH
, &tios
) < 0) {
53 printk(UM_KERN_ERR
"failed to set terminal attributes\n");
59 struct slip_pre_exec_data
{
65 static void slip_pre_exec(void *arg
)
67 struct slip_pre_exec_data
*data
= arg
;
71 dup2(data
->stdout
, 1);
72 if (data
->close_me
>= 0)
73 close(data
->close_me
);
76 static int slip_tramp(char **argv
, int fd
)
78 struct slip_pre_exec_data pe_data
;
80 int status
, pid
, fds
[2], err
, output_len
;
82 err
= os_pipe(fds
, 1, 0);
84 printk(UM_KERN_ERR
"slip_tramp : pipe failed, err = %d\n",
91 pe_data
.stdout
= fds
[1];
92 pe_data
.close_me
= fds
[0];
93 err
= run_helper(slip_pre_exec
, &pe_data
, argv
);
98 output_len
= UM_KERN_PAGE_SIZE
;
99 output
= kmalloc(output_len
, UM_GFP_KERNEL
);
100 if (output
== NULL
) {
101 printk(UM_KERN_ERR
"slip_tramp : failed to allocate output "
103 os_kill_process(pid
, 1);
109 read_output(fds
[0], output
, output_len
);
110 printk("%s", output
);
112 CATCH_EINTR(err
= waitpid(pid
, &status
, 0));
115 else if (!WIFEXITED(status
) || (WEXITSTATUS(status
) != 0)) {
116 printk(UM_KERN_ERR
"'%s' didn't exit with status 0\n", argv
[0]);
134 static int slip_open(void *data
)
136 struct slip_data
*pri
= data
;
137 char version_buf
[sizeof("nnnnn\0")];
138 char gate_buf
[sizeof("nnn.nnn.nnn.nnn\0")];
139 char *argv
[] = { "uml_net", version_buf
, "slip", "up", gate_buf
,
145 printk(UM_KERN_ERR
"slip-open : Failed to open pty, err = %d\n",
151 err
= open(ptsname(mfd
), O_RDWR
, 0);
153 printk(UM_KERN_ERR
"Couldn't open tty for slip line, "
165 if (pri
->gate_addr
!= NULL
) {
166 sprintf(version_buf
, "%d", UML_NET_VERSION
);
167 strcpy(gate_buf
, pri
->gate_addr
);
169 err
= slip_tramp(argv
, sfd
);
172 printk(UM_KERN_ERR
"slip_tramp failed - err = %d\n",
176 err
= os_get_ifname(pri
->slave
, pri
->name
);
178 printk(UM_KERN_ERR
"get_ifname failed, err = %d\n",
182 iter_addresses(pri
->dev
, open_addr
, pri
->name
);
185 err
= os_set_slip(sfd
);
187 printk(UM_KERN_ERR
"Failed to set slip discipline "
188 "encapsulation - err = %d\n", -err
);
201 static void slip_close(int fd
, void *data
)
203 struct slip_data
*pri
= data
;
204 char version_buf
[sizeof("nnnnn\0")];
205 char *argv
[] = { "uml_net", version_buf
, "slip", "down", pri
->name
,
209 if (pri
->gate_addr
!= NULL
)
210 iter_addresses(pri
->dev
, close_addr
, pri
->name
);
212 sprintf(version_buf
, "%d", UML_NET_VERSION
);
214 err
= slip_tramp(argv
, pri
->slave
);
217 printk(UM_KERN_ERR
"slip_tramp failed - errno = %d\n", -err
);
223 int slip_user_read(int fd
, void *buf
, int len
, struct slip_data
*pri
)
225 return slip_proto_read(fd
, buf
, len
, &pri
->slip
);
228 int slip_user_write(int fd
, void *buf
, int len
, struct slip_data
*pri
)
230 return slip_proto_write(fd
, buf
, len
, &pri
->slip
);
233 static void slip_add_addr(unsigned char *addr
, unsigned char *netmask
,
236 struct slip_data
*pri
= data
;
240 open_addr(addr
, netmask
, pri
->name
);
243 static void slip_del_addr(unsigned char *addr
, unsigned char *netmask
,
246 struct slip_data
*pri
= data
;
250 close_addr(addr
, netmask
, pri
->name
);
253 const struct net_user_info slip_user_info
= {
254 .init
= slip_user_init
,
258 .add_address
= slip_add_addr
,
259 .delete_address
= slip_del_addr
,
261 .max_packet
= BUF_SIZE
,