root/opal/mca/event/libevent2022/libevent/sample/dns-example.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. debug_ntoa
  2. main_callback
  3. gai_callback
  4. evdns_server_callback
  5. logfn
  6. main

   1 /*
   2   This example code shows how to use the high-level, low-level, and
   3   server-level interfaces of evdns.
   4 
   5   XXX It's pretty ugly and should probably be cleaned up.
   6  */
   7 
   8 #include <event2/event-config.h>
   9 
  10 /* Compatibility for possible missing IPv6 declarations */
  11 #include "../ipv6-internal.h"
  12 
  13 #include <sys/types.h>
  14 
  15 #ifdef WIN32
  16 #include <winsock2.h>
  17 #include <ws2tcpip.h>
  18 #else
  19 #include <sys/socket.h>
  20 #include <netinet/in.h>
  21 #include <arpa/inet.h>
  22 #endif
  23 
  24 #include <event2/event.h>
  25 #include <event2/dns.h>
  26 #include <event2/dns_struct.h>
  27 #include <event2/util.h>
  28 
  29 #ifdef _EVENT_HAVE_NETINET_IN6_H
  30 #include <netinet/in6.h>
  31 #endif
  32 
  33 #include <stdio.h>
  34 #include <stdlib.h>
  35 #include <string.h>
  36 
  37 #define u32 ev_uint32_t
  38 #define u8 ev_uint8_t
  39 
  40 static const char *
  41 debug_ntoa(u32 address)
  42 {
  43         static char buf[32];
  44         u32 a = ntohl(address);
  45         evutil_snprintf(buf, sizeof(buf), "%d.%d.%d.%d",
  46                                         (int)(u8)((a>>24)&0xff),
  47                                         (int)(u8)((a>>16)&0xff),
  48                                         (int)(u8)((a>>8 )&0xff),
  49                                         (int)(u8)((a    )&0xff));
  50         return buf;
  51 }
  52 
  53 static void
  54 main_callback(int result, char type, int count, int ttl,
  55                           void *addrs, void *orig) {
  56         char *n = (char*)orig;
  57         int i;
  58         for (i = 0; i < count; ++i) {
  59                 if (type == DNS_IPv4_A) {
  60                         printf("%s: %s\n", n, debug_ntoa(((u32*)addrs)[i]));
  61                 } else if (type == DNS_PTR) {
  62                         printf("%s: %s\n", n, ((char**)addrs)[i]);
  63                 }
  64         }
  65         if (!count) {
  66                 printf("%s: No answer (%d)\n", n, result);
  67         }
  68         fflush(stdout);
  69 }
  70 
  71 static void
  72 gai_callback(int err, struct evutil_addrinfo *ai, void *arg)
  73 {
  74         const char *name = arg;
  75         int i;
  76         if (err) {
  77                 printf("%s: %s\n", name, evutil_gai_strerror(err));
  78         }
  79         if (ai && ai->ai_canonname)
  80                 printf("    %s ==> %s\n", name, ai->ai_canonname);
  81         for (i=0; ai; ai = ai->ai_next, ++i) {
  82                 char buf[128];
  83                 if (ai->ai_family == PF_INET) {
  84                         struct sockaddr_in *sin =
  85                             (struct sockaddr_in*)ai->ai_addr;
  86                         evutil_inet_ntop(AF_INET, &sin->sin_addr, buf,
  87                             sizeof(buf));
  88                         printf("[%d] %s: %s\n",i,name,buf);
  89                 } else {
  90                         struct sockaddr_in6 *sin6 =
  91                             (struct sockaddr_in6*)ai->ai_addr;
  92                         evutil_inet_ntop(AF_INET6, &sin6->sin6_addr, buf,
  93                             sizeof(buf));
  94                         printf("[%d] %s: %s\n",i,name,buf);
  95                 }
  96         }
  97 }
  98 
  99 static void
 100 evdns_server_callback(struct evdns_server_request *req, void *data)
 101 {
 102         int i, r;
 103         (void)data;
 104         /* dummy; give 192.168.11.11 as an answer for all A questions,
 105          *      give foo.bar.example.com as an answer for all PTR questions. */
 106         for (i = 0; i < req->nquestions; ++i) {
 107                 u32 ans = htonl(0xc0a80b0bUL);
 108                 if (req->questions[i]->type == EVDNS_TYPE_A &&
 109                     req->questions[i]->dns_question_class == EVDNS_CLASS_INET) {
 110                         printf(" -- replying for %s (A)\n", req->questions[i]->name);
 111                         r = evdns_server_request_add_a_reply(req, req->questions[i]->name,
 112                                                                                   1, &ans, 10);
 113                         if (r<0)
 114                                 printf("eeep, didn't work.\n");
 115                 } else if (req->questions[i]->type == EVDNS_TYPE_PTR &&
 116                     req->questions[i]->dns_question_class == EVDNS_CLASS_INET) {
 117                         printf(" -- replying for %s (PTR)\n", req->questions[i]->name);
 118                         r = evdns_server_request_add_ptr_reply(req, NULL, req->questions[i]->name,
 119                                                                                         "foo.bar.example.com", 10);
 120                         if (r<0)
 121                                 printf("ugh, no luck");
 122                 } else {
 123                         printf(" -- skipping %s [%d %d]\n", req->questions[i]->name,
 124                                    req->questions[i]->type, req->questions[i]->dns_question_class);
 125                 }
 126         }
 127 
 128         r = evdns_server_request_respond(req, 0);
 129         if (r<0)
 130                 printf("eeek, couldn't send reply.\n");
 131 }
 132 
 133 static int verbose = 0;
 134 
 135 static void
 136 logfn(int is_warn, const char *msg) {
 137         if (!is_warn && !verbose)
 138                 return;
 139         fprintf(stderr, "%s: %s\n", is_warn?"WARN":"INFO", msg);
 140 }
 141 
 142 int
 143 main(int c, char **v) {
 144         int idx;
 145         int reverse = 0, servertest = 0, use_getaddrinfo = 0;
 146         struct event_base *event_base = NULL;
 147         struct evdns_base *evdns_base = NULL;
 148         const char *resolv_conf = NULL;
 149         if (c<2) {
 150                 fprintf(stderr, "syntax: %s [-x] [-v] [-c resolv.conf] hostname\n", v[0]);
 151                 fprintf(stderr, "syntax: %s [-servertest]\n", v[0]);
 152                 return 1;
 153         }
 154         idx = 1;
 155         while (idx < c && v[idx][0] == '-') {
 156                 if (!strcmp(v[idx], "-x"))
 157                         reverse = 1;
 158                 else if (!strcmp(v[idx], "-v"))
 159                         verbose = 1;
 160                 else if (!strcmp(v[idx], "-g"))
 161                         use_getaddrinfo = 1;
 162                 else if (!strcmp(v[idx], "-servertest"))
 163                         servertest = 1;
 164                 else if (!strcmp(v[idx], "-c")) {
 165                         if (idx + 1 < c)
 166                                 resolv_conf = v[++idx];
 167                         else
 168                                 fprintf(stderr, "-c needs an argument\n");
 169                 } else
 170                         fprintf(stderr, "Unknown option %s\n", v[idx]);
 171                 ++idx;
 172         }
 173 
 174 #ifdef WIN32
 175         {
 176                 WSADATA WSAData;
 177                 WSAStartup(0x101, &WSAData);
 178         }
 179 #endif
 180 
 181         event_base = event_base_new();
 182         evdns_base = evdns_base_new(event_base, 0);
 183         evdns_set_log_fn(logfn);
 184 
 185         if (servertest) {
 186                 evutil_socket_t sock;
 187                 struct sockaddr_in my_addr;
 188                 sock = socket(PF_INET, SOCK_DGRAM, 0);
 189                 if (sock == -1) {
 190                         perror("socket");
 191                         exit(1);
 192                 }
 193                 evutil_make_socket_nonblocking(sock);
 194                 my_addr.sin_family = AF_INET;
 195                 my_addr.sin_port = htons(10053);
 196                 my_addr.sin_addr.s_addr = INADDR_ANY;
 197                 if (bind(sock, (struct sockaddr*)&my_addr, sizeof(my_addr))<0) {
 198                         perror("bind");
 199                         exit(1);
 200                 }
 201                 evdns_add_server_port_with_base(event_base, sock, 0, evdns_server_callback, NULL);
 202         }
 203         if (idx < c) {
 204                 int res;
 205 #ifdef WIN32
 206                 if (resolv_conf == NULL)
 207                         res = evdns_base_config_windows_nameservers(evdns_base);
 208                 else
 209 #endif
 210                         res = evdns_base_resolv_conf_parse(evdns_base,
 211                             DNS_OPTION_NAMESERVERS,
 212                             resolv_conf ? resolv_conf : "/etc/resolv.conf");
 213 
 214                 if (res < 0) {
 215                         fprintf(stderr, "Couldn't configure nameservers");
 216                         return 1;
 217                 }
 218         }
 219 
 220         printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME);
 221         for (; idx < c; ++idx) {
 222                 if (reverse) {
 223                         struct in_addr addr;
 224                         if (evutil_inet_pton(AF_INET, v[idx], &addr)!=1) {
 225                                 fprintf(stderr, "Skipping non-IP %s\n", v[idx]);
 226                                 continue;
 227                         }
 228                         fprintf(stderr, "resolving %s...\n",v[idx]);
 229                         evdns_base_resolve_reverse(evdns_base, &addr, 0, main_callback, v[idx]);
 230                 } else if (use_getaddrinfo) {
 231                         struct evutil_addrinfo hints;
 232                         memset(&hints, 0, sizeof(hints));
 233                         hints.ai_family = PF_UNSPEC;
 234                         hints.ai_protocol = IPPROTO_TCP;
 235                         hints.ai_flags = EVUTIL_AI_CANONNAME;
 236                         fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
 237                         evdns_getaddrinfo(evdns_base, v[idx], NULL, &hints,
 238                             gai_callback, v[idx]);
 239                 } else {
 240                         fprintf(stderr, "resolving (fwd) %s...\n",v[idx]);
 241                         evdns_base_resolve_ipv4(evdns_base, v[idx], 0, main_callback, v[idx]);
 242                 }
 243         }
 244         fflush(stdout);
 245         event_base_dispatch(event_base);
 246         return 0;
 247 }
 248 

/* [<][>][^][v][top][bottom][index][help] */