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 /* Compatibility for possible missing IPv6 declarations */
11 #include "../ipv6-internal.h"
13 #include <sys/types.h>
19 #include <sys/socket.h>
20 #include <netinet/in.h>
21 #include <arpa/inet.h>
24 #include <event2/event.h>
25 #include <event2/dns.h>
26 #include <event2/dns_struct.h>
27 #include <event2/util.h>
29 #ifdef _EVENT_HAVE_NETINET_IN6_H
30 #include <netinet/in6.h>
37 #define u32 ev_uint32_t
41 debug_ntoa(u32 address
)
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));
54 main_callback(int result
, char type
, int count
, int ttl
,
55 void *addrs
, void *orig
) {
56 char *n
= (char*)orig
;
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
]);
66 printf("%s: No answer (%d)\n", n
, result
);
72 gai_callback(int err
, struct evutil_addrinfo
*ai
, void *arg
)
74 const char *name
= arg
;
77 printf("%s: %s\n", name
, evutil_gai_strerror(err
));
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
) {
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
,
88 printf("[%d] %s: %s\n",i
,name
,buf
);
90 struct sockaddr_in6
*sin6
=
91 (struct sockaddr_in6
*)ai
->ai_addr
;
92 evutil_inet_ntop(AF_INET6
, &sin6
->sin6_addr
, buf
,
94 printf("[%d] %s: %s\n",i
,name
,buf
);
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("ugh, no luck");
123 printf(" -- skipping %s [%d %d]\n", req
->questions
[i
]->name
,
124 req
->questions
[i
]->type
, req
->questions
[i
]->dns_question_class
);
128 r
= evdns_server_request_respond(req
, 0);
130 printf("eeek, couldn't send reply.\n");
133 static int verbose
= 0;
136 logfn(int is_warn
, const char *msg
) {
137 if (!is_warn
&& !verbose
)
139 fprintf(stderr
, "%s: %s\n", is_warn
?"WARN":"INFO", msg
);
143 main(int c
, char **v
) {
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
;
150 fprintf(stderr
, "syntax: %s [-x] [-v] [-c resolv.conf] hostname\n", v
[0]);
151 fprintf(stderr
, "syntax: %s [-servertest]\n", v
[0]);
155 while (idx
< c
&& v
[idx
][0] == '-') {
156 if (!strcmp(v
[idx
], "-x"))
158 else if (!strcmp(v
[idx
], "-v"))
160 else if (!strcmp(v
[idx
], "-g"))
162 else if (!strcmp(v
[idx
], "-servertest"))
164 else if (!strcmp(v
[idx
], "-c")) {
166 resolv_conf
= v
[++idx
];
168 fprintf(stderr
, "-c needs an argument\n");
170 fprintf(stderr
, "Unknown option %s\n", v
[idx
]);
177 WSAStartup(0x101, &WSAData
);
181 event_base
= event_base_new();
182 evdns_base
= evdns_base_new(event_base
, 0);
183 evdns_set_log_fn(logfn
);
186 evutil_socket_t sock
;
187 struct sockaddr_in my_addr
;
188 sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
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) {
201 evdns_add_server_port_with_base(event_base
, sock
, 0, evdns_server_callback
, NULL
);
206 if (resolv_conf
== NULL
)
207 res
= evdns_base_config_windows_nameservers(evdns_base
);
210 res
= evdns_base_resolv_conf_parse(evdns_base
,
211 DNS_OPTION_NAMESERVERS
,
212 resolv_conf
? resolv_conf
: "/etc/resolv.conf");
215 fprintf(stderr
, "Couldn't configure nameservers");
220 printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME
);
221 for (; idx
< c
; ++idx
) {
224 if (evutil_inet_pton(AF_INET
, v
[idx
], &addr
)!=1) {
225 fprintf(stderr
, "Skipping non-IP %s\n", v
[idx
]);
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
]);
240 fprintf(stderr
, "resolving (fwd) %s...\n",v
[idx
]);
241 evdns_base_resolve_ipv4(evdns_base
, v
[idx
], 0, main_callback
, v
[idx
]);
245 event_base_dispatch(event_base
);