DNS server, which rejects all requests.

nodnsd.c 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. /*
  2. * nodnsd - DNS server, which rejects all requests.
  3. *
  4. * The musl library has the misfeature (IMHO), that the resolver
  5. * does DNS requests to localhost, if no nameservers are defined.
  6. * As localhost normally doesn't answer DNS requests, the use of
  7. * unknown hosts leads to a delay until an error is returned.
  8. *
  9. * By starting this server all DNS requests are immediately
  10. * rejected and a delay is avoided.
  11. *
  12. * This program is put into the public domain, use it as you like.
  13. */
  14. #include <stdio.h>
  15. #include <string.h>
  16. #include <stdlib.h>
  17. #include <unistd.h>
  18. #include <arpa/inet.h>
  19. #include <sys/socket.h>
  20. #define BUFLEN 1500 /* length of buffer */
  21. #define PORT 53 /* DNS port */
  22. #define DNS_FLAG_OFF 2 /* DNS flag offset */
  23. #define DNS_FLAG_RESP 0x848f /* DNS response field mask */
  24. #define DNS_FLAG_NXDOM 0x8003 /* DNS response: non-existent domain */
  25. #define DNS_FLAG_RD 0x0100 /* DNS recursion desired */
  26. #define DNS_FLAG_RA 0x0080 /* DNS recursion available */
  27. static void die(char *s) {
  28. perror(s);
  29. exit(1);
  30. }
  31. int main(int argc, char *argv[]) {
  32. struct sockaddr_in6 si_me, si_peer;
  33. socklen_t si_len;
  34. unsigned char buf[BUFLEN];
  35. uint16_t dns_flags;
  36. int ipv6_only;
  37. int pid;
  38. int recv_len;
  39. int sock;
  40. /* no command line arguments */
  41. if (argc > 1) {
  42. fprintf(stderr, "nodnsd - DNS server, which rejects all requests.\n");
  43. exit(1);
  44. }
  45. /* create an UDP socket */
  46. if ((sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP)) < 0)
  47. die("socket");
  48. /* protocol / address / port for bind() */
  49. memset(&si_me, 0, sizeof(si_me));
  50. si_me.sin6_family = AF_INET6;
  51. si_me.sin6_port = htons(PORT);
  52. si_me.sin6_addr = in6addr_any;
  53. /* bind to both IPv4 and IPv6 */
  54. ipv6_only = 0;
  55. if (setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
  56. &ipv6_only, sizeof(ipv6_only)))
  57. die("setsockopt");
  58. /* bind socket to port */
  59. if (bind(sock , (struct sockaddr*)&si_me, sizeof(si_me) ) < 0)
  60. die("bind");
  61. /* background our process */
  62. pid = fork();
  63. if (pid < 0) die("fork");
  64. if (pid > 0) exit(0);
  65. freopen("/dev/null", "r", stdin);
  66. if (setsid() < 0) die("setsid");
  67. /* keep listening for data */
  68. while (1) {
  69. /* try to receive some data, this is a blocking call */
  70. si_len = sizeof(si_peer);
  71. recv_len = recvfrom(sock, buf, sizeof(buf), 0,
  72. (struct sockaddr *)&si_peer, &si_len);
  73. if (recv_len < 0) die("recvfrom");
  74. /* set DNS response to non-existent domain */
  75. dns_flags = (buf[DNS_FLAG_OFF] << 8) | buf[DNS_FLAG_OFF+1];
  76. dns_flags &= ~DNS_FLAG_RESP; /* clear response bits */
  77. dns_flags |= DNS_FLAG_NXDOM; /* set response */
  78. if (dns_flags & DNS_FLAG_RD) dns_flags |= DNS_FLAG_RA;
  79. buf[DNS_FLAG_OFF] = (dns_flags >> 8) & 0xFF;
  80. buf[DNS_FLAG_OFF+1] = dns_flags & 0xFF;
  81. /* now send reply to the client */
  82. if (sendto(sock, buf, recv_len, 0, (struct sockaddr*) &si_peer, si_len) < 0)
  83. die("sendto");
  84. }
  85. close(sock);
  86. return 0;
  87. }