xref: /qemu/include/io/dns-resolver.h (revision 9a2ea4f4a7230fe224dee91d9adf2ef872c3d226)
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
9*c8198bd5SChetan Pant  * version 2.1 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 
249af23989SMarkus Armbruster #include "qapi/qapi-types-sockets.h"
25c1b412f1SDaniel P. Berrange #include "qom/object.h"
26c1b412f1SDaniel P. Berrange #include "io/task.h"
27c1b412f1SDaniel P. Berrange 
28c1b412f1SDaniel P. Berrange #define TYPE_QIO_DNS_RESOLVER "qio-dns-resolver"
2930b5707cSEduardo Habkost OBJECT_DECLARE_SIMPLE_TYPE(QIODNSResolver,
30c734cd40SEduardo Habkost                            QIO_DNS_RESOLVER)
31c1b412f1SDaniel P. Berrange 
32c1b412f1SDaniel P. Berrange 
33c1b412f1SDaniel P. Berrange /**
34c1b412f1SDaniel P. Berrange  * QIODNSResolver:
35c1b412f1SDaniel P. Berrange  *
36c1b412f1SDaniel P. Berrange  * The QIODNSResolver class provides a framework for doing
37c1b412f1SDaniel P. Berrange  * DNS resolution on SocketAddress objects, independently
38c1b412f1SDaniel P. Berrange  * of socket creation.
39c1b412f1SDaniel P. Berrange  *
40c1b412f1SDaniel P. Berrange  * <example>
41c1b412f1SDaniel P. Berrange  *   <title>Resolving addresses synchronously</title>
42c1b412f1SDaniel P. Berrange  *   <programlisting>
43c1b412f1SDaniel P. Berrange  *    int mylisten(SocketAddress *addr, Error **errp) {
44c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver = qio_dns_resolver_get_instance();
45c1b412f1SDaniel P. Berrange  *      SocketAddress **rawaddrs = NULL;
46c1b412f1SDaniel P. Berrange  *      size_t nrawaddrs = 0;
47c1b412f1SDaniel P. Berrange  *      Error *err = NULL;
48c1b412f1SDaniel P. Berrange  *      QIOChannel **socks = NULL;
49c1b412f1SDaniel P. Berrange  *      size_t nsocks = 0;
50c1b412f1SDaniel P. Berrange  *
51c1b412f1SDaniel P. Berrange  *      if (qio_dns_resolver_lookup_sync(dns, addr, &nrawaddrs,
52c1b412f1SDaniel P. Berrange  *                                       &rawaddrs, errp) < 0) {
53c1b412f1SDaniel P. Berrange  *          return -1;
54c1b412f1SDaniel P. Berrange  *      }
55c1b412f1SDaniel P. Berrange  *
56c1b412f1SDaniel P. Berrange  *      for (i = 0; i < nrawaddrs; i++) {
57c1b412f1SDaniel P. Berrange  *         QIOChannel *sock = qio_channel_new();
58c1b412f1SDaniel P. Berrange  *         Error *local_err = NULL;
59c1b412f1SDaniel P. Berrange  *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
60c1b412f1SDaniel P. Berrange  *         if (local_err) {
61c1b412f1SDaniel P. Berrange  *            error_propagate(&err, local_err);
62c1b412f1SDaniel P. Berrange  *         } else {
63c1b412f1SDaniel P. Berrange  *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
64c1b412f1SDaniel P. Berrange  *            socks[nsocks++] = sock;
65c1b412f1SDaniel P. Berrange  *         }
66c1b412f1SDaniel P. Berrange  *         qapi_free_SocketAddress(rawaddrs[i]);
67c1b412f1SDaniel P. Berrange  *      }
68c1b412f1SDaniel P. Berrange  *      g_free(rawaddrs);
69c1b412f1SDaniel P. Berrange  *
70c1b412f1SDaniel P. Berrange  *      if (nsocks == 0) {
71c1b412f1SDaniel P. Berrange  *         error_propagate(errp, err);
72c1b412f1SDaniel P. Berrange  *      } else {
73c1b412f1SDaniel P. Berrange  *         error_free(err);
74c1b412f1SDaniel P. Berrange  *      }
75c1b412f1SDaniel P. Berrange  *   }
76c1b412f1SDaniel P. Berrange  *   </programlisting>
77c1b412f1SDaniel P. Berrange  * </example>
78c1b412f1SDaniel P. Berrange  *
79c1b412f1SDaniel P. Berrange  * <example>
80c1b412f1SDaniel P. Berrange  *   <title>Resolving addresses asynchronously</title>
81c1b412f1SDaniel P. Berrange  *   <programlisting>
82c1b412f1SDaniel P. Berrange  *    typedef struct MyListenData {
83c1b412f1SDaniel P. Berrange  *       Error *err;
84c1b412f1SDaniel P. Berrange  *       QIOChannelSocket **socks;
85c1b412f1SDaniel P. Berrange  *       size_t nsocks;
86c1b412f1SDaniel P. Berrange  *    } MyListenData;
87c1b412f1SDaniel P. Berrange  *
88c1b412f1SDaniel P. Berrange  *    void mylistenresult(QIOTask *task, void *opaque) {
89c1b412f1SDaniel P. Berrange  *      MyListenData *data = opaque;
90c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver =
91c1b412f1SDaniel P. Berrange  *         QIO_DNS_RESOLVER(qio_task_get_source(task);
92c1b412f1SDaniel P. Berrange  *      SocketAddress **rawaddrs = NULL;
93c1b412f1SDaniel P. Berrange  *      size_t nrawaddrs = 0;
94c1b412f1SDaniel P. Berrange  *      Error *err = NULL;
95c1b412f1SDaniel P. Berrange  *
96c1b412f1SDaniel P. Berrange  *      if (qio_task_propagate_error(task, &data->err)) {
97c1b412f1SDaniel P. Berrange  *         return;
98c1b412f1SDaniel P. Berrange  *      }
99c1b412f1SDaniel P. Berrange  *
100c1b412f1SDaniel P. Berrange  *      qio_dns_resolver_lookup_result(resolver, task,
101c1b412f1SDaniel P. Berrange  *                                     &nrawaddrs, &rawaddrs);
102c1b412f1SDaniel P. Berrange  *
103c1b412f1SDaniel P. Berrange  *      for (i = 0; i < nrawaddrs; i++) {
104c1b412f1SDaniel P. Berrange  *         QIOChannel *sock = qio_channel_new();
105c1b412f1SDaniel P. Berrange  *         Error *local_err = NULL;
106c1b412f1SDaniel P. Berrange  *         qio_channel_listen_sync(sock, rawaddrs[i], &local_err);
107c1b412f1SDaniel P. Berrange  *         if (local_err) {
108c1b412f1SDaniel P. Berrange  *            error_propagate(&err, local_err);
109c1b412f1SDaniel P. Berrange  *         } else {
110c1b412f1SDaniel P. Berrange  *            socks = g_renew(QIOChannelSocket *, socks, nsocks + 1);
111c1b412f1SDaniel P. Berrange  *            socks[nsocks++] = sock;
112c1b412f1SDaniel P. Berrange  *         }
113c1b412f1SDaniel P. Berrange  *         qapi_free_SocketAddress(rawaddrs[i]);
114c1b412f1SDaniel P. Berrange  *      }
115c1b412f1SDaniel P. Berrange  *      g_free(rawaddrs);
116c1b412f1SDaniel P. Berrange  *
117c1b412f1SDaniel P. Berrange  *      if (nsocks == 0) {
118c1b412f1SDaniel P. Berrange  *         error_propagate(&data->err, err);
119c1b412f1SDaniel P. Berrange  *      } else {
120c1b412f1SDaniel P. Berrange  *         error_free(err);
121c1b412f1SDaniel P. Berrange  *      }
122c1b412f1SDaniel P. Berrange  *    }
123c1b412f1SDaniel P. Berrange  *
124c1b412f1SDaniel P. Berrange  *    void mylisten(SocketAddress *addr, MyListenData *data) {
125c1b412f1SDaniel P. Berrange  *      QIODNSResolver *resolver = qio_dns_resolver_get_instance();
126c1b412f1SDaniel P. Berrange  *      qio_dns_resolver_lookup_async(dns, addr,
127c1b412f1SDaniel P. Berrange  *                                    mylistenresult, data, NULL);
128c1b412f1SDaniel P. Berrange  *    }
129c1b412f1SDaniel P. Berrange  *   </programlisting>
130c1b412f1SDaniel P. Berrange  * </example>
131c1b412f1SDaniel P. Berrange  */
132c1b412f1SDaniel P. Berrange struct QIODNSResolver {
133c1b412f1SDaniel P. Berrange     Object parent;
134c1b412f1SDaniel P. Berrange };
135c1b412f1SDaniel P. Berrange 
136c1b412f1SDaniel P. Berrange 
137c1b412f1SDaniel P. Berrange 
138c1b412f1SDaniel P. Berrange /**
139c1b412f1SDaniel P. Berrange  * qio_dns_resolver_get_instance:
140c1b412f1SDaniel P. Berrange  *
141c1b412f1SDaniel P. Berrange  * Get the singleton dns resolver instance. The caller
142c1b412f1SDaniel P. Berrange  * does not own a reference on the returned object.
143c1b412f1SDaniel P. Berrange  *
144c1b412f1SDaniel P. Berrange  * Returns: the single dns resolver instance
145c1b412f1SDaniel P. Berrange  */
146c1b412f1SDaniel P. Berrange QIODNSResolver *qio_dns_resolver_get_instance(void);
147c1b412f1SDaniel P. Berrange 
148c1b412f1SDaniel P. Berrange /**
149c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_sync:
150c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
151c1b412f1SDaniel P. Berrange  * @addr: the address to resolve
152c1b412f1SDaniel P. Berrange  * @naddr: pointer to hold number of resolved addresses
153c1b412f1SDaniel P. Berrange  * @addrs: pointer to hold resolved addresses
154c1b412f1SDaniel P. Berrange  * @errp: pointer to NULL initialized error object
155c1b412f1SDaniel P. Berrange  *
156c1b412f1SDaniel P. Berrange  * This will attempt to resolve the address provided
157c1b412f1SDaniel P. Berrange  * in @addr. If resolution succeeds, @addrs will be filled
158c1b412f1SDaniel P. Berrange  * with all the resolved addresses. @naddrs will specify
159c1b412f1SDaniel P. Berrange  * the number of entries allocated in @addrs. The caller
160c1b412f1SDaniel P. Berrange  * is responsible for freeing each entry in @addrs, as
161c1b412f1SDaniel P. Berrange  * well as @addrs itself. @naddrs is guaranteed to be
162c1b412f1SDaniel P. Berrange  * greater than zero on success.
163c1b412f1SDaniel P. Berrange  *
164c1b412f1SDaniel P. Berrange  * DNS resolution will be done synchronously so execution
165c1b412f1SDaniel P. Berrange  * of the caller may be blocked for an arbitrary length
166c1b412f1SDaniel P. Berrange  * of time.
167c1b412f1SDaniel P. Berrange  *
168c1b412f1SDaniel P. Berrange  * Returns: 0 if resolution was successful, -1 on error
169c1b412f1SDaniel P. Berrange  */
170c1b412f1SDaniel P. Berrange int qio_dns_resolver_lookup_sync(QIODNSResolver *resolver,
171c1b412f1SDaniel P. Berrange                                  SocketAddress *addr,
172c1b412f1SDaniel P. Berrange                                  size_t *naddrs,
173c1b412f1SDaniel P. Berrange                                  SocketAddress ***addrs,
174c1b412f1SDaniel P. Berrange                                  Error **errp);
175c1b412f1SDaniel P. Berrange 
176c1b412f1SDaniel P. Berrange /**
177c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_async:
178c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
179c1b412f1SDaniel P. Berrange  * @addr: the address to resolve
180c1b412f1SDaniel P. Berrange  * @func: the callback to invoke on lookup completion
181c1b412f1SDaniel P. Berrange  * @opaque: data blob to pass to @func
182c1b412f1SDaniel P. Berrange  * @notify: the callback to free @opaque, or NULL
183c1b412f1SDaniel P. Berrange  *
184c1b412f1SDaniel P. Berrange  * This will attempt to resolve the address provided
185c1b412f1SDaniel P. Berrange  * in @addr. The callback @func will be invoked when
186c1b412f1SDaniel P. Berrange  * resolution has either completed or failed. On
187c1b412f1SDaniel P. Berrange  * success, the @func should call the method
188c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_result() to obtain the
189c1b412f1SDaniel P. Berrange  * results.
190c1b412f1SDaniel P. Berrange  *
191c1b412f1SDaniel P. Berrange  * DNS resolution will be done asynchronously so execution
192c1b412f1SDaniel P. Berrange  * of the caller will not be blocked.
193c1b412f1SDaniel P. Berrange  */
194c1b412f1SDaniel P. Berrange void qio_dns_resolver_lookup_async(QIODNSResolver *resolver,
195c1b412f1SDaniel P. Berrange                                    SocketAddress *addr,
196c1b412f1SDaniel P. Berrange                                    QIOTaskFunc func,
197c1b412f1SDaniel P. Berrange                                    gpointer opaque,
198c1b412f1SDaniel P. Berrange                                    GDestroyNotify notify);
199c1b412f1SDaniel P. Berrange 
200c1b412f1SDaniel P. Berrange /**
201c1b412f1SDaniel P. Berrange  * qio_dns_resolver_lookup_result:
202c1b412f1SDaniel P. Berrange  * @resolver: the DNS resolver instance
203c1b412f1SDaniel P. Berrange  * @task: the task object to get results for
204c1b412f1SDaniel P. Berrange  * @naddr: pointer to hold number of resolved addresses
205c1b412f1SDaniel P. Berrange  * @addrs: pointer to hold resolved addresses
206c1b412f1SDaniel P. Berrange  *
207c1b412f1SDaniel P. Berrange  * This method should be called from the callback passed
208c1b412f1SDaniel P. Berrange  * to qio_dns_resolver_lookup_async() in order to obtain
209c1b412f1SDaniel P. Berrange  * results.  @addrs will be filled with all the resolved
210c1b412f1SDaniel P. Berrange  * addresses. @naddrs will specify the number of entries
211c1b412f1SDaniel P. Berrange  * allocated in @addrs. The caller is responsible for
212c1b412f1SDaniel P. Berrange  * freeing each entry in @addrs, as well as @addrs itself.
213c1b412f1SDaniel P. Berrange  */
214c1b412f1SDaniel P. Berrange void qio_dns_resolver_lookup_result(QIODNSResolver *resolver,
215c1b412f1SDaniel P. Berrange                                     QIOTask *task,
216c1b412f1SDaniel P. Berrange                                     size_t *naddrs,
217c1b412f1SDaniel P. Berrange                                     SocketAddress ***addrs);
218c1b412f1SDaniel P. Berrange 
219c1b412f1SDaniel P. Berrange #endif /* QIO_DNS_RESOLVER_H */
220