Linux Audio

Check our new training course

Loading...
v3.5.6
  1/*
  2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
  3 * Licensed under the GPL
  4 */
  5
  6#include <stdio.h>
  7#include <stdlib.h>
  8#include <errno.h>
  9#include <termios.h>
 10#include <unistd.h>
 11#include <netinet/in.h>
 12#include "chan_user.h"
 
 13#include "os.h"
 14#include "port.h"
 15#include "um_malloc.h"
 
 16
 17struct port_chan {
 18	int raw;
 19	struct termios tt;
 20	void *kernel_data;
 21	char dev[sizeof("32768\0")];
 22};
 23
 24static void *port_init(char *str, int device, const struct chan_opts *opts)
 25{
 26	struct port_chan *data;
 27	void *kern_data;
 28	char *end;
 29	int port;
 30
 31	if (*str != ':') {
 32		printk(UM_KERN_ERR "port_init : channel type 'port' must "
 33		       "specify a port number\n");
 34		return NULL;
 35	}
 36	str++;
 37	port = strtoul(str, &end, 0);
 38	if ((*end != '\0') || (end == str)) {
 39		printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n",
 40		       str);
 41		return NULL;
 42	}
 43
 44	kern_data = port_data(port);
 45	if (kern_data == NULL)
 46		return NULL;
 47
 48	data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
 49	if (data == NULL)
 50		goto err;
 51
 52	*data = ((struct port_chan) { .raw  		= opts->raw,
 53				      .kernel_data 	= kern_data });
 54	sprintf(data->dev, "%d", port);
 55
 56	return data;
 57 err:
 58	port_kern_free(kern_data);
 59	return NULL;
 60}
 61
 62static void port_free(void *d)
 63{
 64	struct port_chan *data = d;
 65
 66	port_kern_free(data->kernel_data);
 67	kfree(data);
 68}
 69
 70static int port_open(int input, int output, int primary, void *d,
 71		     char **dev_out)
 72{
 73	struct port_chan *data = d;
 74	int fd, err;
 75
 76	fd = port_wait(data->kernel_data);
 77	if ((fd >= 0) && data->raw) {
 78		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
 79		if (err)
 80			return err;
 81
 82		err = raw(fd);
 83		if (err)
 84			return err;
 85	}
 86	*dev_out = data->dev;
 87	return fd;
 88}
 89
 90static void port_close(int fd, void *d)
 91{
 92	struct port_chan *data = d;
 93
 94	port_remove_dev(data->kernel_data);
 95	os_close_file(fd);
 96}
 97
 98const struct chan_ops port_ops = {
 99	.type		= "port",
100	.init		= port_init,
101	.open		= port_open,
102	.close		= port_close,
103	.read	        = generic_read,
104	.write		= generic_write,
105	.console_write	= generic_console_write,
106	.window_size	= generic_window_size,
107	.free		= port_free,
108	.winch		= 1,
109};
110
111int port_listen_fd(int port)
112{
113	struct sockaddr_in addr;
114	int fd, err, arg;
115
116	fd = socket(PF_INET, SOCK_STREAM, 0);
117	if (fd == -1)
118		return -errno;
119
120	arg = 1;
121	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) {
122		err = -errno;
123		goto out;
124	}
125
126	addr.sin_family = AF_INET;
127	addr.sin_port = htons(port);
128	addr.sin_addr.s_addr = htonl(INADDR_ANY);
129	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
130		err = -errno;
131		goto out;
132	}
133
134	if (listen(fd, 1) < 0) {
135		err = -errno;
136		goto out;
137	}
138
139	err = os_set_fd_block(fd, 0);
140	if (err < 0)
141		goto out;
142
143	return fd;
144 out:
145	close(fd);
146	return err;
147}
148
149struct port_pre_exec_data {
150	int sock_fd;
151	int pipe_fd;
152};
153
154static void port_pre_exec(void *arg)
155{
156	struct port_pre_exec_data *data = arg;
157
158	dup2(data->sock_fd, 0);
159	dup2(data->sock_fd, 1);
160	dup2(data->sock_fd, 2);
161	close(data->sock_fd);
162	dup2(data->pipe_fd, 3);
163	shutdown(3, SHUT_RD);
164	close(data->pipe_fd);
165}
166
167int port_connection(int fd, int *socket, int *pid_out)
168{
169	int new, err;
170	char *argv[] = { "/usr/sbin/in.telnetd", "-L",
171			 "/usr/lib/uml/port-helper", NULL };
172	struct port_pre_exec_data data;
173
174	new = accept(fd, NULL, 0);
175	if (new < 0)
176		return -errno;
177
178	err = os_pipe(socket, 0, 0);
179	if (err < 0)
180		goto out_close;
181
182	data = ((struct port_pre_exec_data)
183		{ .sock_fd  		= new,
184		  .pipe_fd 		= socket[1] });
185
186	err = run_helper(port_pre_exec, &data, argv);
187	if (err < 0)
188		goto out_shutdown;
189
190	*pid_out = err;
191	return new;
192
193 out_shutdown:
194	shutdown(socket[0], SHUT_RDWR);
195	close(socket[0]);
196	shutdown(socket[1], SHUT_RDWR);
197	close(socket[1]);
198 out_close:
199	close(new);
200	return err;
201}
v3.1
  1/*
  2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{linux.intel,addtoit}.com)
  3 * Licensed under the GPL
  4 */
  5
  6#include <stdio.h>
  7#include <stdlib.h>
  8#include <errno.h>
  9#include <termios.h>
 10#include <unistd.h>
 11#include <netinet/in.h>
 12#include "chan_user.h"
 13#include "kern_constants.h"
 14#include "os.h"
 15#include "port.h"
 16#include "um_malloc.h"
 17#include "user.h"
 18
 19struct port_chan {
 20	int raw;
 21	struct termios tt;
 22	void *kernel_data;
 23	char dev[sizeof("32768\0")];
 24};
 25
 26static void *port_init(char *str, int device, const struct chan_opts *opts)
 27{
 28	struct port_chan *data;
 29	void *kern_data;
 30	char *end;
 31	int port;
 32
 33	if (*str != ':') {
 34		printk(UM_KERN_ERR "port_init : channel type 'port' must "
 35		       "specify a port number\n");
 36		return NULL;
 37	}
 38	str++;
 39	port = strtoul(str, &end, 0);
 40	if ((*end != '\0') || (end == str)) {
 41		printk(UM_KERN_ERR "port_init : couldn't parse port '%s'\n",
 42		       str);
 43		return NULL;
 44	}
 45
 46	kern_data = port_data(port);
 47	if (kern_data == NULL)
 48		return NULL;
 49
 50	data = uml_kmalloc(sizeof(*data), UM_GFP_KERNEL);
 51	if (data == NULL)
 52		goto err;
 53
 54	*data = ((struct port_chan) { .raw  		= opts->raw,
 55				      .kernel_data 	= kern_data });
 56	sprintf(data->dev, "%d", port);
 57
 58	return data;
 59 err:
 60	port_kern_free(kern_data);
 61	return NULL;
 62}
 63
 64static void port_free(void *d)
 65{
 66	struct port_chan *data = d;
 67
 68	port_kern_free(data->kernel_data);
 69	kfree(data);
 70}
 71
 72static int port_open(int input, int output, int primary, void *d,
 73		     char **dev_out)
 74{
 75	struct port_chan *data = d;
 76	int fd, err;
 77
 78	fd = port_wait(data->kernel_data);
 79	if ((fd >= 0) && data->raw) {
 80		CATCH_EINTR(err = tcgetattr(fd, &data->tt));
 81		if (err)
 82			return err;
 83
 84		err = raw(fd);
 85		if (err)
 86			return err;
 87	}
 88	*dev_out = data->dev;
 89	return fd;
 90}
 91
 92static void port_close(int fd, void *d)
 93{
 94	struct port_chan *data = d;
 95
 96	port_remove_dev(data->kernel_data);
 97	os_close_file(fd);
 98}
 99
