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  
usbip_setup_port_number(char * arg)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  
usbip_net_pack_uint32_t(int pack,uint32_t num)53  uint32_t 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  	return i;
63  }
64  
usbip_net_pack_uint16_t(int pack,uint16_t num)65  uint16_t 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  	return i;
75  }
76  
usbip_net_pack_usb_device(int pack,struct usbip_usb_device * udev)77  void usbip_net_pack_usb_device(int pack, struct usbip_usb_device *udev)
78  {
79  	udev->busnum = usbip_net_pack_uint32_t(pack, udev->busnum);
80  	udev->devnum = usbip_net_pack_uint32_t(pack, udev->devnum);
81  	udev->speed = usbip_net_pack_uint32_t(pack, udev->speed);
82  
83  	udev->idVendor = usbip_net_pack_uint16_t(pack, udev->idVendor);
84  	udev->idProduct = usbip_net_pack_uint16_t(pack, udev->idProduct);
85  	udev->bcdDevice = usbip_net_pack_uint16_t(pack, udev->bcdDevice);
86  }
87  
usbip_net_pack_usb_interface(int pack,struct usbip_usb_interface * udev)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  
usbip_net_xmit(int sockfd,void * buff,size_t bufflen,int sending)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  
usbip_net_recv(int sockfd,void * buff,size_t bufflen)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  
usbip_net_send(int sockfd,void * buff,size_t bufflen)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  
usbip_net_pack_op_common(int pack,struct op_common * op_common)132  static inline void usbip_net_pack_op_common(int pack,
133  					    struct op_common *op_common)
134  {
135  	op_common->version = usbip_net_pack_uint16_t(pack, op_common->version);
136  	op_common->code = usbip_net_pack_uint16_t(pack, op_common->code);
137  	op_common->status = usbip_net_pack_uint32_t(pack, op_common->status);
138  }
139  
usbip_net_send_op_common(int sockfd,uint32_t code,uint32_t status)140  int usbip_net_send_op_common(int sockfd, uint32_t code, uint32_t status)
141  {
142  	struct op_common op_common;
143  	int rc;
144  
145  	memset(&op_common, 0, sizeof(op_common));
146  
147  	op_common.version = USBIP_VERSION;
148  	op_common.code    = code;
149  	op_common.status  = status;
150  
151  	usbip_net_pack_op_common(1, &op_common);
152  
153  	rc = usbip_net_send(sockfd, &op_common, sizeof(op_common));
154  	if (rc < 0) {
155  		dbg("usbip_net_send failed: %d", rc);
156  		return -1;
157  	}
158  
159  	return 0;
160  }
161  
usbip_net_recv_op_common(int sockfd,uint16_t * code,int * status)162  int usbip_net_recv_op_common(int sockfd, uint16_t *code, int *status)
163  {
164  	struct op_common op_common;
165  	int rc;
166  
167  	memset(&op_common, 0, sizeof(op_common));
168  
169  	rc = usbip_net_recv(sockfd, &op_common, sizeof(op_common));
170  	if (rc < 0) {
171  		dbg("usbip_net_recv failed: %d", rc);
172  		goto err;
173  	}
174  
175  	usbip_net_pack_op_common(0, &op_common);
176  
177  	if (op_common.version != USBIP_VERSION) {
178  		err("USBIP Kernel and tool version mismatch: %d %d:",
179  		    op_common.version, USBIP_VERSION);
180  		goto err;
181  	}
182  
183  	switch (*code) {
184  	case OP_UNSPEC:
185  		break;
186  	default:
187  		if (op_common.code != *code) {
188  			dbg("unexpected pdu %#0x for %#0x", op_common.code,
189  			    *code);
190  			/* return error status */
191  			*status = ST_ERROR;
192  			goto err;
193  		}
194  	}
195  
196  	*status = op_common.status;
197  
198  	if (op_common.status != ST_OK) {
199  		dbg("request failed at peer: %d", op_common.status);
200  		goto err;
201  	}
202  
203  	*code = op_common.code;
204  
205  	return 0;
206  err:
207  	return -1;
208  }
209  
usbip_net_set_reuseaddr(int sockfd)210  int usbip_net_set_reuseaddr(int sockfd)
211  {
212  	const int val = 1;
213  	int ret;
214  
215  	ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
216  	if (ret < 0)
217  		dbg("setsockopt: SO_REUSEADDR");
218  
219  	return ret;
220  }
221  
usbip_net_set_nodelay(int sockfd)222  int usbip_net_set_nodelay(int sockfd)
223  {
224  	const int val = 1;
225  	int ret;
226  
227  	ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
228  	if (ret < 0)
229  		dbg("setsockopt: TCP_NODELAY");
230  
231  	return ret;
232  }
233  
usbip_net_set_keepalive(int sockfd)234  int usbip_net_set_keepalive(int sockfd)
235  {
236  	const int val = 1;
237  	int ret;
238  
239  	ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
240  	if (ret < 0)
241  		dbg("setsockopt: SO_KEEPALIVE");
242  
243  	return ret;
244  }
245  
usbip_net_set_v6only(int sockfd)246  int usbip_net_set_v6only(int sockfd)
247  {
248  	const int val = 1;
249  	int ret;
250  
251  	ret = setsockopt(sockfd, IPPROTO_IPV6, IPV6_V6ONLY, &val, sizeof(val));
252  	if (ret < 0)
253  		dbg("setsockopt: IPV6_V6ONLY");
254  
255  	return ret;
256  }
257  
258  /*
259   * IPv6 Ready
260   */
usbip_net_tcp_connect(char * hostname,char * service)261  int usbip_net_tcp_connect(char *hostname, char *service)
262  {
263  	struct addrinfo hints, *res, *rp;
264  	int sockfd;
265  	int ret;
266  
267  	memset(&hints, 0, sizeof(hints));
268  	hints.ai_family = AF_UNSPEC;
269  	hints.ai_socktype = SOCK_STREAM;
270  
271  	/* get all possible addresses */
272  	ret = getaddrinfo(hostname, service, &hints, &res);
273  	if (ret < 0) {
274  		dbg("getaddrinfo: %s service %s: %s", hostname, service,
275  		    gai_strerror(ret));
276  		return ret;
277  	}
278  
279  	/* try the addresses */
280  	for (rp = res; rp; rp = rp->ai_next) {
281  		sockfd = socket(rp->ai_family, rp->ai_socktype,
282  				rp->ai_protocol);
283  		if (sockfd < 0)
284  			continue;
285  
286  		/* should set TCP_NODELAY for usbip */
287  		usbip_net_set_nodelay(sockfd);
288  		/* TODO: write code for heartbeat */
289  		usbip_net_set_keepalive(sockfd);
290  
291  		if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0)
292  			break;
293  
294  		close(sockfd);
295  	}
296  
297  	freeaddrinfo(res);
298  
299  	if (!rp)
300  		return EAI_SYSTEM;
301  
302  	return sockfd;
303  }
304