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