You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

587 lines
19 KiB

  1. #include "dns_parser.h"
  2. #include <node.h>
  3. #include <v8.h>
  4. #include <ares.h>
  5. #include <ares_dns.h>
  6. #include <stdlib.h>
  7. #include <string.h>
  8. #include <stdint.h>
  9. #include <arpa/nameser.h>
  10. #include <arpa/inet.h>
  11. #ifdef __OpenBSD__
  12. # ifndef ns_t_a
  13. # include <nameser.h>
  14. # endif
  15. #endif // __OpenBSD__
  16. namespace dns_parser {
  17. static v8::Persistent<v8::String> question_symbol, answer_symbol, authority_symbol, additional_symbol;
  18. static v8::Persistent<v8::String> type_symbol, ntype_symbol, class_symbol, nclass_symbol, ttl_symbol, rdata_symbol, text_symbol, data_symbol;
  19. static v8::Persistent<v8::String> priority_symbol, weight_symbol, port_symbol, name_symbol, exchange_symbol, target_symbol;
  20. static v8::Persistent<v8::String> mname_symbol, rname_symbol, serial_symbol, refresh_symbol, retry_symbol, expire_symbol, minimum_symbol;
  21. static v8::Persistent<v8::String> space_symbol;
  22. typedef int (*ParseRRData)(const unsigned char *abuf, int alen, const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r);
  23. struct RR_TYPE {
  24. const char *s;
  25. int n;
  26. ParseRRData parse_in; /* only parse class IN */
  27. v8::Persistent<v8::String> symbol;
  28. };
  29. struct RR_CLASS {
  30. const char *s;
  31. int n;
  32. v8::Persistent<v8::String> symbol;
  33. };
  34. static int parse_char_string(const unsigned char *&rr_data, int &rr_len, v8::Local<v8::String> &s) {
  35. if (rr_len <= 0) return ARES_EBADRESP;
  36. int len = (unsigned int) rr_data[0];
  37. rr_data++; rr_len--;
  38. if (len > rr_len) return ARES_EBADRESP;
  39. s = v8::String::New((const char*) rr_data, len);
  40. rr_data += len; rr_len -= len;
  41. return ARES_SUCCESS;
  42. }
  43. static int ParseRRData_A(const unsigned char *, int , const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  44. if (rr_len == sizeof(struct in_addr)) {
  45. struct in_addr a;
  46. memcpy(&a, rr_data, sizeof(a));
  47. char ip[INET_ADDRSTRLEN];
  48. ip[0] = '\0';
  49. ::inet_ntop(AF_INET, &a, ip, INET_ADDRSTRLEN);
  50. v8::Local<v8::String> address = v8::String::New(ip);
  51. r->Set(text_symbol, address);
  52. return ARES_SUCCESS;
  53. }
  54. return ARES_EBADRESP;
  55. }
  56. static int ParseRRData_AAAA(const unsigned char *, int , const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  57. if (rr_len == sizeof(struct in6_addr)) {
  58. struct in6_addr a;
  59. memcpy(&a, rr_data, sizeof(a));
  60. char ip[INET6_ADDRSTRLEN];
  61. ip[0] = '\0';
  62. ::inet_ntop(AF_INET6, &a, ip, INET6_ADDRSTRLEN);
  63. v8::Local<v8::String> address = v8::String::New(ip);
  64. r->Set(text_symbol, address);
  65. return ARES_SUCCESS;
  66. }
  67. return ARES_EBADRESP;
  68. }
  69. static int ParseRRData_MX(const unsigned char *abuf, int alen, const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  70. int status;
  71. if (rr_len < 2) return ARES_EBADRESP;
  72. uint16_t priority;
  73. memcpy(&priority, rr_data, sizeof(priority));
  74. priority = ntohs(priority);
  75. rr_data += sizeof(priority); rr_len -= 2;
  76. char *hostname;
  77. long len;
  78. status = ares_expand_name(rr_data, abuf, alen, &hostname, &len);
  79. if (status != ARES_SUCCESS) return status;
  80. v8::Local<v8::String> v8_hostname = v8::String::New(hostname);
  81. free(hostname);
  82. if (len != rr_len) return ARES_EBADRESP;
  83. v8::Local<v8::Integer> v8_priority = v8::Integer::New(priority);
  84. r->Set(priority_symbol, v8_priority);
  85. r->Set(exchange_symbol, v8_hostname);
  86. v8::Local<v8::String> text = v8::String::Concat(v8_priority->ToString(), space_symbol);
  87. text = v8::String::Concat(text, v8_hostname);
  88. r->Set(text_symbol, text);
  89. return ARES_SUCCESS;
  90. }
  91. static int ParseRRData_NS(const unsigned char *abuf, int alen, const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  92. int status;
  93. char *hostname;
  94. long len;
  95. status = ares_expand_name(rr_data, abuf, alen, &hostname, &len);
  96. if (status != ARES_SUCCESS) return status;
  97. v8::Local<v8::String> v8_hostname = v8::String::New(hostname);
  98. free(hostname);
  99. if (len != rr_len) return ARES_EBADRESP;
  100. r->Set(text_symbol, v8_hostname);
  101. return ARES_SUCCESS;
  102. }
  103. static int ParseRRData_SOA(const unsigned char *abuf, int alen, const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  104. int status;
  105. long len;
  106. char *mname; /* primary NS */
  107. status = ares_expand_name(rr_data, abuf, alen, &mname, &len);
  108. if (status != ARES_SUCCESS) return status;
  109. v8::Local<v8::String> v8_mname = v8::String::New(mname);
  110. free(mname);
  111. if (len > rr_len) return ARES_EBADRESP;
  112. rr_data += len; rr_len -= len;
  113. char *rname; /* owner mailbox */
  114. status = ares_expand_name(rr_data, abuf, alen, &rname, &len);
  115. if (status != ARES_SUCCESS) return status;
  116. v8::Local<v8::String> v8_rname = v8::String::New(rname);
  117. free(rname);
  118. if (len > rr_len) return ARES_EBADRESP;
  119. rr_data += len; rr_len -= len;
  120. if (rr_len != 20) return ARES_EBADRESP;
  121. uint32_t serial, refresh, retry, expire, minimum;
  122. memcpy(&serial, rr_data, sizeof(uint32_t)); serial = ntohl(serial); rr_data += sizeof(uint32_t);
  123. memcpy(&refresh, rr_data, sizeof(uint32_t)); refresh = ntohl(refresh); rr_data += sizeof(uint32_t);
  124. memcpy(&retry, rr_data, sizeof(uint32_t)); retry = ntohl(retry); rr_data += sizeof(uint32_t);
  125. memcpy(&expire, rr_data, sizeof(uint32_t)); expire = ntohl(expire); rr_data += sizeof(uint32_t);
  126. memcpy(&minimum, rr_data, sizeof(uint32_t)); minimum = ntohl(minimum);
  127. v8::Local<v8::Integer>
  128. v8_serial = v8::Integer:: New(serial),
  129. v8_refresh = v8::Integer:: New(refresh),
  130. v8_retry = v8::Integer:: New(retry),
  131. v8_expire = v8::Integer:: New(expire),
  132. v8_minimum = v8::Integer:: New(minimum);
  133. v8::Local<v8::String> text = v8::String::Concat(v8_mname, space_symbol);
  134. text = v8::String::Concat(text, v8_rname); text = v8::String::Concat(text, space_symbol);
  135. text = v8::String::Concat(text, v8_serial->ToString()); text = v8::String::Concat(text, space_symbol);
  136. text = v8::String::Concat(text, v8_refresh->ToString()); text = v8::String::Concat(text, space_symbol);
  137. text = v8::String::Concat(text, v8_retry->ToString()); text = v8::String::Concat(text, space_symbol);
  138. text = v8::String::Concat(text, v8_expire->ToString()); text = v8::String::Concat(text, space_symbol);
  139. text = v8::String::Concat(text, v8_minimum->ToString());
  140. r->Set(text_symbol, text);
  141. r->Set(mname_symbol, v8_mname);
  142. r->Set(rname_symbol, v8_rname);
  143. r->Set(serial_symbol, v8_serial);
  144. r->Set(refresh_symbol, v8_refresh);
  145. r->Set(retry_symbol, v8_retry);
  146. r->Set(expire_symbol, v8_expire);
  147. r->Set(minimum_symbol, v8_minimum);
  148. return ARES_SUCCESS;
  149. }
  150. static int ParseRRData_TXT(const unsigned char *, int , const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  151. int status, i;
  152. if (0 == rr_len) return ARES_EBADRESP;
  153. v8::Local<v8::Array> list = v8::Array::New();
  154. v8::Local<v8::String> s, text = v8::String::New(""), quote = v8::String::NewSymbol("\"");
  155. for (i = 0; 0 < rr_len; i++) {
  156. status = parse_char_string(rr_data, rr_len, s);
  157. if (ARES_SUCCESS != status) return status;
  158. list->Set(v8::Integer::New(i), s);
  159. if (i != 0) text = v8::String::Concat(text, space_symbol);
  160. text = v8::String::Concat(text, quote);
  161. /* TODO: escaping */
  162. text = v8::String::Concat(text, s);
  163. text = v8::String::Concat(text, quote);
  164. }
  165. r->Set(data_symbol, list);
  166. r->Set(text_symbol, text);
  167. return ARES_SUCCESS;
  168. }
  169. static int ParseRRData_SRV(const unsigned char *abuf, int alen, const unsigned char *rr_data, int rr_len, v8::Local<v8::Object> &r) {
  170. int status;
  171. if (rr_len < 6) return ARES_EBADRESP;
  172. uint16_t priority, weight, port;
  173. memcpy(&priority, rr_data, sizeof(uint16_t)); priority = ntohl(priority); rr_data += sizeof(uint16_t); rr_len -= sizeof(uint16_t);
  174. memcpy(&weight, rr_data, sizeof(uint16_t)); weight = ntohl(weight); rr_data += sizeof(uint16_t); rr_len -= sizeof(uint16_t);
  175. memcpy(&port, rr_data, sizeof(uint16_t)); port = ntohl(port); rr_data += sizeof(uint16_t); rr_len -= sizeof(uint16_t);
  176. char *target;
  177. long len;
  178. status = ares_expand_name(rr_data, abuf, alen, &target, &len);
  179. if (status != ARES_SUCCESS) return status;
  180. v8::Local<v8::String> v8_target = v8::String::New(target);
  181. free(target);
  182. if (len != rr_len) return ARES_EBADRESP;
  183. v8::Local<v8::Integer>
  184. v8_priority = v8::Integer:: New(priority),
  185. v8_weight = v8::Integer:: New(weight),
  186. v8_port = v8::Integer:: New(port);
  187. r->Set(priority_symbol, v8_priority);
  188. r->Set(weight_symbol, v8_weight);
  189. r->Set(port_symbol, v8_port);
  190. r->Set(target_symbol, v8_target);
  191. v8::Local<v8::String> text = v8::String::Concat(v8_priority->ToString(), space_symbol);
  192. text = v8::String::Concat(text, v8_weight->ToString()); text = v8::String::Concat(text, space_symbol);
  193. text = v8::String::Concat(text, v8_port->ToString()); text = v8::String::Concat(text, space_symbol);
  194. text = v8::String::Concat(text, v8_target);
  195. r->Set(text_symbol, text);
  196. return ARES_SUCCESS;
  197. }
  198. /* indented ones are deprecated/experimental */
  199. static RR_TYPE rr_types[] = {
  200. { "A", 1, ParseRRData_A, v8::Persistent<v8::String>() },
  201. { "NS", 2, ParseRRData_NS, v8::Persistent<v8::String>() },
  202. { "MD", 3, 0, v8::Persistent<v8::String>() },
  203. { "MF", 4, 0, v8::Persistent<v8::String>() },
  204. { "CNAME", 5, ParseRRData_NS, v8::Persistent<v8::String>() }, /* same RRDATA as NS */
  205. { "SOA", 6, ParseRRData_SOA, v8::Persistent<v8::String>() },
  206. { "MB", 7, 0, v8::Persistent<v8::String>() },
  207. { "MG", 8, 0, v8::Persistent<v8::String>() },
  208. { "MR", 9, 0, v8::Persistent<v8::String>() },
  209. { "NULL", 10, 0, v8::Persistent<v8::String>() },
  210. { "WKS", 11, 0, v8::Persistent<v8::String>() },
  211. { "PTR", 12, ParseRRData_NS, v8::Persistent<v8::String>() }, /* same RRDATA as NS */
  212. { "HINFO", 13, 0, v8::Persistent<v8::String>() },
  213. { "MINFO", 14, 0, v8::Persistent<v8::String>() },
  214. { "MX", 15, ParseRRData_MX, v8::Persistent<v8::String>() },
  215. { "TXT", 16, ParseRRData_TXT, v8::Persistent<v8::String>() },
  216. { "RP", 17, 0, v8::Persistent<v8::String>() },
  217. { "AFSDB", 18, 0, v8::Persistent<v8::String>() },
  218. { "SIG", 24, 0, v8::Persistent<v8::String>() },
  219. { "KEY", 25, 0, v8::Persistent<v8::String>() },
  220. { "AAAA", 28, ParseRRData_AAAA, v8::Persistent<v8::String>() },
  221. { "LOC", 29, 0, v8::Persistent<v8::String>() },
  222. { "SRV", 33, ParseRRData_SRV, v8::Persistent<v8::String>() },
  223. { "NAPTR", 35, 0, v8::Persistent<v8::String>() },
  224. { "KX", 36, 0, v8::Persistent<v8::String>() },
  225. { "CERT", 37, 0, v8::Persistent<v8::String>() },
  226. { "DNAME", 39, 0, v8::Persistent<v8::String>() },
  227. { "OPT", 41, 0, v8::Persistent<v8::String>() },
  228. { "APL", 42, 0, v8::Persistent<v8::String>() },
  229. { "DS", 43, 0, v8::Persistent<v8::String>() },
  230. { "SSHFP", 44, 0, v8::Persistent<v8::String>() },
  231. { "IPSECKEY", 45, 0, v8::Persistent<v8::String>() },
  232. { "RRSIG", 46, 0, v8::Persistent<v8::String>() },
  233. { "NSEC", 47, 0, v8::Persistent<v8::String>() },
  234. { "DNSKEY", 48, 0, v8::Persistent<v8::String>() },
  235. { "DHCID", 49, 0, v8::Persistent<v8::String>() },
  236. { "NSEC3", 50, 0, v8::Persistent<v8::String>() },
  237. { "NSEC3PARAM", 51, 0, v8::Persistent<v8::String>() },
  238. { "HIP", 55, 0, v8::Persistent<v8::String>() },
  239. { "SPF", 99, 0, v8::Persistent<v8::String>() },
  240. { "TKEY", 249, 0, v8::Persistent<v8::String>() },
  241. { "TSIG", 250, 0, v8::Persistent<v8::String>() },
  242. { "IXFR", 251, 0, v8::Persistent<v8::String>() },
  243. { "AXFR", 252, 0, v8::Persistent<v8::String>() },
  244. { "MAILB", 253, 0, v8::Persistent<v8::String>() },
  245. { "MAILA", 254, 0, v8::Persistent<v8::String>() },
  246. { "ANY", 255, 0, v8::Persistent<v8::String>() }, /* aka "*" */
  247. { "TA", 32768, 0, v8::Persistent<v8::String>() },
  248. { "DLV", 32769, 0, v8::Persistent<v8::String>() }
  249. };
  250. static RR_CLASS rr_classes[] = {
  251. { "IN", 1, v8::Persistent<v8::String>() }, /* the Internet */
  252. { "CS", 2, v8::Persistent<v8::String>() }, /* the CSNET class (Obsolete - used only for examples in some obsolete RFCs) */
  253. { "CH", 3, v8::Persistent<v8::String>() }, /* the CHAOS class */
  254. { "HS", 4, v8::Persistent<v8::String>() }, /* Hesiod [Dyer 87] */
  255. { "ANY", 255, v8::Persistent<v8::String>() } /* same value as in rr_type, so no name conflict */
  256. };
  257. void Initialize(v8::Handle<v8::Object> target) {
  258. v8::HandleScope scope;
  259. using namespace v8;
  260. int r = ares_library_init(ARES_LIB_INIT_ALL);
  261. if (0 != r) {
  262. // TODO
  263. // ThrowException(Exception::Error(String::New(ares_strerror(r))));
  264. assert(r == 0);
  265. }
  266. question_symbol = NODE_PSYMBOL("question");
  267. answer_symbol = NODE_PSYMBOL("answer");
  268. authority_symbol = NODE_PSYMBOL("authority");
  269. additional_symbol = NODE_PSYMBOL("additional");
  270. type_symbol = NODE_PSYMBOL("type");
  271. ntype_symbol = NODE_PSYMBOL("ntype");
  272. class_symbol = NODE_PSYMBOL("class");
  273. nclass_symbol = NODE_PSYMBOL("nclass");
  274. ttl_symbol = NODE_PSYMBOL("ttl");
  275. rdata_symbol = NODE_PSYMBOL("rdata");
  276. text_symbol = NODE_PSYMBOL("text");
  277. data_symbol = NODE_PSYMBOL("data");
  278. priority_symbol = NODE_PSYMBOL("priority");
  279. weight_symbol = NODE_PSYMBOL("weight");
  280. port_symbol = NODE_PSYMBOL("port");
  281. name_symbol = NODE_PSYMBOL("name");
  282. exchange_symbol = NODE_PSYMBOL("exchange");
  283. target_symbol = NODE_PSYMBOL("target");
  284. mname_symbol = NODE_PSYMBOL("mname");
  285. rname_symbol = NODE_PSYMBOL("rname");
  286. serial_symbol = NODE_PSYMBOL("serial");
  287. refresh_symbol = NODE_PSYMBOL("refresh");
  288. retry_symbol = NODE_PSYMBOL("retry");
  289. expire_symbol = NODE_PSYMBOL("expire");
  290. minimum_symbol = NODE_PSYMBOL("minimum");
  291. space_symbol = NODE_PSYMBOL(" ");;
  292. v8::Local<v8::Object> types = v8::Object::New();
  293. for (unsigned int i = 0; i < sizeof(rr_types)/sizeof(rr_types[0]); i++) {
  294. rr_types[i].symbol = NODE_PSYMBOL(rr_types[i].s);
  295. target->Set(rr_types[i].symbol, v8::Integer::New(rr_types[i].n));
  296. }
  297. for (unsigned int i = 0; i < sizeof(rr_classes)/sizeof(rr_classes[0]); i++) {
  298. rr_classes[i].symbol = NODE_PSYMBOL(rr_classes[i].s);
  299. target->Set(rr_classes[i].symbol, v8::Integer::New(rr_classes[i].n));
  300. }
  301. }
  302. static inline const char *ares_errno_string(int errorno) {
  303. #define ERRNO_CASE(e) case ARES_##e: return #e;
  304. switch (errorno) {
  305. ERRNO_CASE(SUCCESS)
  306. ERRNO_CASE(ENODATA)
  307. ERRNO_CASE(EFORMERR)
  308. ERRNO_CASE(ESERVFAIL)
  309. ERRNO_CASE(ENOTFOUND)
  310. ERRNO_CASE(ENOTIMP)
  311. ERRNO_CASE(EREFUSED)
  312. ERRNO_CASE(EBADQUERY)
  313. ERRNO_CASE(EBADNAME)
  314. ERRNO_CASE(EBADFAMILY)
  315. ERRNO_CASE(EBADRESP)
  316. ERRNO_CASE(ECONNREFUSED)
  317. ERRNO_CASE(ETIMEOUT)
  318. ERRNO_CASE(EOF)
  319. ERRNO_CASE(EFILE)
  320. ERRNO_CASE(ENOMEM)
  321. ERRNO_CASE(EDESTRUCTION)
  322. ERRNO_CASE(EBADSTR)
  323. ERRNO_CASE(EBADFLAGS)
  324. ERRNO_CASE(ENONAME)
  325. ERRNO_CASE(EBADHINTS)
  326. ERRNO_CASE(ENOTINITIALIZED)
  327. ERRNO_CASE(ELOADIPHLPAPI)
  328. ERRNO_CASE(EADDRGETNETWORKPARAMS)
  329. ERRNO_CASE(ECANCELLED)
  330. default:
  331. assert(0 && "Unhandled c-ares errno");
  332. return "(UNKNOWN)";
  333. }
  334. }
  335. v8::Local<v8::Value> AresException(int status) {
  336. v8::Local<v8::String> code = v8::String::NewSymbol(ares_errno_string(status));
  337. v8::Local<v8::String> message = v8::String::NewSymbol(ares_strerror(status));
  338. v8::Local<v8::String> cons1 = v8::String::Concat(code, v8::String::NewSymbol(", "));
  339. v8::Local<v8::String> cons2 = v8::String::Concat(cons1, message);
  340. v8::Local<v8::Value> e = v8::Exception::Error(cons2);
  341. v8::Local<v8::Object> obj = e->ToObject();
  342. obj->Set(v8::String::NewSymbol("errno"), v8::Integer::New(status));
  343. return e;
  344. }
  345. static void set_type(v8::Local<v8::Object> &r, int rr_type) {
  346. r->Set(ntype_symbol, v8::Integer::New(rr_type));
  347. for (unsigned int i = 0; i < sizeof(rr_types)/sizeof(rr_types[0]); i++) {
  348. if (rr_type == rr_types[i].n) {
  349. r->Set(type_symbol, rr_types[i].symbol);
  350. break;
  351. }
  352. }
  353. }
  354. static void set_class(v8::Local<v8::Object> &r, int rr_class) {
  355. r->Set(nclass_symbol, v8::Integer::New(rr_class));
  356. for (unsigned int i = 0; i < sizeof(rr_classes)/sizeof(rr_classes[0]); i++) {
  357. if (rr_class == rr_classes[i].n) {
  358. r->Set(class_symbol, rr_classes[i].symbol);
  359. break;
  360. }
  361. }
  362. }
  363. static int parse_read_questions(const unsigned char *abuf, int alen, const unsigned char * &aptr, int count, v8::Local<v8::Array> list) {
  364. int status;
  365. long len;
  366. /* skip each question */
  367. for (int i = 0; i < count; i++) {
  368. int rr_type, rr_class;
  369. char *rr_name;
  370. v8::Local<v8::Object> r = v8::Object::New();
  371. /* Decode the RR up to the data field. */
  372. status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
  373. if (status != ARES_SUCCESS) return status;
  374. aptr += len;
  375. if (aptr + QFIXEDSZ > abuf + alen) {
  376. free(rr_name);
  377. return ARES_EBADRESP;
  378. }
  379. rr_type = DNS_RR_TYPE(aptr);
  380. rr_class = DNS_RR_CLASS(aptr);
  381. aptr += QFIXEDSZ;
  382. if (aptr > abuf + alen) {
  383. free(rr_name);
  384. return ARES_EBADRESP;
  385. }
  386. r->Set(name_symbol, v8::String::New(rr_name));
  387. set_type(r, rr_type);
  388. set_class(r, rr_class);
  389. free(rr_name);
  390. list->Set(v8::Integer::New(i), r);
  391. }
  392. return ARES_SUCCESS;
  393. }
  394. static int parse_read_answers(const unsigned char *abuf, int alen, const unsigned char * &aptr, int count, v8::Local<v8::Array> list) {
  395. int status;
  396. long len;
  397. /* Examine each resource record (RR) in turn. */
  398. for (int i = 0; i < count; i++) {
  399. int rr_type, rr_class, rr_len, rr_ttl;
  400. char *rr_name;
  401. const unsigned char *rr_data;
  402. v8::Local<v8::Object> r = v8::Object::New();
  403. /* Decode the RR up to the data field. */
  404. status = ares_expand_name(aptr, abuf, alen, &rr_name, &len);
  405. if (status != ARES_SUCCESS) break;
  406. aptr += len;
  407. if (aptr + RRFIXEDSZ > abuf + alen) {
  408. free(rr_name);
  409. return ARES_EBADRESP;
  410. }
  411. rr_type = DNS_RR_TYPE(aptr);
  412. rr_class = DNS_RR_CLASS(aptr);
  413. rr_ttl = DNS_RR_TTL(aptr);
  414. rr_len = DNS_RR_LEN(aptr);
  415. aptr += RRFIXEDSZ;
  416. rr_data = aptr;
  417. aptr += rr_len;
  418. if (aptr > abuf + alen) {
  419. free(rr_name);
  420. return ARES_EBADRESP;
  421. }
  422. r->Set(name_symbol, v8::String::New(rr_name));
  423. set_class(r, rr_class);
  424. r->Set(ttl_symbol, v8::Integer::New(rr_ttl));
  425. free(rr_name);
  426. r->Set(ntype_symbol, v8::Integer::New(rr_type));
  427. for (unsigned int t = 0; t < sizeof(rr_types)/sizeof(rr_types[0]); t++) {
  428. if (rr_type == rr_types[t].n) {
  429. r->Set(type_symbol, rr_types[t].symbol);
  430. if (C_IN == rr_class && rr_types[t].parse_in) {
  431. status = rr_types[t].parse_in(abuf, alen, rr_data, rr_len, r);
  432. if (status != ARES_SUCCESS) return status;
  433. }
  434. break;
  435. }
  436. }
  437. r->Set(rdata_symbol, v8::String::New((const char*) rr_data, rr_len));
  438. list->Set(v8::Integer::New(i), r);
  439. }
  440. return ARES_SUCCESS;
  441. }
  442. v8::Local<v8::Value> parse_dns_response(const unsigned char *abuf, int alen, int *pstatus) {
  443. unsigned int qdcount, ancount, nscount, arcount;
  444. int status;
  445. const unsigned char *aptr;
  446. if (pstatus) *pstatus = ARES_SUCCESS;
  447. v8::Local<v8::Array> qd = v8::Array::New(), an = v8::Array::New(), ns = v8::Array::New(), ar = v8::Array::New();
  448. v8::Local<v8::Object> msg = v8::Object::New();
  449. /* Give up if abuf doesn't have room for a header. */
  450. if (alen < HFIXEDSZ) {
  451. status = ARES_EBADRESP;
  452. goto error;
  453. }
  454. /* Fetch the question and answer count from the header. */
  455. qdcount = DNS_HEADER_QDCOUNT(abuf);
  456. ancount = DNS_HEADER_ANCOUNT(abuf);
  457. nscount = DNS_HEADER_NSCOUNT(abuf);
  458. arcount = DNS_HEADER_ARCOUNT(abuf);
  459. if (qdcount != 1) {
  460. status = ARES_EBADRESP;
  461. goto error;
  462. }
  463. aptr = abuf + HFIXEDSZ;
  464. status = parse_read_questions(abuf, alen, aptr, qdcount, qd);
  465. if (status != ARES_SUCCESS) goto error;
  466. status = parse_read_answers(abuf, alen, aptr, ancount, an);
  467. if (status != ARES_SUCCESS) goto error;
  468. status = parse_read_answers(abuf, alen, aptr, nscount, ns);
  469. if (status != ARES_SUCCESS) goto error;
  470. status = parse_read_answers(abuf, alen, aptr, arcount, ar);
  471. if (status != ARES_SUCCESS) goto error;
  472. msg->Set(question_symbol, qd);
  473. msg->Set(answer_symbol, an);
  474. msg->Set(authority_symbol, ns);
  475. msg->Set(additional_symbol, ar);
  476. return msg;
  477. error:
  478. if (pstatus) *pstatus = status;
  479. return AresException(status);
  480. }
  481. }