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