xref: /qemu/include/io/dns-resolver.h (revision 9af2398977a78d37bf184d6ff6bd04c72bfbf006)
1c1b412f1SDaniel P. Berrange /*
2c1b412f1SDaniel P. Berrange  * QEMU DNS resolver
3c1b412f1SDaniel P. Berrange  *
4c1b412f1SDaniel P. Berrange  * Copyright (c) 2016-2017 Red Hat, Inc.
5c1b412f1SDaniel P. Berrange  *
6c1b412f1SDaniel P. Berrange  * This library is free software; you can redistribute it and/or
7c1b412f1SDaniel P. Berrange  * modify it under the terms of the GNU Lesser General Public
8c1b412f1SDaniel P. Berrange  * License as published by the Free Software Foundation; either
9c1b412f1SDaniel P. Berrange  * version 2 of the License, or (at your option) any later version.
10c1b412f1SDaniel P. Berrange  *
11c1b412f1SDaniel P. Berrange  * This library is distributed in the hope that it will be useful,
12c1b412f1SDaniel P. Berrange  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13c1b412f1SDaniel P. Berrange  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14c1b412f1SDaniel P. Berrange  * Lesser General Public License for more details.
15c1b412f1SDaniel P. Berrange  *
16c1b412f1SDaniel P. Berrange  * You should have received a copy of the GNU Lesser General Public
17c1b412f1SDaniel P. Berrange  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18c1b412f1SDaniel P. Berrange  *
19c1b412f1SDaniel P. Berrange  */
20c1b412f1SDaniel P. Berrange 
21c1b412f1SDaniel P. Berrange #ifndef QIO_DNS_RESOLVER_H
22c1b412f1SDaniel P. Berrange #define QIO_DNS_RESOLVER_H
23c1b412f1SDaniel P. Berrange 
24c1b412f1SDaniel P. Berrange #include "qemu-common.h"
25*9af23989SMarkus Armbruster #include "qapi/qapi-types-sockets.h"
26c1b412f1SDaniel P. Berrange #include "qom/object.h"
27c1b412f1SDaniel P. Berrange #include "io/task.h"
28c1b412f1SDaniel P. Berrange 
29c1b412f1SDaniel P. Berrange #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
30c1b412f1SDaniel P. Berrange #define QIO_DNS_RESOLVER(obj)                                    \
31c1b412f1SDaniel P. Berrange     OBJECT_CHECK(QIODNSResolver, (obj), TYPE_QIO_DNS_RESOLVER)
32c1b412f1SDaniel P. Berrange #define QIO_DNS_RESOLVER_CLASS(klass)                                    \
33c1b412f1SDaniel P. Berrange     OBJECT_CLASS_CHECK(QIODNSResolverClass, klass, TYPE_QIO_DNS_RESOLVER)
34c1b412f1SDaniel P. Berrange #define QIO_DNS_RESOLVER_GET_CLASS(obj)                                  \
35c1b412f1SDaniel P. Berrange     OBJECT_GET_CLASS(QIODNSResolverClass, obj, TYPE_QIO_DNS_RESOLVER)
36c1b412f1SDaniel P. Berrange 
37c1b412f1SDaniel P. Berrange typedef struct QIODNSResolver QIODNSResolver;
38c1b412f1SDaniel P. Berrange typedef struct QIODNSResolverClass QIODNSResolverClass;
39c1b412f1SDaniel P. Berrange 
40c1b412f1SDaniel P. Berrange /**
41c1b412f1SDaniel P. Berrange  * QIODNSResolver:
42c1b412f1SDaniel P. Berrange  *
43c1b412f1SDaniel P. Berrange  * The QIODNSResolver class provides a framework for doing
44c1b412f1SDaniel P. Berrange  * DNS resolution on SocketAddress objects, independently
45c1b412f1SDaniel P. Berrange  * of socket creation.
46c1b412f1SDaniel P. Berrange  *
47c1b412f1SDaniel P. Berrange  * <example>
48c1b412f1SDaniel P. Berrange  *   <title>Resolving addresses synchronously</title>
49c1b412f1SDaniel P. Berrange  *   <programlisting>
50c1b412f1SDaniel P. Berrange  *    int mylisten(SocketAddress *addr, Error **errp) {
51c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver = qio_dns_resolver_get_instance();
52c1b412f1SDaniel P. Berrange  *      SocketAddress **rawaddrs = NULL;
53c1b412f1SDaniel P. Berrange  *      size_t nrawaddrs = 0;
54c1b412f1SDaniel P. Berrange  *      Error *err = NULL;
55c1b412f1SDaniel P. Berrange  *      QIOChannel **socks = NULL;
56c1b412f1SDaniel P. Berrange  *      size_t nsocks = 0;
57c1b412f1SDaniel P. Berrange  *
58c1b412f1SDaniel P. Berrange  *      if (qio_dns_resolver_lookup_sync(dns, addr, &nrawaddrs,
59c1b412f1SDaniel P. Berrange  *                                       &rawaddrs, errp) < 0) {
60c1b412f1SDaniel P. Berrange  *          return -1;
61c1b412f1SDaniel P. Berrange  *      }
62c1b412f1SDaniel P. Berrange  *
63c1b412f1SDaniel P. Berrange  *      for (i = 0; i < nrawaddrs; i++) {
64c1b412f1SDaniel P. Berrange  *         QIOChannel *sock = qio_channel_new();
65c1b412f1SDaniel P. Berrange  *         Error *local_err = NULL;
66c1b412f1SDaniel P. Berrange  *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
67c1b412f1SDaniel P. Berrange  *         if (local_err) {
68c1b412f1SDaniel P. Berrange  *            error_propagate(&err, local_err);
69c1b412f1SDaniel P. Berrange  *         } else {
70c1b412f1SDaniel P. Berrange  *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
71c1b412f1SDaniel P. Berrange  *            socks[nsocks++] = sock;
72c1b412f1SDaniel P. Berrange  *         }
73c1b412f1SDaniel P. Berrange  *         qapi_free_SocketAddress(rawaddrs[i]);
74c1b412f1SDaniel P. Berrange  *      }
75c1b412f1SDaniel P. Berrange  *      g_free(rawaddrs);
76c1b412f1SDaniel P. Berrange  *
77c1b412f1SDaniel P. Berrange  *      if (nsocks == 0) {
78c1b412f1SDaniel P. Berrange  *         error_propagate(errp, err);
79c1b412f1SDaniel P. Berrange  *      } else {
80c1b412f1SDaniel P. Berrange  *         error_free(err);
81c1b412f1SDaniel P. Berrange  *      }
82c1b412f1SDaniel P. Berrange  *   }
83c1b412f1SDaniel P. Berrange  *   </programlisting>
84c1b412f1SDaniel P. Berrange  * </example>
85c1b412f1SDaniel P. Berrange  *
86c1b412f1SDaniel P. Berrange  * <example>
87c1b412f1SDaniel P. Berrange  *   <title>Resolving addresses asynchronously</title>
88c1b412f1SDaniel P. Berrange  *   <programlisting>
89c1b412f1SDaniel P. Berrange  *    typedef struct MyListenData {
90c1b412f1SDaniel P. Berrange  *       Error *err;
91c1b412f1SDaniel P. Berrange  *       QIOChannelSocket **socks;
92c1b412f1SDaniel P. Berrange  *       size_t nsocks;
93c1b412f1SDaniel P. Berrange  *    } MyListenData;
94c1b412f1SDaniel P. Berrange  *
95c1b412f1SDaniel P. Berrange  *    void mylistenresult(QIOTask *task, void *opaque) {
96c1b412f1SDaniel P. Berrange  *      MyListenData *data = opaque;
97c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver =
98c1b412f1SDaniel P. Berrange  *         QIO_DNS_RESOLVER(qio_task_get_source(task);
99c1b412f1SDaniel P. Berrange  *      SocketAddress **rawaddrs = NULL;
100c1b412f1SDaniel P. Berrange  *      size_t nrawaddrs = 0;
101c1b412f1SDaniel P. Berrange  *      Error *err = NULL;
102c1b412f1SDaniel P. Berrange  *
103c1b412f1SDaniel P. Berrange  *      if (qio_task_propagate_error(task, &data->err)) {
104c1b412f1SDaniel P. Berrange  *         return;
105c1b412f1SDaniel P. Berrange  *      }
106c1b412f1SDaniel P. Berrange  *
107c1b412f1SDaniel P. Berrange  *      qio_dns_resolver_lookup_result(resolver, task,
108c1b412f1SDaniel P. Berrange  *                                     &nrawaddrs, &rawaddrs);
109c1b412f1SDaniel P. Berrange  *
110c1b412f1SDaniel P. Berrange  *      for (i = 0; i < nrawaddrs; i++) {
111c1b412f1SDaniel P. Berrange  *         QIOChannel *sock = qio_channel_new();
112c1b412f1SDaniel P. Berrange  *         Error *local_err = NULL;
113c1b412f1SDaniel P. Berrange  *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
114c1b412f1SDaniel P. Berrange  *         if (local_err) {
115c1b412f1SDaniel P. Berrange  *            error_propagate(&err, local_err);
116c1b412f1SDaniel P. Berrange  *         } else {
117c1b412f1SDaniel P. Berrange  *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
118c1b412f1SDaniel P. Berrange  *            socks[nsocks++] = sock;
119c1b412f1SDaniel P. Berrange  *         }
120c1b412f1SDaniel P. Berrange  *         qapi_free_SocketAddress(rawaddrs[i]);
121c1b412f1SDaniel P. Berrange  *      }
122c1b412f1SDaniel P. Berrange  *      g_free(rawaddrs);
123c1b412f1SDaniel P. Berrange  *
124c1b412f1SDaniel P. Berrange  *      if (nsocks == 0) {
125c1b412f1SDaniel P. Berrange  *         error_propagate(&data->err, err);
126c1b412f1SDaniel P. Berrange  *      } else {
127c1b412f1SDaniel P. Berrange  *         error_free(err);
128c1b412f1SDaniel P. Berrange  *      }
129c1b412f1SDaniel P. Berrange  *    }
130c1b412f1SDaniel P. Berrange  *
131c1b412f1SDaniel P. Berrange  *    void mylisten(SocketAddress *addr, MyListenData *data) {
132c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver = qio_dns_resolver_get_instance();
133c1b412f1SDaniel P. Berrange  *      qio_dns_resolver_lookup_async(dns, addr,
134c1b412f1SDaniel P. Berrange  *                                    mylistenresult, data, NULL);
135c1b412f1SDaniel P. Berrange  *    }
136c1b412f1SDaniel P. Berrange  *   </programlisting>
137c1b412f1SDaniel P. Berrange  * </example>
138c1b412f1SDaniel P. Berrange  */
139c1b412f1SDaniel P. Berrange struct QIODNSResolver {
140c1b412f1SDaniel P. Berrange     Object parent;
141c1b412f1SDaniel P. Berrange };
142c1b412f1SDaniel P. Berrange 
143c1b412f1SDaniel P. Berrange struct QIODNSResolverClass {
144c1b412f1SDaniel P. Berrange     ObjectClass parent;
145c1b412f1SDaniel P. Berrange };
146c1b412f1SDaniel P. Berrange 
147c1b412f1SDaniel P. Berrange 
148c1b412f1SDaniel P. Berrange /**
149c1b412f1SDaniel P. Berrange  * qio_dns_resolver_get_instance:
150c1b412f1SDaniel P. Berrange  *
151c1b412f1SDaniel P. Berrange  * Get the singleton dns resolver instance. The caller
152c1b412f1SDaniel P. Berrange  * does not own a reference on the returned object.
153c1b412f1SDaniel P. Berrange  *
154c1b412f1SDaniel P. Berrange  * Returns: the single dns resolver instance
155c1b412f1SDaniel P. Berrange  */
156c1b412f1SDaniel P. Berrange QIODNSResolver *qio_dns_resolver_get_instance(void);
157c1b412f1SDaniel P. Berrange 
158c1b412f1SDaniel P. Berrange /**
159c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_sync:
160c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
161c1b412f1SDaniel P. Berrange  * @addr: the address to resolve
162c1b412f1SDaniel P. Berrange  * @naddr: pointer to hold number of resolved addresses
163c1b412f1SDaniel P. Berrange  * @addrs: pointer to hold resolved addresses
164c1b412f1SDaniel P. Berrange  * @errp: pointer to NULL initialized error object
165c1b412f1SDaniel P. Berrange  *
166c1b412f1SDaniel P. Berrange  * This will attempt to resolve the address provided
167c1b412f1SDaniel P. Berrange  * in @addr. If resolution succeeds, @addrs will be filled
168c1b412f1SDaniel P. Berrange  * with all the resolved addresses. @naddrs will specify
169c1b412f1SDaniel P. Berrange  * the number of entries allocated in @addrs. The caller
170c1b412f1SDaniel P. Berrange  * is responsible for freeing each entry in @addrs, as
171c1b412f1SDaniel P. Berrange  * well as @addrs itself. @naddrs is guaranteed to be
172c1b412f1SDaniel P. Berrange  * greater than zero on success.
173c1b412f1SDaniel P. Berrange  *
174c1b412f1SDaniel P. Berrange  * DNS resolution will be done synchronously so execution
175c1b412f1SDaniel P. Berrange  * of the caller may be blocked for an arbitrary length
176c1b412f1SDaniel P. Berrange  * of time.
177c1b412f1SDaniel P. Berrange  *
178c1b412f1SDaniel P. Berrange  * Returns: 0 if resolution was successful, -1 on error
179c1b412f1SDaniel P. Berrange  */
180c1b412f1SDaniel P. Berrange int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver,
181c1b412f1SDaniel P. Berrange                                  SocketAddress *addr,
182c1b412f1SDaniel P. Berrange                                  size_t *naddrs,
183c1b412f1SDaniel P. Berrange                                  SocketAddress ***addrs,
184c1b412f1SDaniel P. Berrange                                  Error **errp);
185c1b412f1SDaniel P. Berrange 
186c1b412f1SDaniel P. Berrange /**
187c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_async:
188c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
189c1b412f1SDaniel P. Berrange  * @addr: the address to resolve
190c1b412f1SDaniel P. Berrange  * @func: the callback to invoke on lookup completion
191c1b412f1SDaniel P. Berrange  * @opaque: data blob to pass to @func
192c1b412f1SDaniel P. Berrange  * @notify: the callback to free @opaque, or NULL
193c1b412f1SDaniel P. Berrange  *
194c1b412f1SDaniel P. Berrange  * This will attempt to resolve the address provided
195c1b412f1SDaniel P. Berrange  * in @addr. The callback @func will be invoked when
196c1b412f1SDaniel P. Berrange  * resolution has either completed or failed. On
197c1b412f1SDaniel P. Berrange  * success, the @func should call the method
198c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_result() to obtain the
199c1b412f1SDaniel P. Berrange  * results.
200c1b412f1SDaniel P. Berrange  *
201c1b412f1SDaniel P. Berrange  * DNS resolution will be done asynchronously so execution
202c1b412f1SDaniel P. Berrange  * of the caller will not be blocked.
203c1b412f1SDaniel P. Berrange  */
204c1b412f1SDaniel P. Berrange void qio_dns_resolver_lookup_async(QIODNSResolver *resolver,
205c1b412f1SDaniel P. Berrange                                    SocketAddress *addr,
206c1b412f1SDaniel P. Berrange                                    QIOTaskFunc func,
207c1b412f1SDaniel P. Berrange                                    gpointer opaque,
208c1b412f1SDaniel P. Berrange                                    GDestroyNotify notify);
209c1b412f1SDaniel P. Berrange 
210c1b412f1SDaniel P. Berrange /**
211c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_result:
212c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
213c1b412f1SDaniel P. Berrange  * @task: the task object to get results for
214c1b412f1SDaniel P. Berrange  * @naddr: pointer to hold number of resolved addresses
215c1b412f1SDaniel P. Berrange  * @addrs: pointer to hold resolved addresses
216c1b412f1SDaniel P. Berrange  *
217c1b412f1SDaniel P. Berrange  * This method should be called from the callback passed
218c1b412f1SDaniel P. Berrange  * to qio_dns_resolver_lookup_async() in order to obtain
219c1b412f1SDaniel P. Berrange  * results.  @addrs will be filled with all the resolved
220c1b412f1SDaniel P. Berrange  * addresses. @naddrs will specify the number of entries
221c1b412f1SDaniel P. Berrange  * allocated in @addrs. The caller is responsible for
222c1b412f1SDaniel P. Berrange  * freeing each entry in @addrs, as well as @addrs itself.
223c1b412f1SDaniel P. Berrange  */
224c1b412f1SDaniel P. Berrange void qio_dns_resolver_lookup_result(QIODNSResolver *resolver,
225c1b412f1SDaniel P. Berrange                                     QIOTask *task,
226c1b412f1SDaniel P. Berrange                                     size_t *naddrs,
227c1b412f1SDaniel P. Berrange                                     SocketAddress ***addrs);
228c1b412f1SDaniel P. Berrange 
229c1b412f1SDaniel P. Berrange #endif /* QIO_DNS_RESOLVER_H */
230