test-dns.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <arpa/inet.h>
  4. #include <sys/socket.h>
  5. #include <netdb.h>
  6. #include <ifaddrs.h>
  7. #include <string.h>
  8. #include <malloc.h>
  9. #include <errno.h>
  10. #include <string.h>
  11. #include <stdint.h>
  12. #define BUF_SIZE 1500
  13. /*
  14. * This software is licensed under the CC0.
  15. *
  16. * This is a _basic_ DNS Server for educational use.
  17. * It does not prevent invalid packets from crashing
  18. * the server.
  19. *
  20. * To test start the program and issue a DNS request:
  21. * dig @127.0.0.1 -p 9000 foo.bar.com
  22. */
  23. /*
  24. * Masks and constants.
  25. */
  26. static const uint32_t QR_MASK = 0x8000;
  27. static const uint32_t OPCODE_MASK = 0x7800;
  28. static const uint32_t AA_MASK = 0x0400;
  29. static const uint32_t TC_MASK = 0x0200;
  30. static const uint32_t RD_MASK = 0x0100;
  31. static const uint32_t RA_MASK = 0x8000;
  32. static const uint32_t RCODE_MASK = 0x000F;
  33. /* Response Type */
  34. enum {
  35. Ok_ResponseType = 0,
  36. FormatError_ResponseType = 1,
  37. ServerFailure_ResponseType = 2,
  38. NameError_ResponseType = 3,
  39. NotImplemented_ResponseType = 4,
  40. Refused_ResponseType = 5
  41. };
  42. /* Resource Record Types */
  43. enum {
  44. A_Resource_RecordType = 1,
  45. NS_Resource_RecordType = 2,
  46. CNAME_Resource_RecordType = 5,
  47. SOA_Resource_RecordType = 6,
  48. PTR_Resource_RecordType = 12,
  49. MX_Resource_RecordType = 15,
  50. TXT_Resource_RecordType = 16,
  51. AAAA_Resource_RecordType = 28,
  52. SRV_Resource_RecordType = 33
  53. };
  54. /* Operation Code */
  55. enum {
  56. QUERY_OperationCode = 0, /* standard query */
  57. IQUERY_OperationCode = 1, /* inverse query */
  58. STATUS_OperationCode = 2, /* server status request */
  59. NOTIFY_OperationCode = 4, /* request zone transfer */
  60. UPDATE_OperationCode = 5 /* change resource records */
  61. };
  62. /* Response Code */
  63. enum {
  64. NoError_ResponseCode = 0,
  65. FormatError_ResponseCode = 1,
  66. ServerFailure_ResponseCode = 2,
  67. NameError_ResponseCode = 3
  68. };
  69. /* Query Type */
  70. enum {
  71. IXFR_QueryType = 251,
  72. AXFR_QueryType = 252,
  73. MAILB_QueryType = 253,
  74. MAILA_QueryType = 254,
  75. STAR_QueryType = 255
  76. };
  77. /*
  78. * Types.
  79. */
  80. /* Question Section */
  81. struct Question {
  82. char *qName;
  83. uint16_t qType;
  84. uint16_t qClass;
  85. struct Question* next; // for linked list
  86. };
  87. /* Data part of a Resource Record */
  88. union ResourceData {
  89. struct {
  90. char *txt_data;
  91. } txt_record;
  92. struct {
  93. uint8_t addr[4];
  94. } a_record;
  95. struct {
  96. char* MName;
  97. char* RName;
  98. uint32_t serial;
  99. uint32_t refresh;
  100. uint32_t retry;
  101. uint32_t expire;
  102. uint32_t minimum;
  103. } soa_record;
  104. struct {
  105. char *name;
  106. } name_server_record;
  107. struct {
  108. char name;
  109. } cname_record;
  110. struct {
  111. char *name;
  112. } ptr_record;
  113. struct {
  114. uint16_t preference;
  115. char *exchange;
  116. } mx_record;
  117. struct {
  118. uint8_t addr[16];
  119. } aaaa_record;
  120. struct {
  121. uint16_t priority;
  122. uint16_t weight;
  123. uint16_t port;
  124. char *target;
  125. } srv_record;
  126. };
  127. /* Resource Record Section */
  128. struct ResourceRecord {
  129. char *name;
  130. uint16_t type;
  131. uint16_t class;
  132. uint16_t ttl;
  133. uint16_t rd_length;
  134. union ResourceData rd_data;
  135. struct ResourceRecord* next; // for linked list
  136. };
  137. struct Message {
  138. uint16_t id; /* Identifier */
  139. /* Flags */
  140. uint16_t qr; /* Query/Response Flag */
  141. uint16_t opcode; /* Operation Code */
  142. uint16_t aa; /* Authoritative Answer Flag */
  143. uint16_t tc; /* Truncation Flag */
  144. uint16_t rd; /* Recursion Desired */
  145. uint16_t ra; /* Recursion Available */
  146. uint16_t rcode; /* Response Code */
  147. uint16_t qdCount; /* Question Count */
  148. uint16_t anCount; /* Answer Record Count */
  149. uint16_t nsCount; /* Authority Record Count */
  150. uint16_t arCount; /* Additional Record Count */
  151. /* At least one question; questions are copied to the response 1:1 */
  152. struct Question* questions;
  153. /*
  154. * Resource records to be send back.
  155. * Every resource record can be in any of the following places.
  156. * But every place has a different semantic.
  157. */
  158. struct ResourceRecord* answers;
  159. struct ResourceRecord* authorities;
  160. struct ResourceRecord* additionals;
  161. };
  162. int get_A_Record(uint8_t addr[4], const char domain_name[])
  163. {
  164. if (strcmp("foo.bar.com", domain_name) == 0)
  165. {
  166. addr[0] = 192;
  167. addr[1] = 168;
  168. addr[2] = 1;
  169. addr[3] = 1;
  170. return 0;
  171. }
  172. else
  173. {
  174. return -1;
  175. }
  176. }
  177. int get_AAAA_Record(uint8_t addr[16], const char domain_name[])
  178. {
  179. if (strcmp("foo.bar.com", domain_name) == 0)
  180. {
  181. addr[0] = 0xfe;
  182. addr[1] = 0x80;
  183. addr[2] = 0x00;
  184. addr[3] = 0x00;
  185. addr[4] = 0x00;
  186. addr[5] = 0x00;
  187. addr[6] = 0x00;
  188. addr[7] = 0x00;
  189. addr[8] = 0x00;
  190. addr[9] = 0x00;
  191. addr[10] = 0x00;
  192. addr[11] = 0x00;
  193. addr[12] = 0x00;
  194. addr[13] = 0x00;
  195. addr[14] = 0x00;
  196. addr[15] = 0x01;
  197. return 0;
  198. }
  199. else
  200. {
  201. return -1;
  202. }
  203. }
  204. /*
  205. * Debugging functions.
  206. */
  207. void print_hex(uint8_t* buf, size_t len)
  208. {
  209. int i;
  210. printf("%zu bytes:\n", len);
  211. for(i = 0; i < len; ++i)
  212. printf("%02x ", buf[i]);
  213. printf("\n");
  214. }
  215. void print_resource_record(struct ResourceRecord* rr)
  216. {
  217. int i;
  218. while (rr)
  219. {
  220. printf(" ResourceRecord { name '%s', type %u, class %u, ttl %u, rd_length %u, ",
  221. rr->name,
  222. rr->type,
  223. rr->class,
  224. rr->ttl,
  225. rr->rd_length
  226. );
  227. union ResourceData *rd = &rr->rd_data;
  228. switch (rr->type)
  229. {
  230. case A_Resource_RecordType:
  231. printf("Address Resource Record { address ");
  232. for(i = 0; i < 4; ++i)
  233. printf("%s%u", (i ? "." : ""), rd->a_record.addr[i]);
  234. printf(" }");
  235. break;
  236. case NS_Resource_RecordType:
  237. printf("Name Server Resource Record { name %s }",
  238. rd->name_server_record.name
  239. );
  240. break;
  241. case CNAME_Resource_RecordType:
  242. printf("Canonical Name Resource Record { name %u }",
  243. rd->cname_record.name
  244. );
  245. break;
  246. case SOA_Resource_RecordType:
  247. printf("SOA { MName '%s', RName '%s', serial %u, refresh %u, retry %u, expire %u, minimum %u }",
  248. rd->soa_record.MName,
  249. rd->soa_record.RName,
  250. rd->soa_record.serial,
  251. rd->soa_record.refresh,
  252. rd->soa_record.retry,
  253. rd->soa_record.expire,
  254. rd->soa_record.minimum
  255. );
  256. break;
  257. case PTR_Resource_RecordType:
  258. printf("Pointer Resource Record { name '%s' }",
  259. rd->ptr_record.name
  260. );
  261. break;
  262. case MX_Resource_RecordType:
  263. printf("Mail Exchange Record { preference %u, exchange '%s' }",
  264. rd->mx_record.preference,
  265. rd->mx_record.exchange
  266. );
  267. break;
  268. case TXT_Resource_RecordType:
  269. printf("Text Resource Record { txt_data '%s' }",
  270. rd->txt_record.txt_data
  271. );
  272. break;
  273. case AAAA_Resource_RecordType:
  274. printf("AAAA Resource Record { address ");
  275. for(i = 0; i < 16; ++i)
  276. printf("%s%02x", (i ? ":" : ""), rd->aaaa_record.addr[i]);
  277. printf(" }");
  278. break;
  279. default:
  280. printf("Unknown Resource Record { ??? }");
  281. }
  282. printf("}\n");
  283. rr = rr->next;
  284. }
  285. }
  286. void print_query(struct Message* msg)
  287. {
  288. printf("QUERY { ID: %02x", msg->id);
  289. printf(". FIELDS: [ QR: %u, OpCode: %u ]", msg->qr, msg->opcode);
  290. printf(", QDcount: %u", msg->qdCount);
  291. printf(", ANcount: %u", msg->anCount);
  292. printf(", NScount: %u", msg->nsCount);
  293. printf(", ARcount: %u,\n", msg->arCount);
  294. struct Question* q = msg->questions;
  295. while (q)
  296. {
  297. printf(" Question { qName '%s', qType %u, qClass %u }\n",
  298. q->qName,
  299. q->qType,
  300. q->qClass
  301. );
  302. q = q->next;
  303. }
  304. print_resource_record(msg->answers);
  305. print_resource_record(msg->authorities);
  306. print_resource_record(msg->additionals);
  307. printf("}\n");
  308. }
  309. /*
  310. * Basic memory operations.
  311. */
  312. size_t get16bits(const uint8_t** buffer)
  313. {
  314. uint16_t value;
  315. memcpy(&value, *buffer, 2);
  316. *buffer += 2;
  317. return ntohs(value);
  318. }
  319. void put8bits(uint8_t** buffer, uint8_t value)
  320. {
  321. memcpy(*buffer, &value, 1);
  322. *buffer += 1;
  323. }
  324. void put16bits(uint8_t** buffer, uint16_t value)
  325. {
  326. value = htons(value);
  327. memcpy(*buffer, &value, 2);
  328. *buffer += 2;
  329. }
  330. void put32bits(uint8_t** buffer, uint32_t value)
  331. {
  332. value = htons(value);
  333. memcpy(*buffer, &value, 4);
  334. *buffer += 4;
  335. }
  336. /*
  337. * Deconding/Encoding functions.
  338. */
  339. // 3foo3bar3com0 => foo.bar.com
  340. char* decode_domain_name(const uint8_t** buffer)
  341. {
  342. char name[256];
  343. const uint8_t* buf = *buffer;
  344. int j = 0;
  345. int i = 0;
  346. while (buf[i] != 0)
  347. {
  348. //if (i >= buflen || i > sizeof(name))
  349. // return NULL;
  350. if (i != 0)
  351. {
  352. name[j] = '.';
  353. j += 1;
  354. }
  355. int len = buf[i];
  356. i += 1;
  357. memcpy(name+j, buf+i, len);
  358. i += len;
  359. j += len;
  360. }
  361. name[j] = '\0';
  362. *buffer += i + 1; //also jump over the last 0
  363. return strdup(name);
  364. }
  365. // foo.bar.com => 3foo3bar3com0
  366. void encode_domain_name(uint8_t** buffer, const char* domain)
  367. {
  368. uint8_t* buf = *buffer;
  369. const char* beg = domain;
  370. const char* pos;
  371. int len = 0;
  372. int i = 0;
  373. while ((pos = strchr(beg, '.')))
  374. {
  375. len = pos - beg;
  376. buf[i] = len;
  377. i += 1;
  378. memcpy(buf+i, beg, len);
  379. i += len;
  380. beg = pos + 1;
  381. }
  382. len = strlen(domain) - (beg - domain);
  383. buf[i] = len;
  384. i += 1;
  385. memcpy(buf + i, beg, len);
  386. i += len;
  387. buf[i] = 0;
  388. i += 1;
  389. *buffer += i;
  390. }
  391. void decode_header(struct Message* msg, const uint8_t** buffer)
  392. {
  393. msg->id = get16bits(buffer);
  394. uint32_t fields = get16bits(buffer);
  395. msg->qr = (fields & QR_MASK) >> 15;
  396. msg->opcode = (fields & OPCODE_MASK) >> 11;
  397. msg->aa = (fields & AA_MASK) >> 10;
  398. msg->tc = (fields & TC_MASK) >> 9;
  399. msg->rd = (fields & RD_MASK) >> 8;
  400. msg->ra = (fields & RA_MASK) >> 7;
  401. msg->rcode = (fields & RCODE_MASK) >> 0;
  402. msg->qdCount = get16bits(buffer);
  403. msg->anCount = get16bits(buffer);
  404. msg->nsCount = get16bits(buffer);
  405. msg->arCount = get16bits(buffer);
  406. }
  407. void encode_header(struct Message* msg, uint8_t** buffer)
  408. {
  409. put16bits(buffer, msg->id);
  410. int fields = 0;
  411. fields |= (msg->qr << 15) & QR_MASK;
  412. fields |= (msg->rcode << 0) & RCODE_MASK;
  413. // TODO: insert the rest of the fields
  414. put16bits(buffer, fields);
  415. put16bits(buffer, msg->qdCount);
  416. put16bits(buffer, msg->anCount);
  417. put16bits(buffer, msg->nsCount);
  418. put16bits(buffer, msg->arCount);
  419. }
  420. int decode_msg(struct Message* msg, const uint8_t* buffer, int size)
  421. {
  422. int i;
  423. decode_header(msg, &buffer);
  424. if (msg->anCount != 0 || msg->nsCount != 0)
  425. {
  426. printf("Only questions expected!\n");
  427. return -1;
  428. }
  429. // parse questions
  430. uint32_t qcount = msg->qdCount;
  431. struct Question* qs = msg->questions;
  432. for (i = 0; i < qcount; ++i)
  433. {
  434. struct Question* q = malloc(sizeof(struct Question));
  435. q->qName = decode_domain_name(&buffer);
  436. q->qType = get16bits(&buffer);
  437. q->qClass = get16bits(&buffer);
  438. // prepend question to questions list
  439. q->next = qs;
  440. msg->questions = q;
  441. }
  442. // We do not expect any resource records to parse here.
  443. return 0;
  444. }
  445. // For every question in the message add a appropiate resource record
  446. // in either section 'answers', 'authorities' or 'additionals'.
  447. void resolver_process(struct Message* msg)
  448. {
  449. struct ResourceRecord* beg;
  450. struct ResourceRecord* rr;
  451. struct Question* q;
  452. int rc;
  453. // leave most values intact for response
  454. msg->qr = 1; // this is a response
  455. msg->aa = 1; // this server is authoritative
  456. msg->ra = 0; // no recursion available
  457. msg->rcode = Ok_ResponseType;
  458. // should already be 0
  459. msg->anCount = 0;
  460. msg->nsCount = 0;
  461. msg->arCount = 0;
  462. // for every question append resource records
  463. q = msg->questions;
  464. while (q)
  465. {
  466. rr = malloc(sizeof(struct ResourceRecord));
  467. memset(rr, 0, sizeof(struct ResourceRecord));
  468. rr->name = strdup(q->qName);
  469. rr->type = q->qType;
  470. rr->class = q->qClass;
  471. rr->ttl = 60*60; // in seconds; 0 means no caching
  472. printf("Query for '%s'\n", q->qName);
  473. // We only can only answer two question types so far
  474. // and the answer (resource records) will be all put
  475. // into the answers list.
  476. // This behavior is probably non-standard!
  477. switch (q->qType)
  478. {
  479. case A_Resource_RecordType:
  480. rr->rd_length = 4;
  481. rc = get_A_Record(rr->rd_data.a_record.addr, q->qName);
  482. if (rc < 0)
  483. {
  484. free(rr->name);
  485. free(rr);
  486. goto next;
  487. }
  488. break;
  489. case AAAA_Resource_RecordType:
  490. rr->rd_length = 16;
  491. rc = get_AAAA_Record(rr->rd_data.aaaa_record.addr, q->qName);
  492. if (rc < 0)
  493. {
  494. free(rr->name);
  495. free(rr);
  496. goto next;
  497. }
  498. break;
  499. /*
  500. case NS_Resource_RecordType:
  501. case CNAME_Resource_RecordType:
  502. case SOA_Resource_RecordType:
  503. case PTR_Resource_RecordType:
  504. case MX_Resource_RecordType:
  505. case TXT_Resource_RecordType:
  506. */
  507. default:
  508. free(rr);
  509. msg->rcode = NotImplemented_ResponseType;
  510. printf("Cannot answer question of type %d.\n", q->qType);
  511. goto next;
  512. }
  513. msg->anCount++;
  514. // prepend resource record to answers list
  515. beg = msg->answers;
  516. msg->answers = rr;
  517. rr->next = beg;
  518. // jump here to omit question
  519. next:
  520. // process next question
  521. q = q->next;
  522. }
  523. }
  524. /* @return 0 upon failure, 1 upon success */
  525. int encode_resource_records(struct ResourceRecord* rr, uint8_t** buffer)
  526. {
  527. int i;
  528. while (rr)
  529. {
  530. // Answer questions by attaching resource sections.
  531. encode_domain_name(buffer, rr->name);
  532. put16bits(buffer, rr->type);
  533. put16bits(buffer, rr->class);
  534. put32bits(buffer, rr->ttl);
  535. put16bits(buffer, rr->rd_length);
  536. switch (rr->type)
  537. {
  538. case A_Resource_RecordType:
  539. for(i = 0; i < 4; ++i)
  540. put8bits(buffer, rr->rd_data.a_record.addr[i]);
  541. break;
  542. case AAAA_Resource_RecordType:
  543. for(i = 0; i < 16; ++i)
  544. put8bits(buffer, rr->rd_data.aaaa_record.addr[i]);
  545. break;
  546. default:
  547. fprintf(stderr, "Unknown type %u. => Ignore resource record.\n", rr->type);
  548. return 1;
  549. }
  550. rr = rr->next;
  551. }
  552. return 0;
  553. }
  554. /* @return 0 upon failure, 1 upon success */
  555. int encode_msg(struct Message* msg, uint8_t** buffer)
  556. {
  557. struct Question* q;
  558. int rc;
  559. encode_header(msg, buffer);
  560. q = msg->questions;
  561. while (q)
  562. {
  563. encode_domain_name(buffer, q->qName);
  564. put16bits(buffer, q->qType);
  565. put16bits(buffer, q->qClass);
  566. q = q->next;
  567. }
  568. rc = 0;
  569. rc |= encode_resource_records(msg->answers, buffer);
  570. rc |= encode_resource_records(msg->authorities, buffer);
  571. rc |= encode_resource_records(msg->additionals, buffer);
  572. return rc;
  573. }
  574. void free_resource_records(struct ResourceRecord* rr)
  575. {
  576. struct ResourceRecord* next;
  577. while (rr) {
  578. free(rr->name);
  579. next = rr->next;
  580. free(rr);
  581. rr = next;
  582. }
  583. }
  584. void free_questions(struct Question* qq)
  585. {
  586. struct Question* next;
  587. while (qq) {
  588. free(qq->qName);
  589. next = qq->next;
  590. free(qq);
  591. qq = next;
  592. }
  593. }
  594. int main()
  595. {
  596. // buffer for input/output binary packet
  597. uint8_t buffer[BUF_SIZE];
  598. struct sockaddr_in client_addr;
  599. socklen_t addr_len = sizeof(struct sockaddr_in);
  600. struct sockaddr_in addr;
  601. int nbytes, rc;
  602. int sock;
  603. int port = 53;
  604. struct Message msg;
  605. memset(&msg, 0, sizeof(struct Message));
  606. addr.sin_family = AF_INET;
  607. addr.sin_addr.s_addr = INADDR_ANY;
  608. addr.sin_port = htons(port);
  609. sock = socket(AF_INET, SOCK_DGRAM, 0);
  610. rc = bind(sock, (struct sockaddr*) &addr, addr_len);
  611. if (rc != 0)
  612. {
  613. printf("Could not bind: %s\n", strerror(errno));
  614. return 1;
  615. }
  616. printf("Listening on port %u.\n", port);
  617. while (1)
  618. {
  619. free_questions(msg.questions);
  620. free_resource_records(msg.answers);
  621. free_resource_records(msg.authorities);
  622. free_resource_records(msg.additionals);
  623. memset(&msg, 0, sizeof(struct Message));
  624. nbytes = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &client_addr, &addr_len);
  625. if (decode_msg(&msg, buffer, nbytes) != 0) {
  626. continue;
  627. }
  628. /* Print query */
  629. print_query(&msg);
  630. resolver_process(&msg);
  631. /* Print response */
  632. print_query(&msg);
  633. uint8_t *p = buffer;
  634. if (encode_msg(&msg, &p) != 0) {
  635. continue;
  636. }
  637. int buflen = p - buffer;
  638. sendto(sock, buffer, buflen, 0, (struct sockaddr*) &client_addr, addr_len);
  639. }
  640. }