2 This example code shows how to use the high-level, low-level, and
3 server-level interfaces of evdns.
5 XXX It's pretty ugly and should probably be cleaned up.
8 #include <event2/event-config.h>
10 #include <sys/types.h>
16 #include <sys/socket.h>
17 #include <netinet/in.h>
18 #include <arpa/inet.h>
21 #include <event2/event.h>
22 #include <event2/dns.h>
23 #include <event2/dns_struct.h>
24 #include <event2/util.h>
26 #ifdef _EVENT_HAVE_NETINET_IN6_H
27 #include <netinet/in6.h>
34 #define u32 ev_uint32_t
38 debug_ntoa(u32 address
)
41 u32 a
= ntohl(address
);
42 evutil_snprintf(buf
, sizeof(buf
), "%d.%d.%d.%d",
43 (int)(u8
)((a
>>24)&0xff),
44 (int)(u8
)((a
>>16)&0xff),
45 (int)(u8
)((a
>>8 )&0xff),
46 (int)(u8
)((a
)&0xff));
51 main_callback(int result
, char type
, int count
, int ttl
,
52 void *addrs
, void *orig
) {
53 char *n
= (char*)orig
;
55 for (i
= 0; i
< count
; ++i
) {
56 if (type
== DNS_IPv4_A
) {
57 printf("%s: %s\n", n
, debug_ntoa(((u32
*)addrs
)[i
]));
58 } else if (type
== DNS_PTR
) {
59 printf("%s: %s\n", n
, ((char**)addrs
)[i
]);
63 printf("%s: No answer (%d)\n", n
, result
);
69 gai_callback(int err
, struct evutil_addrinfo
*ai
, void *arg
)
71 const char *name
= arg
;
72 struct evutil_addrinfo
*ai_first
= NULL
;
75 printf("%s: %s\n", name
, evutil_gai_strerror(err
));
77 if (ai
&& ai
->ai_canonname
)
78 printf(" %s ==> %s\n", name
, ai
->ai_canonname
);
79 for (i
=0; ai
; ai
= ai
->ai_next
, ++i
) {
81 if (ai
->ai_family
== PF_INET
) {
82 struct sockaddr_in
*sin
=
83 (struct sockaddr_in
*)ai
->ai_addr
;
84 evutil_inet_ntop(AF_INET
, &sin
->sin_addr
, buf
,
86 printf("[%d] %s: %s\n",i
,name
,buf
);
88 struct sockaddr_in6
*sin6
=
89 (struct sockaddr_in6
*)ai
->ai_addr
;
90 evutil_inet_ntop(AF_INET6
, &sin6
->sin6_addr
, buf
,
92 printf("[%d] %s: %s\n",i
,name
,buf
);
96 evutil_freeaddrinfo(ai_first
);
100 evdns_server_callback(struct evdns_server_request
*req
, 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
,
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);
121 printf(" -- skipping %s [%d %d]\n", req
->questions
[i
]->name
,
122 req
->questions
[i
]->type
, req
->questions
[i
]->dns_question_class
);
126 r
= evdns_server_request_respond(req
, 0);
128 printf("eeek, couldn't send reply.\n");
131 static int verbose
= 0;
134 logfn(int is_warn
, const char *msg
) {
135 if (!is_warn
&& !verbose
)
137 fprintf(stderr
, "%s: %s\n", is_warn
?"WARN":"INFO", msg
);
141 main(int c
, char **v
) {
143 int reverse
= 0, servertest
= 0, use_getaddrinfo
= 0;
144 struct event_base
*event_base
= NULL
;
145 struct evdns_base
*evdns_base
= NULL
;
147 fprintf(stderr
, "syntax: %s [-x] [-v] hostname\n", v
[0]);
148 fprintf(stderr
, "syntax: %s [-servertest]\n", v
[0]);
152 while (idx
< c
&& v
[idx
][0] == '-') {
153 if (!strcmp(v
[idx
], "-x"))
155 else if (!strcmp(v
[idx
], "-v"))
157 else if (!strcmp(v
[idx
], "-g"))
159 else if (!strcmp(v
[idx
], "-servertest"))
162 fprintf(stderr
, "Unknown option %s\n", v
[idx
]);
166 event_base
= event_base_new();
167 evdns_base
= evdns_base_new(event_base
, 0);
168 evdns_set_log_fn(logfn
);
171 evutil_socket_t sock
;
172 struct sockaddr_in my_addr
;
173 sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
174 evutil_make_socket_nonblocking(sock
);
175 my_addr
.sin_family
= AF_INET
;
176 my_addr
.sin_port
= htons(10053);
177 my_addr
.sin_addr
.s_addr
= INADDR_ANY
;
178 if (bind(sock
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
))<0) {
182 evdns_add_server_port_with_base(event_base
, sock
, 0, evdns_server_callback
, NULL
);
186 evdns_base_config_windows_nameservers(evdns_base
);
188 evdns_base_resolv_conf_parse(evdns_base
, DNS_OPTION_NAMESERVERS
,
193 printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME
);
194 for (; idx
< c
; ++idx
) {
197 if (evutil_inet_pton(AF_INET
, v
[idx
], &addr
)!=1) {
198 fprintf(stderr
, "Skipping non-IP %s\n", v
[idx
]);
201 fprintf(stderr
, "resolving %s...\n",v
[idx
]);
202 evdns_base_resolve_reverse(evdns_base
, &addr
, 0, main_callback
, v
[idx
]);
203 } else if (use_getaddrinfo
) {
204 struct evutil_addrinfo hints
;
205 memset(&hints
, 0, sizeof(hints
));
206 hints
.ai_family
= PF_UNSPEC
;
207 hints
.ai_protocol
= IPPROTO_TCP
;
208 hints
.ai_flags
= EVUTIL_AI_CANONNAME
;
209 fprintf(stderr
, "resolving (fwd) %s...\n",v
[idx
]);
210 evdns_getaddrinfo(evdns_base
, v
[idx
], NULL
, &hints
,
211 gai_callback
, v
[idx
]);
213 fprintf(stderr
, "resolving (fwd) %s...\n",v
[idx
]);
214 evdns_base_resolve_ipv4(evdns_base
, v
[idx
], 0, main_callback
, v
[idx
]);
218 event_base_dispatch(event_base
);