]>
Commit | Line | Data |
---|---|---|
edc6f2f5 TG |
1 | /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ |
2 | ||
e963e3ad | 3 | /*** |
edc6f2f5 | 4 | This file is part of systemd. |
e963e3ad DB |
5 | |
6 | Copyright 2005-2008 Lennart Poettering | |
7 | ||
edc6f2f5 TG |
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. | |
e963e3ad | 12 | |
edc6f2f5 | 13 | systemd is distributed in the hope that it will be useful, but |
e963e3ad DB |
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 | ||
edc6f2f5 TG |
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 | ***/ | |
e963e3ad | 21 | |
e963e3ad DB |
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 | ||
5681d7fb TG |
34 | #include "sd-resolv.h" |
35 | #include "resolv-util.h" | |
e963e3ad DB |
36 | #include "macro.h" |
37 | ||
38 | int main(int argc, char *argv[]) { | |
39 | int r = 1, ret; | |
12f404c4 | 40 | _cleanup_resolv_free_ sd_resolv_t *resolv = NULL; |
2a4be8ad DB |
41 | _cleanup_resolv_addrinfo_free_ struct addrinfo *ai = NULL; |
42 | _cleanup_resolv_answer_free_ unsigned char *srv = NULL; | |
43 | sd_resolv_query_t *q1, *q2, *q3; | |
e963e3ad DB |
44 | struct addrinfo hints = {}; |
45 | struct sockaddr_in sa = {}; | |
46 | char host[NI_MAXHOST] = "", serv[NI_MAXSERV] = ""; | |
47 | ||
48 | signal(SIGCHLD, SIG_IGN); | |
49 | ||
12f404c4 DB |
50 | resolv = sd_resolv_new(2); |
51 | if (!resolv) | |
e963e3ad DB |
52 | log_oom(); |
53 | ||
54 | /* Make a name -> address query */ | |
55 | hints.ai_family = PF_UNSPEC; | |
56 | hints.ai_socktype = SOCK_STREAM; | |
57 | ||
12f404c4 | 58 | q1 = sd_resolv_getaddrinfo(resolv, argc >= 2 ? argv[1] : "www.heise.de", NULL, &hints); |
e963e3ad | 59 | if (!q1) |
2a4be8ad | 60 | fprintf(stderr, "sd_resolv_getaddrinfo(): %s\n", strerror(errno)); |
e963e3ad DB |
61 | |
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); | |
66 | ||
12f404c4 | 67 | q2 = sd_resolv_getnameinfo(resolv, (struct sockaddr*) &sa, sizeof(sa), 0, 1, 1); |
e963e3ad | 68 | if (!q2) |
2a4be8ad | 69 | fprintf(stderr, "sd_resolv_getnameinfo(): %s\n", strerror(errno)); |
e963e3ad DB |
70 | |
71 | /* Make a res_query() call */ | |
12f404c4 | 72 | q3 = sd_resolv_res_query(resolv, "_xmpp-client._tcp.gmail.com", C_IN, T_SRV); |
e963e3ad | 73 | if (!q3) |
2a4be8ad | 74 | fprintf(stderr, "sd_resolv_res_query(): %s\n", strerror(errno)); |
e963e3ad DB |
75 | |
76 | /* Wait until the three queries are completed */ | |
12f404c4 DB |
77 | while (!sd_resolv_isdone(resolv, q1) || |
78 | !sd_resolv_isdone(resolv, q2) || | |
79 | !sd_resolv_isdone(resolv, q3)) { | |
80 | if (sd_resolv_wait(resolv, 1) < 0) | |
2a4be8ad | 81 | fprintf(stderr, "sd_resolv_wait(): %s\n", strerror(errno)); |
e963e3ad DB |
82 | } |
83 | ||
84 | /* Interpret the result of the name -> addr query */ | |
12f404c4 | 85 | ret = sd_resolv_getaddrinfo_done(resolv, q1, &ai); |
8e50b5a7 | 86 | if (ret) |
e963e3ad DB |
87 | fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret); |
88 | else { | |
89 | struct addrinfo *i; | |
90 | ||
91 | for (i = ai; i; i = i->ai_next) { | |
92 | char t[256]; | |
93 | const char *p = NULL; | |
94 | ||
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)); | |
99 | ||
100 | printf("%s\n", p); | |
101 | } | |
102 | } | |
103 | ||
104 | /* Interpret the result of the addr -> name query */ | |
12f404c4 | 105 | ret = sd_resolv_getnameinfo_done(resolv, q2, host, sizeof(host), serv, sizeof(serv)); |
8e50b5a7 | 106 | if (ret) |
e963e3ad DB |
107 | fprintf(stderr, "error: %s %i\n", gai_strerror(ret), ret); |
108 | else | |
109 | printf("%s -- %s\n", host, serv); | |
110 | ||
111 | /* Interpret the result of the SRV lookup */ | |
12f404c4 | 112 | ret = sd_resolv_res_done(resolv, q3, &srv); |
8e50b5a7 | 113 | if (ret < 0) { |
e963e3ad DB |
114 | fprintf(stderr, "error: %s %i\n", strerror(errno), ret); |
115 | } else if (ret == 0) { | |
116 | fprintf(stderr, "No reply for SRV lookup\n"); | |
117 | } else { | |
118 | int qdcount; | |
119 | int ancount; | |
120 | int len; | |
121 | const unsigned char *pos = srv + sizeof(HEADER); | |
122 | unsigned char *end = srv + ret; | |
123 | HEADER *head = (HEADER *)srv; | |
124 | char name[256]; | |
125 | ||
126 | qdcount = ntohs(head->qdcount); | |
127 | ancount = ntohs(head->ancount); | |
128 | ||
129 | printf("%d answers for srv lookup:\n", ancount); | |
130 | ||
131 | /* Ignore the questions */ | |
132 | while (qdcount-- > 0 && (len = dn_expand(srv, end, pos, name, 255)) >= 0) { | |
133 | assert(len >= 0); | |
134 | pos += len + QFIXEDSZ; | |
135 | } | |
136 | ||
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; | |
141 | assert(len >= 0); | |
142 | pos += len; | |
143 | /* Ignore type, ttl, class and dlen */ | |
144 | pos += 10; | |
145 | ||
146 | GETSHORT(pref, pos); | |
147 | GETSHORT(weight, pos); | |
148 | GETSHORT(port, 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); | |
152 | ||
153 | pos += len; | |
154 | } | |
155 | } | |
156 | ||
157 | r = 0; | |
158 | ||
159 | return r; | |
160 | } |