100const struct chan_ops port_ops = {
101	.type		= "port",
102	.init		= port_init,
103	.open		= port_open,
104	.close		= port_close,
105	.read	        = generic_read,
106	.write		= generic_write,
107	.console_write	= generic_console_write,
108	.window_size	= generic_window_size,
109	.free		= port_free,
110	.winch		= 1,
111};
112
113int port_listen_fd(int port)
114{
115	struct sockaddr_in addr;
116	int fd, err, arg;
117
118	fd = socket(PF_INET, SOCK_STREAM, 0);
119	if (fd == -1)
120		return -errno;
121
122	arg = 1;
123	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &arg, sizeof(arg)) < 0) {
124		err = -errno;
125		goto out;
126	}
127
128	addr.sin_family = AF_INET;
129	addr.sin_port = htons(port);
130	addr.sin_addr.s_addr = htonl(INADDR_ANY);
131	if (bind(fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
132		err = -errno;
133		goto out;
134	}
135
136	if (listen(fd, 1) < 0) {
137		err = -errno;
138		goto out;
139	}
140
141	err = os_set_fd_block(fd, 0);
142	if (err < 0)
143		goto out;
144
145	return fd;
146 out:
147	close(fd);
148	return err;
149}
150
151struct port_pre_exec_data {
152	int sock_fd;
153	int pipe_fd;
154};
155
156static void port_pre_exec(void *arg)
157{
158	struct port_pre_exec_data *data = arg;
159
160	dup2(data->sock_fd, 0);
161	dup2(data->sock_fd, 1);
162	dup2(data->sock_fd, 2);
163	close(data->sock_fd);
164	dup2(data->pipe_fd, 3);
165	shutdown(3, SHUT_RD);
166	close(data->pipe_fd);
167}
168
169int port_connection(int fd, int *socket, int *pid_out)
170{
171	int new, err;
172	char *argv[] = { "/usr/sbin/in.telnetd", "-L",
173			 "/usr/lib/uml/port-helper", NULL };
174	struct port_pre_exec_data data;
175
176	new = accept(fd, NULL, 0);
177	if (new < 0)
178		return -errno;
179
180	err = os_pipe(socket, 0, 0);
181	if (err < 0)
182		goto out_close;
183
184	data = ((struct port_pre_exec_data)
185		{ .sock_fd  		= new,
186		  .pipe_fd 		= socket[1] });
187
188	err = run_helper(port_pre_exec, &data, argv);
189	if (err < 0)
190		goto out_shutdown;
191
192	*pid_out = err;
193	return new;
194
195 out_shutdown:
196	shutdown(socket[0], SHUT_RDWR);
197	close(socket[0]);
198	shutdown(socket[1], SHUT_RDWR);
199	close(socket[1]);
200 out_close:
201	close(new);
202	return err;
203}