PageRenderTime 48ms CodeModel.GetById 15ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/usbip/userspace/src/usbip_network.c

https://bitbucket.org/slukk/jb-tsm-kernel-4.2
C | 251 lines | 176 code | 61 blank | 14 comment | 22 complexity | 74e3a70f3f3e3fb2d20db8369b42429d MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 *
  3 * Copyright (C) 2005-2007 Takahiro Hirofuchi
  4 */
  5
  6#include "usbip_network.h"
  7
  8void pack_uint32_t(int pack, uint32_t *num)
  9{
 10	uint32_t i;
 11
 12	if (pack)
 13		i = htonl(*num);
 14	else
 15		i = ntohl(*num);
 16
 17	*num = i;
 18}
 19
 20void pack_uint16_t(int pack, uint16_t *num)
 21{
 22	uint16_t i;
 23
 24	if (pack)
 25		i = htons(*num);
 26	else
 27		i = ntohs(*num);
 28
 29	*num = i;
 30}
 31
 32void pack_usb_device(int pack, struct usb_device *udev)
 33{
 34	pack_uint32_t(pack, &udev->busnum);
 35	pack_uint32_t(pack, &udev->devnum);
 36	pack_uint32_t(pack, &udev->speed );
 37
 38	pack_uint16_t(pack, &udev->idVendor );
 39	pack_uint16_t(pack, &udev->idProduct);
 40	pack_uint16_t(pack, &udev->bcdDevice);
 41}
 42
 43void pack_usb_interface(int pack __attribute__((unused)),
 44			struct usb_interface *udev __attribute__((unused)))
 45{
 46	/* uint8_t members need nothing */
 47}
 48
 49
 50static ssize_t usbip_xmit(int sockfd, void *buff, size_t bufflen, int sending)
 51{
 52	ssize_t total = 0;
 53
 54	if (!bufflen)
 55		return 0;
 56
 57	do {
 58		ssize_t nbytes;
 59
 60		if (sending)
 61			nbytes = send(sockfd, buff, bufflen, 0);
 62		else
 63			nbytes = recv(sockfd, buff, bufflen, MSG_WAITALL);
 64
 65		if (nbytes <= 0)
 66			return -1;
 67
 68		buff	= (void *) ((intptr_t) buff + nbytes);
 69		bufflen	-= nbytes;
 70		total	+= nbytes;
 71
 72	} while (bufflen > 0);
 73
 74
 75	return total;
 76}
 77
 78ssize_t usbip_recv(int sockfd, void *buff, size_t bufflen)
 79{
 80	return usbip_xmit(sockfd, buff, bufflen, 0);
 81}
 82
 83ssize_t usbip_send(int sockfd, void *buff, size_t bufflen)
 84{
 85	return usbip_xmit(sockfd, buff, bufflen, 1);
 86}
 87
 88int usbip_send_op_common(int sockfd, uint32_t code, uint32_t status)
 89{
 90	int ret;
 91	struct op_common op_common;
 92
 93	bzero(&op_common, sizeof(op_common));
 94
 95	op_common.version	= USBIP_VERSION;
 96	op_common.code		= code;
 97	op_common.status	= status;
 98
 99	PACK_OP_COMMON(1, &op_common);
100
101	ret = usbip_send(sockfd, (void *) &op_common, sizeof(op_common));
102	if (ret < 0) {
103		err("send op_common");
104		return -1;
105	}
106
107	return 0;
108}
109
110int usbip_recv_op_common(int sockfd, uint16_t *code)
111{
112	int ret;
113	struct op_common op_common;
114
115	bzero(&op_common, sizeof(op_common));
116
117	ret = usbip_recv(sockfd, (void *) &op_common, sizeof(op_common));
118	if (ret < 0) {
119		err("recv op_common, %d", ret);
120		goto err;
121	}
122
123	PACK_OP_COMMON(0, &op_common);
124
125	if (op_common.version != USBIP_VERSION) {
126		err("version mismatch, %d %d", op_common.version, USBIP_VERSION);
127		goto err;
128	}
129
130	switch(*code) {
131		case OP_UNSPEC:
132			break;
133		default:
134			if (op_common.code != *code) {
135				info("unexpected pdu %d for %d", op_common.code, *code);
136				goto err;
137			}
138	}
139
140	if (op_common.status != ST_OK) {
141		info("request failed at peer, %d", op_common.status);
142		goto err;
143	}
144
145	*code = op_common.code;
146
147	return 0;
148err:
149	return -1;
150}
151
152
153int usbip_set_reuseaddr(int sockfd)
154{
155	const int val = 1;
156	int ret;
157
158	ret = setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val));
159	if (ret < 0)
160		err("setsockopt SO_REUSEADDR");
161
162	return ret;
163}
164
165int usbip_set_nodelay(int sockfd)
166{
167	const int val = 1;
168	int ret;
169
170	ret = setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
171	if (ret < 0)
172		err("setsockopt TCP_NODELAY");
173
174	return ret;
175}
176
177int usbip_set_keepalive(int sockfd)
178{
179	const int val = 1;
180	int ret;
181
182	ret = setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
183	if (ret < 0)
184		err("setsockopt SO_KEEPALIVE");
185
186	return ret;
187}
188
189/* IPv6 Ready */
190/*
191 * moved here from vhci_attach.c
192 */
193int tcp_connect(char *hostname, char *service)
194{
195	struct addrinfo hints, *res, *res0;
196	int sockfd;
197	int err;
198
199
200	memset(&hints, 0, sizeof(hints));
201	hints.ai_socktype = SOCK_STREAM;
202
203	/* get all possible addresses */
204	err = getaddrinfo(hostname, service, &hints, &res0);
205	if (err) {
206		err("%s %s: %s", hostname, service, gai_strerror(err));
207		return -1;
208	}
209
210	/* try all the addresses */
211	for (res = res0; res; res = res->ai_next) {
212		char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
213
214		err = getnameinfo(res->ai_addr, res->ai_addrlen,
215				hbuf, sizeof(hbuf), sbuf, sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV);
216		if (err) {
217			err("%s %s: %s", hostname, service, gai_strerror(err));
218			continue;
219		}
220
221		dbg("trying %s port %s\n", hbuf, sbuf);
222
223		sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
224		if (sockfd < 0) {
225			err("socket");
226			continue;
227		}
228
229		/* should set TCP_NODELAY for usbip */
230		usbip_set_nodelay(sockfd);
231		/* TODO: write code for heatbeat */
232		usbip_set_keepalive(sockfd);
233
234		err = connect(sockfd, res->ai_addr, res->ai_addrlen);
235		if (err < 0) {
236			close(sockfd);
237			continue;
238		}
239
240		/* connected */
241		dbg("connected to %s:%s", hbuf, sbuf);
242		freeaddrinfo(res0);
243		return sockfd;
244	}
245
246
247	dbg("%s:%s, %s", hostname, service, "no destination to connect to");
248	freeaddrinfo(res0);
249
250	return -1;
251}