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