chiark / gitweb /
gpt-auto-generator: skip nonexistent devices
[elogind.git] / src / libsystemd-bus / test-dns.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2005-2008 Lennart Poettering
7
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.
12
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.
17
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/>.
20 ***/
21
22 #include <string.h>
23 #include <sys/types.h>
24 #include <sys/socket.h>
25 #include <arpa/inet.h>
26 #include <stdio.h>
27 #include <netinet/in.h>
28 #include <arpa/nameser.h>
29 #include <resolv.h>
30 #include <assert.h>
31 #include <signal.h>
32 #include <errno.h>
33
34 #include "sd-dns.h"
35 #include "dns-util.h"
36 #include "macro.h"
37
38 int main(int argc, char *argv[]) {
39         int r = 1, ret;
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] = "";
47
48         signal(SIGCHLD, SIG_IGN);
49
50         asyncns = asyncns_new(2);
51         if (!asyncns)
52                 log_oom();
53
54         /* Make a name -> address query */
55         hints.ai_family = PF_UNSPEC;
56         hints.ai_socktype = SOCK_STREAM;
57
58         q1 = asyncns_getaddrinfo(asyncns, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
59
60         if (!q1)
61                 fprintf(stderr, "asyncns_getaddrinfo(): %s\n", strerror(errno));
62
63         /* Make an address -> name query */
64         sa.sin_family = AF_INET;
65         sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
66         sa.sin_port = htons(80);
67
68         q2 = asyncns_getnameinfo(asyncns, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1);
69
70         if (!q2)
71                 fprintf(stderr, "asyncns_getnameinfo(): %s\n", strerror(errno));
72
73         /* Make a res_query() call */
74         q3 = asyncns_res_query(asyncns, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);
75
76         if (!q3)
77                 fprintf(stderr, "asyncns_res_query(): %s\n", strerror(errno));
78
79         /* Wait until the three queries are completed */
80         while (!asyncns_isdone(asyncns, q1)
81                         || !asyncns_isdone(asyncns, q2)
82                         || !asyncns_isdone(asyncns, q3)) {
83                 if (asyncns_wait(asyncns, 1) < 0) {
84                         fprintf(stderr, "asyncns_wait(): %s\n", strerror(errno));
85                 }
86         }
87
88         /* Interpret the result of the name -> addr query */
89         if ((ret = asyncns_getaddrinfo_done(asyncns, q1, &ai)))
90                 fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
91         else {
92                 struct addrinfo *i;
93
94                 for (i = ai; i; i = i->ai_next) {
95                         char t[256];
96                         const char *p = NULL;
97
98                         if (i->ai_family == PF_INET)
99                                 p = inet_ntop(AF_INET, &((struct sockaddr_in*) i->ai_addr)->sin_addr, t, sizeof(t));
100                         else if (i->ai_family == PF_INET6)
101                                 p = inet_ntop(AF_INET6, &((struct sockaddr_in6*) i->ai_addr)->sin6_addr, t, sizeof(t));
102
103                         printf("%s\n", p);
104                 }
105         }
106
107         /* Interpret the result of the addr -> name query */
108         if ((ret = asyncns_getnameinfo_done(asyncns, q2, host, sizeof(host), serv, sizeof(serv))))
109                 fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret);
110         else
111                 printf("%s -- %s\n", host, serv);
112
113         /* Interpret the result of the SRV lookup */
114         if ((ret = asyncns_res_done(asyncns, q3, &srv)) < 0) {
115                 fprintf(stderr, "error: %s %i\n", strerror(errno), ret);
116         } else if (ret == 0) {
117                 fprintf(stderr, "No reply for SRV lookup\n");
118         } else {
119                 int qdcount;
120                 int ancount;
121                 int len;
122                 const unsigned char *pos = srv + sizeof(HEADER);
123                 unsigned char *end = srv + ret;
124                 HEADER *head = (HEADER *)srv;
125                 char name[256];
126
127                 qdcount = ntohs(head->qdcount);
128                 ancount = ntohs(head->ancount);
129
130                 printf("%d answers for srv lookup:\n", ancount);
131
132                 /* Ignore the questions */
133                 while (qdcount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
134                         assert(len >= 0);
135                         pos += len + QFIXEDSZ;
136                 }
137
138                 /* Parse the answers */
139                 while (ancount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) {
140                         /* Ignore the initial string */
141                         uint16_t pref, weight, port;
142                         assert(len >= 0);
143                         pos += len;
144                         /* Ignore type, ttl, class and dlen */
145                         pos += 10;
146
147                         GETSHORT(pref, pos);
148                         GETSHORT(weight, pos);
149                         GETSHORT(port, pos);
150                         len = dn_expand(srv, end, pos, name, 255);
151                         printf("\tpreference: %2d weight: %2d port: %d host: %s\n",
152                                         pref, weight, port, name);
153
154                         pos += len;
155                 }
156         }
157
158         r = 0;
159
160         return r;
161 }