captive_dns_server.c 2.29 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Copyright (c) 2014 Cesanta Software Limited
 * All rights reserved
 */

/*
 * Try it out with:
 * $ dig -t A www.google.com -4 @localhost -p 5533
 */

#include "../../mongoose.h"

#include <stdio.h>

static int s_exit_flag = 0;
static in_addr_t s_our_ip_addr;
static const char *s_listening_addr = "udp://:5533";

static void ev_handler(struct mg_connection *nc, int ev, void *ev_data) {
Deomid Ryabkov's avatar
Deomid Ryabkov committed
20 21 22
  struct mg_dns_message *msg;
  struct mg_dns_resource_record *rr;
  struct mg_dns_reply reply;
23 24 25
  int i;

  switch (ev) {
26 27 28
    case MG_DNS_MESSAGE: {
      struct mbuf reply_buf;
      mbuf_init(&reply_buf, 512);
Deomid Ryabkov's avatar
Deomid Ryabkov committed
29
      msg = (struct mg_dns_message *) ev_data;
30
      reply = mg_dns_create_reply(&reply_buf, msg);
31 32

      for (i = 0; i < msg->num_questions; i++) {
33
        char rname[256];
34
        rr = &msg->questions[i];
35
        mg_dns_uncompress_name(msg, &rr->name, rname, sizeof(rname) - 1);
36
        fprintf(stdout, "Q type %d name %s\n", rr->rtype, rname);
37
        if (rr->rtype == MG_DNS_A_RECORD) {
38 39
          mg_dns_reply_record(&reply, rr, NULL, rr->rtype, 10, &s_our_ip_addr,
                              4);
40 41 42 43 44
        }
      }

      /*
       * We don't set the error flag even if there were no answers
45 46
       * matching the MG_DNS_A_RECORD query type.
       * This indicates that we have (synthetic) answers for MG_DNS_A_RECORD.
47 48 49
       * See http://goo.gl/QWvufr for a distinction between NXDOMAIN and NODATA.
       */

Deomid Ryabkov's avatar
Deomid Ryabkov committed
50
      mg_dns_send_reply(nc, &reply);
51
      nc->flags |= MG_F_SEND_AND_CLOSE;
52
      mbuf_free(&reply_buf);
53
      break;
54
    }
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
  }
}

int main(int argc, char *argv[]) {
  struct mg_mgr mgr;
  struct mg_connection *nc;
  int i;

  mg_mgr_init(&mgr, NULL);
  s_our_ip_addr = inet_addr("127.0.0.1");

  /* Parse command line arguments */
  for (i = 1; i < argc; i++) {
    if (strcmp(argv[i], "-D") == 0) {
      mgr.hexdump_file = argv[++i];
    } else if (strcmp(argv[i], "-l") == 0 && i + 1 < argc) {
      s_listening_addr = argv[++i];
    } else {
      s_our_ip_addr = inet_addr(argv[i]);
    }
  }

  fprintf(stderr, "Listening on '%s'\n", s_listening_addr);
  if ((nc = mg_bind(&mgr, s_listening_addr, ev_handler)) == NULL) {
    fprintf(stderr, "cannot bind to socket\n");
    exit(1);
  }
  mg_set_protocol_dns(nc);

  while (s_exit_flag == 0) {
    mg_mgr_poll(&mgr, 1000);
  }
  mg_mgr_free(&mgr);

  return 0;
}