dns.c 9.1 KB

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