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