1
0

dns.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. #include "dns.h"
  2. #include "hsocket.h"
  3. void dns_free(dns_t* dns) {
  4. SAFE_FREE(dns->questions);
  5. SAFE_FREE(dns->answers);
  6. SAFE_FREE(dns->authorities);
  7. SAFE_FREE(dns->addtionals);
  8. }
  9. // www.example.com => 3www7example3com
  10. int dns_name_encode(const char* domain, char* buf) {
  11. const char* p = domain;
  12. char* plen = buf++;
  13. int buflen = 1;
  14. int len = 0;
  15. while (*p != '\0') {
  16. if (*p != '.') {
  17. ++len;
  18. *buf = *p;
  19. }
  20. else {
  21. *plen = len;
  22. //printf("len=%d\n", len);
  23. plen = buf;
  24. len = 0;
  25. }
  26. ++p;
  27. ++buf;
  28. ++buflen;
  29. }
  30. *plen = len;
  31. //printf("len=%d\n", len);
  32. *buf = '\0';
  33. if (len != 0) {
  34. ++buflen; // include last '\0'
  35. }
  36. return buflen;
  37. }
  38. // 3www7example3com => www.example.com
  39. int dns_name_decode(const char* buf, char* domain) {
  40. const char* p = buf;
  41. int len = *p++;
  42. //printf("len=%d\n", len);
  43. int buflen = 1;
  44. while (*p != '\0') {
  45. if (len-- == 0) {
  46. len = *p;
  47. //printf("len=%d\n", len);
  48. *domain = '.';
  49. }
  50. else {
  51. *domain = *p;
  52. }
  53. ++p;
  54. ++domain;
  55. ++buflen;
  56. }
  57. *domain = '\0';
  58. ++buflen; // include last '\0'
  59. return buflen;
  60. }
  61. int dns_rr_pack(dns_rr_t* rr, char* buf, int len) {
  62. char* p = buf;
  63. char encoded_name[256];
  64. int encoded_namelen = dns_name_encode(rr->name, encoded_name);
  65. int packetlen = encoded_namelen + 2 + 2 + (rr->data ? (4+2+rr->datalen) : 0);
  66. if (len < packetlen) {
  67. return -1;
  68. }
  69. memcpy(p, encoded_name, encoded_namelen);
  70. p += encoded_namelen;
  71. uint16_t* pushort = (uint16_t*)p;
  72. *pushort = htons(rr->rtype);
  73. p += 2;
  74. pushort = (uint16_t*)p;
  75. *pushort = htons(rr->rclass);
  76. p += 2;
  77. // ...
  78. if (rr->datalen && rr->data) {
  79. uint32_t* puint = (uint32_t*)p;
  80. *puint = htonl(rr->ttl);
  81. p += 4;
  82. pushort = (uint16_t*)p;
  83. *pushort = htons(rr->datalen);
  84. p += 2;
  85. memcpy(p, rr->data, rr->datalen);
  86. p += rr->datalen;
  87. }
  88. return packetlen;
  89. }
  90. int dns_rr_unpack(char* buf, int len, dns_rr_t* rr, int is_question) {
  91. char* p = buf;
  92. int off = 0;
  93. int namelen = 0;
  94. if (*(uint8_t*)p >= 192) {
  95. // name off, we ignore
  96. namelen = 2;
  97. //uint16_t nameoff = (*(uint8_t*)p - 192) * 256 + *(uint8_t*)(p+1);
  98. }
  99. else {
  100. namelen = dns_name_decode(buf, rr->name);
  101. }
  102. if (namelen < 0) return -1;
  103. p += namelen;
  104. off += namelen;
  105. if (len < off + 4) return -1;
  106. uint16_t* pushort = (uint16_t*)p;
  107. rr->rtype = ntohs(*pushort);
  108. p += 2;
  109. pushort = (uint16_t*)p;
  110. rr->rclass = ntohs(*pushort);
  111. p += 2;
  112. off += 4;
  113. if (!is_question) {
  114. if (len < off + 6) return -1;
  115. uint32_t* puint = (uint32_t*)p;
  116. rr->ttl = ntohl(*puint);
  117. p += 4;
  118. pushort = (uint16_t*)p;
  119. rr->datalen = ntohs(*pushort);
  120. p += 2;
  121. off += 6;
  122. if (len < off + rr->datalen) return -1;
  123. rr->data = p;
  124. p += rr->datalen;
  125. off += rr->datalen;
  126. }
  127. return off;
  128. }
  129. int dns_pack(dns_t* dns, char* buf, int len) {
  130. if (len < sizeof(dnshdr_t)) return -1;
  131. int off = 0;
  132. dnshdr_t* hdr = &dns->hdr;
  133. dnshdr_t htonhdr = dns->hdr;
  134. htonhdr.transaction_id = htons(hdr->transaction_id);
  135. htonhdr.nquestion = htons(hdr->nquestion);
  136. htonhdr.nanswer = htons(hdr->nanswer);
  137. htonhdr.nauthority = htons(hdr->nauthority);
  138. htonhdr.naddtional = htons(hdr->naddtional);
  139. memcpy(buf, &htonhdr, sizeof(dnshdr_t));
  140. off += sizeof(dnshdr_t);
  141. int i;
  142. for (i = 0; i < hdr->nquestion; ++i) {
  143. int packetlen = dns_rr_pack(dns->questions+i, buf+off, len-off);
  144. if (packetlen < 0) return -1;
  145. off += packetlen;
  146. }
  147. for (i = 0; i < hdr->nanswer; ++i) {
  148. int packetlen = dns_rr_pack(dns->answers+i, buf+off, len-off);
  149. if (packetlen < 0) return -1;
  150. off += packetlen;
  151. }
  152. for (i = 0; i < hdr->nauthority; ++i) {
  153. int packetlen = dns_rr_pack(dns->authorities+i, buf+off, len-off);
  154. if (packetlen < 0) return -1;
  155. off += packetlen;
  156. }
  157. for (i = 0; i < hdr->naddtional; ++i) {
  158. int packetlen = dns_rr_pack(dns->addtionals+i, buf+off, len-off);
  159. if (packetlen < 0) return -1;
  160. off += packetlen;
  161. }
  162. return off;
  163. }
  164. int dns_unpack(char* buf, int len, dns_t* dns) {
  165. memset(dns, 0, sizeof(dns_t));
  166. if (len < sizeof(dnshdr_t)) return -1;
  167. int off = 0;
  168. dnshdr_t* hdr = &dns->hdr;
  169. memcpy(hdr, buf, sizeof(dnshdr_t));
  170. off += sizeof(dnshdr_t);
  171. hdr->transaction_id = ntohs(hdr->transaction_id);
  172. hdr->nquestion = ntohs(hdr->nquestion);
  173. hdr->nanswer = ntohs(hdr->nanswer);
  174. hdr->nauthority = ntohs(hdr->nauthority);
  175. hdr->naddtional = ntohs(hdr->naddtional);
  176. int i;
  177. if (hdr->nquestion) {
  178. int bytes = hdr->nquestion * sizeof(dns_rr_t);
  179. dns->questions = (dns_rr_t*)malloc(bytes);
  180. memset(dns->questions, 0, bytes);
  181. for (i = 0; i < hdr->nquestion; ++i) {
  182. int packetlen = dns_rr_unpack(buf+off, len-off, dns->questions+i, 1);
  183. if (packetlen < 0) return -1;
  184. off += packetlen;
  185. }
  186. }
  187. if (hdr->nanswer) {
  188. int bytes = hdr->nanswer * sizeof(dns_rr_t);
  189. dns->answers = (dns_rr_t*)malloc(bytes);
  190. memset(dns->answers, 0, bytes);
  191. for (i = 0; i < hdr->nanswer; ++i) {
  192. int packetlen = dns_rr_unpack(buf+off, len-off, dns->answers+i, 0);
  193. if (packetlen < 0) return -1;
  194. off += packetlen;
  195. }
  196. }
  197. if (hdr->nauthority) {
  198. int bytes = hdr->nauthority * sizeof(dns_rr_t);
  199. dns->authorities = (dns_rr_t*)malloc(bytes);
  200. memset(dns->authorities, 0, bytes);
  201. for (i = 0; i < hdr->nauthority; ++i) {
  202. int packetlen = dns_rr_unpack(buf+off, len-off, dns->authorities+i, 0);
  203. if (packetlen < 0) return -1;
  204. off += packetlen;
  205. }
  206. }
  207. if (hdr->naddtional) {
  208. int bytes = hdr->naddtional * sizeof(dns_rr_t);
  209. dns->addtionals = (dns_rr_t*)malloc(bytes);
  210. memset(dns->addtionals, 0, bytes);
  211. for (i = 0; i < hdr->naddtional; ++i) {
  212. int packetlen = dns_rr_unpack(buf+off, len-off, dns->addtionals+i, 0);
  213. if (packetlen < 0) return -1;
  214. off += packetlen;
  215. }
  216. }
  217. return off;
  218. }
  219. // dns_pack -> sendto -> recvfrom -> dns_unpack
  220. int dns_query(dns_t* query, dns_t* response, const char* nameserver) {
  221. char buf[1024];
  222. int buflen = sizeof(buf);
  223. buflen = dns_pack(query, buf, buflen);
  224. if (buflen < 0) {
  225. return buflen;
  226. }
  227. int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
  228. if (sockfd < 0) {
  229. perror("socket");
  230. return -10;
  231. }
  232. so_sndtimeo(sockfd, 5000);
  233. so_rcvtimeo(sockfd, 5000);
  234. int ret = 0;
  235. int nsend, nrecv;
  236. int nparse;
  237. struct sockaddr_in addr;
  238. socklen_t addrlen = sizeof(addr);
  239. memset(&addr, 0, addrlen);
  240. addr.sin_family = AF_INET;
  241. addr.sin_addr.s_addr = inet_addr(nameserver);
  242. addr.sin_port = htons(DNS_PORT);
  243. nsend = sendto(sockfd, buf, buflen, 0, (struct sockaddr*)&addr, addrlen);
  244. if (nsend != buflen) {
  245. ret = -20;
  246. goto error;
  247. }
  248. nrecv = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr*)&addr, &addrlen);
  249. if (nrecv <= 0) {
  250. ret = -30;
  251. goto error;
  252. }
  253. nparse = dns_unpack(buf, nrecv, response);
  254. if (nparse != nrecv) {
  255. ret = -40;
  256. goto error;
  257. }
  258. error:
  259. if (sockfd != INVALID_SOCKET) {
  260. closesocket(sockfd);
  261. }
  262. return ret;
  263. }
  264. int nslookup(const char* domain, uint32_t* addrs, int naddr, const char* nameserver) {
  265. dns_t query;
  266. memset(&query, 0, sizeof(query));
  267. query.hdr.transaction_id = getpid();
  268. query.hdr.qr = DNS_QUERY;
  269. query.hdr.rd = 1;
  270. query.hdr.nquestion = 1;
  271. dns_rr_t question;
  272. memset(&question, 0, sizeof(question));
  273. strncpy(question.name, domain, sizeof(question.name));
  274. question.rtype = DNS_TYPE_A;
  275. question.rclass = DNS_CLASS_IN;
  276. query.questions = &question;
  277. dns_t resp;
  278. memset(&resp, 0, sizeof(resp));
  279. int ret = dns_query(&query, &resp, nameserver);
  280. if (ret != 0) {
  281. return ret;
  282. }
  283. dns_rr_t* rr = resp.answers;
  284. int addr_cnt = 0;
  285. if (resp.hdr.transaction_id != query.hdr.transaction_id ||
  286. resp.hdr.qr != DNS_RESPONSE ||
  287. resp.hdr.rcode != 0) {
  288. ret = -1;
  289. goto end;
  290. }
  291. if (resp.hdr.nanswer == 0) {
  292. ret = 0;
  293. goto end;
  294. }
  295. for (int i = 0; i < resp.hdr.nanswer; ++i, ++rr) {
  296. if (rr->rtype == DNS_TYPE_A) {
  297. if (addr_cnt < naddr && rr->datalen == 4) {
  298. memcpy(addrs+addr_cnt, rr->data, 4);
  299. }
  300. ++addr_cnt;
  301. }
  302. /*
  303. else if (rr->rtype == DNS_TYPE_CNAME) {
  304. char name[256];
  305. dns_name_decode(rr->data, name);
  306. }
  307. */
  308. }
  309. ret = addr_cnt;
  310. end:
  311. dns_free(&resp);
  312. return ret;
  313. }