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