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