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