static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[], int maxsockfd) { struct addrinfo *ai; int ret, nsockfd = 0; const size_t ai_buf_size = NI_MAXHOST + NI_MAXSERV + 2; char ai_buf[ai_buf_size]; for (ai = ai_head; ai && nsockfd < maxsockfd; ai = ai->ai_next) { int sock; addrinfo_to_text(ai, ai_buf, ai_buf_size); printf("opening %s\n", ai_buf); sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sock < 0) { printf("socket: %s: %d (%s)", ai_buf, errno, strerror(errno)); continue; } usbip_net_set_reuseaddr(sock); usbip_net_set_nodelay(sock); /* We use seperate sockets for IPv4 and IPv6 * (see do_standalone_mode()) */ usbip_net_set_v6only(sock); if (sock >= FD_SETSIZE) { printf("FD_SETSIZE: %s: sock=%d, max=%d", ai_buf, sock, FD_SETSIZE); close(sock); continue; } ret = bind(sock, ai->ai_addr, ai->ai_addrlen); if (ret < 0) { printf("bind: %s: %d (%s)", ai_buf, errno, strerror(errno)); close(sock); continue; } ret = listen(sock, SOMAXCONN); if (ret < 0) { printf("listen: %s: %d (%s)", ai_buf, errno, strerror(errno)); close(sock); continue; } printf("listening on %s\n", ai_buf); sockfdlist[nsockfd++] = sock; } return nsockfd; }
static int listen_all_addrinfo(struct addrinfo *ai_head, int sockfdlist[]) { struct addrinfo *ai; int ret, nsockfd = 0; for (ai = ai_head; ai && nsockfd < MAXSOCKFD; ai = ai->ai_next) { sockfdlist[nsockfd] = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); if (sockfdlist[nsockfd] < 0) continue; usbip_net_set_reuseaddr(sockfdlist[nsockfd]); usbip_net_set_nodelay(sockfdlist[nsockfd]); if (sockfdlist[nsockfd] >= FD_SETSIZE) { close(sockfdlist[nsockfd]); sockfdlist[nsockfd] = -1; continue; } ret = bind(sockfdlist[nsockfd], ai->ai_addr, ai->ai_addrlen); if (ret < 0) { close(sockfdlist[nsockfd]); sockfdlist[nsockfd] = -1; continue; } ret = listen(sockfdlist[nsockfd], SOMAXCONN); if (ret < 0) { close(sockfdlist[nsockfd]); sockfdlist[nsockfd] = -1; continue; } log_addrinfo(ai); nsockfd++; } if (nsockfd == 0) return -1; dbg("listening on %d address%s", nsockfd, (nsockfd == 1) ? "" : "es"); return nsockfd; }
/* * IPv6 Ready */ int usbip_net_tcp_connect(char *hostname, char *service) { struct addrinfo hints, *res, *rp; int sockfd; int ret; memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; /* get all possible addresses */ ret = getaddrinfo(hostname, service, &hints, &res); if (ret < 0) { dbg("getaddrinfo: %s service %s: %s", hostname, service, gai_strerror(ret)); return ret; } /* try the addresses */ for (rp = res; rp; rp = rp->ai_next) { sockfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (sockfd < 0) continue; /* should set TCP_NODELAY for usbip */ usbip_net_set_nodelay(sockfd); /* TODO: write code for heartbeat */ usbip_net_set_keepalive(sockfd); if (connect(sockfd, rp->ai_addr, rp->ai_addrlen) == 0) break; close(sockfd); } if (!rp) return EAI_SYSTEM; freeaddrinfo(res); return sockfd; }
static int recv_request_import(int sockfd) { struct op_import_request req; struct op_common reply; struct usbip_exported_device *edev; struct usbip_usb_device pdu_udev; int found = 0; int error = 0; int rc; memset(&req, 0, sizeof(req)); memset(&reply, 0, sizeof(reply)); rc = usbip_net_recv(sockfd, &req, sizeof(req)); if (rc < 0) { dbg("usbip_net_recv failed: import request"); return -1; } PACK_OP_IMPORT_REQUEST(0, &req); dlist_for_each_data(host_driver->edev_list, edev, struct usbip_exported_device) { if (!strncmp(req.busid, edev->udev.busid, SYSFS_BUS_ID_SIZE)) { info("found requested device: %s", req.busid); found = 1; break; } } if (found) { /* should set TCP_NODELAY for usbip */ usbip_net_set_nodelay(sockfd); /* export device needs a TCP/IP socket descriptor */ rc = usbip_host_export_device(edev, sockfd); if (rc < 0) error = 1; } else { info("requested device not found: %s", req.busid); error = 1; } rc = usbip_net_send_op_common(sockfd, OP_REP_IMPORT, (!error ? ST_OK : ST_NA)); if (rc < 0) { dbg("usbip_net_send_op_common failed: %#0x", OP_REP_IMPORT); return -1; } if (error) { dbg("import request busid %s: failed", req.busid); return -1; } memcpy(&pdu_udev, &edev->udev, sizeof(pdu_udev)); usbip_net_pack_usb_device(1, &pdu_udev); rc = usbip_net_send(sockfd, &pdu_udev, sizeof(pdu_udev)); if (rc < 0) { dbg("usbip_net_send failed: devinfo"); return -1; } dbg("import request busid %s: complete", req.busid); return 0; }