chiark / gitweb /
Rename more things to elogind
[elogind.git] / src / libelogind / 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/socket.h>
25 #include <arpa/inet.h>
26 #include <stdio.h>
27 #include <netinet/in.h>
28 #include <resolv.h>
29 #include <errno.h>
30
31 #include "socket-util.h"
32 #include "sd-resolve.h"
33 #include "resolve-util.h"
34 #include "macro.h"
35
36 static int getaddrinfo_handler(sd_resolve_query *q, int ret, const struct addrinfo *ai, void *userdata) {
37         const struct addrinfo *i;
38
39         assert_se(q);
40
41         if (ret != 0) {
42                 log_error("getaddrinfo error: %s %i", gai_strerror(ret), ret);
43                 return 0;
44         }
45
46         for (i = ai; i; i = i->ai_next) {
47                 _cleanup_free_ char *addr = NULL;
48
49                 assert_se(sockaddr_pretty(i->ai_addr, i->ai_addrlen, false, true, &addr) == 0);
50                 puts(addr);
51         }
52
53         printf("canonical name: %s\n", strna(ai->ai_canonname));
54
55         return 0;
56 }
57
58 static int getnameinfo_handler(sd_resolve_query *q, int ret, const char *host, const char *serv, void *userdata) {
59         assert_se(q);
60
61         if (ret != 0) {
62                 log_error("getnameinfo error: %s %i", gai_strerror(ret), ret);
63                 return 0;
64         }
65
66         printf("Host: %s -- Serv: %s\n", strna(host), strna(serv));
67         return 0;
68 }
69
70 static int res_handler(sd_resolve_query *q, int ret, unsigned char *answer, void *userdata) {
71         int qdcount, ancount, len;
72         const unsigned char *pos = answer + sizeof(HEADER);
73         unsigned char *end = answer + ret;
74         HEADER *head = (HEADER *) answer;
75         char name[256];
76         assert_se(q);
77
78         if (ret < 0) {
79                 log_error("res_query() error: %s %i", strerror(errno), errno);
80                 return 0;
81         }
82
83         if (ret == 0) {
84                 log_error("No reply for SRV lookup");
85                 return 0;
86         }
87
88         qdcount = ntohs(head->qdcount);
89         ancount = ntohs(head->ancount);
90
91         printf("%d answers for srv lookup:\n", ancount);
92
93         /* Ignore the questions */
94         while (qdcount-- > 0 && (len = dn_expand(answer, end, pos, name, 255)) >= 0) {
95                 assert_se(len >= 0);
96                 pos += len + QFIXEDSZ;
97         }
98
99         /* Parse the answers */
100         while (ancount-- > 0 && (len = dn_expand(answer, end, pos, name, 255)) >= 0) {
101                 /* Ignore the initial string */
102                 uint16_t pref, weight, port;
103                 assert_se(len >= 0);
104                 pos += len;
105                 /* Ignore type, ttl, class and dlen */
106                 pos += 10;
107
108                 GETSHORT(pref, pos);
109                 GETSHORT(weight, pos);
110                 GETSHORT(port, pos);
111                 len = dn_expand(answer, end, pos, name, 255);
112                 printf("\tpreference: %2d weight: %2d port: %d host: %s\n",
113                        pref, weight, port, name);
114
115                 pos += len;
116         }
117
118         return 0;
119 }
120
121 int main(int argc, char *argv[]) {
122         _cleanup_resolve_query_unref_ sd_resolve_query *q1 = NULL, *q2 = NULL, *q3 = NULL;
123         _cleanup_resolve_unref_ sd_resolve *resolve = NULL;
124         int r = 0;
125
126         struct addrinfo hints = {
127                 .ai_family = PF_UNSPEC,
128                 .ai_socktype = SOCK_STREAM,
129                 .ai_flags = AI_CANONNAME
130         };
131
132         struct sockaddr_in sa = {
133                 .sin_family = AF_INET,
134                 .sin_port = htons(80)
135         };
136
137         assert_se(sd_resolve_default(&resolve) >= 0);
138
139         /* Test a floating resolver query */
140         sd_resolve_getaddrinfo(resolve, NULL, "redhat.com", "http", NULL, getaddrinfo_handler, NULL);
141
142         /* Make a name -> address query */
143         r = sd_resolve_getaddrinfo(resolve, &q1, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints, getaddrinfo_handler, NULL);
144         if (r < 0)
145                 log_error_errno(r, "sd_resolve_getaddrinfo(): %m");
146
147         /* Make an address -> name query */
148         sa.sin_addr.s_addr = inet_addr(argc >= 3 ? argv[2] : "193.99.144.71");
149         r = sd_resolve_getnameinfo(resolve, &q2, (struct sockaddr*) &sa, sizeof(sa), 0, SD_RESOLVE_GET_BOTH, getnameinfo_handler, NULL);
150         if (r < 0)
151                 log_error_errno(r, "sd_resolve_getnameinfo(): %m");
152
153         /* Make a res_query() call */
154         r = sd_resolve_res_query(resolve, &q3, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV, res_handler, NULL);
155         if (r < 0)
156                 log_error_errno(r, "sd_resolve_res_query(): %m");
157
158         /* Wait until the three queries are completed */
159         while (sd_resolve_query_is_done(q1) == 0 ||
160                sd_resolve_query_is_done(q2) == 0 ||
161                sd_resolve_query_is_done(q3) == 0) {
162
163                 r = sd_resolve_wait(resolve, (uint64_t) -1);
164                 if (r < 0) {
165                         log_error_errno(r, "sd_resolve_wait(): %m");
166                         assert_not_reached("sd_resolve_wait() failed");
167                 }
168         }
169
170         return 0;
171 }