blob: d819d44c8de97997efd6c7ab1a9a4de8c53a5469 [file] [log] [blame]
The Android Open Source Projectdd7bc332009-03-03 19:32:55 -08001/* libs/utils/adb_networking.c
2**
3** Copyright 2006, The Android Open Source Project
4**
5** Licensed under the Apache License, Version 2.0 (the "License");
6** you may not use this file except in compliance with the License.
7** You may obtain a copy of the License at
8**
9** http://www.apache.org/licenses/LICENSE-2.0
10**
11** Unless required by applicable law or agreed to in writing, software
12** distributed under the License is distributed on an "AS IS" BASIS,
13** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14** See the License for the specific language governing permissions and
15** limitations under the License.
16*/
17
18#define ADB_PORT 5037
19
20#define _GNU_SOURCE /* for asprintf */
21#include <stdio.h>
22#include <unistd.h>
23#include <stdlib.h>
24#include <errno.h>
25#include <netinet/in.h>
26#include <arpa/inet.h>
27#include <string.h>
28
29#include <cutils/adb_networking.h>
30#include <cutils/sockets.h>
31#include <cutils/properties.h>
32
33#define ADB_RESPONSE_SIZE 4
34
35/**
36 * Unfortunately, java.net.Socket wants to create it's filedescriptor early
37 * So, this function takes an fd that must be an unconnected
38 * PF_LOCAL SOCK_STREAM
39 */
40int adb_networking_connect_fd(int fd, struct sockaddr_in *p_address)
41{
42 struct sockaddr_in local_addr;
43 socklen_t alen;
44 char *cmd;
45 char buf[ADB_RESPONSE_SIZE + 1];
46 ssize_t count_read;
47 int ret;
48 int err;
49 /* for impl of inet_ntoa below*/
50 union {
51 uint8_t b[4];
52 uint32_t l;
53 } a;
54
55 /* First, connect to adb */
56
57 memset(&local_addr, 0, sizeof(local_addr));
58 local_addr.sin_family = AF_INET;
59 local_addr.sin_port = htons(ADB_PORT);
60 local_addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
61
62 do {
63 err = connect(fd, (struct sockaddr *) &local_addr, sizeof(local_addr));
64 } while (err < 0 && errno == EINTR);
65
66 if (err < 0) {
67 return -1;
68 }
69
70 a.l = p_address->sin_addr.s_addr;
71
72 // compose the command
73 asprintf(&cmd, "tcp:%u:%u.%u.%u.%u",
74 (unsigned int)ntohs(p_address->sin_port),
75 a.b[0],a.b[1],a.b[2],a.b[3]);
76
77 // buf is now the ascii hex length of cmd
78 snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
79
80 // write the 4-byte length
81 do {
82 err = write(fd, buf, 4);
83 } while (err < 0 && errno == EINTR);
84
85 // write the command
86 do {
87 err = write(fd, cmd, strlen(cmd));
88 } while (err < 0 && errno == EINTR);
89
90 // read the result
91 do {
92 count_read = read(fd, buf, sizeof(buf) - 1);
93 } while (count_read < 0 && errno != EINTR);
94
95 if (count_read == ADB_RESPONSE_SIZE
96 && 0 == strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
97 ret = 0;
98 } else {
99 /* what errno here? <shrug? */
100 errno = ENETUNREACH;
101 ret = -1;
102 }
103
104 free(cmd);
105
106 return ret;
107}
108
109/**
110 * Fills in *p_out_addr and returns 0 on success
111 * Memset's *p_out_addr and returns -1 on fail
112 */
113
114int adb_networking_gethostbyname(const char *name, struct in_addr *p_out_addr)
115{
116 int fd;
117 char *cmd = NULL;
118 char buf[ADB_RESPONSE_SIZE + 1];
119 int err;
120 ssize_t count_read;
121
122 fd = socket_loopback_client(ADB_PORT, SOCK_STREAM);
123
124 if (fd < 0) {
125 return -1;
126 }
127
128 // compose the command
129 asprintf(&cmd, "dns:%s", name);
130
131 // buf is now the ascii hex length of cmd
132 snprintf(buf, sizeof(buf), "%04X", strlen(cmd));
133
134 // write the 4-byte length
135 do {
136 err = write(fd, buf, 4);
137 } while (err < 0 && errno == EINTR);
138
139 // write the command
140 do {
141 err = write(fd, cmd, strlen(cmd));
142 } while (err < 0 && errno == EINTR);
143
144 // read the result
145 do {
146 count_read = read(fd, buf, ADB_RESPONSE_SIZE);
147 } while (count_read < 0 && errno != EINTR);
148
149 if (count_read != ADB_RESPONSE_SIZE
150 || 0 != strncmp(buf, "OKAY", ADB_RESPONSE_SIZE)) {
151 goto error;
152 }
153
154 // read the actual IP address
155 do {
156 count_read = read(fd, &(p_out_addr->s_addr), sizeof(p_out_addr->s_addr));
157 } while (count_read < 0 && errno != EINTR);
158
159 if (count_read != 4) {
160 goto error;
161 }
162
163 free(cmd);
164 close(fd);
165 return 0;
166error:
167 free(cmd);
168 close(fd);
169 memset(p_out_addr, 0, sizeof(struct in_addr));
170 return -1;
171}
172