chiark / gitweb /
6334dad982c2cc8476fcd98912b0313f0ba14d34
[elogind.git] / src / libsystemd / sd-resolve / test-resolve.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   Copyright 2014 Daniel Buch
8
9   systemd is free software; you can redistribute it and/or modify it
10   under the terms of the GNU Lesser General Public License as published by
11   the Free Software Foundation; either version 2.1 of the License, or
12   (at your option) any later version.
13
14   systemd is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public License
20   along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 ***/
22
23 #include <string.h>
24 #include <sys/types.h>
25 #include <sys/socket.h>
26 #include <arpa/inet.h>
27 #include <stdio.h>
28 #include <netinet/in.h>
29 #include <arpa/nameser.h>
30 #include <resolv.h>
31 #include <assert.h>
32 #include <signal.h>
33 #include <errno.h>
34
35 #include "socket-util.h"
36 #include "sd-resolve.h"
37 #include "resolve-util.h"
38 #include "macro.h"
39
40 int main(int argc, char *argv[]) {
41         int r = 0;
42         _cleanup_resolve_unref_ sd_resolve *resolve = NULL;
43         _cleanup_resolve_addrinfo_free_ struct addrinfo *ai = NULL;
44         _cleanup_free_ unsigned char *srv = NULL;
45         _cleanup_free_ char *host = NULL, *serv = NULL;
46         sd_resolve_query *q1 = NULL, *q2 = NULL, *q3 = NULL;
47
48         struct addrinfo hints = {
49                 .ai_family = PF_UNSPEC,
50                 .ai_socktype = SOCK_STREAM,
51                 .ai_flags = AI_CANONNAME
52         };
53
54         struct sockaddr_in sa = {
55                 .sin_family = AF_INET,
56                 .sin_port = htons(80)
57         };
58
59         assert_se(sd_resolve_new(&resolve) >= 0);
60
61         /* Make a name -> address query */
62         r = sd_resolve_getaddrinfo(resolve, &q1, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints);
63         if (r < 0)
64                 log_error("sd_resolve_getaddrinfo(): %s\n", strerror(-r));
65
66         /* Make an address -> name query */
67         sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71"),
68         r = sd_resolve_getnameinfo(resolve, &q2, (struct sockaddr*) &sa, sizeof(sa), 0, true, true);
69         if (r < 0)
70                 log_error("sd_resolve_getnameinfo(): %s\n", strerror(-r));
71
72         /* Make a res_query() call */
73         r = sd_resolve_res_query(resolve, &q3, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV);
74         if (r < 0)
75                 log_error("sd_resolve_res_query(): %s\n", strerror(-r));
76
77         /* Wait until the three queries are completed */
78         while (sd_resolve_is_done(q1) == 0 ||
79                sd_resolve_is_done(q2) == 0 ||
80                sd_resolve_is_done(q3) == 0) {
81
82                 r = sd_resolve_wait(resolve, (uint64_t) -1);
83                 if (r < 0) {
84                         log_error("sd_resolve_wait(): %s\n", strerror(-r));
85                         assert_not_reached("sd_resolve_wait() failed");
86                 }
87         }
88
89         /* Interpret the result of the name -> addr query */
90         r = sd_resolve_getaddrinfo_done(q1, &ai);
91         if (r != 0)
92                 log_error("error: %s %i\n", gai_strerror(r), r);
93         else {
94                 struct addrinfo *i;
95
96                 for (i = ai; i; i = i->ai_next) {
97                         _cleanup_free_ char *addr = NULL;
98
99                         assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, &addr) == 0);
100
101                         puts(addr);
102                 }
103
104                 printf("canonical name: %s\n", strna(ai->ai_canonname));
105         }
106
107         /* Interpret the result of the addr -> name query */
108         r = sd_resolve_getnameinfo_done(q2, &host, &serv);
109         if (r)
110                 log_error("error: %s %i\n", gai_strerror(r), r);
111         else
112                 printf("Host: %s -- Serv: %s\n", host, serv);
113
114         /* Interpret the result of the SRV lookup */
115         r = sd_resolve_res_done(q3, &srv);
116         if (r < 0)
117                 log_error("error: %s %i\n", strerror(-r), r);
118         else if (r == 0)
119                 log_error("No reply for SRV lookup\n");
120         else {
121                 int qdcount, ancount, len;
122                 const unsigned char *pos = srv + sizeof(HEADER);
123                 unsigned char *end = srv + r;
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         return 0;
159 }