2
0

dns.c 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. /*
  2. * Copyright (C) 2014 John Crispin <blogic@openwrt.org>
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU Lesser General Public License version 2.1
  6. * as published by the Free Software Foundation
  7. *
  8. * This program is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * GNU General Public License for more details.
  12. */
  13. #include <sys/types.h>
  14. #include <sys/stat.h>
  15. #include <fcntl.h>
  16. #include <time.h>
  17. #include <stdio.h>
  18. #include <unistd.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <netinet/in.h>
  22. #include <arpa/inet.h>
  23. #include <asm/byteorder.h>
  24. #include <arpa/nameser.h>
  25. #include <resolv.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <libubox/uloop.h>
  29. #include <libubox/usock.h>
  30. #include <libubox/utils.h>
  31. #include "announce.h"
  32. #include "util.h"
  33. #include "dns.h"
  34. #include "interface.h"
  35. char rdata_buffer[MAX_DATA_LEN + 1];
  36. static char name_buffer[MAX_NAME_LEN + 1];
  37. const char*
  38. dns_type_string(uint16_t type)
  39. {
  40. switch (type) {
  41. case TYPE_A:
  42. return "A";
  43. case TYPE_AAAA:
  44. return "AAAA";
  45. case TYPE_PTR:
  46. return "PTR";
  47. case TYPE_TXT:
  48. return "TXT";
  49. case TYPE_SRV:
  50. return "SRV";
  51. case TYPE_ANY:
  52. return "ANY";
  53. }
  54. return "N/A";
  55. }
  56. void
  57. dns_send_question(struct interface *iface, const char *question, int type)
  58. {
  59. static struct dns_header h = {
  60. .questions = cpu_to_be16(1),
  61. };
  62. static struct dns_question q = {
  63. .class = cpu_to_be16(1),
  64. };
  65. static struct iovec iov[] = {
  66. {
  67. .iov_base = &h,
  68. .iov_len = sizeof(h),
  69. },
  70. {
  71. .iov_base = name_buffer,
  72. },
  73. {
  74. .iov_base = &q,
  75. .iov_len = sizeof(q),
  76. }
  77. };
  78. int len;
  79. q.type = __cpu_to_be16(type);
  80. len = dn_comp(question, (void *) name_buffer, sizeof(name_buffer), NULL, NULL);
  81. if (len < 1)
  82. return;
  83. iov[1].iov_len = len;
  84. if (interface_send_packet(iface, iov, ARRAY_SIZE(iov)) < 0)
  85. fprintf(stderr, "failed to send question\n");
  86. else
  87. DBG(1, "Q <- %s %s\n", dns_type_string(type), question);
  88. }
  89. struct dns_reply {
  90. int type;
  91. struct dns_answer a;
  92. uint16_t rdlength;
  93. uint8_t *rdata;
  94. char *buffer;
  95. };
  96. #define MAX_ANSWER 8
  97. static struct dns_reply dns_reply[1 + (MAX_ANSWER * 3)];
  98. static int dns_answer_cnt;
  99. void
  100. dns_init_answer(void)
  101. {
  102. dns_answer_cnt = 0;
  103. }
  104. void
  105. dns_add_answer(int type, const uint8_t *rdata, uint16_t rdlength)
  106. {
  107. struct dns_reply *a = &dns_reply[dns_answer_cnt];
  108. if (dns_answer_cnt == MAX_ANSWER)
  109. return;
  110. a->rdata = memdup(rdata, rdlength);
  111. a->type = type;
  112. a->rdlength = rdlength;
  113. dns_answer_cnt++;
  114. }
  115. void
  116. dns_send_answer(struct interface *iface, const char *answer)
  117. {
  118. uint8_t buffer[256];
  119. struct dns_header h = { 0 };
  120. struct iovec *iov;
  121. int len, i;
  122. if (!dns_answer_cnt)
  123. return;
  124. h.answers = __cpu_to_be16(dns_answer_cnt);
  125. h.flags = __cpu_to_be16(0x8400);
  126. iov = alloca(sizeof(struct iovec) * ((dns_answer_cnt * 3) + 1));
  127. iov[0].iov_base = &h;
  128. iov[0].iov_len = sizeof(struct dns_header);
  129. for (i = 0; i < dns_answer_cnt; i++) {
  130. struct dns_answer *a = &dns_reply[i].a;
  131. int id = (i * 3) + 1;
  132. memset(a, 0, sizeof(*a));
  133. a->type = __cpu_to_be16(dns_reply[i].type);
  134. a->class = __cpu_to_be16(1);
  135. a->ttl = __cpu_to_be32(announce_ttl);
  136. a->rdlength = __cpu_to_be16(dns_reply[i].rdlength);
  137. len = dn_comp(answer, buffer, sizeof(buffer), NULL, NULL);
  138. if (len < 1)
  139. return;
  140. dns_reply[i].buffer = iov[id].iov_base = memdup(buffer, len);
  141. iov[id].iov_len = len;
  142. iov[id + 1].iov_base = a;
  143. iov[id + 1].iov_len = sizeof(struct dns_answer);
  144. iov[id + 2].iov_base = dns_reply[i].rdata;
  145. iov[id + 2].iov_len = dns_reply[i].rdlength;
  146. DBG(1, "A <- %s %s\n", dns_type_string(dns_reply[i].type), answer);
  147. }
  148. if (interface_send_packet(iface, iov, (dns_answer_cnt * 3) + 1) < 0)
  149. fprintf(stderr, "failed to send question\n");
  150. for (i = 0; i < dns_answer_cnt; i++) {
  151. free(dns_reply[i].buffer);
  152. free(dns_reply[i].rdata);
  153. }
  154. dns_answer_cnt = 0;
  155. }
  156. static int
  157. scan_name(const uint8_t *buffer, int len)
  158. {
  159. int offset = 0;
  160. while (len && (*buffer != '\0')) {
  161. int l = *buffer;
  162. if (IS_COMPRESSED(l))
  163. return offset + 2;
  164. len -= l + 1;
  165. offset += l + 1;
  166. buffer += l + 1;
  167. }
  168. if (!len || !offset || (*buffer != '\0'))
  169. return -1;
  170. return offset + 1;
  171. }
  172. struct dns_header*
  173. dns_consume_header(uint8_t **data, int *len)
  174. {
  175. struct dns_header *h = (struct dns_header *) *data;
  176. uint16_t *swap = (uint16_t *) h;
  177. int endianess = 6;
  178. if (*len < sizeof(struct dns_header))
  179. return NULL;
  180. while (endianess--) {
  181. *swap = __be16_to_cpu(*swap);
  182. swap++;
  183. }
  184. *len -= sizeof(struct dns_header);
  185. *data += sizeof(struct dns_header);
  186. return h;
  187. }
  188. struct dns_question*
  189. dns_consume_question(uint8_t **data, int *len)
  190. {
  191. struct dns_question *q = (struct dns_question *) *data;
  192. uint16_t *swap = (uint16_t *) q;
  193. int endianess = 2;
  194. if (*len < sizeof(struct dns_question))
  195. return NULL;
  196. while (endianess--) {
  197. *swap = __be16_to_cpu(*swap);
  198. swap++;
  199. }
  200. *len -= sizeof(struct dns_question);
  201. *data += sizeof(struct dns_question);
  202. return q;
  203. }
  204. struct dns_answer*
  205. dns_consume_answer(uint8_t **data, int *len)
  206. {
  207. struct dns_answer *a = (struct dns_answer *) *data;
  208. if (*len < sizeof(struct dns_answer))
  209. return NULL;
  210. a->type = __be16_to_cpu(a->type);
  211. a->class = __be16_to_cpu(a->class);
  212. a->ttl = __be32_to_cpu(a->ttl);
  213. a->rdlength = __be16_to_cpu(a->rdlength);
  214. *len -= sizeof(struct dns_answer);
  215. *data += sizeof(struct dns_answer);
  216. return a;
  217. }
  218. char*
  219. dns_consume_name(const uint8_t *base, int blen, uint8_t **data, int *len)
  220. {
  221. int nlen = scan_name(*data, *len);
  222. if (nlen < 1)
  223. return NULL;
  224. if (dn_expand(base, base + blen, *data, name_buffer, MAX_NAME_LEN) < 0) {
  225. perror("dns_consume_name/dn_expand");
  226. return NULL;
  227. }
  228. *len -= nlen;
  229. *data += nlen;
  230. return name_buffer;
  231. }