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) 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 dbg("version mismatch: %d %d", op_common.version, 183 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 goto err; 195 } 196 } 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 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 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 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 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 */ 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