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