Linux Audio

Check our new training course

Loading...
v6.2
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
 
  4 */
  5
  6#include <stdio.h>
  7#include <unistd.h>
  8#include <stdarg.h>
  9#include <errno.h>
 10#include <stddef.h>
 11#include <string.h>
 12#include <sys/socket.h>
 13#include <sys/wait.h>
 14#include <net_user.h>
 15#include <os.h>
 16#include <um_malloc.h>
 
 
 17
 18int tap_open_common(void *dev, char *gate_addr)
 19{
 20	int tap_addr[4];
 21
 22	if (gate_addr == NULL)
 23		return 0;
 24	if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
 25		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) {
 26		printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n",
 27		       gate_addr);
 28		return -EINVAL;
 29	}
 30	return 0;
 31}
 32
 33void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
 34{
 35	int tap_addr[4];
 36
 37	if ((gate_addr != NULL) &&
 38	    (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
 39		    &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
 40	    (eth_addr[0] == tap_addr[0]) &&
 41	    (eth_addr[1] == tap_addr[1]) &&
 42	    (eth_addr[2] == tap_addr[2]) &&
 43	    (eth_addr[3] == tap_addr[3])) {
 44		printk(UM_KERN_ERR "The tap IP address and the UML eth IP "
 45		       "address must be different\n");
 46	}
 47}
 48
 49/* Do reliable error handling as this fails frequently enough. */
 50void read_output(int fd, char *output, int len)
 51{
 52	int remain, ret, expected;
 53	char c;
 54	char *str;
 55
 56	if (output == NULL) {
 57		output = &c;
 58		len = sizeof(c);
 59	}
 60
 61	*output = '\0';
 62	ret = read(fd, &remain, sizeof(remain));
 63
 64	if (ret != sizeof(remain)) {
 65		if (ret < 0)
 66			ret = -errno;
 67		expected = sizeof(remain);
 68		str = "length";
 69		goto err;
 70	}
 71
 72	while (remain != 0) {
 73		expected = (remain < len) ? remain : len;
 74		ret = read(fd, output, expected);
 75		if (ret != expected) {
 76			if (ret < 0)
 77				ret = -errno;
 78			str = "data";
 79			goto err;
 80		}
 81		remain -= ret;
 82	}
 83
 84	return;
 85
 86err:
 87	if (ret < 0)
 88		printk(UM_KERN_ERR "read_output - read of %s failed, "
 89		       "errno = %d\n", str, -ret);
 90	else
 91		printk(UM_KERN_ERR "read_output - read of %s failed, read only "
 92		       "%d of %d bytes\n", str, ret, expected);
 93}
 94
 95int net_read(int fd, void *buf, int len)
 96{
 97	int n;
 98
 99	n = read(fd,  buf,  len);
100
101	if ((n < 0) && (errno == EAGAIN))
102		return 0;
103	else if (n == 0)
104		return -ENOTCONN;
105	return n;
106}
107
108int net_recvfrom(int fd, void *buf, int len)
109{
110	int n;
111
112	CATCH_EINTR(n = recvfrom(fd,  buf,  len, 0, NULL, NULL));
113	if (n < 0) {
114		if (errno == EAGAIN)
115			return 0;
116		return -errno;
117	}
118	else if (n == 0)
119		return -ENOTCONN;
120	return n;
121}
122
123int net_write(int fd, void *buf, int len)
124{
125	int n;
126
127	n = write(fd, buf, len);
128
129	if ((n < 0) && (errno == EAGAIN))
130		return 0;
131	else if (n == 0)
132		return -ENOTCONN;
133	return n;
134}
135
136int net_send(int fd, void *buf, int len)
137{
138	int n;
139
140	CATCH_EINTR(n = send(fd, buf, len, 0));
141	if (n < 0) {
142		if (errno == EAGAIN)
143			return 0;
144		return -errno;
145	}
146	else if (n == 0)
147		return -ENOTCONN;
148	return n;
149}
150
151int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
152{
153	int n;
154
155	CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
156			       sock_len));
157	if (n < 0) {
158		if (errno == EAGAIN)
159			return 0;
160		return -errno;
161	}
162	else if (n == 0)
163		return -ENOTCONN;
164	return n;
165}
166
167struct change_pre_exec_data {
168	int close_me;
169	int stdout_fd;
170};
171
172static void change_pre_exec(void *arg)
173{
174	struct change_pre_exec_data *data = arg;
175
176	close(data->close_me);
177	dup2(data->stdout_fd, 1);
178}
179
180static int change_tramp(char **argv, char *output, int output_len)
181{
182	int pid, fds[2], err;
183	struct change_pre_exec_data pe_data;
184
185	err = os_pipe(fds, 1, 0);
186	if (err < 0) {
187		printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n",
188		       -err);
189		return err;
190	}
191	pe_data.close_me = fds[0];
192	pe_data.stdout_fd = fds[1];
193	pid = run_helper(change_pre_exec, &pe_data, argv);
194
195	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
196		read_output(fds[0], output, output_len);
197
198	close(fds[0]);
199	close(fds[1]);
200
201	if (pid > 0)
202		helper_wait(pid);
203	return pid;
204}
205
206static void change(char *dev, char *what, unsigned char *addr,
207		   unsigned char *netmask)
208{
209	char addr_buf[sizeof("255.255.255.255\0")];
210	char netmask_buf[sizeof("255.255.255.255\0")];
211	char version[sizeof("nnnnn\0")];
212	char *argv[] = { "uml_net", version, what, dev, addr_buf,
213			 netmask_buf, NULL };
214	char *output;
215	int output_len, pid;
216
217	sprintf(version, "%d", UML_NET_VERSION);
218	sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
219	sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
220		netmask[2], netmask[3]);
221
222	output_len = UM_KERN_PAGE_SIZE;
223	output = uml_kmalloc(output_len, UM_GFP_KERNEL);
224	if (output == NULL)
225		printk(UM_KERN_ERR "change : failed to allocate output "
226		       "buffer\n");
227
228	pid = change_tramp(argv, output, output_len);
229	if (pid < 0) {
230		kfree(output);
231		return;
232	}
233
234	if (output != NULL) {
235		printk("%s", output);
236		kfree(output);
237	}
238}
239
240void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
241{
242	change(arg, "add", addr, netmask);
243}
244
245void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
246{
247	change(arg, "del", addr, netmask);
248}
249
250char *split_if_spec(char *str, ...)
251{
252	char **arg, *end, *ret = NULL;
253	va_list ap;
254
255	va_start(ap, str);
256	while ((arg = va_arg(ap, char **)) != NULL) {
257		if (*str == '\0')
258			goto out;
259		end = strchr(str, ',');
260		if (end != str)
261			*arg = str;
262		if (end == NULL)
263			goto out;
264		*end++ = '\0';
265		str = end;
266	}
267	ret = str;
268out:
269	va_end(ap);
270	return ret;
271}
v3.1
 
  1/*
  2 * Copyright (C) 2001 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
  3 * Licensed under the GPL
  4 */
  5
  6#include <stdio.h>
  7#include <unistd.h>
  8#include <stdarg.h>
  9#include <errno.h>
 10#include <stddef.h>
 11#include <string.h>
 12#include <sys/socket.h>
 13#include <sys/wait.h>
 14#include "net_user.h"
 15#include "kern_constants.h"
 16#include "os.h"
 17#include "um_malloc.h"
 18#include "user.h"
 19
 20int tap_open_common(void *dev, char *gate_addr)
 21{
 22	int tap_addr[4];
 23
 24	if (gate_addr == NULL)
 25		return 0;
 26	if (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
 27		  &tap_addr[1], &tap_addr[2], &tap_addr[3]) != 4) {
 28		printk(UM_KERN_ERR "Invalid tap IP address - '%s'\n",
 29		       gate_addr);
 30		return -EINVAL;
 31	}
 32	return 0;
 33}
 34
 35void tap_check_ips(char *gate_addr, unsigned char *eth_addr)
 36{
 37	int tap_addr[4];
 38
 39	if ((gate_addr != NULL) &&
 40	    (sscanf(gate_addr, "%d.%d.%d.%d", &tap_addr[0],
 41		    &tap_addr[1], &tap_addr[2], &tap_addr[3]) == 4) &&
 42	    (eth_addr[0] == tap_addr[0]) &&
 43	    (eth_addr[1] == tap_addr[1]) &&
 44	    (eth_addr[2] == tap_addr[2]) &&
 45	    (eth_addr[3] == tap_addr[3])) {
 46		printk(UM_KERN_ERR "The tap IP address and the UML eth IP "
 47		       "address must be different\n");
 48	}
 49}
 50
 51/* Do reliable error handling as this fails frequently enough. */
 52void read_output(int fd, char *output, int len)
 53{
 54	int remain, ret, expected;
 55	char c;
 56	char *str;
 57
 58	if (output == NULL) {
 59		output = &c;
 60		len = sizeof(c);
 61	}
 62
 63	*output = '\0';
 64	ret = read(fd, &remain, sizeof(remain));
 65
 66	if (ret != sizeof(remain)) {
 67		if (ret < 0)
 68			ret = -errno;
 69		expected = sizeof(remain);
 70		str = "length";
 71		goto err;
 72	}
 73
 74	while (remain != 0) {
 75		expected = (remain < len) ? remain : len;
 76		ret = read(fd, output, expected);
 77		if (ret != expected) {
 78			if (ret < 0)
 79				ret = -errno;
 80			str = "data";
 81			goto err;
 82		}
 83		remain -= ret;
 84	}
 85
 86	return;
 87
 88err:
 89	if (ret < 0)
 90		printk(UM_KERN_ERR "read_output - read of %s failed, "
 91		       "errno = %d\n", str, -ret);
 92	else
 93		printk(UM_KERN_ERR "read_output - read of %s failed, read only "
 94		       "%d of %d bytes\n", str, ret, expected);
 95}
 96
 97int net_read(int fd, void *buf, int len)
 98{
 99	int n;
100
101	n = read(fd,  buf,  len);
102
103	if ((n < 0) && (errno == EAGAIN))
104		return 0;
105	else if (n == 0)
106		return -ENOTCONN;
107	return n;
108}
109
110int net_recvfrom(int fd, void *buf, int len)
111{
112	int n;
113
114	CATCH_EINTR(n = recvfrom(fd,  buf,  len, 0, NULL, NULL));
115	if (n < 0) {
116		if (errno == EAGAIN)
117			return 0;
118		return -errno;
119	}
120	else if (n == 0)
121		return -ENOTCONN;
122	return n;
123}
124
125int net_write(int fd, void *buf, int len)
126{
127	int n;
128
129	n = write(fd, buf, len);
130
131	if ((n < 0) && (errno == EAGAIN))
132		return 0;
133	else if (n == 0)
134		return -ENOTCONN;
135	return n;
136}
137
138int net_send(int fd, void *buf, int len)
139{
140	int n;
141
142	CATCH_EINTR(n = send(fd, buf, len, 0));
143	if (n < 0) {
144		if (errno == EAGAIN)
145			return 0;
146		return -errno;
147	}
148	else if (n == 0)
149		return -ENOTCONN;
150	return n;
151}
152
153int net_sendto(int fd, void *buf, int len, void *to, int sock_len)
154{
155	int n;
156
157	CATCH_EINTR(n = sendto(fd, buf, len, 0, (struct sockaddr *) to,
158			       sock_len));
159	if (n < 0) {
160		if (errno == EAGAIN)
161			return 0;
162		return -errno;
163	}
164	else if (n == 0)
165		return -ENOTCONN;
166	return n;
167}
168
169struct change_pre_exec_data {
170	int close_me;
171	int stdout;
172};
173
174static void change_pre_exec(void *arg)
175{
176	struct change_pre_exec_data *data = arg;
177
178	close(data->close_me);
179	dup2(data->stdout, 1);
180}
181
182static int change_tramp(char **argv, char *output, int output_len)
183{
184	int pid, fds[2], err;
185	struct change_pre_exec_data pe_data;
186
187	err = os_pipe(fds, 1, 0);
188	if (err < 0) {
189		printk(UM_KERN_ERR "change_tramp - pipe failed, err = %d\n",
190		       -err);
191		return err;
192	}
193	pe_data.close_me = fds[0];
194	pe_data.stdout = fds[1];
195	pid = run_helper(change_pre_exec, &pe_data, argv);
196
197	if (pid > 0)	/* Avoid hang as we won't get data in failure case. */
198		read_output(fds[0], output, output_len);
199
200	close(fds[0]);
201	close(fds[1]);
202
203	if (pid > 0)
204		helper_wait(pid);
205	return pid;
206}
207
208static void change(char *dev, char *what, unsigned char *addr,
209		   unsigned char *netmask)
210{
211	char addr_buf[sizeof("255.255.255.255\0")];
212	char netmask_buf[sizeof("255.255.255.255\0")];
213	char version[sizeof("nnnnn\0")];
214	char *argv[] = { "uml_net", version, what, dev, addr_buf,
215			 netmask_buf, NULL };
216	char *output;
217	int output_len, pid;
218
219	sprintf(version, "%d", UML_NET_VERSION);
220	sprintf(addr_buf, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
221	sprintf(netmask_buf, "%d.%d.%d.%d", netmask[0], netmask[1],
222		netmask[2], netmask[3]);
223
224	output_len = UM_KERN_PAGE_SIZE;
225	output = uml_kmalloc(output_len, UM_GFP_KERNEL);
226	if (output == NULL)
227		printk(UM_KERN_ERR "change : failed to allocate output "
228		       "buffer\n");
229
230	pid = change_tramp(argv, output, output_len);
231	if (pid < 0) {
232		kfree(output);
233		return;
234	}
235
236	if (output != NULL) {
237		printk("%s", output);
238		kfree(output);
239	}
240}
241
242void open_addr(unsigned char *addr, unsigned char *netmask, void *arg)
243{
244	change(arg, "add", addr, netmask);
245}
246
247void close_addr(unsigned char *addr, unsigned char *netmask, void *arg)
248{
249	change(arg, "del", addr, netmask);
250}
251
252char *split_if_spec(char *str, ...)
253{
254	char **arg, *end;
255	va_list ap;
256
257	va_start(ap, str);
258	while ((arg = va_arg(ap, char **)) != NULL) {
259		if (*str == '\0')
260			return NULL;
261		end = strchr(str, ',');
262		if (end != str)
263			*arg = str;
264		if (end == NULL)
265			return NULL;
266		*end++ = '\0';
267		str = end;
268	}
 
 
269	va_end(ap);
270	return str;
271}