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