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