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