|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #include <stdio.h> |
|
7 #include <sys/types.h> |
|
8 #include <sys/socket.h> |
|
9 #include <sys/un.h> |
|
10 #include <unistd.h> |
|
11 #include <errno.h> |
|
12 |
|
13 #if defined(AIX) || defined(__linux) |
|
14 #include <sys/select.h> // for fd_set |
|
15 #endif |
|
16 |
|
17 #if defined(__linux) |
|
18 // Didn't find gettdtablehi() or gettdtablesize() on linux. Using FD_SETSIZE |
|
19 #define getdtablehi() FD_SETSIZE |
|
20 #else |
|
21 #define getdtablehi() getdtablesize() |
|
22 |
|
23 // If you find a system doesn't have getdtablesize try #define getdtablesize |
|
24 // to FD_SETSIZE. And if you encounter a system that doesn't even have |
|
25 // FD_SETSIZE, just grab your ankles and use 255. |
|
26 #endif |
|
27 |
|
28 |
|
29 #include "nspr.h" |
|
30 #include "nsCRT.h" |
|
31 #include "unix_dns.h" |
|
32 |
|
33 struct sockaddr_un unix_addr; |
|
34 |
|
35 int async_dns_lookup(char* hostName) |
|
36 { |
|
37 fprintf(stderr, "start async_dns_lookup\n"); |
|
38 int socket_fd = socket(PF_UNIX, SOCK_STREAM, 0); |
|
39 if (socket_fd == -1) { |
|
40 fprintf(stderr, "socket returned error.\n"); |
|
41 return -1; |
|
42 } |
|
43 |
|
44 unix_addr.sun_family = AF_UNIX; |
|
45 strcpy(unix_addr.sun_path, DNS_SOCK_NAME); |
|
46 |
|
47 int err = connect(socket_fd,(struct sockaddr*)&unix_addr, sizeof(unix_addr)); |
|
48 if (err == -1) { |
|
49 fprintf(stderr, "connect failed (errno = %d).\n",errno); |
|
50 close(socket_fd); |
|
51 return -1; |
|
52 } |
|
53 |
|
54 char buf[256]; |
|
55 strcpy(buf, "lookup: "); |
|
56 strcpy(&buf[8], hostName); |
|
57 |
|
58 err = send(socket_fd, buf, strlen(buf)+1, 0); |
|
59 if (err < 0) |
|
60 fprintf(stderr, "send(%s) returned error (errno=%d).\n",buf, errno); |
|
61 |
|
62 // receive 4 byte ID |
|
63 err = recv(socket_fd, buf, 256, 0); |
|
64 if (err < 0) |
|
65 fprintf(stderr, "recv() returned error (errno=%d).\n", errno); |
|
66 else |
|
67 { |
|
68 // printf("recv() returned %d bytes."); |
|
69 int id = *(int *)buf; |
|
70 fprintf(stderr, "id: %d\n", id); |
|
71 } |
|
72 |
|
73 return socket_fd; |
|
74 } |
|
75 |
|
76 static char * |
|
77 string_trim(char *s) |
|
78 { |
|
79 char *s2; |
|
80 if (!s) return 0; |
|
81 s2 = s + strlen(s) - 1; |
|
82 while (s2 > s && (*s2 == '\n' || *s2 == '\r' || *s2 == ' ' || *s2 == '\t')) |
|
83 *s2-- = 0; |
|
84 while (*s == ' ' || *s == '\t' || *s == '\n' || *s == '\r') |
|
85 s++; |
|
86 return s; |
|
87 } |
|
88 |
|
89 hostent * |
|
90 bytesToHostent(char *buf) |
|
91 { |
|
92 int i; |
|
93 // int size = 0; |
|
94 int len, aliasCount, addressCount; |
|
95 int addrtype, addrlength; |
|
96 char* p = buf; |
|
97 char s[1024]; |
|
98 |
|
99 len = *(int *)p; // length of name |
|
100 p += sizeof(int); // advance past name length |
|
101 |
|
102 memcpy(s, p, len); s[len] = 0; |
|
103 fprintf(stderr, "hostname: %s\n", s); |
|
104 |
|
105 p += len; // advance past name |
|
106 aliasCount = *(int *)p; // number of aliases |
|
107 p += sizeof(int); // advance past alias count |
|
108 |
|
109 for (i=0; i<aliasCount; i++) { |
|
110 len = *(int *)p; // length of alias name |
|
111 p += sizeof(int); // advance past alias name length |
|
112 |
|
113 memcpy(s, p, len); s[len] = 0; |
|
114 fprintf(stderr, "alias: %s\n", s); |
|
115 |
|
116 p += len; // advance past alias name |
|
117 } |
|
118 |
|
119 addrtype = *(int *)p; |
|
120 |
|
121 fprintf(stderr, "addrtype: %d\n", addrtype); |
|
122 |
|
123 p += sizeof(int); |
|
124 addrlength = *(int *)p; |
|
125 |
|
126 fprintf(stderr, "addrlength: %d\n", addrlength); |
|
127 |
|
128 p += sizeof(int); |
|
129 addressCount = *(int *)p; |
|
130 p += sizeof(int); |
|
131 |
|
132 for (i=0; i<addressCount; i++) { |
|
133 len = *(int *)p; |
|
134 p += sizeof(int); |
|
135 |
|
136 fprintf(stderr, "addr len: %d\n", len); |
|
137 fprintf(stderr, "addr : %x\n", *(int *)p); |
|
138 |
|
139 p += len; |
|
140 } |
|
141 |
|
142 // size = p - buf; |
|
143 // size += 1 + aliasCount; |
|
144 return 0; |
|
145 } |
|
146 |
|
147 int |
|
148 main(int argc, char* argv[]) |
|
149 { |
|
150 PRStatus status; |
|
151 |
|
152 // launch daemon |
|
153 printf("### launch daemon...\n"); |
|
154 |
|
155 PRProcessAttr *attributes = PR_NewProcessAttr(); |
|
156 if (attributes == nullptr) { |
|
157 printf("PR_NewProcessAttr() failed.\n"); |
|
158 return -1; |
|
159 } |
|
160 |
|
161 PRProcess *daemon = PR_CreateProcess("nsDnsAsyncLookup", nullptr, nullptr, attributes); |
|
162 if (daemon == nullptr) { |
|
163 printf("PR_CreateProcess failed.\n"); |
|
164 } else { |
|
165 // status = PR_DetachProcess(daemon); |
|
166 //if (status != 0) |
|
167 // printf("PR_DetachProcess returned %d\n", status); |
|
168 //daemon = nullptr; |
|
169 } |
|
170 |
|
171 PR_DestroyProcessAttr(attributes); |
|
172 |
|
173 // create socket and connect to daemon |
|
174 int socket_fd = 0; |
|
175 |
|
176 |
|
177 bool notDone = true; |
|
178 char buf[1024]; |
|
179 |
|
180 while(notDone) { |
|
181 int status = 0; |
|
182 fd_set fdset; |
|
183 |
|
184 FD_ZERO(&fdset); |
|
185 FD_SET(fileno(stdin), &fdset); |
|
186 if (socket_fd > 0) |
|
187 FD_SET(socket_fd, &fdset); |
|
188 |
|
189 status = select(getdtablehi(), &fdset, 0, 0, 0); |
|
190 if (status <= 0) |
|
191 { |
|
192 fprintf(stderr, "%s: select() returned %d\n", argv[0], status); |
|
193 exit(-1); |
|
194 } |
|
195 |
|
196 // which fd is set? |
|
197 |
|
198 if (FD_ISSET(fileno(stdin), &fdset)) |
|
199 { |
|
200 char *line = fgets(buf, sizeof(buf)-1, stdin); |
|
201 line = string_trim(line); |
|
202 |
|
203 if(!strcmp(line, "quit") || !strcmp(line, "exit")) |
|
204 { |
|
205 fprintf(stderr, "bye now.\n"); |
|
206 notDone = false; |
|
207 } |
|
208 else if (!strncmp(line, "abort ", 6)) |
|
209 { |
|
210 // abort id |
|
211 } |
|
212 else if (strchr(line, ' ') || strchr(line, '\t')) |
|
213 { |
|
214 fprintf(stderr, "%s: unrecognized command %s.\n", argv[0], line); |
|
215 } |
|
216 else |
|
217 { |
|
218 fprintf(stderr, "%s: looking up %s...\n", argv[0], line); |
|
219 // initiate dns lookup |
|
220 socket_fd = async_dns_lookup(line); |
|
221 } |
|
222 } |
|
223 |
|
224 if (socket_fd && FD_ISSET(socket_fd, &fdset)) |
|
225 { |
|
226 // read from socket, parse results |
|
227 int size = read(socket_fd, buf, 1024); |
|
228 if (size > 0) |
|
229 { |
|
230 // parse buffer into hostent |
|
231 char *p = buf; |
|
232 fprintf(stderr, "bytes read: %d\n", size); |
|
233 fprintf(stderr, "response code: %d\n", *(int *)p); |
|
234 p += sizeof(int); |
|
235 |
|
236 for (int i=0; i < size; i++) { |
|
237 if (!(i%8)) |
|
238 fprintf(stderr, "\n"); |
|
239 fprintf(stderr, "%2.2x ",(unsigned char)buf[i]); |
|
240 } |
|
241 fprintf(stderr, "\n"); |
|
242 hostent *h; |
|
243 h = bytesToHostent(p); |
|
244 } |
|
245 close(socket_fd); |
|
246 socket_fd = 0; |
|
247 } |
|
248 } |
|
249 |
|
250 return 0; |
|
251 } |
|
252 |
|
253 /* |
|
254 buffer |
|
255 |
|
256 int nameLen; |
|
257 |
|
258 if (nameLen > 0) |
|
259 char [nameLen+1] name |
|
260 |
|
261 int aliasCount |
|
262 for each alias |
|
263 int aliasNameLen |
|
264 char [aliasNameLen+1] aliasName |
|
265 |
|
266 int h_addrtype |
|
267 int h_length |
|
268 int addrCount |
|
269 for each addr |
|
270 char[h_length] addr |
|
271 |
|
272 |
|
273 |
|
274 */ |