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