1 /* $NetBSD: dns-example.c,v 1.1.1.1 2013/04/11 16:43:31 christos Exp $ */
3 This example code shows how to use the high-level, low-level, and
4 server-level interfaces of evdns.
6 XXX It's pretty ugly and should probably be cleaned up.
9 #include <event2/event-config.h>
11 /* Compatibility for possible missing IPv6 declarations */
12 #include "../ipv6-internal.h"
14 #include <sys/types.h>
20 #include <sys/socket.h>
21 #include <netinet/in.h>
22 #include <arpa/inet.h>
25 #include <event2/event.h>
26 #include <event2/dns.h>
27 #include <event2/dns_struct.h>
28 #include <event2/util.h>
30 #ifdef _EVENT_HAVE_NETINET_IN6_H
31 #include <netinet/in6.h>
38 #define u32 ev_uint32_t
42 debug_ntoa(u32 address
)
45 u32 a
= ntohl(address
);
46 evutil_snprintf(buf
, sizeof(buf
), "%d.%d.%d.%d",
47 (int)(u8
)((a
>>24)&0xff),
48 (int)(u8
)((a
>>16)&0xff),
49 (int)(u8
)((a
>>8 )&0xff),
50 (int)(u8
)((a
)&0xff));
55 main_callback(int result
, char type
, int count
, int ttl
,
56 void *addrs
, void *orig
) {
57 char *n
= (char*)orig
;
59 for (i
= 0; i
< count
; ++i
) {
60 if (type
== DNS_IPv4_A
) {
61 printf("%s: %s\n", n
, debug_ntoa(((u32
*)addrs
)[i
]));
62 } else if (type
== DNS_PTR
) {
63 printf("%s: %s\n", n
, ((char**)addrs
)[i
]);
67 printf("%s: No answer (%d)\n", n
, result
);
73 gai_callback(int err
, struct evutil_addrinfo
*ai
, void *arg
)
75 const char *name
= arg
;
78 printf("%s: %s\n", name
, evutil_gai_strerror(err
));
80 if (ai
&& ai
->ai_canonname
)
81 printf(" %s ==> %s\n", name
, ai
->ai_canonname
);
82 for (i
=0; ai
; ai
= ai
->ai_next
, ++i
) {
84 if (ai
->ai_family
== PF_INET
) {
85 struct sockaddr_in
*sin
=
86 (struct sockaddr_in
*)ai
->ai_addr
;
87 evutil_inet_ntop(AF_INET
, &sin
->sin_addr
, buf
,
89 printf("[%d] %s: %s\n",i
,name
,buf
);
91 struct sockaddr_in6
*sin6
=
92 (struct sockaddr_in6
*)ai
->ai_addr
;
93 evutil_inet_ntop(AF_INET6
, &sin6
->sin6_addr
, buf
,
95 printf("[%d] %s: %s\n",i
,name
,buf
);
101 evdns_server_callback(struct evdns_server_request
*req
, void *data
)
105 /* dummy; give 192.168.11.11 as an answer for all A questions,
106 * give foo.bar.example.com as an answer for all PTR questions. */
107 for (i
= 0; i
< req
->nquestions
; ++i
) {
108 u32 ans
= htonl(0xc0a80b0bUL
);
109 if (req
->questions
[i
]->type
== EVDNS_TYPE_A
&&
110 req
->questions
[i
]->dns_question_class
== EVDNS_CLASS_INET
) {
111 printf(" -- replying for %s (A)\n", req
->questions
[i
]->name
);
112 r
= evdns_server_request_add_a_reply(req
, req
->questions
[i
]->name
,
115 printf("eeep, didn't work.\n");
116 } else if (req
->questions
[i
]->type
== EVDNS_TYPE_PTR
&&
117 req
->questions
[i
]->dns_question_class
== EVDNS_CLASS_INET
) {
118 printf(" -- replying for %s (PTR)\n", req
->questions
[i
]->name
);
119 r
= evdns_server_request_add_ptr_reply(req
, NULL
, req
->questions
[i
]->name
,
120 "foo.bar.example.com", 10);
122 printf("ugh, no luck");
124 printf(" -- skipping %s [%d %d]\n", req
->questions
[i
]->name
,
125 req
->questions
[i
]->type
, req
->questions
[i
]->dns_question_class
);
129 r
= evdns_server_request_respond(req
, 0);
131 printf("eeek, couldn't send reply.\n");
134 static int verbose
= 0;
137 logfn(int is_warn
, const char *msg
) {
138 if (!is_warn
&& !verbose
)
140 fprintf(stderr
, "%s: %s\n", is_warn
?"WARN":"INFO", msg
);
144 main(int c
, char **v
) {
146 int reverse
= 0, servertest
= 0, use_getaddrinfo
= 0;
147 struct event_base
*event_base
= NULL
;
148 struct evdns_base
*evdns_base
= NULL
;
149 const char *resolv_conf
= NULL
;
151 fprintf(stderr
, "syntax: %s [-x] [-v] [-c resolv.conf] hostname\n", v
[0]);
152 fprintf(stderr
, "syntax: %s [-servertest]\n", v
[0]);
156 while (idx
< c
&& v
[idx
][0] == '-') {
157 if (!strcmp(v
[idx
], "-x"))
159 else if (!strcmp(v
[idx
], "-v"))
161 else if (!strcmp(v
[idx
], "-g"))
163 else if (!strcmp(v
[idx
], "-servertest"))
165 else if (!strcmp(v
[idx
], "-c")) {
167 resolv_conf
= v
[++idx
];
169 fprintf(stderr
, "-c needs an argument\n");
171 fprintf(stderr
, "Unknown option %s\n", v
[idx
]);
178 WSAStartup(0x101, &WSAData
);
182 event_base
= event_base_new();
183 evdns_base
= evdns_base_new(event_base
, 0);
184 evdns_set_log_fn(logfn
);
187 evutil_socket_t sock
;
188 struct sockaddr_in my_addr
;
189 sock
= socket(PF_INET
, SOCK_DGRAM
, 0);
194 evutil_make_socket_nonblocking(sock
);
195 my_addr
.sin_family
= AF_INET
;
196 my_addr
.sin_port
= htons(10053);
197 my_addr
.sin_addr
.s_addr
= INADDR_ANY
;
198 if (bind(sock
, (struct sockaddr
*)&my_addr
, sizeof(my_addr
))<0) {
202 evdns_add_server_port_with_base(event_base
, sock
, 0, evdns_server_callback
, NULL
);
207 if (resolv_conf
== NULL
)
208 res
= evdns_base_config_windows_nameservers(evdns_base
);
211 res
= evdns_base_resolv_conf_parse(evdns_base
,
212 DNS_OPTION_NAMESERVERS
,
213 resolv_conf
? resolv_conf
: "/etc/resolv.conf");
216 fprintf(stderr
, "Couldn't configure nameservers");
221 printf("EVUTIL_AI_CANONNAME in example = %d\n", EVUTIL_AI_CANONNAME
);
222 for (; idx
< c
; ++idx
) {
225 if (evutil_inet_pton(AF_INET
, v
[idx
], &addr
)!=1) {
226 fprintf(stderr
, "Skipping non-IP %s\n", v
[idx
]);
229 fprintf(stderr
, "resolving %s...\n",v
[idx
]);
230 evdns_base_resolve_reverse(evdns_base
, &addr
, 0, main_callback
, v
[idx
]);
231 } else if (use_getaddrinfo
) {
232 struct evutil_addrinfo hints
;
233 memset(&hints
, 0, sizeof(hints
));
234 hints
.ai_family
= PF_UNSPEC
;
235 hints
.ai_protocol
= IPPROTO_TCP
;
236 hints
.ai_flags
= EVUTIL_AI_CANONNAME
;
237 fprintf(stderr
, "resolving (fwd) %s...\n",v
[idx
]);
238 evdns_getaddrinfo(evdns_base
, v
[idx
], NULL
, &hints
,
239 gai_callback
, v
[idx
]);
241 fprintf(stderr
, "resolving (fwd) %s...\n",v
[idx
]);
242 evdns_base_resolve_ipv4(evdns_base
, v
[idx
], 0, main_callback
, v
[idx
]);
246 event_base_dispatch(event_base
);