/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 · 23 complexity · 74e3a70f3f3e3fb2d20db8369b42429d MD5 · raw file

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