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