1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2005-2008 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <arpa/inet.h>
27 #include <netinet/in.h>
28 #include <arpa/nameser.h>
38 int main(int argc, char *argv[]) {
40 _cleanup_asyncns_free_ asyncns_t *asyncns = NULL;
41 _cleanup_asyncns_addrinfo_free_ struct addrinfo *ai = NULL;
42 _cleanup_asyncns_answer_free_ unsigned char *srv = NULL;
43 asyncns_query_t *q1, *q2, *q3;
44 struct addrinfo hints = {};
45 struct sockaddr_in sa = {};
46 char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = "";
48 signal(SIGCHLD, SIG_IGN);
50 asyncns = asyncns_new(2);
54 /* Make a name -> address query */
55 hints.ai_family = PF_UNSPEC;
56 hints.ai_socktype = SOCK_STREAM;
58 q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
60 fprintf(stderr, "asyncns_getaddrinfo(): %s\n", strerror(errno));
62 /* Make an address -> name query */
63 sa.sin_family = AF_INET;
64 sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
65 sa.sin_port = htons(80);
67 q2 = asyncns_getnameinfo(asyncns, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);
69 fprintf(stderr, "asyncns_getnameinfo(): %s\n", strerror(errno));
71 /* Make a res_query() call */
72 q3 = asyncns_res_query(asyncns, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);
74 fprintf(stderr, "asyncns_res_query(): %s\n", strerror(errno));
76 /* Wait until the three queries are completed */
77 while (!asyncns_isdone(asyncns, q1) ||
78 !asyncns_isdone(asyncns, q2) ||
79 !asyncns_isdone(asyncns, q3)) {
80 if (asyncns_wait(asyncns, 1) < 0)
81 fprintf(stderr, "asyncns_wait(): %s\n", strerror(errno));
84 /* Interpret the result of the name -> addr query */
85 ret = asyncns_getaddrinfo_done(asyncns, q1, &ai);
87 fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
91 for (i = ai; i; i = i->ai_next) {
95 if (i->ai_family == PF_INET)
96 p = inet_ntop(AF_INET, &((struct sockaddr_in*) i->ai_addr)->sin_addr, t, sizeof(t));
97 else if (i->ai_family == PF_INET6)
98 p = inet_ntop(AF_INET6, &((struct sockaddr_in6*) i->ai_addr)->sin6_addr, t, sizeof(t));
104 /* Interpret the result of the addr -> name query */
105 ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv));
107 fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
109 printf("%s -- %s\n", host, serv);
111 /* Interpret the result of the SRV lookup */
112 ret = asyncns_res_done(asyncns, q3, &srv);
114 fprintf(stderr, "error: %s %i\n", strerror(errno), ret);
115 } else if (ret == 0) {
116 fprintf(stderr, "No reply for SRV lookup\n");
121 const unsigned char *pos = srv + sizeof(HEADER);
122 unsigned char *end = srv + ret;
123 HEADER *head = (HEADER *)srv;
126 qdcount = ntohs(head->qdcount);
127 ancount = ntohs(head->ancount);
129 printf("%d answers for srv lookup:\n", ancount);
131 /* Ignore the questions */
132 while (qdcount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
134 pos += len + QFIXEDSZ;
137 /* Parse the answers */
138 while (ancount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
139 /* Ignore the initial string */
140 uint16_t pref, weight, port;
143 /* Ignore type, ttl, class and dlen */
147 GETSHORT(weight, pos);
149 len = dn_expand(srv, end, pos, name, 255);
150 printf("\tpreference: %2d weight: %2d port: %d host: %s\n",
151 pref, weight, port, name);