xref: /linux/tools/usb/usbip/src/usbip_network.c (revision 56fb34d86e875dbb0d3e6a81c5d3d035db373031)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2011 matt mooney <mfm@muteddisk.com>
4  *               2005-2007 Takahiro Hirofuchi
5  */
6 
7 #include <sys/socket.h>
8 
9 #include <string.h>
10 
11 #include <arpa/inet.h>
12 #include <netdb.h>
13 #include <netinet/tcp.h>
14 #include <unistd.h>
15 
16 #ifdef HAVE_LIBWRAP
17 #include <tcpd.h>
18 #endif
19 
20 #include "usbip_common.h"
21 #include "usbip_network.h"
22 
23 int usbip_port = 3240;
24 char *usbip_port_string = "3240";
25 
26 void usbip_setup_port_number(char *arg)
27 {
28 	dbg("parsing port arg '%s'", arg);
29 	char *end;
30 	unsigned long int port = strtoul(arg, &end, 10);
31 
32 	if (end == arg) {
33 		err("port: could not parse '%s' as a decimal integer", arg);
34 		return;
35 	}
36 
37 	if (*end != '\0') {
38 		err("port: garbage at end of '%s'", arg);
39 		return;
40 	}
41 
42 	if (port > UINT16_MAX) {
43 		err("port: %s too high (max=%d)",
44 		    arg, UINT16_MAX);
45 		return;
46 	}
47 
48 	usbip_port = port;
49 	usbip_port_string = arg;
50 	info("using port %d (\"%s\")", usbip_port, usbip_port_string);
51 }
52 
53 void usbip_net_pack_uint32_t(int pack, uint32_t *num)
54 {
55 	uint32_t i;
56 
57 	if (pack)
58 		i = htonl(*num);
59 	else
60 		i = ntohl(*num);
61 
62 	*num = i;
63 }
64 
65 void usbip_net_pack_uint16_t(int pack, uint16_t *num)
66 {
67 	uint16_t i;
68 
69 	if (pack)
70 		i = htons(*num);
71 	else
72 		i = ntohs(*num);
73 
74 	*num = i;
75 }
76 
77 void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
78 {
79 	usbip_net_pack_uint32_t(pack, &udev->busnum);
80 	usbip_net_pack_uint32_t(pack, &udev->devnum);
81 	usbip_net_pack_uint32_t(pack, &udev->speed);
82 
83 	usbip_net_pack_uint16_t(pack, &udev->idVendor);
84 	usbip_net_pack_uint16_t(pack, &udev->idProduct);
85 	usbip_net_pack_uint16_t(pack, &udev->bcdDevice);
86 }
87 
88 void usbip_net_pack_usb_interface(int pack __attribute__((unused)),
89 				  struct usbip_usb_interface *udev
90 				  __attribute__((unused)))
91 {
92 	/* uint8_t members need nothing */
93 }
94 
95 static ssize_t usbip_net_xmit(int sockfd, void *buff, size_t bufflen,
96 			      int sending)
97 {
98 	ssize_t nbytes;
99 	ssize_t total = 0;
100 
101 	if (!bufflen)
102 		return 0;
103 
104 	do {
105 		if (sending)
106 			nbytes = send(sockfd, buff, bufflen, 0);
107 		else
108 			nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
109 
110 		if (nbytes <= 0)
111 			return -1;
112 
113 		buff	 = (void *)((intptr_t) buff + nbytes);
114 		bufflen	-= nbytes;
115 		total	+= nbytes;
116 
117 	} while (bufflen > 0);
118 
119 	return total;
120 }
121 
122 ssize_t usbip_net_recv(int sockfd, void *buff, size_t bufflen)
123 {
124 	return usbip_net_xmit(sockfd, buff, bufflen, 0);
125 }
126 
127 ssize_t usbip_net_send(int sockfd, void *buff, size_t bufflen)
128 {
129 	return usbip_net_xmit(sockfd, buff, bufflen, 1);
130 }
131 
132 int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
133 {
134 	struct op_common op_common;
135 	int rc;
136 
137 	memset(&op_common, 0, sizeof(op_common));
138 
139 	op_common.version = USBIP_VERSION;
140 	op_common.code    = code;
141 	op_common.status  = status;
142 
143 	PACK_OP_COMMON(1, &op_common);
144 
145 	rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
146 	if (rc < 0) {
147 		dbg("usbip_net_send failed: %d", rc);
148 		return -1;
149 	}
150 
151 	return 0;
152 }
153 
154 int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status)
155 {
156 	struct op_common op_common;
157 	int rc;
158 
159 	memset(&op_common, 0, sizeof(op_common));
160 
161 	rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
162 	if (rc < 0) {
163 		dbg("usbip_net_recv failed: %d", rc);
164 		goto err;
165 	}
166 
167 	PACK_OP_COMMON(0, &op_common);
168 
169 	if (op_common.version != USBIP_VERSION) {
170 		err("USBIP Kernel and tool version mismatch: %d %d:",
171 		    op_common.version, USBIP_VERSION);
172 		goto err;
173 	}
174 
175 	switch (*code) {
176 	case OP_UNSPEC:
177 		break;
178 	default:
179 		if (op_common.code != *code) {
180 			dbg("unexpected pdu %#0x for %#0x", op_common.code,
181 			    *code);
182 			/* return error status */
183 			*status = ST_ERROR;
184 			goto err;
185 		}
186 	}
187 
188 	*status = op_common.status;
189 
190 	if (op_common.status != ST_OK) {
191 		dbg("request failed at peer: %d", op_common.status);
192 		goto err;
193 	}
194 
195 	*code = op_common.code;
196 
197 	return 0;
198 err:
199 	return -1;
200 }
201 
202 int usbip_net_set_reuseaddr(int sockfd)
203 {
204 	const int val = 1;
205 	int ret;
206 
207 	ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
208 	if (ret < 0)
209 		dbg("setsockopt: SO_REUSEADDR");
210 
211 	return ret;
212 }
213 
214 int usbip_net_set_nodelay(int sockfd)
215 {
216 	const int val = 1;
217 	int ret;
218 
219 	ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
220 	if (ret < 0)
221 		dbg("setsockopt: TCP_NODELAY");
222 
223 	return ret;
224 }
225 
226 int usbip_net_set_keepalive(int sockfd)
227 {
228 	const int val = 1;
229 	int ret;
230 
231 	ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
232 	if (ret < 0)
233 		dbg("setsockopt: SO_KEEPALIVE");
234 
235 	return ret;
236 }
237 
238 int usbip_net_set_v6only(int sockfd)
239 {
240 	const int val = 1;
241 	int ret;
242 
243 	ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
244 	if (ret < 0)
245 		dbg("setsockopt: IPV6_V6ONLY");
246 
247 	return ret;
248 }
249 
250 /*
251  * IPv6 Ready
252  */
253 int usbip_net_tcp_connect(char *hostname, char *service)
254 {
255 	struct addrinfo hints, *res, *rp;
256 	int sockfd;
257 	int ret;
258 
259 	memset(&hints, 0, sizeof(hints));
260 	hints.ai_family = AF_UNSPEC;
261 	hints.ai_socktype = SOCK_STREAM;
262 
263 	/* get all possible addresses */
264 	ret = getaddrinfo(hostname, service, &hints, &res);
265 	if (ret < 0) {
266 		dbg("getaddrinfo: %s service %s: %s", hostname, service,
267 		    gai_strerror(ret));
268 		return ret;
269 	}
270 
271 	/* try the addresses */
272 	for (rp = res; rp; rp = rp->ai_next) {
273 		sockfd = socket(rp->ai_family, rp->ai_socktype,
274 				rp->ai_protocol);
275 		if (sockfd < 0)
276 			continue;
277 
278 		/* should set TCP_NODELAY for usbip */
279 		usbip_net_set_nodelay(sockfd);
280 		/* TODO: write code for heartbeat */
281 		usbip_net_set_keepalive(sockfd);
282 
283 		if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
284 			break;
285 
286 		close(sockfd);
287 	}
288 
289 	freeaddrinfo(res);
290 
291 	if (!rp)
292 		return EAI_SYSTEM;
293 
294 	return sockfd;
295 }
296