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