1 #include "UsbIpUtils.h"
2 
3 #include <arpa/inet.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <log/log.h>
7 #include <netinet/in.h>
8 #include <netinet/tcp.h>
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <sys/socket.h>
13 #include <unistd.h>
14 
15 constexpr uint16_t kIpVersion = 0x0111;
16 
17 constexpr uint16_t kOpRequest = 0x8003;
18 constexpr uint16_t kOpResponse = 0x0003;
19 
20 //  Fields associated with all USBIP packets.
21 typedef struct op_req_common {
22     uint16_t ip_version;
23     uint16_t command_code;
24     uint32_t status;
25 } op_req_common;
26 
27 typedef struct op_req_import {
28     op_req_common common;
29     uint32_t busid[8];
30 } op_req_import;
31 
32 typedef struct op_rep_import {
33     op_req_common common;
34 } op_rep_import;
35 
36 // Metadata fields only valid for successful status flag.
37 typedef struct op_rep_import_metadata {
38     uint32_t path[64];
39     uint32_t bus_id[8];
40     uint32_t bus_num;
41     uint32_t dev_num;
42     uint32_t speed;
43     uint16_t id_vendor;
44     uint16_t id_product;
45     uint16_t bcd_device;
46     uint8_t device_class;
47     uint8_t device_subclass;
48     uint8_t device_protocol;
49     uint8_t configuration_value;
50     uint8_t num_configurations;
51     uint8_t num_interfaces;
52 } op_rep_import_success;
53 
get_usbip_connection(const char * server,const char * port,const char * dev_id,usbip_conn_info * info)54 bool get_usbip_connection(const char *server, const char *port,
55                           const char *dev_id, usbip_conn_info *info) {
56     struct sockaddr_in address;
57 
58     // Setup socket to the server.
59     if ((info->sock_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0) {
60         ALOGE("Opening socket failed: %s\n", strerror(errno));
61         return false;
62     }
63 
64     int flags = 1;
65     if (setsockopt(info->sock_fd, SOL_SOCKET, SO_KEEPALIVE, &flags,
66                    sizeof(flags)) == -1) {
67         ALOGE("Failed to enable keep alive: %s\n", strerror(errno));
68         close(info->sock_fd);
69         return false;
70     }
71     if (setsockopt(info->sock_fd, SOL_TCP, TCP_NODELAY, &flags,
72                    sizeof(flags)) == -1) {
73         ALOGE("Failed to enable no delay: %s\n", strerror(errno));
74         close(info->sock_fd);
75         return false;
76     }
77 
78     address.sin_family = AF_INET;
79     if (inet_aton(server, &address.sin_addr) == 0) {
80         ALOGE("Failure to convert ip address %s\n", server);
81         close(info->sock_fd);
82         return false;
83     }
84 
85     errno = 0;
86     char *error;
87     address.sin_port = strtol(port, &error, 10);
88     if (address.sin_port == 0) {
89         ALOGE("Port is invalid %s\n", port);
90         close(info->sock_fd);
91         return false;
92     }
93     address.sin_port = htons(address.sin_port);
94     if (connect(info->sock_fd, (struct sockaddr *)&address, sizeof(address)) ==
95         -1) {
96         ALOGE("Connection failed: %s\n", strerror(errno));
97         close(info->sock_fd);
98         return false;
99     }
100 
101     // Fill in op request
102     op_req_import op_req;
103     op_req.common.ip_version = htons(kIpVersion);
104     op_req.common.command_code = htons(kOpRequest);
105     op_req.common.status = 0x0000;
106     strncpy((char *)op_req.busid, dev_id, sizeof(op_req.busid));
107 
108     if (send(info->sock_fd, &op_req, sizeof(op_req), 0) == -1) {
109         ALOGE("Error sending op_req: %s\n", strerror(errno));
110         close(info->sock_fd);
111         return false;
112     }
113 
114     // Read in op response.
115     op_rep_import op_rep;
116     if (recv(info->sock_fd, &op_rep, sizeof(op_rep), MSG_WAITALL) == -1) {
117         ALOGE("Error receiving op_rep: %s\n", strerror(errno));
118         close(info->sock_fd);
119         return false;
120     }
121 
122     if (op_rep.common.status != 0) {
123         ALOGE("op_rep status is invalid.\n");
124         close(info->sock_fd);
125         return false;
126     }
127 
128     uint16_t command = ntohs(op_rep.common.command_code);
129     if (command != kOpResponse) {
130         ALOGE("Invalid command expected: %d received: %d", command, kOpResponse);
131         close(info->sock_fd);
132         return false;
133     }
134 
135     op_rep_import_success data;
136     if (recv(info->sock_fd, &data, sizeof(data), MSG_WAITALL) == -1) {
137         ALOGE("Error receiving op_rep_data: %s\n", strerror(errno));
138         close(info->sock_fd);
139         return false;
140     }
141 
142     int temp_bus_num = ntohl(data.bus_num);
143     int temp_dev_num = ntohl(data.dev_num);
144     info->speed = ntohl(data.speed);
145     info->dev_id = (temp_bus_num << 16) | temp_dev_num;
146     return true;
147 }
148 
get_free_vhci_port(FILE * file,int speed)149 int get_free_vhci_port(FILE *file, int speed) {
150     // Throw away the header line.
151     char *buf = NULL;
152     size_t length = 0;
153     if (getline(&buf, &length, file) == -1) {
154         ALOGE("Couldn't get the header line: %s\n", strerror(errno));
155         free(buf);
156         return -1;
157     }
158     free(buf);
159 
160     char busid[32];
161     char hub[3];
162     int port = 0;
163     int status = 0;
164     int spd = 0;
165     int dev = 0;
166     int sockfd = 0;
167     const char *expected_hub = (speed == USBIP_SPEED_SUPER) ? "ss" : "hs";
168 
169     // Scan status lines for a free USB port.
170     while (fscanf(file, "%2s %d %d %d %x %u %31s\n", hub, &port, &status, &spd,
171                   &dev, &sockfd, busid) != EOF) {
172         if (strcmp(expected_hub, hub) == 0 && status == USBIP_VDEV_NULL) {
173             return port;
174         }
175     }
176 
177     return -1;
178 }
179