aboutsummaryrefslogblamecommitdiffstats
path: root/libglouglou/libggnet_dns.c
blob: 25bada32461f99cb78d11f99f6d4eebda3a1f775 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                                                                      


                                         
                                 
 

                                              


                                             


                                                 
             
               

    

                



              
                                       
 

                                        

 
                      
                                          




                                                                     
                            
                             
                     






                                       
                                             
             
                                                 

            
                     



                                               

                                                                     

                                                 
                                                               




                                                                             
                


                   







                                                                    





                                                      
                            
              
 

                                                                     

            
                   



                                            
 
                          
                            

            
#include <stdlib.h>
#include <string.h>

#include "libggnet_dns.h"

/*
 * For dns with libevent, see
 * http://www.wangafu.net/~nickm/libevent-2.0/doxygen/html/dns_8h.html
 * http://www.wangafu.net/~nickm/libevent-book/Ref9_dns.html
 * spike/evdns_chrooted.c
 * spike/evdns.c
 */

static void _cb_evdns_reverse(int, char, int, int, void *, void *);

struct ggnet_dns *
ggnet_dns_new(struct event_base *ev_base)
{
  struct ggnet_dns *ggdns = NULL;

  ggdns = calloc(1, sizeof(struct ggnet_dns));
  if (!ggdns) {
    printf("could not allocate ggnet_dns\n");
    exit(1);
  }
  ggdns->ev_base = ev_base;
  ggdns->evdns_base = evdns_base_new(ev_base, 1);
  if (!ggdns->evdns_base)
    goto err;
  return ggdns;

err:
  if (ggdns)
    free(ggdns);
  return NULL;
}

void
ggnet_dns_free(struct ggnet_dns *ggdns)
{
  evdns_base_free(ggdns->evdns_base, 1);
  free(ggdns);
}

struct ggnet_dns_req *
ggnet_dns_reverse(struct ggnet_dns *ggdns,
                  struct in_addr *ip,
                    void (*cb_usr)(struct in_addr *, char *, void *),
                    void *data)
{
  struct evutil_addrinfo hints;
  struct ggnet_dns_req *req;
  struct evdns_request *ereq;
  struct in_addr nip;

  memset(&hints, 0, sizeof(hints));
  hints.ai_family = AF_UNSPEC;
  hints.ai_flags = EVUTIL_AI_CANONNAME;
  hints.ai_socktype = SOCK_STREAM;
  hints.ai_protocol = IPPROTO_TCP;

  req = malloc(sizeof(struct ggnet_dns_req));
  if (!req) {
    printf("could not allocate ggnet_dns_req\n");
    exit(1);
  }
  req->ggdns = ggdns;
  memcpy(&req->ip, ip, sizeof(struct in_addr));
  req->cb_usr = cb_usr;
  req->data = data;

  nip.s_addr = htonl(ip->s_addr); /* evdns eats network byte order */

  LIST_INSERT_HEAD(&ggdns->req_list, req, entry);
  ggdns->req_pending++;
  ereq = evdns_base_resolve_reverse(ggdns->evdns_base, &nip, 0,
                                    _cb_evdns_reverse, req);
  if (ereq == NULL) {
    printf("libggnet_dns WARNING: dns request for %d returned immediately\n",
           ip->s_addr);
    /* remove req from list and free it happened in the callback. */
    return NULL;
  }
  req->ereq = ereq;

  return req;
}

void
ggnet_dns_cancel(struct ggnet_dns *ggdns, struct ggnet_dns_req *req)
{
  evdns_cancel_request(ggdns->evdns_base, req->ereq);
  /* remove req from list and free it happened in the callback. */
}

static void
_cb_evdns_reverse(int result, char type, int count,
                  int ttl, void *addresses, void *arg)
{
  struct ggnet_dns_req *req;
  char **name;

  if (count > 1)
    printf("libggnet_dns XXX: has %d PTR records !\n", count); // XXX

  req = arg;
  name = addresses;
  if (result != DNS_ERR_NONE || count == 0)
    req->cb_usr(&req->ip, NULL, req->data);
  else
    req->cb_usr(&req->ip, *name, req->data);

  LIST_REMOVE(req, entry);
  req->ggdns->req_pending--;
  free(req);
}