+++ /dev/null
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:·
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.·
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.·
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+++ /dev/null
-ACLOCAL_AMFLAGS = -I m4 ${ACLOCAL_FLAGS}
-AM_MAKEFLAGS = --no-print-directory
-
-AM_CPPFLAGS = \
- -include $(top_builddir)/config.h \
- -DSYSCONFDIR=\""$(sysconfdir)"\" \
- -DLIBEXECDIR=\""$(libexecdir)"\" \
- -I${top_srcdir}/include \
- -I${top_srcdir}/lib \
- -I${top_srcdir}/compat
-
-AM_CFLAGS = -Wall -Werror
-AM_LDFLAGS =
-
-SED_PROCESS = \
- $(AM_V_GEN)$(MKDIR_P) $(dir $@) && $(SED) \
- -e 's,@VERSION\@,$(VERSION),g' \
- -e 's,@prefix\@,$(prefix),g' \
- -e 's,@exec_prefix\@,$(exec_prefix),g' \
- -e 's,@libdir\@,$(libdir),g' \
- -e 's,@includedir\@,$(includedir),g' \
- < $< > $@ || rm $@
-
-%.pc: %.pc.in Makefile
- $(SED_PROCESS)
-
-include_HEADERS = \
- include/netresolve.h \
- include/netresolve-nonblock.h \
- include/netresolve-event.h \
- include/netresolve-glib.h \
- include/netresolve-epoll.h \
- include/netresolve-select.h
-
-lib_LTLIBRARIES = \
- libnetresolve.la \
- libnetresolve-libc.la \
- libnss_netresolve.la
-
-libnetresolve_la_SOURCES = \
- include/netresolve-backend.h \
- include/netresolve-cli.h \
- include/netresolve-private.h \
- lib/backend.c \
- lib/compat.c \
- lib/context.c \
- lib/epoll.c \
- lib/event.c \
- lib/logging.c \
- lib/query.c \
- lib/request.c \
- lib/select.c \
- lib/service.c \
- lib/socket.c \
- lib/string.c
-libnetresolve_la_CPPFLAGS = $(AM_CPPFLAGS)
-libnetresolve_la_LDFLAGS = \
- $(AM_LDFLAGS) $(LDNS_LIBS) \
- -export-symbols-regex '^netresolve_'
-
-libnetresolve_libc_la_SOURCES = include/netresolve-compat.h compat/libc.c
-libnetresolve_libc_la_LDFLAGS = $(AM_LDFLAGS) --export-all-symbols
-libnetresolve_libc_la_LIBADD = libnetresolve.la
-
-if BUILD_FRONTEND_ASYNCNS
-lib_LTLIBRARIES += libnetresolve-asyncns.la
-
-libnetresolve_asyncns_la_SOURCES = compat/asyncns.c
-libnetresolve_asyncns_la_LDFLAGS = $(AM_LDFLAGS) --export-all-symbols
-libnetresolve_asyncns_la_LIBADD = libnetresolve.la
-endif
-
-libnss_netresolve_la_SOURCES = compat/nsswitch.c
-libnss_netresolve_la_LIBADD = libnetresolve.la
-libnss_netresolve_la_LDFLAGS = $(AM_LDFLAGS) -version-info 2:0:0
-
-lib_LTLIBRARIES += \
- libnetresolve-backend-unix.la \
- libnetresolve-backend-any.la \
- libnetresolve-backend-loopback.la \
- libnetresolve-backend-numerichost.la \
- libnetresolve-backend-hosts.la \
- libnetresolve-backend-hostname.la \
- libnetresolve-backend-libc.la \
- libnetresolve-backend-nss.la \
- libnetresolve-backend-exec.la
-
-if BUILD_BACKEND_ASYNCNS
-lib_LTLIBRARIES += libnetresolve-backend-asyncns.la
-endif
-if BUILD_BACKEND_ARESDNS
-lib_LTLIBRARIES += libnetresolve-backend-aresdns.la
-endif
-if BUILD_BACKEND_UBDNS
-lib_LTLIBRARIES += libnetresolve-backend-ubdns.la
-endif
-if BUILD_BACKEND_AVAHI
-lib_LTLIBRARIES += libnetresolve-backend-avahi.la
-endif
-
-libnetresolve_backend_unix_la_SOURCES = backends/unix.c
-libnetresolve_backend_unix_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_any_la_SOURCES = backends/any.c
-libnetresolve_backend_any_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_loopback_la_SOURCES = backends/loopback.c
-libnetresolve_backend_loopback_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_numerichost_la_SOURCES = backends/numerichost.c
-libnetresolve_backend_numerichost_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_hosts_la_SOURCES = backends/hosts.c
-libnetresolve_backend_hosts_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_hostname_la_SOURCES = backends/hostname.c
-libnetresolve_backend_hostname_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_libc_la_SOURCES = backends/libc.c
-libnetresolve_backend_libc_la_LIBADD = libnetresolve.la
-libnetresolve_backend_libc_la_LDFLAGS = $(AM_LDFLAGS) -lresolv
-
-libnetresolve_backend_nss_la_SOURCES = backends/nss.c
-libnetresolve_backend_nss_la_LIBADD = libnetresolve.la
-
-libnetresolve_backend_exec_la_SOURCES = backends/exec.c
-libnetresolve_backend_exec_la_LIBADD = libnetresolve.la
-
-if BUILD_BACKEND_ARESDNS
-libnetresolve_backend_aresdns_la_SOURCES = backends/dns.c
-libnetresolve_backend_aresdns_la_LIBADD = libnetresolve.la
-libnetresolve_backend_aresdns_la_LDFLAGS = $(AM_LDFLAGS) $(ARES_LIBS)
-libnetresolve_backend_aresdns_la_CPPFLAGS = $(AM_CPPFLAGS) $(ARES_CFLAGS) -DUSE_ARES=1
-libnetresolve_la_CPPFLAGS += -DUSE_ARES=1
-endif
-if BUILD_BACKEND_UBDNS
-libnetresolve_backend_ubdns_la_SOURCES = backends/dns.c
-libnetresolve_backend_ubdns_la_LIBADD = libnetresolve.la
-libnetresolve_backend_ubdns_la_LDFLAGS = $(AM_LDFLAGS) $(UNBOUND_LIBS)
-libnetresolve_backend_ubdns_la_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_UNBOUND=1
-libnetresolve_la_CPPFLAGS += -DUSE_UNBOUND=1
-endif
-if BUILD_BACKEND_AVAHI
-libnetresolve_backend_avahi_la_SOURCES = backends/dns.c
-libnetresolve_backend_avahi_la_LIBADD = libnetresolve.la
-libnetresolve_backend_avahi_la_LDFLAGS = $(AM_LDFLAGS) $(AVAHI_LIBS)
-libnetresolve_backend_avahi_la_CPPFLAGS = $(AM_CPPFLAGS) -DUSE_AVAHI=1
-endif
-if BUILD_BACKEND_ASYNCNS
-libnetresolve_backend_asyncns_la_SOURCES = backends/asyncns.c
-libnetresolve_backend_asyncns_la_LIBADD = libnetresolve.la
-libnetresolve_backend_asyncns_la_LDFLAGS = $(ASYNCNS_LIBS)
-endif
-
-bin_PROGRAMS = netresolve getaddrinfo getnameinfo gethostbyname gethostbyaddr res_query
-bin_SCRIPTS = tools/wrapresolve
-
-netresolve_SOURCES = tools/netresolve.c
-netresolve_LDADD = libnetresolve.la
-netresolve_LDFLAGS = $(AM_LDFLAGS) $(LDNS_LIBS)
-
-getaddrinfo_SOURCES = tools/getaddrinfo.c tools/compat.c
-
-getnameinfo_SOURCES = tools/getnameinfo.c tools/compat.c
-
-gethostbyname_SOURCES = tools/gethostbyname.c tools/compat.c
-
-gethostbyaddr_SOURCES = tools/gethostbyaddr.c tools/compat.c
-
-res_query_SOURCES = tools/res_query.c tools/compat.c
-res_query_LDFLAGS = $(AM_LDFLAGS) $(LDNS_LIBS) -lresolv
-
-TESTS = \
- tests/test-netresolve.sh \
- test-sync \
- test-epoll \
- test-select \
- test-bind-connect \
- tests/test-compat.sh
-EXTRA_DIST = \
- tools/compat.h \
- tests/common.h \
- tests/test-netresolve.sh \
- tests/data/any \
- tests/data/localhost \
- tests/data/localhost \
- tests/data/localhost4 \
- tests/data/localhost6 \
- tests/data/numeric4 \
- tests/data/numeric4lo \
- tests/data/numeric4lo \
- tests/data/numeric4nines \
- tests/data/empty \
- tests/data/numeric6 \
- tests/data/numeric6lo \
- tests/data/numeric6nines \
- tests/data/empty \
- tests/data/dns \
- tests/data/services \
- tests/data/unix \
- tests/data/unix-stream \
- tests/data/unix-dgram \
- tests/data/empty
-noinst_PROGRAMS = \
- test-sync \
- test-epoll \
- test-select \
- test-bind-connect \
- test-getaddrinfo \
- test-gethostbyname \
- test-gethostbyname2 \
- test-gethostbyname_r \
- test-gethostbyname2_r
-if BUILD_FRONTEND_ASYNCNS
-noinst_PROGRAMS += \
- test-asyncns \
- test-asyncns-cancel
-endif
-if BUILD_ALL_TESTS
-TESTS += \
- test-libevent \
- test-glib
-noinst_PROGRAMS += \
- test-libevent \
- test-glib
-endif
-
-test_sync_SOURCES = tests/test-sync.c tests/common.c tests/common.h
-test_sync_LDADD = libnetresolve.la
-
-test_epoll_SOURCES = tests/test-async.c tests/test-async-epoll.c tests/common.c
-test_epoll_LDADD = libnetresolve.la
-
-test_select_SOURCES = tests/test-async.c tests/test-async-select.c tests/common.c
-test_select_LDADD = libnetresolve.la
-
-test_libevent_SOURCES = tests/test-libevent.c tests/common.c
-test_libevent_LDADD = libnetresolve.la
-test_libevent_LDFLAGS = $(AM_LDFLAGS) $(EVENT_LIBS)
-
-test_glib_SOURCES = tests/test-glib.c tests/common.c
-test_glib_LDADD = libnetresolve.la
-test_glib_CFLAGS = $(AM_CFLAGS) $(GLIB_CFLAGS)
-test_glib_LDFLAGS = $(AM_LDFLAGS) $(GLIB_LIBS)
-
-test_bind_connect_SOURCES = tests/test-bind-connect.c
-test_bind_connect_LDADD = libnetresolve.la
-
-test_getaddrinfo_SOURCES = tests/test-getaddrinfo.c
-
-test_gethostbyname_SOURCES = tests/test-gethostbyname.c
-
-test_gethostbyname2_SOURCES = tests/test-gethostbyname.c
-test_gethostbyname2_CFLAGS = -DGETHOSTBYNAME2
-
-test_gethostbyname_r_SOURCES = tests/test-gethostbyname.c
-test_gethostbyname_r_CFLAGS = -DREENTRANT
-
-test_gethostbyname2_r_SOURCES = tests/test-gethostbyname.c
-test_gethostbyname2_r_CFLAGS = -DGETHOSTBYNAME2 -DREENTRANT
-
-test_asyncns_SOURCES = tests/test-asyncns.c
-test_asyncns_LDFLAGS = -lasyncns
-
-test_asyncns_cancel_SOURCES = tests/test-asyncns-cancel.c
-test_asyncns_cancel_LDFLAGS = -lasyncns
+++ /dev/null
-netresolve-0.0.1
-================
-# netresolve library and tools
+Repository and all related resources moved to:
-Netresolve is a package for nonblocking network name resolution via backends
-intended as a replacement for name service switch based name resolution in
-glibc.
-
-## Contact
-
-Pavel Šimerda
-psimerda at redhat.com
-pavlix at pavlix.net (mail and jabber)
-pavlix at IRC Freenode
-
-## Core features
-
- * File descriptor based nonblocking host/service name resolution API
- - suitable for various file descriptor based event loops
- - unlike glibc or POSIX APIs
- * Extensible request and result APIs
- - unlike glibc or POSIX APIs
- - host/service queries (like `getaddrinfo`)
- - SRV record support for host/service queries
- - reverse queries (like `getnameinfo`)
- - DNS style queries (like `res_query` but via backends)
- * Backend-based network name resolution somewhat similar to glibc's nsswitch
- - more flexible than DNS-only libraries
- - with configurable backend options (not available in nsswitch)
- - also supports nsswitch backends (via `libnetresolve_nss.so`)
- * Avoids limitations and bugs found in glibc
- - support for `ifindex` and `scope_id` (problematic in nsswitch)
- - support for TTL information (problematic in nsswitch)
- * DNS happy eyeballs implementation
- - concurent A/AAAA requests
- - quick timeout when there's no answer to one of A/AAAA requests
- * Socket API
- - callback based wrappers over `socket()`, `bind()` and `connect()`
- - the application receives a successfully bound or connected socket
- * TCP happy eyeballs implementation
- - concurrent IPv4/IPv6 connect
- - quick timeout when there's no answer to one of IPv4/IPv6 TCP SYN packets
- * Security information
- - well-known and locally configured data is considered secure
- - experimental support for DNSSEC authenticated data
-
-## Command line tool
-
-The command line tool is useful for testing the netresolve library as well as testing various libraries supported by netresolve including glibc and libunbound.
-
-Forward query:
-
- netresolve --node localhost
-
- netresolve --node www.sourceware.org --service http --protocol tcp
-
-Forward query with SRV resolution:
-
- netresolve --srv --node jabber.org --service xmpp-client --protocol tcp
-
-Reverse query:
-
- netresolve --address 192.228.79.201
-
- netresolve --address 2001:503:ba3e::2:30
-
- netresolve --port 80
-
- netresolve --address 192.228.79.201 --port 80
-
-DNS style query:
-
- netresolve --type srv --node _xmpp-client._tcp._jabber.com
-
- netresolve --class ch --type txt --node version.bind
-
-Connection support similar to netcat or socat:
-
- netresolve --connect --node localhost --service 22
-
-## Experimental DNSSEC support via command line
-
-Query information using a DNS backend and trust the AD flag:
-
- netresolve --backends aresdns:trust --node www.dnssec.cz
-
-Query information using a validating DNS backend:
-
- netresolve --backends ubdns:validate --node www.dnssec.cz
-
-## Library API – simple blocking queries
-
-Program or library using netresolve has to allocate a netresolve context (or context) which is then used to perform all the queries. You may want to create multiple contexts to have different configurations prepared for use. By default the netresolve context is in blocking mode. Consult the next section about event loop integration on how to create a netresolve context in nonblocking mode.
-
- #include <netresolve.h>
-
- netresolve_t context = netresolve_context_new();
-
-Then you tweak the context configuration to your liking.
-
- netresolve_set_protocol(context, IPPROTO_TCP);
- netresolve_set_dns_srv_lookup(context, true);
-
-When you're happy with the configuration, you can run your queries using `netresolve_query_forward()`, `netresolve_query_reverse()` or `netresolve_query_dns()`. Any of the functions waits until the query is successfully finished, failed or timed out.
-
- netresolve_query_t query = netresolve_query_forward(context, "www.sourceware.org", "http", NULL, NULL);
-
-TODO: Error reporting.
-
-You can pick up your query immediately.
-
- size_t count = netresolve_query_get_count(query);
-
- for (size_t idx = 0; idx < count; idx++) {
- int family;
- const void *address;
- int ifindex;
- int socktype;
- int protocol;
- int port;
- int priority;
- int weight;
- uint32_t ttl;
-
- netresolve_query_get_node_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_service_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_aux_info(query, idx, &family, &address, &ifindex);
-
- /* do something with the data */
- }
-
-You can free the query object when you no longer need it.
-
- netresolve_query_free(query);
-
-When you're not going to use the context to perform any queries nor use the existing query objects to examine the results, you can free the context
-together with all queries that haven't been freed as written above.
-
- netresolve_context_free(context);
-
-An example of using netresolve in blocking mode can be found in `test/test-sync.c`.
-
-## Library API – callback based nonblocking queries
-
-The nonblocking mode is designed to be independent of a specific event loop implementation. You can use one of the existing event loop connectors or write your own easily. Connectors for libevent and glib are distributed as header files to avoid additional dependencies. Connectors using epoll-style and select-style file descriptor sets are built into the library.
-
-### Creating a libevent based context
-
-Provided that you have a `struct event_base *base` pointer to the event base, create the netresolve context before issuing any queries.
-
- #include <netresolve-event.h>
-
- netresolve_t context = netresolve_event_new(base);
-
-Free it as usual.
-
- netresolve_context_free(context);
-
-### Creating a glib based context
-
-With glib you can easily create a channel attached to the default context.
-
- #include <netresolve-glib.h>
-
- netresolve_t context = netresolve_glib_new();
-
-Free it as usual.
-
- netresolve_context_free(context);
-
-### Issue queries and pick up the data
-
-Issue a query with a callback and user data.
-
- netresolve_query_t query = netresolve_query_forward(context, "www.sourceware.org", "http", callbac, user_data);
-
-Pickup the data in your callback and free the query if you no longer need it.
-
- void
- callback(netresolve_query_t query, void *user_data)
- {
- size_t count = netresolve_query_get_count(query);
-
- for (size_t idx = 0; idx < count; idx++) {
- int family;
- const void *address;
- int ifindex;
- int socktype;
- int protocol;
- int port;
- int priority;
- int weight;
- uint32_t ttl;
-
- netresolve_query_get_node_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_service_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_aux_info(query, idx, &family, &address, &ifindex);
-
- /* do something with the data */
- }
-
- netresolve_query_free(query);
- }
-
-Note: You can use callbacks with blocking mode as well, although it's not as useful as with nonblocking mode. This feature is especially useful in code that is written to work with both blocking and nonblocking mode.
-
-### Context based on epoll kernel feature
-
-Create the context.
-
- #include <netresolve-epoll.h>
-
- netresolve_t context = netresolve_epoll_new();
-
-Retrieve the file descriptor.
-
- int fd = netresolve_epoll_fd(context);
-
-When the epoll file descriptor is ready *ready for reading*, dispatch.
-
- netresolve_epoll_dispatch(context);
-
-Free it as usual.
-
- netresolve_context_free(context);
-
-### Context based on file descriptor sets
-
-Create the context.
-
- #include <netresolve-select.h>
-
- netresolve_t context = netresolve_select_new()
-
-Retrieve the file descriptors.
-
- fd_set rfds, wfds;
- int nfds;
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- nfds = netresolve_select_apply_fds(context, &rfds, &wfds);
-
-When a file descriptor in rfds is ready for reading, dispatch.
-
- netresolve_select_dispatch_read(context, rfds);
-
-When a file descriptor in wfds is ready for writing, dispatch.
-
- netresolve_select_dispatch_write(context, rfds);
-
-Free it as usual.
-
- netresolve_context_free(context);
-
-### Custom nonblocking context
-
-If none of the included integration functions match your needs, you can create the context using `netresolve_context_new()` and then attach your own set of callbacks using `netresolve_set_fd_callbacks()`. You need to provide two callbacks. The `watch_fd()` function adds an event source consisting of a file descriptor, and a set of events (subset of `POLLIN | POLLOUT`) and an opaque pointer `data` and the `unwatch_fd()` function that removes the source. When a file descriptor event occurs, the event loop implementation calls `netresolve_dispatch()` with the respective `source` and the subset of events that occured. The integration code can optionally provide a `user_data` pointer that can ten be retrieved with `netresolve_get_user_data()` and a `free_user_data()` callback that will be called during the context destruction and a pointer for each event source returned by `watch_fd()` that will then be passed to `unwatch_fd()` as the `handle` argument. The `user_data` pointer typically points to an object representing the event loop and the `handle` pointer points to an object representing the event source.
-
- void *watch_fd(netresolve_t context, int fd, int events, netresolve_source_t source);
- void unwatch_fd(netresolve_t context, int fd, void *handle);
- void free_user_data(void *user_data);
-
-Install callbacks.
-
- netresolve_set_fd_callbacks(context, watch_fd, unwatch_fd, user_data, free_user_data);
-
-Dispatch an event.
-
- netresolve_dispatch(context, source, events);
-
-## Thread safety
-
-Use one context object per thread. Avoid accessing the context and query objects from different threads for now.
-
-### POSIX-like API
-
-You can use a compatibility API most resembling the POSIX one but still allowing for nonblocking mode. The context object must be created as usual and you can also tweak its configuration and set up nonblocking mode and callbacks. This API can be nonblocking depending on the context configuration already described.
-
- #include <netresolve-compat.h>
-
-A special query constructor lets you use input arguments as with `getaddrinfo()`.
-
- struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = 0, .ai_protocol = IPPROTO_TCP, .ai_flags = 0 };
- netresolve_query_t query = netresolve_query_getaddrinfo(context, "www.sourceware.org", "http", &hints, callback, user_data);
-
-A special query result getter lets you use output arguments as with `getaddrinfo()` and destroys the query object for your convenience.
-
- struct addrinfo *result;
- uint32_t ttl;
- int status = netresolve_query_addrinfo_done(query, &list, &ttl);
-
-When you don't need the result object any more, free it.
-
- netresolve_freeaddrinfo(result);
-
-An alternative `getaddrinfo()` implementation using netresolve in `compat/libc.c` serves as an example of how to use this compatibility API.
-
-## GNU libc nsswitch backend
-
-A backend for glibc nsswitch is provided as `libnss_netresolve.so` that exposes part of netresolve funcionality via the glibc name resolution API. The backend also supports a variant of `_nss_*_getaddrinfo()` API proposed by Alexandre Oliva.
-
-## POSIX/GNU libc API replacement
-
-If your program doesn't need the full power of the provided API but you still want to use `netresolve` as your resolver implementation, you can simply link your program to `libnetresolve-libc.so` which overrides selected libc name resolution functions.
-
-Supported functions:
-
- * `getaddrinfo()`
- * `getnameinfo()`
- * `gethostbyname()`, `gethostbyname_r()`
- * `gethostbyname2()`, `gethostbyname2_r()`
- * `gethostbyaddr()`
-
-You can use the `wrapresolve` command to start a program with `LD_PRELOAD` configured so that your program uses netresolve functions instead of libc.
-
- wrapresolve curl http://www.sourceware.org/
-
-You can tweak netresolve configuration via environment variables, or you can use convenience options provided by `wrapresolve`. Currently there are options to force IPv4-only or IPv6-only resolution.
-
- wrapresolve -4 curl http://www.nix.cz/
-
- wrapresolve -6 curl http://www.nix.cz/
-
-The netresolve package also provides a couple of testing tools for the above libc functions that can be used to test both libc and the replacement functions.
-
- getaddrinfo --node localhost --service http
-
- wrapresolve getaddrinfo --node localhost --service http
-
-## libasyncns API replacement
-
-The `wrapresolve` command also pulls in `libnetresolve-asyncns.so` which implements libasyncns API using netresolve.
-
-## Socket API
-
-Two non-blocking APIs wrapping name resolution together with the `socket()`, `bind()`, `listen()` and `connect()` calls are available.
-
-The simpler one is `netresolve_bind()` that creates listening sockets for all available addresses and passes them back via a series of calls of the provided callback. You can easily learn when the last socket is passed by checking `netresolve_query_get_count()` and free the structures using `netresolve_bind_free()`.
-
-The more sophisticated one is `netresolve_connect()` that uses the list of addresses to get a single connected socket, maintaining address preference by family and other characteristics, and using a short timeout to bypass the preference when it would take too much time. A function called `netresolve_connect_next()` can be used to overcome application level issues with one of the addresses and to get a new connection using the next available address. Once happy with the connected socket or to abort the process, run `netresolve_connect_free()`.
-
-## Backends
-
-The list of backends can be chosen using `netresolve_set_backend_string()` or via the `NETRESOLVE_BACKENDS` environment variable. Backends are separated by a comma and accept options separated by a colon. A plus sign prepended to the backend name can be used to run that backend even if another backend already succeeded.
-
- export NETRESOLVE_BACKENDS=any,loopback,numerichost,hosts,hostname,avahi,aresdns
-
-The command line interface also supports an option to select the backend.
-
- netresolve --backend any,loopback,numerichost,hosts,hostname,avahi,aresdns
-
-The default list of backends is slightly wider then the example one above and attempts all sorts of name resolution tools in order to give you full results.
-
-### General purpose backends
-
-Three backends, `any`, `loopback` and `numerichost`, are available that perform trivial translations. The `hosts` backends uses `/etc/hosts` database of nodes. Nonblocking API is most useful for remote services. We have two nonblocking DNS backends, `aresdns` and `ubdns`. We support special configuration of the two DNS backends, `aresdns:trust` reads the DNS AD flag and marks the query result secure and `ubdns:validate` instructs libunbound to perform the validation. On systems with Avahi service running, the `avahi` backend offers Multicast DNS name resolution.
-
-### POSIX and glibc compatibility backends
-
-You can ask `netresolve` to call `getaddrinfo()` to gather the data using the `getaddrinfo` backend. This is useful for testing the libc API as well as comparing results of general purpose netresolve backends to other implementations. This backend blocks until the `getaddrinfo()` function exits.
-
- netresolve --backends getaddrinfo --node www.sourceware.org
-
-We also support glibc nsswitch modules through the `nss` backend. It finds the nsswitch dynamic module by name, loads the supported API functions and runs the most suitable one. The algorithm used in netresolve was inspired by glibc `getaddrinfo()` and glibc nscd code. This backend blocks until the nsswitch module function exits.
-
- netresolve --backends nss:files --node localhost
-
- netresolve --backends nss:dns --node www.sourceware.org
-
-You can also pass the nsswitch module by absolute or relative path.
-
- netresolve --backends nss:/usr/lib64/libnss_files.so
-
-Or you can select the specific nsswitch API to be used.
-
- # call `_nss_files_gethostbyname_r`
- netresolve --backends nss:files:gethostbyname --node localhost
-
- # call `_nss_files_gethostbyname2_r`
- netresolve --backends nss:files:gethostbyname2 --node localhost
-
- # call `_nss_files_gethostbyname3_r`
- netresolve --backends nss:files:gethostbyname3 --node localhost
-
- # call `_nss_files_gethostbyname4_r`
- netresolve --backends nss:files:gethostbyname4 --node localhost
-
-You can use the nss plugin to test systemd-resolved via `libnss_resolve.so`.
-
- netresolve --backends nss:resolve --node localhost
-
-We have experimental support for new nsswitch API based on a variant of `getaddrinfo()` proposed by Alexandre Oliva. This proposed API would consolidate the nsswitch APIs and overcome some of the limitations describe at the beginning of this document.
-
-### Auxiliary backends
-
-There's an experimental backend to call a script to perform name resolution
-and feed it with the request serialized in a couple of text lines and read
-the result from it.
-
- netresolve --backends exec:/path/to/my/script --node localhost
-
-
-That one can be used for interactive testing as well:
-
- netresolve --backends exec:socat:-:/dev/tty --node www.example.com
-
-Note: This backend is untested and maybe not even functional.
-
-## Writing a custom backend
-
-When a name resolution request is ready, netresolve calls one of the setup functions depending on the query type. If any of the setup functions is missing, netresolve assumes that the backend doesn't support the respective query type at all.
-
- setup_forward(context, settings);
-
- setup_reverse(context, settings);
-
- setup_dns(context, settings);
-
-The setup function initializes the query using input data from `netresolve_backend_get_*()` functions. It creates a state object using `netresolve_backend_new_priv()` (if necessary) to share its data with the other backend API functions. Finally it does one of the following:
-
-1. Add any data items using `netresolve_backend_add_*()` functions and call `netresolve_backend_finished()` to signal immediate success.
-2. Call `netresolve_backend_failed()` to signal immediate failure.
-3. Add one or more watchers using `netresolve_backend_watch_fd()` and `netresolve_backend_watch_timeout()`.
-
-In the third case, a dispath function is called by netresolve. It is not needed in the other two cases.
-
- dispatch(context, settings);
-
-The dispatch function retrieves the state object using `netresolve_backend_get_priv()`. Then it does one of the following:
-
-1. Add any data items and call `netresolve_backend_finished()` to signal success.
-2. Call `netresolve_backend_failed()` to signal failure.
-3. Leaves one or more watchers active.
-
-When success or failure was reported by the plugin, or when the query has been cancelled, the cleanup function is called.
-
- cleanup(context, settings);
-
-The cleanup function also retrieves the state object, removes remaining watchers using `netresolve_backend_watch_fd()` and/or `netresolve_backend_remove_timeout()`, closes open file descriptors, returns allocated memory (except the context object itself which is freed by netresolve itself).
-
-Calls to the above functions in a single backend are serialized, calling a backend API function doesn't cause any side effects for the backend.
-
-## API/ABI stability
-
-The library is still considered experimental. The functions in `netresolve.h` are getting stable very soon.
-
-## Known bugs
-
-The library doesn't currently sort paths according to their priority and/or RFC rules. The c-ares library blocks when /etc/resolv.conf is empty instead of quitting immediately, which in turn breaks tests when offline. The DNS backend doesn't support search domains. For more information, see the `TODO` file.
-
-## Acknowledgements and inspiration
-
- * Tore Anderson was the first who discussed name resolution issues with me and especially the reasons to suppress A or AAAA queries when global address of the respective family is not present in the system.
- - [sourceware.org: #12377](https://sourceware.org/bugzilla/show_bug.cgi?id=12377)
- * Simo Sorce told me about `getaddrinfo()` issues with canonical names.
- * Ulrich Drepper wrote a good amount of documentation on network name resolution.
- - [Userlevel IPv6 Programming Introduction](http://www.akkadia.org/drepper/userapi-ipv6.html)
- - [Asynchronous Hostname Lookup API](http://www.akkadia.org/drepper/asynchnl.pdf)
- * Carlos O'Donnel helped me to find my way in the glibc community.
- * Nick Jones brought in the idea of a file descriptor based nonblocking API.
- - [libc-alpha: asynchronous getaddrinfo and getnameinfo](https://sourceware.org/ml/libc-alpha/2013-01/msg00356.html)
- - [fedora-devel: asynchronous name resolution requirements](https://lists.fedoraproject.org/pipermail/devel/2013-January/177290.html)
- * Petr Špaček pointed me to SSSD developers.
- * Jakub Hrozek told me about c-ares DNS library and about SSSD name resolution requirements.
- - https://fedorahosted.org/sssd/ticket/2155
- * Miloslav Trmač reminded me of the need to also provide binding and connecting facilities on top of name resolution.
- * Lennart Poettering wrote *libasyncns*, an async wrapper over libc resolver functions
- * Alexandre Oliva wrote a number of proposals to improve glibc name resolution
-
-## Related projects
-
-### glibc
-
-One way to look at netresolve is to see it as a testbed for future glibc improvements. It's written with testing and debugging in mind and prototyping new ideas in netresolve is very easy. Another way is to see it as a more flexible alternative to glibc host and service name resolution functionality. Either way glibc and POSIX were the main inspirations for this project.
-
-### c-ares
-
-They provide `ares_fds()` and `ares_timeout()` to update the current set of file descriptors and the associated timeout. The `netresolve` callback API improves greatly on that. The application submits the `watch_fd()` callback.
-
-### sssd
-
-They provide a backend-based caching service for user/group name resolution, authentication and related stuff. As netresolve doesn't really need to cache its results nor does it need to perform authentication services, it provides just a shared library, not a long-running daemon. Also, for DNS resolution they currently use `c-ares`.
-
-### libevent, squid, etc...
-
-According to the website, libevent is using internal asynchronous DNS as well. The same applies to squid. Apparently the operating system's resolution API is not sufficient for many tools.
-
-### systemd-resolved
-
-To my knowledge, name resolution related systemd features were announced after I published netresolve. The relation to that project is yet to be seen.
-
-## License
-
-Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice, this
- list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+https://github.com/pavlix/netresolve
+++ /dev/null
-# TODO list
-
-## Core library issues
-
- * socket: decouple event processing from query
- * query: allow multiple reverse names
-
-## Features
-
- * Improve path ordering
- - use rules from http://tools.ietf.org/html/rfc6724
- - use /etc/gai.conf
- * Allow backend list setting at any time or at least check whether they can be changed
- * Read a configuration file in `/etc/netresolve` in addition to environment variables
- * Consider using -fvisibility=hidden
- * Consider using a separate libnetresolve-backend.so
-
-## Frontends, integration and testing
-
- * Extend the libc API frontend
- - `getaddrinfo_a()`, `gai_suspend()`, `gai_error()` and `gai_cancel()` (glibc specific)
- * Implement more frontends
- - the getdns API frontend
- * Integrate with more event loops/connectors
- - libverto
- - Python PEP 3156
- - libsystemd
- - and more...
- * Build a fake ares/libunbound library to support DNS testing
- * A comprehensive dualstack test plan
- - DNS: AAAA wildcard search available, only global A record set
- - DNS: AAAA record not answered, A answered (and vice versa)
- - DNS: SRV not answered, A/AAAA answered
- - TCP: IPv6/SYN not answered, IPv4 SYN answered (and vice versa)
- - TCP: first IPv6/SYN not answered, second IPv6/SYN answered (the same for IPv4)
- - TCP: IPv6-only destination, first address not answered, next address works
- - TCP: first SYN answered, application layer failure, next address works
- - UDP: application layer failure, next address works
-
-## Backends
-
- * Improve `nss` backend
- - support `/etc/nsswitch` configuration
- - consider supporting hostent listing
- * Improve the DNS backends
- - consider domain search support
- - consider `ai_addrconfig`-like functionality
- * Fix `exec` backend
- - it hasn't been tested recently
- - fix the code, extend the format
- - add automated tests
- * Implement more backends
- - nonblocking systemd-resolved based backend (blocking mode available via nss-resolve)
- - standalone nonblocking LLMNR backend
- - the getdns API backend
-
-## Portability
-
- * Support non-timerfd platforms
- - pass timeout creation and removal request to the application/connector
-
-## Documentation and non-development stuff
-
- * Website
- * Manpages
- * Provide fixes for glibc resolver
- * IETF notes, errata and drafts
+++ /dev/null
-#!/bin/bash -xe
-
-mkdir -p m4
-autoreconf --install --symlink
-
-if [ -z "$NOCONFIGURE" ]; then
- ./configure "$@";
-fi
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-
-static bool
-is_any(int family, const void *address)
-{
- switch (family) {
- case AF_INET:
- return !memcmp(address, &inaddr_any, sizeof inaddr_any);
- case AF_INET6:
- return !memcmp(address, &in6addr_any, sizeof in6addr_any);
- default:
- return false;
- }
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
-
- /* skip if requested */
- if (netresolve_backend_get_default_loopback(query)) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (node && *node) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_add_path(query, AF_INET, &inaddr_any, 0, 0, 0, 0, 0, 0, 0);
- netresolve_backend_add_path(query, AF_INET6, &in6addr_any, 0, 0, 0, 0, 0, 0, 0);
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
-}
-
-void
-query_reverse(netresolve_query_t query, char **settings)
-{
- int family = netresolve_backend_get_family(query);
- const void *address = netresolve_backend_get_address(query);
-
- /* skip if requested */
- if (netresolve_backend_get_default_loopback(query)) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (!is_any(family, address)) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_add_name_info(query, "", NULL);
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <asyncns.h>
-
-struct priv_asyncns {
- asyncns_t *asyncns;
-};
-
-static void
-dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct priv_asyncns *priv = netresolve_backend_get_priv(query);
- asyncns_query_t *q;
- struct addrinfo *result;
- int status;
-
- asyncns_wait(priv->asyncns, 0);
- if (!(q = asyncns_getnext(priv->asyncns)))
- return;
-
- status = asyncns_getaddrinfo_done(priv->asyncns, q, &result);
-
- netresolve_backend_apply_addrinfo(query, status, result, 0);
- asyncns_freeaddrinfo(result);
-}
-
-static void
-cleanup(void *data)
-{
- struct priv_asyncns *priv = data;
-
- asyncns_free(priv->asyncns);
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- struct priv_asyncns *priv = netresolve_backend_new_priv(query, sizeof *priv, cleanup);
- const char *nodename = netresolve_backend_get_nodename(query);
- const char *servname = netresolve_backend_get_servname(query);
- struct addrinfo hints = netresolve_backend_get_addrinfo_hints(query);
-
- if (!priv || !(priv->asyncns = asyncns_new(2))) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (!asyncns_getaddrinfo(priv->asyncns, nodename, servname, &hints)) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_watch_add(query, asyncns_fd(priv->asyncns), POLLIN, dispatch, NULL);
-
- return;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <ldns/ldns.h>
-
-#if defined(USE_UNBOUND)
-
-#include <unbound.h>
-#define priv_dns priv_dns
-
-static void ubdns_callback(void *arg, int status, struct ub_result* result);
-
-#elif defined(USE_ARES)
-
-#include <ares.h>
-#define priv_dns priv_aresdns
-
-static void aresdns_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen);
-
-#elif defined(USE_AVAHI)
-
-#include <avahi-client/client.h>
-#include <avahi-client/lookup.h>
-#include <avahi-common/error.h>
-#define priv_dns priv_avahi
-
-static void record_callback (
- AvahiRecordBrowser *b,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiBrowserEvent event,
- const char *name,
- uint16_t class,
- uint16_t type,
- const void *rdata,
- size_t size,
- AvahiLookupResultFlags flags,
- void *userdata);
-static void address_callback (
- AvahiAddressResolver *r,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiResolverEvent event,
- const AvahiAddress *a,
- const char *name,
- AvahiLookupResultFlags flags,
- void *userdata);
-
-#endif
-
-struct priv_srv {
- struct priv_dns *priv;
- struct priv_srv *previous, *next;
- int priority;
- int weight;
- uint16_t port;
- char *name;
-};
-
-struct priv_dns {
- netresolve_query_t query;
- int protocol;
- int family;
-#if defined(USE_AVAHI)
- AvahiAddress address;
-#else
- const uint8_t *address;
-#endif
- int cls;
- int type;
-
- struct priv_srv srv;
- int pending;
- bool answered;
- bool failed;
- bool secure;
-#if defined(USE_UNBOUND)
- struct ub_ctx* ctx;
- bool validate;
- netresolve_watch_t watch;
-#elif defined(USE_ARES)
- ares_channel channel;
- fd_set rfds, wfds;
- int nfds;
- netresolve_watch_t *watches;
-#elif defined(USE_AVAHI)
- struct AvahiClient *client;
- struct AvahiHostNameResolver *resolver;
- struct AvahiPoll poll_config;
- AvahiLookupFlags flags;
-#endif
-};
-
-static void
-lookup_dns(struct priv_srv *srv, const char *name, int type, int class)
-{
- struct priv_dns *priv = srv->priv;
-
- debug("Looking up %s record for %s", ldns_rr_descript(type)->_name, name);
-
- priv->pending++;
-
-#if defined(USE_UNBOUND)
- ub_resolve_async(priv->ctx, name, type, class, srv, ubdns_callback, NULL);
-#elif defined(USE_ARES)
- ares_query(priv->channel, name, class, type, aresdns_callback, srv);
-#elif defined(USE_AVAHI)
- if (!avahi_record_browser_new(
- priv->client,
- AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC,
- srv->name,
- class,
- type,
- priv->flags,
- record_callback,
- srv)) {
- error("Failed to create record browser: %s\n",
- avahi_strerror(avahi_client_errno(priv->client)));
- netresolve_backend_failed(priv->query);
- }
-#endif
-}
-
-static const char *
-protocol_to_string(int proto)
-{
- switch (proto) {
- case IPPROTO_UDP:
- return "udp";
- case IPPROTO_TCP:
- return "tcp";
- case IPPROTO_SCTP:
- return "sctp";
- default:
- return "0";
- }
-}
-
-static void
-lookup_srv(struct priv_dns *priv)
-{
- char *name;
-
- if (asprintf(&name, "_%s._%s.%s",
- netresolve_backend_get_servname(priv->query),
- protocol_to_string(priv->protocol),
- netresolve_backend_get_nodename(priv->query)) != -1) {
- lookup_dns(&priv->srv, name, LDNS_RR_TYPE_SRV, LDNS_RR_CLASS_IN);
- free(name);
- } else {
- error("memory allocation failed");
- priv->failed = true;
- }
-}
-
-static void
-lookup_host(struct priv_srv *srv)
-{
- struct priv_dns *priv = srv->priv;
-
- if (priv->family == AF_INET || priv->family == AF_UNSPEC)
- lookup_dns(srv, srv->name, LDNS_RR_TYPE_A, LDNS_RR_CLASS_IN);
- if (priv->family == AF_INET6 || priv->family == AF_UNSPEC)
- lookup_dns(srv, srv->name, LDNS_RR_TYPE_AAAA, LDNS_RR_CLASS_IN);
-}
-
-static void
-lookup_address(struct priv_dns *priv)
-{
-#if defined(USE_AVAHI)
- priv->pending++;
-
- if (!avahi_address_resolver_new(
- priv->client,
- AVAHI_IF_UNSPEC,
- priv->family == AVAHI_PROTO_UNSPEC,
- &priv->address,
- priv->flags,
- address_callback,
- priv)) {
- error("Failed to create record browser: %s\n",
- avahi_strerror(avahi_client_errno(priv->client)));
- netresolve_backend_failed(priv->query);
- }
-#else
- char name[128];
-
- switch (priv->family) {
- case AF_INET:
- snprintf(name, sizeof name, "%d.%d.%d.%d.in-addr.arpa.",
- priv->address[3],
- priv->address[2],
- priv->address[1],
- priv->address[0]);
- break;
- case AF_INET6:
- snprintf(name, sizeof name, "%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.%x.ip6.arpa",
- priv->address[0xf] & 0x0f, priv->address[0xf] >> 4,
- priv->address[0xe] & 0x0f, priv->address[0xe] >> 4,
- priv->address[0xd] & 0x0f, priv->address[0xd] >> 4,
- priv->address[0xc] & 0x0f, priv->address[0xc] >> 4,
- priv->address[0xb] & 0x0f, priv->address[0xb] >> 4,
- priv->address[0xa] & 0x0f, priv->address[0xa] >> 4,
- priv->address[0x9] & 0x0f, priv->address[0x9] >> 4,
- priv->address[0x8] & 0x0f, priv->address[0x8] >> 4,
- priv->address[0x7] & 0x0f, priv->address[0x7] >> 4,
- priv->address[0x6] & 0x0f, priv->address[0x6] >> 4,
- priv->address[0x5] & 0x0f, priv->address[0x5] >> 4,
- priv->address[0x4] & 0x0f, priv->address[0x4] >> 4,
- priv->address[0x3] & 0x0f, priv->address[0x3] >> 4,
- priv->address[0x2] & 0x0f, priv->address[0x2] >> 4,
- priv->address[0x1] & 0x0f, priv->address[0x1] >> 4,
- priv->address[0x0] & 0x0f, priv->address[0x0] >> 4);
- break;
- default:
- abort();
- }
-
- lookup_dns(&priv->srv, name, LDNS_RR_TYPE_PTR, LDNS_RR_CLASS_IN);
-#endif
-}
-
-static void
-set_name(struct priv_dns *priv, const char *name)
-{
- char *s = strdup(name);
- char *last = s + strlen(s) - 1;
-
- if (*last == '.')
- *last = '\0';
-
- netresolve_backend_add_name_info(priv->query, s, NULL);
-
- free(s);
-}
-
-static void
-apply_name(struct priv_dns *priv, const char *type, ldns_rr *rr)
-{
- char *name = ldns_rdf2str(ldns_rr_rdf(rr, 0));
-
- debug("Found %s: %s", type, name);
-
- set_name(priv, name);
-
- free(name);
-}
-
-static void
-apply_address(struct priv_srv *srv, const char *type, int family, ldns_rr *rr)
-{
- debug("Found %s", type);
-
- netresolve_backend_add_path(srv->priv->query,
- family, ldns_rdf_data(ldns_rr_rdf(rr, 0)), 0,
- 0, srv->priv->protocol, srv->port,
- srv->priority, srv->weight, ldns_rr_ttl(rr));
-
- srv->priv->answered = true;
-}
-
-static void
-apply_srv(struct priv_dns *priv, ldns_rr *rr)
-{
- struct priv_srv *srv = calloc(1, sizeof *srv);
-
- if (!srv) {
- error("Memory allocation failed.");
- netresolve_backend_failed(priv->query);
- return;
- }
-
- srv->priv = priv;
- srv->previous = priv->srv.previous;
- srv->next = &priv->srv;
- srv->previous->next = srv->next->previous = srv;
-
- srv->priority = ldns_rdf2native_int16(ldns_rr_rdf(rr, 0));
- srv->weight = ldns_rdf2native_int16(ldns_rr_rdf(rr, 1));
- srv->port = ldns_rdf2native_int16(ldns_rr_rdf(rr, 2));
- srv->name = ldns_rdf2str(ldns_rr_rdf(rr, 3));
-
- debug("Found SRV: %d %d %d %s", srv->priority, srv->weight, srv->port, srv->name);
-
- set_name(priv, srv->name);
-
- lookup_host(srv);
-}
-
-static void
-apply_record(struct priv_srv *srv, ldns_rr *rr)
-{
- struct priv_dns *priv = srv->priv;
-
- switch (ldns_rr_get_type(rr)) {
- case LDNS_RR_TYPE_CNAME:
- apply_name(priv, "CNAME", rr);
- break;
- case LDNS_RR_TYPE_PTR:
- apply_name(priv, "PTR", rr);
- priv->answered = true;
- break;
- case LDNS_RR_TYPE_A:
- apply_address(srv, "A", AF_INET, rr);
- break;
- case LDNS_RR_TYPE_AAAA:
- apply_address(srv, "AAAA", AF_INET6, rr);
- break;
- case LDNS_RR_TYPE_SRV:
- apply_srv(priv, rr);
- break;
- default:
- error("Unkown record type: %s", ldns_rr_descript(ldns_rr_get_type(rr))->_name);
- break;
- }
-}
-
-#if defined(USE_ARES) || defined(USE_UNBOUND)
-static void
-apply_answer(struct priv_srv *srv, const uint8_t *data, size_t length)
-{
- struct priv_dns *priv = srv->priv;
-
- assert(data);
- assert(length);
-
- if (priv->type) {
- netresolve_backend_set_dns_answer(priv->query, data, length);
- priv->answered = true;
- return;
- }
-
- ldns_pkt *pkt;
-
- if (ldns_wire2pkt(&pkt, data, length)) {
- error("can't parse the DNS answer");
- priv->failed = true;
- return;
- }
-
- ldns_pkt_rcode rcode = ldns_pkt_get_rcode(pkt);
- ldns_rr_type type = ldns_pkt_question(pkt)->_rrs[0]->_rr_type;
- ldns_rr_list *answer = ldns_pkt_answer(pkt);
-
-#if defined(USE_UNBOUND)
- if (!priv->validate)
-#endif
- if (!ldns_pkt_ad(pkt))
- priv->secure = false;
-
- /* libunbound seems to sometimes return an empty result with
- * rcode set to zero
- */
- if (rcode == 0 && answer->_rr_count == 0) {
- debug("fixing up rcode because of zero rr_count after libunbound");
- rcode = LDNS_RCODE_NXDOMAIN;
- }
-
- switch (rcode) {
- case 0:
- break;
- case LDNS_RCODE_NXDOMAIN:
- debug("%s records not found (%d queries left)",
- ldns_rr_descript(type)->_name,
- priv->pending);
- if (type == LDNS_RR_TYPE_SRV)
- lookup_host(&priv->srv);
- else
- priv->failed = true;
- goto out;
- default:
- error("rcode: %d", rcode);
- priv->failed = true;
- goto out;
- }
-
- for (int i = 0; i < answer->_rr_count; i++) {
- ldns_rr *rr = answer->_rrs[i];
-
- apply_record(srv, rr);
- }
-
-out:
- ldns_pkt_free(pkt);
-}
-#endif
-
-static void
-check(struct priv_dns *priv)
-{
- assert(priv->pending >= 0);
-
- if (!priv->pending) {
- if (priv->answered) {
- if (priv->secure)
- netresolve_backend_set_secure(priv->query);
- }
-
-#if defined(USE_AVAHI)
- if (priv->answered)
-#else
- if (!priv->failed)
-#endif
- netresolve_backend_finished(priv->query);
- else
- netresolve_backend_failed(priv->query);
- }
-}
-
-#if defined(USE_UNBOUND)
-
-static void apply_answer(struct priv_srv *srv, const uint8_t *answer, size_t length);
-
-static void
-ubdns_callback(void *arg, int status, struct ub_result* result)
-{
- struct priv_srv *srv = arg;
- struct priv_dns *priv = srv->priv;
-
- priv->pending--;
-
- if (status) {
- error("libunbound: %s", ub_strerror(status));
- priv->failed = true;
- return;
- }
-
- if (!result->secure)
- priv->secure = false;
-
- if (!result->bogus)
- apply_answer(srv, result->answer_packet, result->answer_len);
- else {
- error("libunbound: received bogus result");
- priv->secure = false;
- priv->failed = true;
- }
-
- ub_resolve_free(result);
-
- check(priv);
-}
-
-static void
-dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct priv_dns *priv = netresolve_backend_get_priv(query);
-
- ub_process(priv->ctx);
-}
-
-#elif defined(USE_ARES)
-
-static void dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data);
-
-static void
-watch_file_descriptors(struct priv_dns *priv)
-{
- assert(priv->nfds == 0);
-
- priv->nfds = ares_fds(priv->channel, &priv->rfds, &priv->wfds);
- priv->watches = realloc(priv->watches, priv->nfds * sizeof *priv->watches);
-
- for (int fd = 0; fd < priv->nfds; fd++) {
- if (FD_ISSET(fd, &priv->rfds))
- priv->watches[fd] = netresolve_watch_add(priv->query, fd, POLLIN, dispatch, NULL);
- if (FD_ISSET(fd, &priv->wfds))
- priv->watches[fd] = netresolve_watch_add(priv->query, fd, POLLOUT, dispatch, NULL);
- }
-}
-
-static void
-unwatch_file_descriptors(struct priv_dns *priv)
-{
- assert(priv->nfds != 0);
-
- for (int fd = 0; fd < priv->nfds; fd++)
- if (FD_ISSET(fd, &priv->rfds))
- netresolve_watch_remove(priv->query, priv->watches[fd], false);
-
- FD_ZERO(&priv->rfds);
- FD_ZERO(&priv->wfds);
- priv->nfds = 0;
-}
-
-static void
-dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct priv_dns *priv = netresolve_backend_get_priv(query);
-
- unwatch_file_descriptors(priv);
- ares_process_fd(priv->channel,
- events & POLLIN ? fd : ARES_SOCKET_BAD,
- events & POLLOUT ? fd : ARES_SOCKET_BAD);
- watch_file_descriptors(priv);
-
- check(priv);
-}
-
-static void apply_answer(struct priv_srv *srv, const uint8_t *answer, size_t length);
-
-static void
-aresdns_callback(void *arg, int status, int timeouts, unsigned char *abuf, int alen)
-{
- struct priv_srv *srv = arg;
- struct priv_dns *priv = srv->priv;
-
- priv->pending--;
-
- switch (status) {
- case ARES_EDESTRUCTION:
- /* Cleaning up. */
- return;
- case ARES_SUCCESS:
- case ARES_ENOTFOUND:
- break;
- default:
- error("ares: %s", ares_strerror(status));
- priv->failed = true;
- return;
- }
-
- apply_answer(srv, abuf, alen);
-
- check(priv);
-}
-
-#elif defined(USE_AVAHI)
-
-struct AvahiWatch {
- netresolve_query_t query;
- netresolve_watch_t watch;
- int fd;
- int events;
- AvahiWatchCallback callback;
- void *userdata;
-};
-
-struct AvahiTimeout {
- netresolve_query_t query;
- netresolve_timeout_t timeout;
- int fd;
- AvahiTimeoutCallback callback;
- void *userdata;
-};
-
-void
-watch_callback(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- AvahiWatch *w = data;
-
- w->callback(w, w->fd, events, w->userdata);
-}
-
-void
-watch_update(AvahiWatch *w, AvahiWatchEvent event)
-{
- if (w->watch) {
- netresolve_watch_remove(w->query, w->watch, false);
- w->watch = NULL;
- }
-
- /* FIXME: The event should be properly translated but so far it worked. */
- if (event)
- w->watch = netresolve_watch_add(w->query, w->fd, event, watch_callback, w);
-}
-
-AvahiWatch *
-watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata)
-{
- struct priv_avahi *priv = api->userdata;
- AvahiWatch *w = calloc(1, sizeof *w);
-
- w->query = priv->query;
- w->fd = fd;
- w->callback = callback;
- w->userdata = userdata;
-
- watch_update(w, event);
-
- return w;
-}
-
-static void
-watch_free(AvahiWatch *w)
-{
- watch_update(w, 0);
-
- memset(w, 0, sizeof *w);
- free(w);
-}
-
-void
-timeout_callback(netresolve_query_t query, netresolve_timeout_t timeout, void *data)
-{
- AvahiTimeout *t = data;
-
- t->callback(t, t->userdata);
-}
-
-static void
-timeout_update(AvahiTimeout *t, const struct timeval *tv)
-{
- if (t->timeout) {
- netresolve_timeout_remove(t->query, t->timeout);
- t->timeout = NULL;
- }
-
- if (tv) {
- long int sec = tv->tv_sec;
- long int nsec = tv->tv_usec * 1000;
-
- t->timeout = netresolve_timeout_add(t->query, sec, nsec, timeout_callback, t);
- }
-}
-
-AvahiTimeout *
-timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata)
-{
- struct priv_avahi *priv = api->userdata;
- AvahiTimeout *t = calloc(1, sizeof *t);
-
- t->query = priv->query;
- t->fd = -1;
- t->callback = callback;
- t->userdata = userdata;
-
- timeout_update(t, tv);
-
- return t;
-}
-
-void
-timeout_free(AvahiTimeout *t)
-{
- timeout_update(t, NULL);
-
- memset(t, 0, sizeof *t);
- free(t);
-}
-
-static void
-client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
- struct priv_avahi *priv = userdata;
-
- if (state == AVAHI_CLIENT_FAILURE) {
- error("Avahi connection failure: %s", avahi_strerror(avahi_client_errno(c)));
- netresolve_backend_failed(priv->query);
- }
-}
-
-static void
-record_callback (
- AvahiRecordBrowser *b,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiBrowserEvent event,
- const char *name,
- uint16_t class,
- uint16_t type,
- const void *rdata,
- size_t size,
- AvahiLookupResultFlags flags,
- void *userdata)
-{
- struct priv_srv *srv = userdata;
- struct priv_avahi *priv = srv->priv;
-
- switch (event) {
- case AVAHI_BROWSER_NEW:
- {
- ldns_rr *rr = ldns_rr_new_frm_type(type);
- ldns_rdf *rdf = NULL;
-
- switch (type) {
- case LDNS_RR_TYPE_A:
- rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_A, size, rdata);
- break;
- case LDNS_RR_TYPE_AAAA:
- rdf = ldns_rdf_new_frm_data(LDNS_RDF_TYPE_AAAA, size, rdata);
- break;
- default:
- error("Unexpected RR type: %i", type);
- return;
- }
- if (rdf)
- ldns_rr_set_rdf(rr, rdf, 0);
-
- apply_record(srv, rr);
-
- ldns_rr_free(rr);
- }
- break;
- case AVAHI_BROWSER_ALL_FOR_NOW:
- debug("avahi: all for now");
- priv->pending--;
- assert(!rdata);
- break;
- case AVAHI_BROWSER_CACHE_EXHAUSTED:
- debug("avahi: cache exhausted");
- assert(!rdata);
- break;
- case AVAHI_BROWSER_FAILURE:
- error("Avahi resolver failed.");
- netresolve_backend_failed(priv->query);
- break;
- default:
- error("Unknown Avahi event: %d", event);
- netresolve_backend_failed(priv->query);
- return;
- }
-
- check(priv);
-}
-
-static void
-address_callback (
- AvahiAddressResolver *r,
- AvahiIfIndex interface,
- AvahiProtocol protocol,
- AvahiResolverEvent event,
- const AvahiAddress *a,
- const char *name,
- AvahiLookupResultFlags flags,
- void *userdata)
-{
- struct priv_avahi *priv = userdata;
-
- priv->pending--;
-
- switch (event) {
- case AVAHI_RESOLVER_FOUND:
- netresolve_backend_add_name_info(priv->query, name, NULL);
- break;
- case AVAHI_RESOLVER_FAILURE:
- error("Avahi resolver failed.");
- netresolve_backend_failed(priv->query);
- break;
- default:
- error("Unknown Avahi event: %d", event);
- netresolve_backend_failed(priv->query);
- return;
- }
-
- check(priv);
-}
-
-#endif
-
-static void
-cleanup(void *data)
-{
- struct priv_dns *priv = data;
-
- while (priv->srv.next != &priv->srv) {
- struct priv_srv *srv = priv->srv.next;
-
- priv->srv.next = srv->next;
- srv->next->previous = &priv->srv;
-
- free(srv->name);
- free(srv);
- }
-
-#if defined(USE_UNBOUND)
- if (priv->watch)
- netresolve_watch_remove(priv->query, priv->watch, false);
- if (priv->ctx);
- ub_ctx_delete(priv->ctx);
-#elif defined(USE_ARES)
- if (priv->nfds)
- unwatch_file_descriptors(priv);
- free(priv->watches);
- ares_destroy(priv->channel);
-#elif defined(USE_AVAHI)
- if (priv->client)
- avahi_client_free(priv->client);
-#endif
-}
-
-static struct priv_dns *
-setup(netresolve_query_t query, char **settings)
-{
- struct priv_dns *priv = netresolve_backend_new_priv(query, sizeof *priv, cleanup);
- int status;
-#if defined(USE_UNBOUND)
- const char *server = NULL;
-#elif defined(USE_UNBOUND)
-
-#endif
-
- if (!priv)
- return NULL;;
-
- priv->srv.priv = priv;
- priv->srv.previous = priv->srv.next = &priv->srv;
-
- for (; *settings; settings++) {
- if (!strcmp(*settings, "trust"))
- priv->secure = true;
-#if defined(USE_UNBOUND)
- else if (!strcmp(*settings, "validate"))
- priv->validate = priv->secure = true;
- else if (!strncmp(*settings, "server=", 7))
- server = *settings + 7;
-#endif
- }
-
- const char *name = netresolve_backend_get_nodename(query);
- priv->srv.name = name ? strdup(name) : NULL;
- priv->family = netresolve_backend_get_family(query);
-
- priv->query = query;
-
-#if defined(USE_UNBOUND)
- priv->ctx = ub_ctx_create();
- if(!priv->ctx)
- return NULL;;
-
- if (server) {
- if ((status = ub_ctx_set_fwd(priv->ctx, server)) != 0) {
- error("libunbound: %s", ub_strerror(status));
- return NULL;
- }
- } else {
- if ((status = ub_ctx_resolvconf(priv->ctx, NULL)) != 0) {
- error("libunbound: %s", ub_strerror(status));
- return NULL;;
- }
- }
- if (priv->validate && (status = ub_ctx_add_ta_file(priv->ctx, "/etc/dnssec/root-anchors.txt"))) {
- error("libunbound: %s", ub_strerror(status));
- return NULL;
- }
- priv->watch = netresolve_watch_add(query, ub_fd(priv->ctx), POLLIN, dispatch, NULL);
-#elif defined(USE_ARES)
- /* ares doesn't seem to accept const options */
- static struct ares_options options = {
- .flags = ARES_FLAG_NOSEARCH | ARES_FLAG_NOALIASES,
- .lookups = "b"
- };
-
- status = ares_library_init(ARES_LIB_INIT_ALL);
- if (status != ARES_SUCCESS) {
- error("ares library: %s", ares_strerror(status));
- return NULL;
- }
- status = ares_init_options(&priv->channel, &options,
- ARES_OPT_FLAGS | ARES_OPT_LOOKUPS);
- if (status != ARES_SUCCESS) {
- error("ares channel: %s", ares_strerror(status));
- return NULL;
- }
-#elif defined(USE_AVAHI)
- priv->poll_config.userdata = priv;
- priv->poll_config.watch_new = watch_new;
- priv->poll_config.watch_update = watch_update;
- //priv->poll_config.watch_get_events = watch_get_events;
- priv->poll_config.watch_free = watch_free;
- priv->poll_config.timeout_new = timeout_new;
- priv->poll_config.timeout_update = timeout_update;
- priv->poll_config.timeout_free = timeout_free;
-
- priv->client = avahi_client_new(&priv->poll_config, 0, client_callback, priv, &status);
- if (!priv->client) {
- error("Avahi client failure: %s", avahi_strerror(status));
- return NULL;
- }
-#endif
-
- return priv;
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- struct priv_dns *priv;
-
- if (!(priv = setup(query, settings)) || !priv->srv.name) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (netresolve_backend_get_dns_srv_lookup(query)) {
- priv->protocol = netresolve_backend_get_protocol(priv->query);
- lookup_srv(priv);
- } else
- lookup_host(&priv->srv);
-
-#if defined(USE_ARES)
- watch_file_descriptors(priv);
-#endif
-}
-
-void
-query_reverse(netresolve_query_t query, char **settings)
-{
- struct priv_dns *priv;
- const uint8_t *address = netresolve_backend_get_address(query);
-
- if (!(priv = setup(query, settings)) || !address) {
- netresolve_backend_failed(query);
- return;
- }
-
-#if defined(USE_AVAHI)
-
- switch (priv->family) {
- case AF_INET:
- priv->address.proto = AVAHI_PROTO_INET;
- memcpy(&priv->address.data, netresolve_backend_get_address(query), sizeof priv->address.data.ipv4);
- break;
- case AF_INET6:
- priv->address.proto = AVAHI_PROTO_INET6;
- memcpy(&priv->address.data, netresolve_backend_get_address(query), sizeof priv->address.data.ipv6);
- break;
- default:
- break;
- }
-#else
- priv->address = address;
-#endif
-
- lookup_address(priv);
-
-#if defined(USE_ARES)
- watch_file_descriptors(priv);
-#endif
-}
-
-void
-query_dns(netresolve_query_t query, char **settings)
-{
- struct priv_dns *priv;
-
- if (!(priv = setup(query, settings)) || !priv->srv.name) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_get_dns_query(query, &priv->cls, &priv->type);
- lookup_dns(&priv->srv, priv->srv.name, priv->type, priv->cls);
-
-#if defined(USE_ARES)
- watch_file_descriptors(priv);
-#endif
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <signal.h>
-#include <stdio.h>
-
-struct buffer {
- char *buffer;
- char *start;
- char *end;
-};
-
-struct priv_exec {
- netresolve_query_t query;
- int pid;
- struct buffer inbuf;
- netresolve_watch_t input;
- struct buffer outbuf;
- netresolve_watch_t output;
-};
-
-static bool
-start_subprocess(char *const command[], int *pid, int *infd, int *outfd)
-{
- int p1[2], p2[2];
-
- if (!pid || !infd || !outfd)
- return false;
-
- if (pipe(p1) == -1)
- goto err_pipe1;
- if (pipe(p2) == -1)
- goto err_pipe2;
- if ((*pid = fork()) == -1)
- goto err_fork;
-
- if (*pid) {
- *infd = p1[1];
- *outfd = p2[0];
- close(p1[0]);
- close(p2[1]);
- return true;
- } else {
- dup2(p1[0], 0);
- dup2(p2[1], 1);
- close(p1[0]);
- close(p1[1]);
- close(p2[0]);
- close(p2[1]);
- execvp(*command, command);
- /* Subprocess error occured. */
- fprintf(stderr, "error running %s: %s", *command, strerror(errno));
- abort();
- }
-
-err_fork:
- close(p2[1]);
- close(p2[0]);
-err_pipe2:
- close(p1[1]);
- close(p1[0]);
-err_pipe1:
- return false;
-}
-
-static bool
-received_line(netresolve_query_t query, struct priv_exec *priv, const char *line)
-{
- char addrprefix[] = "address ";
- int addrprefixlen = strlen(addrprefix);
- char pathprefix[] = "path ";
- int pathprefixlen = strlen(pathprefix);
- Address address;
- int family;
- int ifindex;
- int socktype;
- int protocol;
- int port;
-
- debug("received: %s", priv->outbuf.buffer);
-
- if (!*line)
- return true;
-
- if (!strncmp(addrprefix, line, addrprefixlen)) {
- if (netresolve_backend_parse_address(line + addrprefixlen,
- &address, &family, &ifindex))
- netresolve_backend_add_path(query, family, &address, ifindex, 0, 0, 0, 0, 0, 0);
- } else if (!strncmp(pathprefix, line, pathprefixlen)) {
- if (netresolve_backend_parse_path(line + pathprefixlen,
- &address, &family, &ifindex, &socktype, &protocol, &port))
- netresolve_backend_add_path(query, family, &address, ifindex, socktype, protocol, port, 0, 0, 0);
- }
-
- return false;
-}
-
-static void
-dispatch_input(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct priv_exec *priv = data;
-
- assert(events & POLLOUT);
-
- debug("exec: events %d on fd %d", events, fd);
-
- if (priv->inbuf.start != priv->inbuf.end) {
- ssize_t size = write(priv->input->fd, priv->inbuf.start, priv->inbuf.end - priv->inbuf.start);
- if (size > 0) {
- priv->inbuf.start += size;
- return;
- }
- debug("write failed: %s", strerror(errno));
- }
-
- netresolve_watch_remove(query, priv->input, true);
- priv->input->fd = -1;
-}
-
-static void
-dispatch_output(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct priv_exec *priv = data;
- char *nl;
- int size;
-
- assert(events & (POLLIN | POLLHUP));
-
- debug("exec: events %d on fd %d", events, fd);
-
- if (events & POLLHUP) {
- error("exec: incomplete response");
- netresolve_backend_failed(query);
- return;
- }
-
- if (!priv->outbuf.buffer) {
- priv->outbuf.buffer = priv->outbuf.start = malloc(1024);
- if (priv->outbuf.buffer)
- priv->outbuf.end = priv->outbuf.start + 1024;
- }
- if (!priv->outbuf.buffer) {
- netresolve_backend_failed(query);
- return;
- }
-
- size = read(priv->output->fd, priv->outbuf.start, priv->outbuf.end - priv->outbuf.start);
- if (size <= 0) {
- abort();
- if (size < 0)
- error("read: %s", strerror(errno));
- netresolve_backend_failed(query);
- return;
- }
- debug("read: %*s", size, priv->outbuf.start);
- priv->outbuf.start += size;
-
- while ((nl = memchr(priv->outbuf.buffer, '\n', priv->outbuf.start - priv->outbuf.buffer))) {
- *nl++ = '\0';
- if (received_line(query, priv, priv->outbuf.buffer)) {
- netresolve_backend_finished(query);
- return;
- }
- memmove(priv->outbuf.buffer, nl, priv->outbuf.end - priv->outbuf.start);
- priv->outbuf.start = priv->outbuf.buffer + (priv->outbuf.start - nl);
- }
-}
-
-void
-cleanup(void *data)
-{
- struct priv_exec *priv = data;
-
- if (priv->input)
- netresolve_watch_remove(priv->query, priv->input, true);
- if (priv->output)
- netresolve_watch_remove(priv->query, priv->output, true);
- /* TODO: Implement proper child handling. */
- kill(priv->pid, SIGKILL);
- free(priv->inbuf.buffer);
- free(priv->outbuf.buffer);
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- struct priv_exec *priv = netresolve_backend_new_priv(query, sizeof *priv, cleanup);
- int infd;
- int outfd;
-
- priv->query = query;
-
- if (!priv || !start_subprocess(settings, &priv->pid, &infd, &outfd)) {
- netresolve_backend_failed(query);
- return;
- }
-
- priv->inbuf.buffer = strdup(netresolve_get_request_string(query));
- priv->inbuf.start = priv->inbuf.buffer;
- priv->inbuf.end = priv->inbuf.buffer + strlen(priv->inbuf.buffer);
-
- priv->input = netresolve_watch_add(query, infd, POLLOUT, dispatch_input, priv);
- priv->output = netresolve_watch_add(query, outfd, POLLIN, dispatch_output, priv);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <sys/utsname.h>
-#include <ifaddrs.h>
-
-static bool
-add_addresses(netresolve_query_t query, struct ifaddrs *list, bool filter)
-{
- bool result = false;
-
- for (struct ifaddrs *item = list; item; item = item->ifa_next) {
- struct sockaddr *sa = item->ifa_addr;
- void *address = NULL;
- int ifindex = 0;
-
- if (!sa)
- continue;
-
- debug("found address: dev %s family %d", item->ifa_name, sa->sa_family);
-
- switch (sa->sa_family) {
- case AF_INET:
- address = &((struct sockaddr_in *) sa)->sin_addr;
- if (filter && !memcmp(address, &inaddr_loopback, sizeof inaddr_loopback))
- continue;
- break;
- case AF_INET6:
- address = &((struct sockaddr_in6 *) sa)->sin6_addr;
- ifindex = ((struct sockaddr_in6 *) sa)->sin6_scope_id;
- if (filter && !memcmp(address, &in6addr_loopback, sizeof inaddr_loopback))
- continue;
- break;
- default:
- continue;
- }
-
- netresolve_backend_add_path(query, sa->sa_family, address, ifindex, 0, 0, 0, 0, 0, 0);
- result = true;
- }
-
- return result;
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *nodename = netresolve_backend_get_nodename(query);
- struct ifaddrs *list;
- struct utsname name;
-
- uname(&name);
- if (!nodename || strcmp(nodename, name.nodename)) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (getifaddrs(&list)) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (!add_addresses(query, list, true))
- add_addresses(query, list, false);
-
- netresolve_backend_set_canonical_name(query, nodename);
- netresolve_backend_finished(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-struct hosts_list {
- struct hosts_item *items;
- int count;
- int reserved;
-};
-
-struct hosts_item {
- char *name;
- int family;
- union {
- struct in_addr address4;
- struct in6_addr address6;
- } address;
- int ifindex;
-};
-
-static size_t
-family_to_length(int family)
-{
- switch (family) {
- case AF_INET:
- return 4;
- case AF_INET6:
- return 16;
- default:
- return 0;
- }
-}
-
-static void
-add_node(struct hosts_list *list, const char *name, int family, void *address, int ifindex)
-{
- struct hosts_item item = {
- .family = family,
- .ifindex = ifindex,
- .name = name ? strdup(name) : NULL
- };
-
- memcpy(&item.address, address, family_to_length(family));
-
- if (list->count == list->reserved) {
- if (!list->reserved)
- list->reserved = 256;
- else
- list->reserved *= 2;
- list->items = realloc(list->items, list->reserved * sizeof item);
- }
-
- debug("hosts: adding item %s family %d", item.name, item.family);
- memcpy(&list->items[list->count++], &item, sizeof item);
-}
-
-static void
-read_item(struct hosts_list *list, char *line)
-{
- const char *name;
- Address address;
- int family;
- int ifindex;
-
- if (!(netresolve_backend_parse_address(strtok(line, " \t"), &address, &family, &ifindex)))
- return;
- while ((name = strtok(NULL, " \t")))
- add_node(list, name, family, &address, ifindex);
-}
-
-#define BUFFER_SIZE 1024
-
-static char *
-concat(const char *a, const char *b)
-{
- char *result = malloc(strlen(a) + strlen(b) + 1);
-
- if (result) {
- strcpy(result, a);
- strcat(result, b);
- }
-
- return result;
-}
-
-static char *
-get_hosts_file(void)
-{
- const char *etc = getenv("NETRESOLVE_SYSCONFDIR") ?: "/etc";
- const char *suffix = "/hosts";
-
- return concat(etc, suffix);
-}
-
-static void
-read_list(struct hosts_list *list)
-{
- char *hosts_file = get_hosts_file();
- int fd = open(hosts_file, O_RDONLY);
- char buffer[BUFFER_SIZE];
- char *current = buffer;
- char *end = buffer + sizeof buffer;
- char *new;
- size_t size;
-
- free(hosts_file);
-
- if (fd == -1) {
- error("Cannot read hosts file '%s': %s", hosts_file, strerror(errno));
- goto fail_open;
- }
-
- while (true) {
- if (current == end)
- goto out;
-
- size = read(fd, current, end-current);
-
- if (size == 0)
- goto out;
- if (size == -1)
- goto out;
-
- current += size;
-
- /* buffer ...record... new ...next... current ...empty... end */
- for (new = buffer; new < current; new++) {
- /* Comment */
- if (*new == '#')
- *new = '\0';
- /* New line */
- if (*new == '\n') {
- *new++ = '\0';
- read_item(list, buffer);
- memmove(buffer, new, current - new);
- current = buffer + (current - new);
- new = buffer - 1;
- }
- }
-
- }
-out:
- close(fd);
-fail_open:
- add_node(list, NULL, 0, NULL, 0);
- list->reserved = list->count;
- list->items = realloc(list->items, list->reserved * sizeof *list->items);
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- struct hosts_list list = { 0 };
- struct hosts_item *item;
- int count = 0;
-
- if (!node) {
- netresolve_backend_failed(query);
- return;
- }
-
- /* TODO: Would be nice to read the hosts once in a thread-safe way and with timestamp checking. */
- read_list(&list);
-
- for (item = list.items; item->name; item++) {
- if (strcmp(node, item->name))
- continue;
- netresolve_backend_add_path(query, item->family, &item->address, item->ifindex, 0, 0, 0, 0, 0, 0);
- count++;
- }
-
- if (count) {
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
-
- free(list.items);
-}
-
-void
-query_reverse(netresolve_query_t query, char **settings)
-{
- int family = netresolve_backend_get_family(query);
- const void *address = netresolve_backend_get_address(query);
- struct hosts_list list = { 0 };
- struct hosts_item *item;
- int count = 0;
-
- /* FIXME: we need to read the host once and in a thread-safe manner */
- read_list(&list);
-
- for (item = list.items; item->name; item++) {
- if (family != item->family)
- continue;
- if (memcmp(address, &item->address, family_to_length(family)))
- continue;
- count++;
- netresolve_backend_add_name_info(query, item->name, NULL);
- }
-
- if (count) {
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
-
- free(list.items);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <resolv.h>
-
-#define SIZE 16 * 1024
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- const char *service = netresolve_backend_get_servname(query);
- struct addrinfo hints = netresolve_backend_get_addrinfo_hints(query);
- int status;
- struct addrinfo *result;
-
- if ((status = getaddrinfo(node, service, &hints, &result))) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_apply_addrinfo(query, status, result, 0);
-}
-
-void
-query_reverse(netresolve_query_t query, char **settings)
-{
- int flags = 0;
- union {
- struct sockaddr sa;
- struct sockaddr_in sa4;
- struct sockaddr_in6 sa6;
- } sa = { { 0 } };
- int status;
- char nodename[SIZE], servname[SIZE];
-
- sa.sa.sa_family = netresolve_backend_get_family(query);
-
- switch (sa.sa.sa_family) {
- case AF_INET:
- memcpy(&sa.sa4.sin_addr, netresolve_backend_get_address(query), sizeof sa.sa4.sin_addr);
- sa.sa4.sin_port = netresolve_backend_get_port(query);
- status = getnameinfo(&sa.sa, sizeof sa.sa4, nodename, sizeof nodename, servname, sizeof servname, flags);
- break;
- case AF_INET6:
- memcpy(&sa.sa6.sin6_addr, netresolve_backend_get_address(query), sizeof sa.sa6.sin6_addr);
- sa.sa6.sin6_port = netresolve_backend_get_port(query);
- status = getnameinfo(&sa.sa, sizeof sa.sa4, nodename, sizeof nodename, servname, sizeof servname, flags);
- break;
- default:
- status = EAI_FAMILY;
- break;
- }
-
- if (status) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_add_name_info(query, nodename, servname);
- netresolve_backend_finished(query);
-}
-
-void
-query_dns(netresolve_query_t query, char **settings)
-{
- const char *dname = netresolve_backend_get_nodename(query);
- bool search = netresolve_backend_get_dns_search(query);
- int cls;
- int type;
- uint8_t answer[SIZE];
- size_t length;
-
- netresolve_backend_get_dns_query(query, &cls, &type);
-
- length = (search ? res_search : res_query)(dname, cls, type, answer, sizeof answer);
-
- if (length == -1) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_set_dns_answer(query, answer, length);
- netresolve_backend_finished(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-static bool
-is_any(int family, const void *address)
-{
- switch (family) {
- case AF_INET:
- return !memcmp(address, &inaddr_any, sizeof inaddr_any);
- case AF_INET6:
- return !memcmp(address, &in6addr_any, sizeof in6addr_any);
- default:
- return false;
- }
-}
-
-static bool
-is_loopback(int family, const void *address)
-{
- switch (family) {
- case AF_INET:
- return !memcmp(address, &inaddr_loopback, sizeof inaddr_loopback);
- case AF_INET6:
- return !memcmp(address, &in6addr_loopback, sizeof in6addr_loopback);
- default:
- return false;
- }
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- bool ipv4 = !node || !*node || !strcmp(node, "localhost") || !strcmp(node, "localhost4");
- bool ipv6 = !node || !*node || !strcmp(node, "localhost") || !strcmp(node, "localhost6");
-
- if (!ipv4 && !ipv6) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_set_canonical_name(query, "localhost");
- if (ipv4)
- netresolve_backend_add_path(query, AF_INET, &inaddr_loopback, 0, 0, 0, 0, 0, 0, 0);
- if (ipv6)
- netresolve_backend_add_path(query, AF_INET6, &in6addr_loopback, 0, 0, 0, 0, 0, 0, 0);
-
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
-}
-
-void
-query_reverse(netresolve_query_t query, char **settings)
-{
- int family = netresolve_backend_get_family(query);
- const void *address = netresolve_backend_get_address(query);
-
- if (!is_any(family, address) && !is_loopback(family, address)) {
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_add_name_info(query, "localhost", NULL);
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <dlfcn.h>
-#include <resolv.h>
-
-#define SIZE (128*1024)
-
-struct priv_nss {
- char *name;
- char *filename;
- const char *api;
- void *dl_handle;
- /* gethostbyname:
- *
- * Supports only IPv4.
- */
- enum nss_status (*gethostbyname_r)(const char *name,
- struct hostent *host,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop);
- /* gethostbyname2:
- *
- * Offers an additional argument 'af' to choose between IPv4 and IPv6 name
- * resolution, doesn't support mixed IPv4/IPv6
- */
- enum nss_status (*gethostbyname2_r)(const char *name, int af,
- struct hostent *host,
- char *buffer, size_t buflen,
- int *errnop, int *h_errnop);
- /* gethostbyname3:
- *
- * Supports IPv4/IPv6 via 'af' like gethostbyname2(), 'ttlp' for returning
- * the TTL, 'canonp' for returning the canonical name.
- */
- enum nss_status (*gethostbyname3_r)(const char *name, int af,
- struct hostent *host,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop, int32_t *ttlp, char **canonp);
- /* gethostbyname4:
- *
- * Returns mixed IPv4/IPv6 and TTL via 'ttlp'. Doesn't support separate
- * IPv4/IPv6 nor canonical name.
- */
- enum nss_status (*gethostbyname4_r)(const char *name,
- struct gaih_addrtuple **pat,
- char *buffer, size_t buflen, int *errnop,
- int *h_errnop, int32_t *ttlp);
- /* getaddrinfo:
- *
- * A getaddrinfo based API encorporating capabilities of all
- * gethostbyname*_r APIs and more.
- */
- int (*getaddrinfo)(res_state state, const char *nodename, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **res,
- int32_t *ttlp);
-};
-
-static int
-combine_statuses(int s4, int s6)
-{
- /* NSS_STATUS_TRYAGAIN first, as it means we don't have the final version
- * of the information.
- */
- if (s4 == NSS_STATUS_TRYAGAIN || s6 == NSS_STATUS_TRYAGAIN)
- return NSS_STATUS_TRYAGAIN;
- /* NSS_STATUS_SUCCESS next, as e.g. libnss_mdns4's gethostbyname3 returns
- * NSS_STATUS_UNAVAIL for family=AF_INET6 requests.
- */
- if (s4 == NSS_STATUS_SUCCESS || s6 == NSS_STATUS_SUCCESS)
- return NSS_STATUS_SUCCESS;
- /* NSS_STATUS_NOTFOUND only accepted when returned for both protocols. */
- if (s4 == NSS_STATUS_NOTFOUND && s6 == NSS_STATUS_NOTFOUND)
- return NSS_STATUS_NOTFOUND;
- /* Fallback to NSS_STATUS_UNAVAIL. */
- return NSS_STATUS_UNAVAIL;
-}
-
-static void
-try_symbol_pattern(netresolve_query_t query, struct priv_nss *priv, void **f, const char *pattern, const char *api)
-{
- char symbol[1024] = { 0 };
-
- if (priv->api && strcmp(priv->api, api))
- return;
-
- snprintf(symbol, sizeof symbol, pattern, priv->name);
- *f = dlsym(priv->dl_handle, symbol);
-
- if (*f)
- debug("loaded %s (%s)", symbol, api);
- else
- debug("not loaded %s (%s): %s", symbol, api, dlerror());
-}
-
-static void
-initialize(struct priv_nss *priv, netresolve_query_t query, char **settings)
-{
- char *p;
-
- if (!settings || !*settings) {
- error("missing argument");
- goto out;
- }
-
- /* parse settings */
- priv->name = strdup(*settings++);
- if (*settings)
- priv->api = *settings++;
- if ((p = strrchr(priv->name, '/'))) {
- priv->filename = strdup(priv->name);
- p++;
- if (!strncmp(p, "libnss_", 7)) {
- p += 7;
- memmove(priv->name, p, strlen(p));
- }
- if ((p = strchr(priv->name, '.')))
- *p = '\0';
- } else
- if (asprintf(&priv->filename, "libnss_%s.so.2", priv->name) == -1)
- priv->filename = NULL;
-
- /* load nsswitch module */
- debug("loading NSS module: %s", priv->filename);
- priv->dl_handle = dlopen(priv->filename, RTLD_LAZY);
- if (!priv->dl_handle) {
- error("%s", dlerror());
- goto out;
- }
-
- /* find nsswitch entry points */
- try_symbol_pattern(query, priv, (void *) &priv->gethostbyname_r, "_nss_%s_gethostbyname_r", "gethostbyname");
- try_symbol_pattern(query, priv, (void *) &priv->gethostbyname2_r, "_nss_%s_gethostbyname2_r", "gethostbyname2");
- try_symbol_pattern(query, priv, (void *) &priv->gethostbyname3_r, "_nss_%s_gethostbyname3_r", "gethostbyname3");
- try_symbol_pattern(query, priv, (void *) &priv->gethostbyname4_r, "_nss_%s_gethostbyname4_r", "gethostbyname4");
- try_symbol_pattern(query, priv, (void *) &priv->getaddrinfo, "_nss_%s_getaddrinfo", "getaddrinfo");
-
-out:
- free(priv->name);
- priv->name = NULL;
- free(priv->filename);
- priv->filename = NULL;
-}
-
-static void
-finalize(struct priv_nss *priv)
-{
- dlclose(priv->dl_handle);
-}
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- int family = netresolve_backend_get_family(query);
- struct priv_nss priv = { 0 };
-
- initialize(&priv, query, settings);
-
- if (!priv.dl_handle) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (priv.getaddrinfo) {
- const char *service = netresolve_backend_get_servname(query);
- struct addrinfo hints = netresolve_backend_get_addrinfo_hints(query);
- int status;
- struct addrinfo *result;
- int32_t ttl;
-
- status = DL_CALL_FCT(priv.getaddrinfo, (NULL, node, service, &hints, &result, &ttl));
- netresolve_backend_apply_addrinfo(query, status, result, ttl);
- if (status == 0)
- freeaddrinfo(result);
- } else if (node && priv.gethostbyname4_r && family == AF_UNSPEC) {
- char buffer[SIZE] = { 0 };
- enum nss_status status;
- /* The libnss_files.so plugin checks the gaih_addrtuple pointer for being
- * NULL and fails badly otherwise. Whether such behavior is correct
- * remains a question.
- */
- struct gaih_addrtuple *result = NULL;
- int errnop, h_errnop;
- int32_t ttl = 0;
-
- /* Without this, libnss_files won't resolve using multiple records
- * in /etc/hosts, e.g. won't return both IPv4 and IPv6 for "localhost"
- * even when /etc/hosts is configured correctly.
- *
- * See relevant files in glibc sources:
- * - nss_files/files-hosts.c
- * - resolv/res_hconf.h
- */
- extern struct {
- int initialized;
- int unused1;
- int unused2[4];
- int num_trimdomains;
- const char *trimdomain[4];
- unsigned int flags;
- } _res_hconf;
- _res_hconf.flags = 0x10;
-
- status = DL_CALL_FCT(priv.gethostbyname4_r, (node, &result,
- buffer, sizeof buffer, &errnop, &h_errnop, &ttl));
- netresolve_backend_apply_addrtuple(query, status, result, ttl);
- } else if (node && (priv.gethostbyname3_r || priv.gethostbyname2_r)) {
- char buffer4[SIZE] = { 0 };
- char buffer6[SIZE] = { 0 };
- int status4 = NSS_STATUS_NOTFOUND, status6 = NSS_STATUS_NOTFOUND;
- struct hostent he4, he6;
- int errnop, h_errnop;
- int32_t ttl4 = 0;
- int32_t ttl6 = 0;
- char *canonname4 = NULL;
- char *canonname6 = NULL;
-
- if (priv.gethostbyname3_r) {
- if (family == AF_INET || family == AF_UNSPEC)
- status4 = DL_CALL_FCT(priv.gethostbyname3_r, (node, AF_INET,
- &he4, buffer4, sizeof buffer4, &errnop, &h_errnop, &ttl4, &canonname4));
- if (family == AF_INET6 || family == AF_UNSPEC)
- status6 = DL_CALL_FCT(priv.gethostbyname3_r, (node, AF_INET6,
- &he6, buffer6, sizeof buffer6, &errnop, &h_errnop, &ttl6, &canonname6));
- } else {
- if (family == AF_INET || family == AF_UNSPEC)
- status4 = DL_CALL_FCT(priv.gethostbyname2_r, (node, AF_INET,
- &he4, buffer4, sizeof buffer4, &errnop, &h_errnop));
- if (family == AF_INET6 || family == AF_UNSPEC)
- status6 = DL_CALL_FCT(priv.gethostbyname2_r, (node, AF_INET6,
- &he6, buffer6, sizeof buffer6, &errnop, &h_errnop));
- }
-
- if (combine_statuses(status4, status6) == NSS_STATUS_SUCCESS) {
- if (status6 == NSS_STATUS_SUCCESS && canonname6)
- netresolve_backend_set_canonical_name(query, canonname6);
- else if (status4 == NSS_STATUS_SUCCESS && canonname4)
- netresolve_backend_set_canonical_name(query, canonname4);
- if (status6 == NSS_STATUS_SUCCESS)
- netresolve_backend_apply_hostent(query, &he6, 0, 0, 0, 0, 0, ttl4);
- if (status4 == NSS_STATUS_SUCCESS)
- netresolve_backend_apply_hostent(query, &he4, 0, 0, 0, 0, 0, ttl6);
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
- } else if (node && priv.gethostbyname_r) {
- char buffer[SIZE];
- int errnop, h_errnop;
- struct hostent he;
- enum nss_status status;
-
- status = DL_CALL_FCT(priv.gethostbyname_r, (node,
- &he, buffer, sizeof buffer, &errnop, &h_errnop));
-
- if (status == NSS_STATUS_SUCCESS) {
- netresolve_backend_apply_hostent(query, &he, 0, 0, 0, 0, 0, 0);
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
- } else {
- debug("no suitable backend found");
- netresolve_backend_failed(query);
- }
-
- finalize(&priv);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- Address address;
- int family;
- int ifindex;
-
- if (!netresolve_backend_parse_address(node, &address, &family, &ifindex)) {
- netresolve_backend_failed(query);
- return;
- }
-
- if (ifindex >= 0) {
- netresolve_backend_add_path(query, family, &address, ifindex, 0, 0, 0, 0, 0, 0);
- netresolve_backend_set_canonical_name(query, node);
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-backend.h>
-#include <stdlib.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-void
-query_forward(netresolve_query_t query, char **settings)
-{
- const char *node = netresolve_backend_get_nodename(query);
- int family = netresolve_backend_get_family(query);
- int socktype = netresolve_backend_get_socktype(query);
-
- if (family != AF_UNIX || !node || *node != '/'){
- netresolve_backend_failed(query);
- return;
- }
-
- netresolve_backend_add_path(query, AF_UNIX, node, 0, socktype, 0, 0, 0, 0, 0);
- netresolve_backend_set_secure(query);
- netresolve_backend_finished(query);
-}
+++ /dev/null
-#include <netresolve-private.h>
-#include <netresolve-compat.h>
-#include <netresolve-epoll.h>
-//#include <libasyncns.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <poll.h>
-
-typedef struct netresolve_asyncns asyncns_t;
-typedef struct netresolve_asyncns_query asyncns_query_t;
-
-struct netresolve_asyncns_query {
- asyncns_t *asyncns;
- netresolve_query_t query;
- bool done;
- void *userdata;
- asyncns_query_t *previous;
- asyncns_query_t *next;
-};
-
-struct netresolve_asyncns {
- netresolve_t context;
- asyncns_query_t queries;
-};
-
-static void
-enqueue(asyncns_query_t *list, asyncns_query_t *q)
-{
- q->previous = list->previous;
- q->next = list;
-
- q->previous->next = q;
- q->next->previous = q;
-}
-
-static void
-dequeue(asyncns_query_t *q)
-{
- q->previous->next = q->next;
- q->next->previous = q->previous;
-}
-
-static void
-callback(netresolve_query_t query, void *user_data)
-{
- asyncns_query_t *q = user_data;
-
- q->done = true;
-}
-
-asyncns_t *
-asyncns_new (unsigned n_proc)
-{
- asyncns_t *asyncns;
-
- if (!(asyncns = calloc(1, sizeof *asyncns)))
- goto fail_asyncns;
-
- if (!(asyncns->context = netresolve_epoll_new()))
- goto fail_context;
-
- asyncns->queries.previous = asyncns->queries.next = &asyncns->queries;
-
- return asyncns;
-fail_context:
- free(asyncns);
-fail_asyncns:
- return NULL;
-}
-
-int
-asyncns_fd(asyncns_t *asyncns)
-{
- return netresolve_epoll_fd(asyncns->context);
-}
-
-int
-asyncns_wait(asyncns_t *asyncns, int block)
-{
- if (block)
- netresolve_epoll_wait(asyncns->context);
- else
- netresolve_epoll_dispatch(asyncns->context);
-
- /* undocumented return value */
- return 0;
-}
-
-static asyncns_query_t *
-add_query(asyncns_t *asyncns, asyncns_query_t *q, netresolve_query_t query)
-{
- if (!query) {
- free(q);
- return NULL;
- }
-
- q->asyncns = asyncns;
- q->query = query;
-
- enqueue(&asyncns->queries, q);
-
- return q;
-}
-
-static netresolve_query_t
-remove_query(asyncns_query_t *q)
-{
- netresolve_query_t query = q->query;
-
- dequeue(q);
- free(q);
-
- return query;
-}
-
-asyncns_query_t *
-asyncns_getaddrinfo(asyncns_t *asyncns, const char *node, const char *service, const struct addrinfo *hints)
-{
- asyncns_query_t *q;
-
- if (!(q = calloc(1, sizeof *q)))
- return NULL;
-
- return add_query(asyncns, q, netresolve_query_getaddrinfo(asyncns->context, node, service, hints, callback, q));
-}
-
-int
-asyncns_getaddrinfo_done (asyncns_t *asyncns, asyncns_query_t *q, struct addrinfo **result)
-{
- return netresolve_query_getaddrinfo_done(remove_query(q), result, NULL);
-}
-
-asyncns_query_t *
-asyncns_getnameinfo (asyncns_t *asyncns, const struct sockaddr *sa, socklen_t salen, int flags, int gethost, int getserv)
-{
- asyncns_query_t *q;
-
- if (!(q = calloc(1, sizeof *q)))
- return NULL;
-
- return add_query(asyncns, q, netresolve_query_getnameinfo(asyncns->context, sa, salen, flags, callback, q));
-}
-
-int
-asyncns_getnameinfo_done (asyncns_t *asyncns, asyncns_query_t *q, char *host, size_t hostlen, char *serv, size_t servlen)
-{
- char *myhost;
- char *myserv;
- int status;
-
- status = netresolve_query_getnameinfo_done(remove_query(q), &myhost, &myserv, NULL);
-
- if (!status) {
- size_t myhostlen = strlen(myhost) + 1;
- size_t myservlen = strlen(myserv) + 1;
-
- if (hostlen <= myhostlen && servlen <= myservlen) {
- memcpy(host, myhost, myhostlen);
- memcpy(serv, myserv, myservlen);
- } else
- status = ERANGE;
-
- free(myhost);
- free(myserv);
- }
-
- return status;
-}
-
-asyncns_query_t *
-asyncns_res_query (asyncns_t *asyncns, const char *dname, int class, int type)
-{
- asyncns_query_t *q;
-
- if (!(q = calloc(1, sizeof *q)))
- return NULL;
-
- return add_query(asyncns, q, netresolve_query_dns(asyncns->context, dname, class, type, callback, q));
-}
-
-asyncns_query_t *
-asyncns_res_search (asyncns_t *asyncns, const char *dname, int class, int type)
-{
- /* FIXME: enable search */
-
- return asyncns_res_query(asyncns, dname, class, type);
-}
-
-int
-asyncns_res_done (asyncns_t *asyncns, asyncns_query_t *q, unsigned char **answer)
-{
- size_t length;
- const char *query_answer = netresolve_query_get_dns_answer(q->query, &length);
-
- *answer = malloc(length);
- memcpy(*answer, query_answer, length);
-
- netresolve_query_free(remove_query(q));
-
- return 0;
-}
-
-asyncns_query_t *
-asyncns_getnext (asyncns_t *asyncns)
-{
- asyncns_query_t *list = &asyncns->queries;
-
- for (asyncns_query_t *q = list->next; q != list; q = q->next)
- if (q->done)
- return q;
-
- return NULL;
-}
-
-int
-asyncns_getnqueries (asyncns_t *asyncns)
-{
- asyncns_query_t *list = &asyncns->queries;
- int count = 0;
-
- for (asyncns_query_t *q = list->next; q != list; q = q->next)
- count++;
-
- return count;
-}
-
-void
-asyncns_cancel (asyncns_t *asyncns, asyncns_query_t *q)
-{
- netresolve_query_free(q->query);
- dequeue(q);
- free(q);
-}
-
-void
-asyncns_free (asyncns_t *asyncns)
-{
- asyncns_query_t *list = &asyncns->queries;
-
- while (list->next != list)
- asyncns_cancel(asyncns, list->next);
-
- netresolve_context_free(asyncns->context);
-
- free(asyncns);
-}
-
-void
-asyncns_freeaddrinfo (struct addrinfo *result)
-{
- netresolve_freeaddrinfo(result);
-}
-
-void
-asyncns_freeanswer (unsigned char *answer)
-{
- free(answer);
-}
-
-int
-asyncns_isdone (asyncns_t *asyncns, asyncns_query_t *q)
-{
- return q->done;
-}
-
-void
-asyncns_setuserdata (asyncns_t *asyncns, asyncns_query_t *q, void *userdata)
-{
- q->userdata = userdata;
-}
-
-void *
-asyncns_getuserdata (asyncns_t *asyncns, asyncns_query_t *q)
-{
- return q->userdata;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-compat.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <resolv.h>
-
-/* getaddrinfo:
- *
- * Translate `nodename` and `servname` using `hints` into a linked list of
- * address records including both L3 and L4 information. Canonical name,
- * if requested, is present in the first address record.
- *
- * The caller is responsible for freeing the data using `freeaddrinfo()`. The
- * function is reentrant, threat safe and doesn't leak memory.
- *
- * Defined in POSIX.1-2008.
- */
-int
-getaddrinfo(const char *nodename, const char *servname,
- const struct addrinfo *hints, struct addrinfo **result)
-{
- netresolve_query_t query = netresolve_query_getaddrinfo(NULL, nodename, servname, hints, NULL, NULL);
- int status = EAI_SYSTEM;
-
- if (query)
- status = netresolve_query_getaddrinfo_done(query, result, NULL);
-
- return status;
-}
-
-/* freeaddrinfo:
- *
- * Free data returned by `getaddrinfo()`.
- *
- * Defined in POSIX.1-2008.
- */
-void
-freeaddrinfo(struct addrinfo *result)
-{
- netresolve_freeaddrinfo(result);
-}
-
-/* getnameinfo:
- *
- * Translate the `sa` into `host` and `serv`. The caller supplies buffers to
- * store the result.
- *
- * Defined in POSIX.1-2008.
- */
-int getnameinfo(const struct sockaddr *sa, socklen_t salen,
- char *host, socklen_t hostlen,
- char *serv, socklen_t servlen,
- int flags)
-{
- netresolve_query_t query = netresolve_query_getnameinfo(NULL, sa, salen, flags, NULL, NULL);
- int status = EAI_SYSTEM;
- char *myhost = NULL;
- char *myserv = NULL;
- int myhostlen, myservlen;
-
- if (query)
- status = netresolve_query_getnameinfo_done(query, &myhost, &myserv, NULL);
-
- if (!status) {
- myhostlen = myhost ? strlen(myhost) + 1 : 0;
- myservlen = myserv ? strlen(myserv) + 1 : 0;
- if ((host && myhostlen > hostlen) || (serv && myservlen > servlen))
- return EAI_OVERFLOW;
- if (host) {
- memset(host, 0, hostlen);
- if (myhost)
- memcpy(host, myhost, myhostlen);
- }
- if (serv) {
- memset(serv, 0, servlen);
- if (myserv)
- memcpy(serv, myserv, myservlen);
- }
- }
-
- return status;
-}
-
-/* gethostbyname2:
- *
- * Legacy extended version of `gethostbyname()`o lookup either IPv4 or IPv6 addresses for a
- * specified family. Result for AF_UNSPEC is not specified.
- *
- * Replaced by `getaddrinfo()` as follows:
- *
- * * nodename = node
- * * servname = NULL
- * * hints.family = family
- * * hints.socktype = SOCK_RAW
- *
- * See notes for `gethostbyname()`.
- *
- * GNU extention to POSIX.1-2001 `gethostbyname()`
- */
-struct hostent *
-gethostbyname2(const char *node, int family)
-{
- netresolve_query_t query = netresolve_query_gethostbyname(NULL, node, family, NULL, NULL);
- static struct hostent *he = NULL;
-
- if (query) {
- netresolve_freehostent(he);
- he = netresolve_query_gethostbyname_done(query, &h_errno, NULL);
- }
-
- return he;
-}
-
-/* Legacy functions without a family parameter will only lookup IPv4. */
-#define GETHOSTBYNAME_FAMILY AF_INET
-
-/* gethostbyname:
- *
- * Legacy API to lookup IPv4 addresses for a specified hostname. Memory for
- * the result is allocated in a static buffer. The caller must not free it
- * and the function is not reentrant.
- *
- * Replaced by `getaddrinfo()` as follows:
- *
- * * nodename = node
- * * servname = NULL
- * * hints.family = AF_INET
- * * hints.socktype = SOCK_RAW
- *
- * Note: Using SOCK_RAW is not explicitly mandated by POSIX but it is required
- * by the GNU implementation.
- *
- * Defined in POSIX.1-2001, removed in POSIX.1-2008.
- */
-struct hostent *
-gethostbyname(const char *node)
-{
- return gethostbyname2(node, GETHOSTBYNAME_FAMILY);
-}
-
-struct hostent *
-gethostbyaddr(const void *addr, socklen_t len, int type)
-{
- netresolve_query_t query = netresolve_query_gethostbyaddr(NULL, addr, len, type, NULL, NULL);
- static struct hostent *he = NULL;
-
- if (query) {
- netresolve_freehostent(he);
- he = netresolve_query_gethostbyaddr_done(query, &h_errno, NULL);
- }
-
- return he;
-}
-
-
-/* gethostbyname2_r:
- *
- * Reentrant version of `gethostbyname2()`, see notes for `gethostbyname()`.
- */
-int
-gethostbyname2_r(const char *name, int family,
- struct hostent *he, char *buffer, size_t buflen,
- struct hostent **result, int *h_errnop)
-{
- netresolve_query_t query = netresolve_query_gethostbyname(NULL, name, family, NULL, NULL);
- struct hostent *tmp;
-
- if (!query) {
- *result = NULL;
- return errno;
- }
-
- tmp = netresolve_query_gethostbyname_done(query, h_errnop, NULL);
-
- size_t len_name = tmp->h_name ? strlen(tmp->h_name) + 1 : 0;
- size_t count = 0;
- for (char **alias = tmp->h_aliases; *alias; alias++)
- count++;
- size_t len_aliases = (count + 1) * sizeof *tmp->h_aliases;
- count = 0;
- for (char **addr = tmp->h_addr_list; *addr; addr++)
- count++;
- size_t len_addr_list = (count + 1) * sizeof *tmp->h_addr_list;
- size_t len_addr_data = count * tmp->h_length;
- size_t len_total = len_aliases + len_name + len_addr_list + len_addr_data;
-
- if (len_total > buflen) {
- *result = NULL;
- return ERANGE;
- }
-
- memcpy(he, tmp, sizeof *he);
- memset(buffer, 0, buflen);
- he->h_name = buffer;
- he->h_aliases = (void *) buffer + len_name;
- he->h_addr_list = (void *) buffer + len_name + len_aliases;
- memcpy(he->h_name, tmp->h_name, len_name);
- /* we don't allocate space for actual aliases */
- memset(he->h_aliases, 0, len_aliases);
- memcpy(he->h_addr_list, tmp->h_addr_list, len_addr_list);
- for (int i = 0; tmp->h_addr_list[i]; i++) {
- he->h_addr_list[i] = buffer + len_name + len_aliases + len_addr_list + i * tmp->h_length;
- memcpy(he->h_addr_list[i], tmp->h_addr_list[i], he->h_length);
- }
-
- netresolve_freehostent(tmp);
-
- *result = he;
-
- return 0;
-}
-
-/* gethostbyname2_r:
- *
- * Reentrant version of `gethostbyname()`, see notes for `gethostbyname()`.
- */
-int
-gethostbyname_r(const char *name,
- struct hostent *he, char *buffer, size_t buflen,
- struct hostent **result, int *h_errnop)
-{
- return gethostbyname2_r(name, GETHOSTBYNAME_FAMILY, he, buffer, buflen, result, h_errnop);
-}
-
-static int
-_res_query(const char *dname, int class, int type, bool search, unsigned char *answer, int length)
-{
- netresolve_query_t query = netresolve_query_dns(NULL, dname, class, type, NULL, NULL);
- const char *myanswer;
- size_t mylength = -1;
-
- if (query) {
- myanswer = netresolve_query_get_dns_answer(query, &mylength);
-
- if (mylength > length)
- goto out;
-
- memcpy(answer, myanswer, mylength);
- }
-
-out:
- netresolve_query_free(query);
- return mylength;
-}
-
-int
-res_query(const char *dname, int class, int type, unsigned char *answer, int anslen)
-{
- return _res_query(dname, class, type, false, answer, anslen);
-}
-
-int
-res_search(const char *dname, int class, int type, unsigned char *answer, int anslen)
-{
- return _res_query(dname, class, type, true, answer, anslen);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-compat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-#include <assert.h>
-#include <arpa/inet.h>
-#include <nss.h>
-#include <netdb.h>
-#include <resolv.h>
-
-int
-_nss_netresolve_getaddrinfo(res_state state, const char *nodename, const char *servname,
- const struct addrinfo *hints,
- struct addrinfo **result, int32_t *ttl)
-{
- netresolve_t context;
- netresolve_query_t query;
- int status = EAI_SYSTEM;
-
- if (!(context = netresolve_context_new()))
- return status;
-
- if ((query = netresolve_query_getaddrinfo(context, nodename, servname, hints, NULL, NULL)))
- status = netresolve_query_getaddrinfo_done(query, result, ttl);
-
- netresolve_context_free(context);
- return status;
-}
-
-struct buffer_t {
- char *data;
- size_t length;
- int *errnop;
-};
-
-static void *
-buffer_append(const void *data, size_t size, struct buffer_t *buffer)
-{
- void *position = buffer->data;
-
- if (data && !size)
- size = strlen(data) + 1;
-
- if (buffer->length < size) {
- *buffer->errnop = ERANGE;
- return NULL;
- }
-
- buffer->data += size;
- buffer->length -= size;
-
- if (data)
- memcpy(position, data, size);
- else
- memset(position, 0, size);
-
- return position;
-}
-
-static void
-extract_address(struct addrinfo *item, void *address)
-{
- if (address) {
- switch (item->ai_family) {
- case AF_INET:
- memcpy(address, &((struct sockaddr_in *) (item->ai_addr))->sin_addr, sizeof (struct in_addr));
- return;
- case AF_INET6:
- memcpy(address, &((struct sockaddr_in6 *) (item->ai_addr))->sin6_addr, sizeof (struct in6_addr));
- return;
- }
- }
-}
-
-enum nss_status
-_nss_netresolve_gethostbyname4_r(const char *nodename,
- struct gaih_addrtuple **result,
- char *bufptr, size_t buflen, int *errnop,
- int *h_errnop, int32_t *ttlp)
-{
- struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = SOCK_RAW,
- .ai_flags = AI_CANONNAME
- };
- struct buffer_t buffer = { .data = bufptr, .length = buflen, .errnop = errnop };
- int status;
- struct addrinfo *list;
-
- status = _nss_netresolve_getaddrinfo(NULL, nodename, NULL, &hints, &list, ttlp);
-
- if (status)
- return NSS_STATUS_UNAVAIL;
-
- /* addresses */
- for (struct addrinfo *item = list; item; item = item->ai_next) {
- if (!(*result = buffer_append(NULL, sizeof **result, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- (*result)->family = item->ai_family;
- extract_address(item, &(*result)->addr);
-
- /* canonical name piggybacking on the first address */
- if (item == list && list->ai_canonname)
- if (!((*result)->name = buffer_append(list->ai_canonname, 0, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- result = &(*result)->next;
- }
-
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status
-_nss_netresolve_gethostbyname3_r(const char *nodename, int family,
- struct hostent *he,
- char *bufptr, size_t buflen, int *errnop,
- int *h_errnop, int32_t *ttlp, char **canonp)
-{
- struct addrinfo hints = {
- .ai_family = family,
- .ai_socktype = SOCK_RAW,
- .ai_flags = AI_CANONNAME
- };
- struct buffer_t buffer = { .data = bufptr, .length = buflen, .errnop = errnop };
- int status;
- struct addrinfo *list;
- int count;
-
- status = _nss_netresolve_getaddrinfo(NULL, nodename, NULL, &hints, &list, ttlp);
-
- if (status)
- return NSS_STATUS_UNAVAIL;
-
- /* address family */
- he->h_addrtype = family;
- he->h_length = (family == AF_INET) ? 4 : 16;
-
- /* pointers to addresses */
- count = 0;
- for (struct addrinfo *item = list; item; item = item->ai_next)
- count++;
- if (!(he->h_addr_list = buffer_append(NULL, (count + 1) * sizeof *he->h_addr_list, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- /* addresses */
- count = 0;
- for (struct addrinfo *item = list; item; item = item->ai_next) {
- if (item->ai_family != family)
- continue;
-
- if (!(he->h_addr_list[count] = buffer_append(NULL, he->h_length, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- extract_address(item, he->h_addr_list[count]);
-
- count++;
- }
-
- /* canonical name */
- if (list->ai_canonname)
- if (!(he->h_name = buffer_append(list->ai_canonname, 0, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- return NSS_STATUS_SUCCESS;
-}
-
-enum nss_status
-_nss_netresolve_gethostbyname2_r(const char *nodename, int family,
- struct hostent *he,
- char *buffer, size_t buflen, int *errnop, int *h_errnop)
-{
- return _nss_netresolve_gethostbyname3_r(nodename, family, he, buffer, buflen, errnop, h_errnop, NULL, NULL);
-}
-
-enum nss_status
-_nss_netresolve_gethostbyname_r(const char *nodename,
- struct hostent *he,
- char *buffer, size_t buflen, int *errnop, int *h_errnop)
-{
- return _nss_netresolve_gethostbyname2_r(nodename, AF_INET, he, buffer, buflen, errnop, h_errnop);
-}
-
-enum nss_status
-_nss_netresolve_gethostbyaddr2_r (const void *addr, socklen_t len, int type,
- struct hostent *he, char *bufptr, size_t buflen,
- int *errnop, int *h_errnop, int32_t *ttlp)
-{
- netresolve_query_t query = netresolve_query_gethostbyaddr(NULL, addr, len, type, NULL, NULL);
- struct buffer_t buffer = { .data = bufptr, .length = buflen, .errnop = errnop };
-
- assert(he);
-
- if (query) {
- struct hostent *temp = netresolve_query_gethostbyaddr_done(query, &h_errno, NULL);
- size_t naddr = 0;
-
- for (char **item = temp->h_addr_list; *item; item++)
- naddr++;
-
- memcpy(he, temp, sizeof *he);
-
- if (!(he->h_name = buffer_append(he->h_name, 0, &buffer)))
- return NSS_STATUS_TRYAGAIN;
- if (!(he->h_aliases = buffer_append(NULL, sizeof *he->h_aliases, &buffer)))
- return NSS_STATUS_TRYAGAIN;
- if (!(he->h_addr_list = buffer_append(he->h_addr_list, (naddr+1) * sizeof *he->h_addr_list, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- for (char **item = he->h_addr_list; *item; item++)
- if (!(*item = buffer_append(*item, he->h_length, &buffer)))
- return NSS_STATUS_TRYAGAIN;
-
- netresolve_freehostent(temp);
-
- return NSS_STATUS_SUCCESS;
- }
-
- return NSS_STATUS_UNAVAIL;
-}
-
-enum nss_status
-_nss_netresolve_gethostbyaddr_r (const void *addr, socklen_t addrlen, int type,
- struct hostent *host, char *bufptr, size_t buflen,
- int *errnop, int *h_errnop)
-{
- return _nss_netresolve_gethostbyaddr2_r(addr, addrlen, type,
- host, bufptr, buflen,
- errnop, h_errnop, NULL);
-}
+++ /dev/null
-AC_PREREQ(2.60)
-AC_INIT([netresolve], [0.0.1], [psimerda@redhat.com], [netresolve], [])
-AC_CONFIG_SRCDIR([tools/netresolve.c])
-AC_CONFIG_AUX_DIR([build-aux])
-AM_INIT_AUTOMAKE([check-news foreign 1.11 -Wall -Wno-portability silent-rules tar-pax no-dist-gzip dist-xz subdir-objects])
-AC_USE_SYSTEM_EXTENSIONS
-LT_INIT([disable-static pic-only dlopen])
-AC_PROG_CC_STDC
-AC_CHECK_FUNC(__secure_getenv,
- AC_DEFINE(secure_getenv, __secure_getenv, [A prefixed version of secure_getenv found.]))
-AC_SYS_LARGEFILE
-AC_CONFIG_MACRO_DIR([m4])
-AM_SILENT_RULES([yes])
-AC_PROG_SED
-AC_PROG_INSTALL
-
-# mandatory dependencies
-AC_CHECK_LIB([dl], [dlopen])
-AC_CHECK_HEADER([epoll.h])
-
-# optional dependencies
-AC_ARG_WITH(ldns, AS_HELP_STRING([--with-ldns|--without-ldns], [Use ldns for DNS data operations (Default: yes)]), [use_ldns="$with_ldns"])/
-if test "$use_ldns" != no; then
- AC_CHECK_LIB([ldns], [ldns_wire2pkt], [use_ldns=yes], [use_ldns=no])
- if test "$with_ldns" = yes -a "$with_ldns" = no; then AC_MSG_ERROR([Bulding with ldns requested but not available.]); fi
-fi
-AS_IF([test "$use_ldns" = yes], AC_DEFINE(USE_LDNS, 1, [Use ldns library for DNS data operations (Default: yes).]))
-AS_IF([test "$use_ldns" = yes], AC_SUBST(LDNS_LIBS, -lldns))
-
-AC_ARG_WITH(c-ares, AS_HELP_STRING([--with-c-ares|--without-c-ares], [Build c-ares backend (Default: yes)]), [build_aresdns="$with_c_ares"])
-if test "$build_aresdns" != no; then
- PKG_CHECK_MODULES([ARES], [libcares], [build_aresdns=yes], [build_aresdns=no])
- if test "$use_ldns" = no; then build_aresdns=no; fi
- if test "$with_c_ares" = yes -a "$build_aresdns" = no; then AC_MSG_ERROR([Support for c-ares requested but not available.]); fi
-fi
-AM_CONDITIONAL(BUILD_BACKEND_ARESDNS, [test $build_aresdns = yes])
-
-AC_ARG_WITH(unbound, AS_HELP_STRING([--with-unbound|--without-unbound], [Build libunbound backend (Default: yes)]), [build_ubdns="$with_unbound"])
-if test "$build_ubdns" != no; then
- AC_CHECK_LIB([unbound], [ub_ctx_create], [build_ubdns=yes], [build_ubdns=no])
- if test "$use_ldns" = no; then build_ubdns=no; fi
- if test "$with_unbound" = yes -a "$build_ubdns" = no; then AC_MSG_ERROR([Support for libunbound requested but not available.]); fi
-fi
-AM_CONDITIONAL(BUILD_BACKEND_UBDNS, [test "$build_ubdns" = yes])
-AS_IF([test "$build_ubdns" = yes], AC_SUBST(UNBOUND_LIBS, -lunbound))
-
-AC_ARG_WITH(avahi, AS_HELP_STRING([--with-avahi|--without-avahi], [Build libavahi backend (Default: yes)]), [build_avahi="$with_avahi"])
-if test "$build_avahi" != no; then
- PKG_CHECK_MODULES([AVAHI], [avahi-client], [build_avahi=yes], [build_avahi=no])
- if test "$with_avahi" = yes -a "$build_avahi" = no; then AC_MSG_ERROR([Support for libavahi requested but not available.]); fi
-fi
-AM_CONDITIONAL(BUILD_BACKEND_AVAHI, [test $build_avahi = yes])
-
-AC_ARG_WITH(asyncns, AS_HELP_STRING([--with-asyncns|--without-asyncns], [Build libasyncns based backend (Default: yes)]), [build_asyncns="$with_asyncns"])
-if test "$build_asyncns" != no; then
- PKG_CHECK_MODULES([ASYNCNS], [libasyncns], [build_asyncns=yes], [build_asyncns=no])
- if test "$with_asyncns" = yes -a "$build_asyncns" = no; then AC_MSG_ERROR([Support for libasyncns requested but not available.]); fi
-fi
-AM_CONDITIONAL(BUILD_FRONTEND_ASYNCNS, [test $build_asyncns = yes])
-AM_CONDITIONAL(BUILD_BACKEND_ASYNCNS, [test $build_asyncns = yes])
-
-AC_ARG_ENABLE(tests, AS_HELP_STRING([--enable-tests|--disable-tests], [Build tests using additional dependencies (Default: no)]))
-AS_IF([test "$enable_tests" = yes],
- PKG_CHECK_MODULES([GLIB], [glib-2.0])
- AC_CHECK_LIB([event], [event_base_new], [EVENT_LIBS=-levent])
- AC_SUBST(EVENT_LIBS))
-AM_CONDITIONAL(BUILD_ALL_TESTS, [test "$enable_tests" = yes])
-
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_FILES([
- Makefile
- tools/wrapresolve
-])
-AC_OUTPUT
-AC_MSG_RESULT([
-$PACKAGE $VERSION
-
-Directories:
-
- * prefix: ${prefix}
- * sysconfdir: ${sysconfdir}
- * libdir: ${libdir}
- * includedir: ${includedir}
-
-Compiler:
-
- * compiler: ${CC}
- * cflags: ${CFLAGS}
- * ldflags: ${LDFLAGS}
-
-Optional frontends:
-
- * asyncns: $build_asyncns
-
-Optional backends:
-
- * aresdns: $build_aresdns
- * ubdns: $build_ubdns
- * avahi: $build_avahi
- * asyncns: $build_asyncns
-
-Other dependencies:
-
- * ldns: $use_ldns
-])
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_BACKEND_H
-#define NETRESOLVE_BACKEND_H
-
-#include <netresolve-nonblock.h>
-
-#include <stdbool.h>
-#include <string.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#include <nss.h>
-#include <poll.h>
-
-typedef struct netresolve_query *netresolve_query_t;
-typedef struct netresolve_watch *netresolve_timeout_t;
-
-__attribute__((unused))
-static struct in_addr inaddr_any = { 0 };
-
-__attribute__((unused))
-#if BYTE_ORDER == BIG_ENDIAN
-static const struct in_addr inaddr_loopback = { 0x7f000001 };
-#elif BYTE_ORDER == LITTLE_ENDIAN
-static const struct in_addr inaddr_loopback = { 0x0100007f };
-#else
- #error Neither big endian nor little endian
-#endif
-
-/* Input: Forward lookup */
-const char *netresolve_backend_get_nodename(netresolve_query_t query);
-const char *netresolve_backend_get_servname(netresolve_query_t query);
-int netresolve_backend_get_family(netresolve_query_t query);
-int netresolve_backend_get_protocol(netresolve_query_t query);
-int netresolve_backend_get_socktype(netresolve_query_t query);
-bool netresolve_backend_get_default_loopback(netresolve_query_t query);
-bool netresolve_backend_get_dns_srv_lookup(netresolve_query_t query);
-bool netresolve_backend_get_dns_search(netresolve_query_t query);
-
-/* Input: Reverse lookup */
-void *netresolve_backend_get_address(netresolve_query_t query);
-uint16_t netresolve_backend_get_port(netresolve_query_t query);
-
-/* Input: DNS record lookup */
-const char *netresolve_backend_get_dns_query(netresolve_query_t query, int *cls, int *type);
-/* Convenience input */
-struct addrinfo netresolve_backend_get_addrinfo_hints(netresolve_query_t query);
-
-/* Output */
-void netresolve_backend_add_path(netresolve_query_t query,
- int family, const void *address, int ifindex,
- int socktype, int protocol, int port,
- int priority, int weight, int32_t ttl);
-void netresolve_backend_add_name_info(netresolve_query_t query, const char *nodename, const char *servname);
-void netresolve_backend_set_canonical_name(netresolve_query_t query, const char *canonical_name);
-void netresolve_backend_set_dns_answer(netresolve_query_t query, const void *answer, size_t length);
-void netresolve_backend_set_secure(netresolve_query_t query);
-
-/* Convenience output */
-void netresolve_backend_apply_addrinfo(netresolve_query_t query,
- int status, const struct addrinfo *result, int32_t ttl);
-void netresolve_backend_apply_addrtuple(netresolve_query_t query,
- enum nss_status status, const struct gaih_addrtuple *result,
- int32_t ttl);
-void netresolve_backend_apply_hostent(netresolve_query_t query,
- const struct hostent *he,
- int socktype, int protocol, int port,
- int priority, int weight, int32_t ttl);
-
-/* Tools */
-typedef void (*netresolve_backend_cleanup_t)(void *priv);
-
-void *netresolve_backend_new_priv(netresolve_query_t query, size_t size, netresolve_backend_cleanup_t cleanup);
-void *netresolve_backend_get_priv(netresolve_query_t query);
-void netresolve_backend_finished(netresolve_query_t query);
-void netresolve_backend_failed(netresolve_query_t query);
-
-/* Events */
-typedef void (*netresolve_watch_callback_t)(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data);
-typedef void (*netresolve_timeout_callback_t)(netresolve_query_t query, netresolve_timeout_t timeout, void *data);
-
-netresolve_watch_t netresolve_watch_add(netresolve_query_t query, int fd, int events,
- netresolve_watch_callback_t callback, void *data);
-void netresolve_watch_remove(netresolve_query_t query, netresolve_watch_t watch, bool do_close);
-netresolve_timeout_t netresolve_timeout_add(netresolve_query_t query, time_t sec, long nsec,
- netresolve_timeout_callback_t callback, void *data);
-netresolve_timeout_t netresolve_timeout_add_ms(netresolve_query_t query, long msec,
- netresolve_timeout_callback_t callback, void *data);
-void netresolve_timeout_remove(netresolve_query_t query, netresolve_timeout_t timeout);
-
-/* Logging */
-#define error(...) netresolve_log(0x20, __VA_ARGS__)
-#define debug(...) netresolve_log(0x40, __VA_ARGS__)
-void netresolve_log(int level, const char *fmt, ...);
-
-/* Convenience */
-typedef union { struct in_addr address4; struct in6_addr address6; } Address;
-bool netresolve_backend_parse_address(const char *string_orig,
- Address *address, int *family, int *ifindex);
-bool netresolve_backend_parse_path(const char *str,
- Address *address, int *family, int *ifindex,
- int *socktype, int *protocol, int *port);
-
-/* Backend function prototypes */
-void query_forward(netresolve_query_t query, char **settings);
-void query_reverse(netresolve_query_t query, char **settings);
-void query_dns(netresolve_query_t query, char **settings);
-
-/* String functions */
-const char *netresolve_get_request_string(netresolve_query_t query);
-const char *netresolve_get_path_string(netresolve_query_t query, int i);
-const char *netresolve_get_response_string(netresolve_query_t query);
-
-#endif /* NETRESOLVE_BACKEND_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_COMPAT_H
-#define NETRESOLVE_COMPAT_H
-
-#include <netresolve.h>
-#include <netdb.h>
-
-/* Utility functions */
-const struct sockaddr *netresolve_query_get_sockaddr(const netresolve_query_t query, size_t idx,
- socklen_t *salen, int *socktype, int *protocol, int32_t *ttl);
-
-/* Functions resembling modern POSIX host/service resolution API */
-netresolve_query_t netresolve_query_getaddrinfo(netresolve_t context,
- const char *node, const char *service, const struct addrinfo *hints,
- netresolve_query_callback callback, void *user_data);
-int netresolve_query_getaddrinfo_done(netresolve_query_t query,
- struct addrinfo **res, int32_t *ttlp);
-netresolve_query_t netresolve_query_getnameinfo(netresolve_t context,
- const struct sockaddr *sa, socklen_t salen, int flags,
- netresolve_query_callback callback, void *user_data);
-int netresolve_query_getnameinfo_done(netresolve_query_t query,
- char **host, char **serv, int32_t *ttlp);
-
-/* Functions resembling obsolete POSIX host/service resolution API */
-netresolve_query_t netresolve_query_gethostbyname(netresolve_t context,
- const char *name, int family,
- netresolve_query_callback callback, void *user_data);
-struct hostent *netresolve_query_gethostbyname_done(netresolve_query_t query,
- int *h_errnop, int32_t *ttlp);
-netresolve_query_t netresolve_query_gethostbyaddr(netresolve_t context,
- const void *address, int length, int family,
- netresolve_query_callback callback, void *user_data);
-struct hostent *netresolve_query_gethostbyaddr_done(netresolve_query_t query,
- int *h_errnop, int32_t *ttlp);
-
-/* Destructors */
-void netresolve_freeaddrinfo(struct addrinfo *ai);
-void netresolve_freehostent(struct hostent *he);
-
-#endif /* NETRESOLVE_COMPAT_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_EPOLL_H
-#define NETRESOLVE_EPOLL_H
-
-#include <netresolve.h>
-#include <sys/epoll.h>
-
-netresolve_t netresolve_epoll_new(void);
-int netresolve_epoll_fd(netresolve_t context);
-void netresolve_epoll_dispatch(netresolve_t context);
-
-void netresolve_epoll_wait(netresolve_t context);
-
-#endif /* NETRESOLVE_EPOLL_H */
+++ /dev/null
-/* Copyright (c) 2013-2014 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_EVENT_H
-#define NETRESOLVE_EVENT_H
-
-#include <netresolve-nonblock.h>
-#include <event2/event.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/* FIXME: This header file should be turned in a library to avoid symbol name clashes. */
-
-struct netresolve_event_source {
- netresolve_t context;
- struct event *event;
- netresolve_watch_t source;
-};
-
-static int
-condition_to_events(short condition)
-{
- int events = 0;
-
- if (condition & EV_READ)
- events |= POLLIN;
- if (condition & EV_WRITE)
- events |= POLLOUT;
-
- return events;
-}
-
-static short
-events_to_condition(int events)
-{
- short condition = EV_PERSIST;
-
- if (events & POLLIN)
- condition |= EV_READ;
- if (events & POLLOUT)
- condition |= EV_WRITE;
-
- return condition;
-}
-
-static void
-handler(int fd, short condition, void *data)
-{
- struct netresolve_event_source *event_source = data;
-
- netresolve_dispatch(event_source->context, event_source->source, condition_to_events(condition));
-}
-
-static void*
-add_watch(netresolve_t context, int fd, int events, netresolve_watch_t source)
-{
- struct event_base *base = netresolve_get_user_data(context);
- struct netresolve_event_source *event_source = calloc(1, sizeof *event_source);
-
- assert(event_source);
-
- event_source->context = context;
- event_source->event = event_new(base, fd, events_to_condition(events), handler, event_source);
- event_source->source = source;
-
- assert(event_source->event);
-
- event_add(event_source->event, NULL);
-
- return event_source;
-}
-
-static void
-remove_watch(netresolve_t context, int fd, void *handle)
-{
- struct netresolve_event_source *event_source = handle;
-
- event_free(event_source->event);
- free(event_source);
-}
-
-__attribute__((unused))
-static netresolve_t
-netresolve_event_new(struct event_base *base)
-{
- netresolve_t context = netresolve_context_new();
-
- if (context)
- netresolve_set_fd_callbacks(context, add_watch, remove_watch, NULL, base);
-
- return context;
-}
-
-#endif /* NETRESOLVE_EVENT_H */
+++ /dev/null
-/* Copyright (c) 2013-2014 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in glib_source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of glib_source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO GLIB SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_GLIB_H
-#define NETRESOLVE_GLIB_H
-
-#include <netresolve-nonblock.h>
-#include <glib.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <assert.h>
-
-/* FIXME: This header file should be turned in a library to avoid symbol name clashes. */
-
-struct netresolve_glib_source {
- netresolve_t context;
- GIOChannel *stream;
- netresolve_watch_t source;
-};
-
-static int
-condition_to_events(int condition)
-{
- int events = 0;
-
- if (condition & G_IO_IN)
- events |= POLLIN;
- if (condition & G_IO_OUT)
- events |= POLLOUT;
-
- return events;
-}
-
-static int
-events_to_condition(int events)
-{
- GIOCondition condition = 0;
-
- if (events & POLLIN)
- condition |= G_IO_IN;
- if (events & POLLOUT)
- condition |= G_IO_OUT;
-
- return condition;
-}
-
-static gboolean
-handler(GIOChannel *stream, GIOCondition condition, gpointer data)
-{
- struct netresolve_glib_source *glib_source = data;
-
- netresolve_dispatch(glib_source->context, glib_source->source, condition_to_events(condition));
-
- return TRUE;
-}
-
-static void*
-add_watch(netresolve_t context, int fd, int events, netresolve_watch_t source)
-{
- struct netresolve_glib_source *glib_source = calloc(1, sizeof *glib_source);
-
- assert(glib_source);
-
- glib_source->context = context;
- glib_source->stream = g_io_channel_unix_new(fd);
- glib_source->source = source;
-
- g_io_add_watch(glib_source->stream, events_to_condition(events), handler, glib_source);
-
- return glib_source;
-}
-
-static void
-remove_watch(netresolve_t context, int fd, void *handle)
-{
- struct netresolve_glib_source *glib_source = handle;
-
- g_io_channel_unref(glib_source->stream);
- free(glib_source);
-}
-
-__attribute__((unused))
-static netresolve_t
-netresolve_glib_new(void)
-{
- netresolve_t context = netresolve_context_new();
-
- assert(context);
-
- netresolve_set_fd_callbacks(context, add_watch, remove_watch, NULL, NULL);
-
- return context;
-}
-
-#endif /* NETRESOLVE_GLIB_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_NONBLOCK_H
-#define NETRESOLVE_NONBLOCK_H
-
-#include <netresolve.h>
-
-typedef struct netresolve_watch *netresolve_watch_t;
-
-typedef void *(*netresolve_watch_add_callback_t)(netresolve_t context, int fd, int events, netresolve_watch_t source);
-typedef void (*netresolve_watch_remove_callback_t)(netresolve_t context, int fd, void *handle);
-typedef void (*netresolve_cleanup_callback_t)(void *user_data);
-
-void netresolve_set_fd_callbacks(netresolve_t context,
- netresolve_watch_add_callback_t add_watch,
- netresolve_watch_remove_callback_t remove_watch,
- netresolve_cleanup_callback_t cleanup,
- void *user_data);
-void *netresolve_get_user_data(netresolve_t context);
-void netresolve_dispatch(netresolve_t context, netresolve_watch_t watch, int events);
-
-#endif /* NETRESOLVE_NONBLOCK_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_PRIVATE_H
-#define NETRESOLVE_PRIVATE_H
-
-#include <netresolve.h>
-#include <netresolve-nonblock.h>
-#include <netresolve-socket.h>
-#include <netresolve-backend.h>
-#include <netresolve-compat.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdbool.h>
-#include <nss.h>
-#include <netdb.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <sys/socket.h>
-#include <unistd.h>
-#include <assert.h>
-
-#define debug_context(context, format, ...) debug( \
- "[context %p] " format, \
- context, \
- ##__VA_ARGS__)
-
-#define debug_query(query, format, ...) debug( \
- "[query %p %s %s] " format, \
- query, \
- query->backend && *query->backend ? (*query->backend)->settings[0] : "-", \
- netresolve_query_state_to_string(query->state), \
- ##__VA_ARGS__)
-
-enum netresolve_state {
- NETRESOLVE_STATE_NONE,
- NETRESOLVE_STATE_SETUP,
- NETRESOLVE_STATE_WAITING,
- NETRESOLVE_STATE_WAITING_MORE,
- NETRESOLVE_STATE_RESOLVED,
- NETRESOLVE_STATE_DONE,
- NETRESOLVE_STATE_ERROR,
- NETRESOLVE_STATE_FAILED
-};
-
-enum netresolve_socket_state {
- SOCKET_STATE_NONE,
- SOCKET_STATE_SCHEDULED,
- SOCKET_STATE_READY,
- SOCKET_STATE_DONE
-};
-
-enum netresolve_request_type {
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_REQUEST_REVERSE,
- NETRESOLVE_REQUEST_DNS,
- _NETRSOLVE_REQUEST_TYPES
-};
-
-enum netresolve_security {
- NETRESOLVE_SECURITY_INSECURE,
- NETRESOLVE_SECURITY_SECURE
-};
-
-struct netresolve_epoll {
- int fd;
- int count;
- int nevents;
- struct epoll_event *events;
-};
-
-struct netresolve_backend {
- bool mandatory;
- char **settings;
- void *dl_handle;
- void (*setup[_NETRSOLVE_REQUEST_TYPES])(netresolve_query_t query, char **settings);
- netresolve_backend_cleanup_t cleanup;
- void *data;
-};
-
-struct netresolve_path {
- struct {
- int family;
- union {
- char address[1024];
- struct in_addr address4;
- struct in6_addr address6;
- };
- int ifindex;
- } node;
- struct {
- int socktype;
- int protocol;
- int port;
- } service;
- int priority;
- int weight;
- int ttl;
- struct {
- enum netresolve_socket_state state;
- netresolve_watch_t watch;
- int fd;
- } socket;
-};
-
-struct netresolve_query {
- struct netresolve_context *context;
- struct netresolve_watch {
- netresolve_query_t query;
- int fd;
- netresolve_watch_callback_t callback;
- netresolve_timeout_callback_t timeout_callback;
- void *data;
- void *handle;
- struct netresolve_watch *previous, *next;
- } watches;
- netresolve_query_callback callback;
- void *user_data;
- enum netresolve_state state;
- int nfds;
- netresolve_timeout_t delayed;
- netresolve_timeout_t request_timeout;
- netresolve_timeout_t result_timeout;
- struct netresolve_backend **backend;
- struct netresolve_request {
- enum netresolve_request_type type;
- /* Perform L3 address resolution using 'nodename' if not NULL. Use
- * 'family' to chose between IPv4, IPv6 and mixed IPv4/IPv6
- * resolution and additional flags to further tweak nodename name
- * resolution.
- */
- char *nodename;
- int family;
- /* Perform L4 port resolution using 'servname' if not NULL. Use
- * 'socktype' and 'protocol' to limit the possible options and
- * additional flags to further tweak servname name resolution.
- */
- char *servname;
- int socktype;
- int protocol;
- int port;
- /* Advanced configuration */
- bool default_loopback;
- bool dns_srv_lookup;
- bool dns_search;
- int clamp_ttl;
- /* Reverse query */
- union {
- char address[1024];
- struct in_addr address4;
- struct in6_addr address6;
- };
- int ifindex;
- /* DNS data query */
- char *dns_name;
- int dns_class;
- int dns_type;
- /* Timeout configuration */
- int request_timeout;
- int result_timeout;
- } request;
- struct netresolve_response {
- struct netresolve_path *paths;
- size_t pathcount;
- char *nodename;
- char *servname;
- struct {
- void *answer;
- size_t length;
- } dns;
- enum netresolve_security security;
- } response;
-
- struct netresolve_service_list *services;
-
- union {
- struct sockaddr sa;
- struct sockaddr_in sin;
- struct sockaddr_in6 sin6;
- } sa_buffer;
- char buffer[1024];
- struct netresolve_query *previous, *next;
-};
-
-struct netresolve_context {
- struct netresolve_query queries;
- struct netresolve_request request;
- struct netresolve_epoll epoll;
- int nfds;
- struct netresolve_backend **backends;
- struct {
- netresolve_watch_add_callback_t add_watch;
- netresolve_watch_remove_callback_t remove_watch;
- void *user_data;
- netresolve_cleanup_callback_t cleanup;
- } callbacks;
- struct netresolve_config {
- int force_family;
- } config;
-};
-
-/* Query */
-netresolve_query_t netresolve_query(netresolve_t context, netresolve_query_callback callback, void *user_data,
- enum netresolve_option type, ...);
-const char *netresolve_query_state_to_string(enum netresolve_state state);
-void netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state);
-void netresolve_query_dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data);
-
-/* Request */
-bool netresolve_request_set_options_from_va(struct netresolve_request *request, va_list ap);
-bool netresolve_request_get_options_from_va(struct netresolve_request *request, va_list ap);
-
-/* Services */
-struct netresolve_service_list;
-typedef void (*netresolve_service_callback)(const char *name, int socktype, int protocol, int port, void *user_data);
-struct netresolve_service_list *netresolve_service_list_new(const char *path);
-void netresolve_service_list_free(struct netresolve_service_list *services);
-void netresolve_service_list_query(struct netresolve_service_list **services,
- const char *name, int socktype, int protocol, int port,
- netresolve_service_callback callback, void *user_data);
-
-/* Utilities */
-int netresolve_family_from_string(const char *str);
-int netresolve_socktype_from_string(const char *str);
-int netresolve_protocol_from_string(const char *str);
-
-/* String output */
-const char *netresolve_get_request_string(netresolve_query_t query);
-const char *netresolve_get_path_string(netresolve_query_t query, int i);
-const char *netresolve_get_response_string(netresolve_query_t query);
-
-/* Event loop for blocking mode */
-bool netresolve_epoll_install(netresolve_t context,
- struct netresolve_epoll *loop,
- bool internal);
-void netresolve_epoll_wait(netresolve_t context);
-
-#endif /* NETRESOLVE_PRIVATE_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_SELECT_H
-#define NETRESOLVE_SELECT_H
-
-#include <netresolve.h>
-#include <sys/select.h>
-
-netresolve_t netresolve_select_new();
-int netresolve_select_apply_fds(netresolve_t context, fd_set *rfds, fd_set *wfds);
-void netresolve_select_dispatch_read(netresolve_t context, int fd);
-void netresolve_select_dispatch_write(netresolve_t context, int fd);
-int netresolve_select_wait(netresolve_t context, struct timeval *timeout);
-
-#endif /* NETRESOLVE_SELECT_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_SOCKET_H
-#define NETRESOLVE_SOCKET_H
-
-#include <netresolve.h>
-
-typedef void (*netresolve_socket_callback_t)(netresolve_query_t query, int idx, int sock, void *user_data);
-
-netresolve_query_t netresolve_connect(netresolve_t context,
- const char *nodename, const char *servname,
- int family, int socktype, int protocol,
- netresolve_socket_callback_t callback, void *user_data);
-void netresolve_connect_next(netresolve_query_t query);
-void netresolve_connect_free(netresolve_query_t query);
-
-netresolve_query_t netresolve_bind(netresolve_t context,
- const char *nodename, const char *servname,
- int family, int socktype, int protocol,
- netresolve_socket_callback_t callback, void *user_data);
-void netresolve_bind_free(netresolve_query_t query);
-
-#endif /* NETRESOLVE_SOCKET_H */
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#ifndef NETRESOLVE_H
-#define NETRESOLVE_H
-
-#include <stdbool.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-typedef struct netresolve_context *netresolve_t;
-typedef struct netresolve_query *netresolve_query_t;
-
-/* Configuration options */
-enum netresolve_option {
- NETRESOLVE_OPTION_DONE,
-/* Flags:
- *
- * NETRESOLVE_OPTION_DEFAULT_LOOPBACK:
- * - When set, NULL resolves to a loopback address, otherwise it resolves
- * to an empty address. The opposite of getaddrinfo's AI_PASSIVE.
- * NETRESOLVE_OPTION_DNS_SRV_LOOKUP:
- * - When set, forward lookups use DNS SRV records when applicable.
- */
- NETRESOLVE_OPTION_DEFAULT_LOOPBACK = 0x10, /* bool default_loopback */
- NETRESOLVE_OPTION_DNS_SRV_LOOKUP, /* bool dns_srv_lookup */
-/* Node and service name:
- *
- * You don't normally need to set them as they are specified as parameters
- * to the `netresolve_query_forward()` function.
- */
- NETRESOLVE_OPTION_NODE_NAME = 0x100, /* const char *nodename */
- NETRESOLVE_OPTION_SERVICE_NAME, /* const char *servname */
-/* Family, socktype and protocol:
- *
- * You can set them to adjust forward name resolution configuration before
- * calling the `netresolve_query_forward()` function.
- */
- NETRESOLVE_OPTION_FAMILY = 0x110, /* int family */
- NETRESOLVE_OPTION_SOCKTYPE, /* int socktype */
- NETRESOLVE_OPTION_PROTOCOL, /* int protocol */
-/* IPv4 or IPv6 address, port number:
- *
- * You don't normally need to set them as they are specified as parameters
- * to the `netresolve_query_reverse()` function.
- */
- NETRESOLVE_OPTION_IFINDEX = 0x200, /* int ifindex */
- NETRESOLVE_OPTION_IP4_ADDRESS = 0x210, /* const struct in_addr *address */
- NETRESOLVE_OPTION_IP6_ADDRESS, /* const struct in6_addr *address */
- NETRESOLVE_OPTION_PORT = 0x220, /* int port */
-/* DNS record resolution:
- *
- * You don't normally need to set them as they are specified as parameters
- * to the `netresolve_query_dns()` function.
- */
- NETRESOLVE_OPTION_DNS_NAME = 0x300, /* const char *dname */
- NETRESOLVE_OPTION_DNS_CLASS, /* int class */
- NETRESOLVE_OPTION_DNS_TYPE, /* int type */
-};
-
-/* Context construction and destruction */
-netresolve_t netresolve_context_new(void);
-void netresolve_context_free(netresolve_t context);
-
-/* Context configuration */
-void netresolve_set_backend_string(netresolve_t context, const char *string);
-void netresolve_context_set_options(netresolve_t context, ...);
-
-/* Query construction and destruction */
-typedef void (*netresolve_query_callback)(netresolve_query_t query, void *user_data);
-
-netresolve_query_t netresolve_query_forward(netresolve_t context,
- const char *node, const char *service,
- netresolve_query_callback callback, void *user_data);
-netresolve_query_t netresolve_query_reverse(netresolve_t context,
- int family, const void *address, int ifindex, int protocol, int port,
- netresolve_query_callback callback, void *user_data);
-netresolve_query_t netresolve_query_dns(netresolve_t context,
- const char *dname, int cls, int type,
- netresolve_query_callback callback, void *user_data);
-void netresolve_query_free(netresolve_query_t query);
-
-/* Query result getters (forward queries) */
-size_t netresolve_query_get_count(const netresolve_query_t query);
-void netresolve_query_get_node_info(const netresolve_query_t query, size_t idx,
- int *family, const void **address, int *ifindex);
-void netresolve_query_get_service_info(const netresolve_query_t query, size_t idx,
- int *socktype, int *protocol, int *port);
-void netresolve_query_get_aux_info(const netresolve_query_t query, size_t idx,
- int *priority, int *weight, int *ttl);
-#define netresolve_query_get_canonical_name(query) netresolve_query_get_node_name(query)
-
-/* Query result getters (reverse queries) */
-const char *netresolve_query_get_node_name(const netresolve_query_t query);
-const char *netresolve_query_get_service_name(const netresolve_query_t query);
-
-/* Query result getters (DNS queries) */
-const void *netresolve_query_get_dns_answer(const netresolve_query_t query, size_t *size);
-
-/* Query result getters (universal) */
-bool netresolve_query_get_secure(const netresolve_query_t query);
-
-/* Logging */
-enum netresolve_log_level {
- NETRESOLVE_LOG_LEVEL_QUIET = 0x00,
- NETRESOLVE_LOG_LEVEL_FATAL = 0x10,
- NETRESOLVE_LOG_LEVEL_ERROR = 0x20,
- NETRESOLVE_LOG_LEVEL_INFO = 0x30,
- NETRESOLVE_LOG_LEVEL_DEBUG = 0x40
-};
-void netresolve_set_log_level(enum netresolve_log_level level);
-
-#endif /* NETRESOLVE_H */
+++ /dev/null
-/getaddrinfo
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <sys/epoll.h>
-
-#include <netresolve-backend.h>
-
-#include "netresolve-private.h"
-
-const char *
-netresolve_backend_get_nodename(netresolve_query_t query)
-{
- if (query->request.dns_name)
- return query->request.dns_name;
- else
- return query->request.nodename;
-}
-
-const char *
-netresolve_backend_get_servname(netresolve_query_t query)
-{
- return query->request.servname;
-}
-
-int
-netresolve_backend_get_family(netresolve_query_t query)
-{
- return query->request.family;
-}
-
-int
-netresolve_backend_get_socktype(netresolve_query_t query)
-{
- return query->request.socktype;
-}
-
-int
-netresolve_backend_get_protocol(netresolve_query_t query)
-{
- return query->request.protocol;
-}
-
-bool
-netresolve_backend_get_default_loopback(netresolve_query_t query)
-{
- return query->request.default_loopback;
-}
-
-bool
-netresolve_backend_get_dns_srv_lookup(netresolve_query_t query)
-{
- return query->request.dns_srv_lookup;
-}
-
-bool
-netresolve_backend_get_dns_search(netresolve_query_t query)
-{
- return query->request.dns_search;
-}
-
-void *
-netresolve_backend_get_address(netresolve_query_t query)
-{
- return query->request.address;
-}
-
-uint16_t
-netresolve_backend_get_port(netresolve_query_t query)
-{
- return query->request.port;
-}
-
-const char *
-netresolve_backend_get_dns_query(netresolve_query_t query, int *cls, int *type)
-{
- *cls = query->request.dns_class;
- *type = query->request.dns_type;
- return query->request.dns_name;
-}
-
-struct addrinfo
-netresolve_backend_get_addrinfo_hints(netresolve_query_t query)
-{
- struct addrinfo hints = {
- .ai_family = netresolve_backend_get_family(query),
- .ai_socktype = netresolve_backend_get_socktype(query),
- .ai_protocol = netresolve_backend_get_protocol(query),
- .ai_flags = 0,
- };
-
- if (!netresolve_backend_get_default_loopback(query))
- hints.ai_flags |= AI_PASSIVE;
-
- return hints;
-}
-
-static size_t
-family_to_length(int family)
-{
- switch (family) {
- case AF_INET:
- return 4;
- case AF_INET6:
- return 16;
- default:
- return 0;
- }
-}
-
-static int
-path_cmp(const struct netresolve_path *p1, const struct netresolve_path *p2)
-{
- if (p1->node.family == AF_INET6 && p2->node.family == AF_INET)
- return -1;
- if (p1->node.family == AF_INET && p2->node.family == AF_INET6)
- return 1;
-
- return 0;
-}
-
-static void
-add_path(netresolve_query_t query, const struct netresolve_path *path)
-{
- struct netresolve_response *response = &query->response;
- int i;
-
- for (i = 0; i < response->pathcount; i++)
- if (path_cmp(path, &response->paths[i]) < 0)
- break;
-
- response->paths = realloc(response->paths, (response->pathcount + 2) * sizeof *path);
- memmove(&response->paths[i+1], &response->paths[i],
- (response->pathcount++ - i) * sizeof *response->paths);
- memcpy(&response->paths[i], path, sizeof *path);
- memset(&response->paths[response->pathcount], 0, sizeof *response->paths);
-
- debug_query(query, "added path: %s", netresolve_get_path_string(query, i));
-
- if (query->state == NETRESOLVE_STATE_WAITING)
- netresolve_query_set_state(query, NETRESOLVE_STATE_WAITING_MORE);
-}
-
-struct path_data {
- struct netresolve_query *query;
- struct netresolve_path *path;
-};
-
-static void
-path_callback(const char *name, int socktype, int protocol, int port, void *user_data)
-{
- struct path_data *data = user_data;
- struct netresolve_path path = *data->path;
-
- path.service.socktype = socktype;
- path.service.protocol = protocol;
- path.service.port = port;
-
- add_path(data->query, &path);
-}
-
-void
-netresolve_backend_add_path(netresolve_query_t query,
- int family, const void *address, int ifindex,
- int socktype, int protocol, int port,
- int priority, int weight, int32_t ttl)
-{
- struct netresolve_request *request = &query->request;
-
- if (request->family != AF_UNSPEC && request->family != family)
- return;
-
- if (family == AF_UNIX && !socktype) {
- netresolve_backend_add_path(query, family, address, 0, SOCK_STREAM, 0, 0, priority, weight, ttl);
- netresolve_backend_add_path(query, family, address, 0, SOCK_DGRAM, 0, 0, priority, weight, ttl);
- return;
- }
-
- size_t length = family_to_length(family);
- struct netresolve_path path = {
- .node = {
- .family = family,
- .address = { 0 },
- .ifindex = ifindex
- },
- .service = {
- .socktype = socktype ? socktype : request->socktype,
- .protocol = protocol ? protocol : request->protocol,
- .port = port
- },
- .priority = priority,
- .weight = weight,
- .ttl = ttl
- };
-
- if (length)
- memcpy(path.node.address, address, length);
- else
- strncpy(path.node.address, address, sizeof path.node.address);
-
- if (query->request.servname && (!socktype || !protocol || !port)) {
- struct path_data data = { .query = query, .path = &path };
-
- netresolve_service_list_query(&query->services,
- request->servname, path.service.socktype, path.service.protocol, 0,
- path_callback, &data);
- return;
- }
-
- add_path(query, &path);
-}
-
-void
-netresolve_backend_set_canonical_name(netresolve_query_t query, const char *canonical_name)
-{
- free(query->response.nodename);
- query->response.nodename = strdup(canonical_name);
-}
-
-static void
-service_callback(const char *name, int socktype, int protocol, int port, void *user_data)
-{
- netresolve_query_t query = user_data;
-
- if (query->response.servname)
- return;
-
- query->response.servname = name ? strdup(name) : NULL;
-}
-
-void
-netresolve_backend_add_name_info(netresolve_query_t query, const char *nodename, const char *servname)
-{
- if (query->response.nodename) {
- debug_query(query, "ignored name info: %s/%s", nodename, servname);
- return;
- }
-
- debug_query(query, "set name info: %s/%s", nodename, servname);
-
- query->response.nodename = nodename ? strdup(nodename) : NULL;
-
- if (!query->response.servname) {
- int protocol = netresolve_backend_get_protocol(query);
-
- netresolve_service_list_query(&query->services,
- NULL, 0, protocol, query->request.port,
- service_callback, query);
- }
-}
-void
-netresolve_backend_set_secure(netresolve_query_t query)
-{
- query->response.security = NETRESOLVE_SECURITY_SECURE;
-}
-
-void
-netresolve_backend_set_dns_answer(netresolve_query_t query, const void *answer, size_t length)
-{
- query->response.dns.answer = malloc(length);
- memcpy(query->response.dns.answer, answer, length);
- query->response.dns.length = length;
-}
-
-void *
-netresolve_backend_new_priv(netresolve_query_t query, size_t size, netresolve_backend_cleanup_t cleanup)
-{
- struct netresolve_backend *backend = *query->backend;
-
- assert(backend);
- assert(!backend->data);
-
- backend->cleanup = cleanup;
- backend->data = calloc(1, size);
-
- if (!backend->data)
- netresolve_backend_failed(query);
-
- return backend->data;
-}
-
-void *
-netresolve_backend_get_priv(netresolve_query_t query)
-{
- return (*query->backend)->data;
-}
-
-void
-netresolve_backend_finished(netresolve_query_t query)
-{
- netresolve_query_set_state(query, NETRESOLVE_STATE_RESOLVED);
-}
-
-void
-netresolve_backend_failed(netresolve_query_t query)
-{
- netresolve_query_set_state(query, NETRESOLVE_STATE_ERROR);
-}
-
-bool
-netresolve_backend_parse_address(const char *string_orig, Address *address, int *family, int *ifindex)
-{
- char *string;
- char *ifname;
-
- if (!string_orig)
- return false;
-
- string = strdupa(string_orig);
-
- ifname = strchr(string, '%');
- if (ifname)
- *ifname++ = '\0';
- if (!ifname)
- ifname = "";
-
- if (inet_pton(AF_INET, string, address) == 1)
- *family = AF_INET;
- else if (inet_pton(AF_INET6, string, address) == 1)
- *family = AF_INET6;
- else
- return false;
-
- if (ifindex) {
- *ifindex = if_nametoindex(ifname);
- if (!*ifindex) {
- char *endptr = NULL;
-
- *ifindex = strtol(ifname, &endptr, 10);
- if (*endptr)
- *ifindex = -1;
- }
- }
-
- return true;
-}
-
-struct enum_item {
- int id;
- const char *name;
-};
-
-static int
-enum_id_from_name(char *str, struct enum_item *list)
-{
- struct enum_item *item;
- if (!str)
- return 0;
-
- if (list)
- for (item = list; item->name; item++)
- return item->id;
-
- return strtol(str, NULL, 10);
-}
-
-struct enum_item socktypes[] = {
- { SOCK_STREAM, "stream" },
- { SOCK_DGRAM, "dgram" },
- { SOCK_SEQPACKET, "seqpacket" },
- { 0, NULL }
-};
-
-struct enum_item protocols[] = {
- { IPPROTO_TCP, "tcp" },
- { IPPROTO_UDP, "udp" },
- { IPPROTO_SCTP, "sctp" },
- { 0, NULL }
-};
-
-bool
-netresolve_backend_parse_path(const char *str,
- Address *address, int *family, int *ifindex,
- int *socktype, int *protocol, int *port)
-{
- char *saveptr;
-
- /* Silence stupid gcc/glibc warning, see:
- *
- * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=26634
- */
- saveptr = NULL;
-
- if (!netresolve_backend_parse_address(strtok_r(strdupa(str), " ", &saveptr), address, family, ifindex))
- return false;
- *socktype = enum_id_from_name(strtok_r(NULL, " ", &saveptr), socktypes);
- *protocol = enum_id_from_name(strtok_r(NULL, " ", &saveptr), protocols);
- *port = enum_id_from_name(strtok_r(NULL, " ", &saveptr), NULL);
-
- return true;
-}
-
-void
-netresolve_backend_apply_addrinfo(netresolve_query_t query,
- int status, const struct addrinfo *result, int32_t ttl)
-{
- const struct addrinfo *item;
-
- switch (status) {
- case 0:
- for (item = result; item; item = item->ai_next) {
- union {
- struct in_addr address4;
- struct in6_addr address6;
- } address = {{0}};
- int ifindex = 0;
- int port = 0;
-
- switch (item->ai_family) {
- case AF_INET:
- memcpy(&address.address4, &((struct sockaddr_in *) item->ai_addr)->sin_addr, sizeof address.address4);
- port = ntohs(((struct sockaddr_in *) item->ai_addr)->sin_port);
- break;
- case AF_INET6:
- memcpy(&address.address6, &((struct sockaddr_in6 *) item->ai_addr)->sin6_addr, sizeof address.address6);
- if (IN6_IS_ADDR_LINKLOCAL(&address.address6))
- ifindex = ((struct sockaddr_in6 *) item->ai_addr)->sin6_scope_id;
- port = ntohs(((struct sockaddr_in6 *) item->ai_addr)->sin6_port);
- break;
- }
-
- netresolve_backend_add_path(query,
- item->ai_family, &address, ifindex,
- item->ai_socktype, item->ai_protocol, port,
- 0, 0, ttl);
- }
- /* fall through */
- case EAI_NONAME:
- case EAI_NODATA:
- netresolve_backend_finished(query);
- break;
- default:
- netresolve_backend_failed(query);
- }
-}
-
-void
-netresolve_backend_apply_addrtuple(netresolve_query_t query,
- enum nss_status status, const struct gaih_addrtuple *result,
- int32_t ttl)
-{
- const struct gaih_addrtuple *item;
-
- if (status == NSS_STATUS_SUCCESS) {
- for (item = result; item; item = item->next) {
- netresolve_backend_add_path(query,
- item->family, item->addr, item->scopeid,
- 0, 0, 0,
- 0, 0, ttl);
- }
- netresolve_backend_finished(query);
- } else
- netresolve_backend_failed(query);
-}
-
-void
-netresolve_backend_apply_hostent(netresolve_query_t query,
- const struct hostent *he,
- int socktype, int protocol, int port,
- int priority, int weight, int32_t ttl)
-{
- char **addr;
-
- for (addr = he->h_addr_list; *addr; addr++)
- netresolve_backend_add_path(query,
- he->h_addrtype, *addr, 0,
- socktype, protocol, port,
- priority, weight, ttl);
-
- if (he->h_name)
- netresolve_backend_set_canonical_name(query, he->h_name);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <string.h>
-
-/* FIXME: Get rid of this. */
-#include <netresolve-private.h>
-
-/* netresolve_query_get_sockaddr:
- *
- * Retrieve the address information as `struct sockaddr` and a couple of
- * separate values typically used with the BSD socket API.
- */
-const struct sockaddr *
-netresolve_query_get_sockaddr(netresolve_query_t query, size_t idx,
- socklen_t *salen, int *socktype, int *protocol, int32_t *ttl)
-{
- int family, ifindex, port;
- const void *address;
-
- netresolve_query_get_node_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_service_info(query, idx, socktype, protocol, &port);
- netresolve_query_get_aux_info(query, idx, NULL, NULL, ttl);
-
- if (!address)
- return NULL;
-
- memset(&query->sa_buffer, 0, sizeof query->sa_buffer);
-
- switch (family) {
- case AF_INET:
- query->sa_buffer.sin.sin_family = family;
- query->sa_buffer.sin.sin_port = htons(port);
- query->sa_buffer.sin.sin_addr = *(struct in_addr *) address;
- if (salen)
- *salen = sizeof query->sa_buffer.sin;
- break;
- case AF_INET6:
- query->sa_buffer.sin6.sin6_family = family;
- query->sa_buffer.sin6.sin6_port = htons(port);
- query->sa_buffer.sin6.sin6_scope_id = ifindex;
- query->sa_buffer.sin6.sin6_addr = *(struct in6_addr *) address;
- if (salen)
- *salen = sizeof query->sa_buffer.sin6;
- break;
- default:
- return NULL;
- }
-
- return &query->sa_buffer.sa;
-}
-
-/* netresolve_query_getaddrinfo:
- *
- * Configures the context and calls `netresolve_query()` according to the
- * input parameters which are the same as for POSIX `getaddrinfo()`. As this
- * function both depends on and changes the context configuration, it's
- * recommended that a dedicated context is created and used only for
- * `netresolve_query_getaddrinfo()` queries.
- *
- * When the query is finished, you can pick up the result using
- * `netresolve_query_getaddrinfo_done()` and free it using
- * `netresolve_query_getaddrinfo_free()`.
- */
-netresolve_query_t
-netresolve_query_getaddrinfo(netresolve_t context,
- const char *nodename, const char *servname, const struct addrinfo *hints,
- netresolve_query_callback callback, void *user_data)
-{
- netresolve_query_t query;
- static const struct addrinfo default_hints = { 0 };
-
- if (!hints)
- hints = &default_hints;
-
- query = netresolve_query(context, callback, user_data,
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_OPTION_NODE_NAME, nodename,
- NETRESOLVE_OPTION_SERVICE_NAME, servname ?: "",
- NETRESOLVE_OPTION_FAMILY, hints->ai_family,
- NETRESOLVE_OPTION_SOCKTYPE, hints->ai_socktype,
- NETRESOLVE_OPTION_PROTOCOL, hints->ai_protocol,
- NETRESOLVE_OPTION_DEFAULT_LOOPBACK, !(hints->ai_flags & AI_PASSIVE),
- NETRESOLVE_OPTION_DONE);
-
- if (!(hints->ai_flags & AI_CANONNAME)) {
- free(query->response.nodename);
- query->response.nodename = strdup("");
- }
-
- return query;
-}
-
-int
-netresolve_query_getaddrinfo_done(netresolve_query_t query, struct addrinfo **res, int32_t *ttlp)
-{
- size_t npaths = netresolve_query_get_count(query);
- const char *canonname = netresolve_query_get_node_name(query);
- struct addrinfo head = {0};
- struct addrinfo *ai = &head;
- int i;
-
- if (ttlp)
- *ttlp = INT32_MAX;
-
- for (i = 0; i < npaths; i++) {
- int socktype, protocol;
- socklen_t salen;
- int32_t ttl;
-
- const struct sockaddr *sa = netresolve_query_get_sockaddr(query, i, &salen, &socktype, &protocol, &ttl);
-
- if (ttlp && ttl < *ttlp)
- *ttlp = ttl;
-
- ai = ai->ai_next = calloc(1, sizeof *ai + salen);
- if (!ai) {
- freeaddrinfo(head.ai_next);
- netresolve_query_free(query);
- return EAI_SYSTEM;
- }
- ai->ai_family = sa->sa_family;
- ai->ai_socktype = socktype;
- ai->ai_protocol = protocol;
- ai->ai_addrlen = salen;
- ai->ai_addr = (struct sockaddr *) (ai + 1);
- memcpy(ai->ai_addr, sa, salen);
-
- if (i == 0 && canonname && *canonname)
- ai->ai_canonname = strdup(canonname);
- }
-
- netresolve_query_free(query);
-
- *res = head.ai_next;
- return *res ? 0 : EAI_NODATA;
-}
-
-netresolve_query_t
-netresolve_query_getnameinfo(netresolve_t context,
- const struct sockaddr *sa, socklen_t salen, int flags,
- netresolve_query_callback callback, void *user_data)
-{
- struct sockaddr_in *sa4 = (void *) sa;
- struct sockaddr_in6 *sa6 = (void *) sa;
- int protocol = flags & NI_DGRAM ? IPPROTO_UDP : IPPROTO_TCP;
-
- switch (sa->sa_family) {
- case AF_INET:
- if (salen != sizeof *sa4)
- return NULL;
- return netresolve_query_reverse(context, sa4->sin_family, &sa4->sin_addr, 0,
- protocol, ntohs(sa4->sin_port), callback, user_data);
- case AF_INET6:
- if (salen != sizeof *sa6)
- return NULL;
- return netresolve_query_reverse(context, sa6->sin6_family, &sa6->sin6_addr, sa6->sin6_scope_id,
- protocol, ntohs(sa6->sin6_port), callback, user_data);
- default:
- return NULL;
- }
-}
-
-int
-netresolve_query_getnameinfo_done(netresolve_query_t query, char **node, char **service, int32_t *ttl)
-{
- const char *mynode = netresolve_query_get_node_name(query);
- const char *myservice = netresolve_query_get_service_name(query);
-
- if (node)
- *node = mynode ? strdup(mynode) : NULL;
- if (service)
- *service = myservice ? strdup(myservice) : NULL;
-
- netresolve_query_free(query);
-
- return 0;
-}
-
-/* netresolve_query_gethostbyname:
- *
- * Calls `netresolve_query()` to just resolve a node name. As its operation
- * depends on context configuration, it's recommended that a dedicated context
- * is created and used only for `netresolve_query_gethostbyname()` queries.
- *
- * When the query is finished, you can pick up the result using
- * `netresolve_query_gethostbyname_done()` and free using
- * `netresolve_query_gethostbyname_free()`.
- */
-netresolve_query_t
-netresolve_query_gethostbyname(netresolve_t context,
- const char *name, int family,
- netresolve_query_callback callback, void *user_data)
-{
- return netresolve_query(context, callback, user_data,
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_OPTION_NODE_NAME, name,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_DONE);
-}
-
-static struct hostent *
-get_hostent(netresolve_query_t query, int *h_errnop, int32_t *ttlp)
-{
- size_t npaths = netresolve_query_get_count(query);
- const char *canonname = netresolve_query_get_node_name(query);
- struct hostent *he = NULL;
- int idx;
- int n = 0;
-
- if (!(he = calloc(1, sizeof *he))) {
- *h_errnop = NO_RECOVERY;
- goto out;
- }
-
- if (ttlp)
- *ttlp = INT32_MAX;
-
- if (canonname)
- he->h_name = strdup(canonname);
- he->h_aliases = calloc(1, sizeof *he->h_aliases);
- he->h_addr_list = calloc(npaths + 1, sizeof *he->h_addr_list);
-
- for (idx = 0; idx < npaths; idx++) {
- int family, ifindex, socktype, protocol, port;
- int32_t ttl;
- const void *address;
-
- netresolve_query_get_node_info(query, idx, &family, &address, &ifindex);
- netresolve_query_get_service_info(query, idx, &socktype, &protocol, &port);
- netresolve_query_get_aux_info(query, idx, NULL, NULL, &ttl);
-
- if (ttlp && ttl < *ttlp)
- *ttlp = ttl;
-
- if (family != AF_INET && family != AF_INET6)
- continue;
-
- if (he->h_addrtype) {
- if (he->h_addrtype != family)
- continue;
- } else {
- he->h_addrtype = family;
- he->h_length = family == AF_INET ? 4 : 16;
- }
-
- he->h_addr_list[n] = calloc(1, he->h_length);
- if (!he->h_addr_list[n])
- break;
- memcpy(he->h_addr_list[n], address, he->h_length);
- n++;
- }
-
-out:
- netresolve_query_free(query);
-
- return he;
-}
-
-struct hostent *
-netresolve_query_gethostbyname_done(netresolve_query_t query, int *h_errnop, int32_t *ttlp)
-{
- size_t npaths = netresolve_query_get_count(query);
-
- if (!npaths) {
- *h_errnop = HOST_NOT_FOUND;
- return NULL;
- }
-
- return get_hostent(query, h_errnop, ttlp);
-}
-
-netresolve_query_t netresolve_query_gethostbyaddr(netresolve_t context,
- const void *address, int length, int family,
- netresolve_query_callback callback, void *user_data)
-{
- switch (family) {
- case AF_INET:
- if (length != 4)
- return NULL;
- break;
- case AF_INET6:
- if (length != 16)
- return NULL;
- default:
- return NULL;
- }
-
- netresolve_query_t query = netresolve_query_reverse(context, family, address, 0, 0, 0, callback, user_data);
-
- if (query)
- netresolve_backend_add_path(query, family, address, 0, 0, 0, 0, 0, 0, 0);
-
- return query;
-}
-
-struct hostent *
-netresolve_query_gethostbyaddr_done(netresolve_query_t query, int *h_errnop, int32_t *ttlp)
-{
- return get_hostent(query, h_errnop, ttlp);
-}
-
-void
-netresolve_freeaddrinfo(struct addrinfo *ai)
-{
- struct addrinfo *tmp;
-
- while (ai) {
- tmp = ai;
- ai = ai->ai_next;
- free(tmp->ai_canonname);
- free(tmp);
- }
-}
-
-void
-netresolve_freehostent(struct hostent *he)
-{
- char **p;
-
- if (!he)
- return;
-
- free(he->h_name);
- for (p = he->h_aliases; *p; p++)
- free(*p);
- free(he->h_aliases);
- for (p = he->h_addr_list; *p; p++)
- free(*p);
- free(he->h_addr_list);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <unistd.h>
-#include <string.h>
-#include <dlfcn.h>
-
-static bool
-getenv_bool(const char *name, bool def)
-{
- const char *value = secure_getenv(name);
-
- return value ? (!strcasecmp(value, "yes") || !strcasecmp(value, "true") || !strcasecmp(value, "1")) : def;
-}
-
-static int
-getenv_int(const char *name, int def)
-{
- const char *value = secure_getenv(name);
-
- return value ? strtoll(value, NULL, 10) : def;
-}
-
-static int
-getenv_family(const char *name, int def)
-{
- const char *value = secure_getenv(name);
-
- return value ? netresolve_family_from_string(value) : def;
-}
-
-netresolve_t
-netresolve_context_new(void)
-{
- netresolve_t context;
-
- /* FIXME: this should probably be only called once */
- netresolve_set_log_level(getenv_bool("NETRESOLVE_VERBOSE", false) ? NETRESOLVE_LOG_LEVEL_DEBUG : NETRESOLVE_LOG_LEVEL_QUIET);
-
- if (!(context = calloc(1, sizeof *context)))
- return NULL;
-
- context->queries.previous = context->queries.next = &context->queries;
- context->epoll.fd = -1;
-
- context->config.force_family = getenv_family("NETRESOLVE_FORCE_FAMILY", AF_UNSPEC);
-
- context->request.default_loopback = getenv_bool("NETRESOLVE_FLAG_DEFAULT_LOOPBACK", false);
- context->request.clamp_ttl = getenv_int("NETRESOLVE_CLAMP_TTL", -1);
- context->request.request_timeout = getenv_int("NETRESOLVE_REQUEST_TIMEOUT", 15000);
- context->request.result_timeout = getenv_int("NETRESOLVE_RESULT_TIMEOUT", 5000);
-
- return context;
-}
-
-void
-netresolve_context_free(netresolve_t context)
-{
- struct netresolve_query *queries = &context->queries;
-
- debug_context(context, "destroying context");
-
- while (queries->next != queries)
- netresolve_query_free(queries->next);
-
- netresolve_set_backend_string(context, "");
-
- if (context->callbacks.cleanup)
- context->callbacks.cleanup(context->callbacks.user_data);
-
- memset(context, 0, sizeof *context);
- free(context);
-}
-
-void
-netresolve_context_set_options(netresolve_t context, ...)
-{
- va_list ap;
-
- va_start(ap, context);
- netresolve_request_set_options_from_va(&context->request, ap);
- va_end(ap);
-}
-
-static void
-free_backend(struct netresolve_backend *backend)
-{
- char **p;
-
- if (!backend)
- return;
- if (backend->settings) {
- for (p = backend->settings; *p; p++)
- free(*p);
- free(backend->settings);
- }
- if (backend->dl_handle)
- dlclose(backend->dl_handle);
- free(backend);
-}
-
-static struct netresolve_backend *
-load_backend(char **take_settings)
-{
- struct netresolve_backend *backend = calloc(1, sizeof *backend);
- const char *name;
- char filename[1024];
-
- if (!backend)
- return NULL;
- if (!take_settings || !*take_settings)
- goto fail;
-
- name = *take_settings;
- if (*name == '+') {
- backend->mandatory = true;
- name++;
- }
-
- backend->settings = take_settings;
- snprintf(filename, sizeof filename, "libnetresolve-backend-%s.so", name);
- backend->dl_handle = dlopen(filename, RTLD_NOW);
- if (!backend->dl_handle) {
- error("%s", dlerror());
- goto fail;
- }
-
- backend->setup[NETRESOLVE_REQUEST_FORWARD] = dlsym(backend->dl_handle, "query_forward");
- backend->setup[NETRESOLVE_REQUEST_REVERSE] = dlsym(backend->dl_handle, "query_reverse");
- backend->setup[NETRESOLVE_REQUEST_DNS] = dlsym(backend->dl_handle, "query_dns");
-
- return backend;
-fail:
- free_backend(backend);
- return NULL;
-}
-
-void
-netresolve_set_backend_string(netresolve_t context, const char *string)
-{
- const char *setup, *end;
- char **settings = NULL;
- int nsettings = 0;
- int nbackends = 0;
-
- /* Default */
- if (string == NULL)
- string =
- "unix|any|loopback|numerichost|hosts|hostname|avahi"
-#if defined(USE_ARES)
- "|aresdns"
-#elif defined(USE_UNBOUND)
- "|ubdns"
-#endif
- ;
-
- /* Clear old backends */
- if (context->backends) {
- struct netresolve_backend **backend;
-
- for (backend = context->backends; *backend; backend++)
- free_backend(*backend);
- free(context->backends);
- context->backends = NULL;
- }
-
- /* Empty string suggest we only clean up. */
- if (!*string)
- return;
-
- /* Install new set of backends */
- for (setup = end = string; true; end++) {
- if (*end == ' ' || *end == '|' || *end == '\0') {
- settings = realloc(settings, (nsettings + 2) * sizeof *settings);
- settings[nsettings++] = strndup(setup, end - setup);
- settings[nsettings] = NULL;
- setup = end + 1;
- }
- if (*end == '|' || *end == '\0') {
- if (settings && *settings && **settings) {
- context->backends = realloc(context->backends, (nbackends + 2) * sizeof *context->backends);
- context->backends[nbackends] = load_backend(settings);
- if (context->backends[nbackends]) {
- nbackends++;
- context->backends[nbackends] = NULL;
- }
- } else
- free(settings);
- nsettings = 0;
- settings = NULL;
- }
- if (*end == '\0') {
- break;
- }
- }
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-epoll.h>
-#include <netresolve-private.h>
-#include <unistd.h>
-#include <assert.h>
-
-#define EPOLL_MAXEVENTS 128
-
-static void *
-add_watch(netresolve_t context, int fd, int events, netresolve_watch_t watch)
-{
- struct netresolve_epoll *loop = netresolve_get_user_data(context);
- struct epoll_event event = { .events = events, .data = { .ptr = watch } };
-
- assert(watch);
-
- if (epoll_ctl(loop->fd, EPOLL_CTL_ADD, fd, &event) == -1) {
- error("epoll_ctl: %s", strerror(errno));
- abort();
- }
-
- loop->count++;
-
- return watch;
-}
-
-static void
-remove_watch(netresolve_t context, int fd, void *handle)
-{
- struct netresolve_epoll *loop = netresolve_get_user_data(context);
- int i;
-
- if (epoll_ctl(loop->fd, EPOLL_CTL_DEL, fd, NULL) == -1) {
- error("epoll_ctl: %s", strerror(errno));
- abort();
- }
-
- /* Disable any pending events. */
- for (i = 0; i < loop->nevents; i++) {
- if (handle == loop->events[i].data.ptr) {
- loop->events[i].data.ptr = NULL;
- debug_context(context, "epoll: disabled pending event %d for removed watch %p", i, handle);
- }
- }
-
- loop->count--;
-}
-
-static void
-cleanup_members(void *user_data)
-{
- struct netresolve_epoll *loop = user_data;
-
- assert(!loop->count);
-
- if (close(loop->fd) == -1)
- error("closing epoll file descriptor %d: %s", loop->fd, strerror(errno));
-
- free(loop->events);
- memset(loop, 0, sizeof *loop);
-}
-
-static void
-cleanup(void *user_data)
-{
- cleanup_members(user_data);
- free(user_data);
-}
-
-/* netresolve_epoll_install:
- *
- * This function is used internally by netresolve to install the default epoll
- * based main loop to support the blocking mode. In applications, use
- * `netresolve_epoll_new()` instead.
- */
-bool
-netresolve_epoll_install(netresolve_t context,
- struct netresolve_epoll *loop,
- bool internal)
-{
- assert(!loop->events);
-
- if (!(loop->events = calloc(EPOLL_MAXEVENTS, sizeof *loop->events)))
- goto fail_events;
-
- if ((loop->fd = epoll_create1(EPOLL_CLOEXEC)) == -1) {
- error("epoll_create1: %s", strerror(errno));
- goto fail_epoll;
- }
-
- netresolve_set_fd_callbacks(context, add_watch, remove_watch, internal ? cleanup_members : cleanup, loop);
-
- debug("created epoll file descriptor: %d", loop->fd);
-
- return true;
-fail_epoll:
- free(loop->events);
-fail_events:
- free(loop);
-
- return false;
-}
-
-/* netresolve_epoll_new:
- *
- * Use this constructor instead of `netresolve_context_new()` to use the library in
- * a file descriptor based nonblocking mode. Always use
- * `netresolve_epoll_close()` to dispose of the context.
- */
-netresolve_t
-netresolve_epoll_new(void)
-{
- netresolve_t context = netresolve_context_new();
-
- if (context) {
- if (netresolve_epoll_fd(context) == -1) {
- netresolve_context_free(context);
- context = NULL;
- }
- }
-
- return context;
-}
-
-/* netresolve_epoll_fd:
- *
- * Retrieve the epoll file descriptor from the context. Do not add any file
- * descriptors to the epoll instance. Just use the file descriptor in your
- * event loop and poll it for reading.
- *
- * As a bonus, You can call this function between `netresolve_context_new()` and the
- * first query to convert a blocking context to an epoll based non-blocking
- * one. A sequence of `netresolve_context_new()` and `netresolve_epoll_fd()` is thus
- * equivalent to `netresolve_epoll_new()` with an optional
- * `netresolve_epoll_fd()` to retrieve the file descriptor.
- */
-int
-netresolve_epoll_fd(netresolve_t context)
-{
- struct netresolve_epoll *loop = netresolve_get_user_data(context);
-
- /* Automatically turn netresolve context into an epoll based nonblocking one */
- if (!loop) {
- if (!(loop = calloc(1, sizeof *loop)))
- return -1;
- if (!netresolve_epoll_install(context, loop, false)) {
- free(loop);
- return -1;
- }
- }
-
- return loop->fd;
-}
-
-static int
-dispatch_events(netresolve_t context, int timeout)
-{
- struct netresolve_epoll *loop = netresolve_get_user_data(context);
- int i;
-
- debug_context(context, "epoll: waiting");
- loop->nevents = TEMP_FAILURE_RETRY(epoll_wait(loop->fd, loop->events, EPOLL_MAXEVENTS, timeout));
-
- switch (loop->nevents) {
- case -1:
- error("epoll_wait: %s", strerror(errno));
- abort();
- case 0:
- error("epoll_wait: no events");
- break;
- default:
- debug_context(context, "epoll_wait: new events: %d", loop->nevents);
- for (i = 0; i < loop->nevents; i++)
- if (loop->events[i].data.ptr)
- netresolve_dispatch(context, loop->events[i].data.ptr, loop->events[i].events);
- }
-
- return loop->nevents;
-}
-
-/* netresolve_epoll_dispatch:
- *
- * Call this function when the file descriptor is ready for reading.
- */
-void
-netresolve_epoll_dispatch(netresolve_t context)
-{
- /* FIXME: We currently need to run the dispatch events repeatedly as long
- * as there are still pending events in order to keep asyncns_wait working
- * correctly with block=0 as it relies on all pending events being
- * processed.
- */
- while (dispatch_events(context, 0) > 0)
- ;
-}
-
-/* netresolve_epoll_wait:
- *
- * This function is used internally by netresolve to run an epoll based
- * main loop for the context until all pending queries are fully
- * processed. You wouldn't run it in your application but it is definitely
- * useful for simple testing, as it simulates a real application main
- * loop and allows for processing queries simultaneously.
- */
-void
-netresolve_epoll_wait(netresolve_t context)
-{
- struct netresolve_epoll *loop = netresolve_get_user_data(context);
-
- while (loop->count > 0)
- dispatch_events(context, -1);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <poll.h>
-#include <sys/timerfd.h>
-#include <unistd.h>
-
-void
-netresolve_set_fd_callbacks(netresolve_t context,
- netresolve_watch_add_callback_t add_watch,
- netresolve_watch_remove_callback_t remove_watch,
- netresolve_cleanup_callback_t cleanup,
- void *user_data)
-{
- assert(add_watch && remove_watch);
- assert(!context->callbacks.add_watch && !context->callbacks.remove_watch);
-
- context->callbacks.add_watch = add_watch;
- context->callbacks.remove_watch = remove_watch;
- context->callbacks.cleanup = cleanup;
-
- context->callbacks.user_data = user_data;
-}
-
-void *
-netresolve_get_user_data(netresolve_t context)
-{
- return context->callbacks.user_data;
-}
-
-netresolve_watch_t
-netresolve_watch_add(netresolve_query_t query, int fd, int events,
- netresolve_watch_callback_t callback, void *data)
-{
- struct netresolve_watch *watches = &query->watches;
- struct netresolve_watch *watch;
-
- assert(fd >= 0);
- assert(events && !(events & ~(POLLIN | POLLOUT)));
-
- if (!(watch = calloc(1, sizeof(*watch))))
- abort();
-
- watch->query = query;
- watch->fd = fd;
- watch->callback = callback;
- watch->data = data;
- watch->handle = query->context->callbacks.add_watch(query->context, fd, events, watch);
-
- watch->previous = watches->previous;
- watch->next = watches;
- watch->previous->next = watch->next->previous = watch;
-
- query->nfds++;
- query->context->nfds++;
-
- debug_query(query, "added file descriptor: fd=%d events=%d watch=%p (total %d/%d)", fd, events, watch, query->nfds, query->context->nfds);
-
- assert(watch);
-
- return watch;
-}
-
-void
-netresolve_watch_remove(netresolve_query_t query, netresolve_watch_t watch, bool do_close)
-{
- struct netresolve_watch *watches = &query->watches;
-
- assert(query->nfds > 0);
- assert(query->context->nfds > 0);
- assert(watch != watches);
-
- watch->previous->next = watch->next;
- watch->next->previous = watch->previous;
-
- query->nfds--;
- query->context->nfds--;
-
- query->context->callbacks.remove_watch(query->context, watch->fd, watch->handle);
-
- debug_query(query, "removed file descriptor: fd=%d watch=%p (total %d/%d)", watch->fd, watch, query->nfds, query->context->nfds);
-
- if (do_close) {
- close(watch->fd);
- debug_query(query, "closed file descriptor: fd=%d", watch->fd);
- }
-
- memset(watch, 0, sizeof *watch);
- free(watch);
-}
-
-static void
-timeout_watch_callback(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- watch->timeout_callback(query, watch, data);
-}
-
-netresolve_timeout_t
-netresolve_timeout_add(netresolve_query_t query, time_t sec, long nsec,
- netresolve_timeout_callback_t callback, void *data)
-{
- netresolve_watch_t watch;
- int fd;
- struct itimerspec timerspec = {{0, 0}, {sec, (sec != 0 || nsec != 0) ? nsec : 1}};
-
- if ((fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK)) == -1)
- return NULL;
-
- if (timerfd_settime(fd, 0, &timerspec, NULL) == -1) {
- close(fd);
- return NULL;
- }
-
- debug_query(query, "adding timeout: fd=%d sec=%d nsec=%ld", fd, (int) sec, nsec);
-
- watch = netresolve_watch_add(query, fd, POLLIN, NULL, data);
-
- if (watch && callback) {
- watch->callback = timeout_watch_callback;
- watch->timeout_callback = callback;
- }
-
- assert(watch);
-
- return watch;
-}
-
-netresolve_timeout_t
-netresolve_timeout_add_ms(netresolve_query_t query, time_t msec,
- netresolve_timeout_callback_t callback, void *data)
-{
- return netresolve_timeout_add(query, msec / 1000, (msec % 1000) * 1000000L, callback, data);
-}
-
-void
-netresolve_timeout_remove(netresolve_query_t query, netresolve_timeout_t timeout)
-{
- debug_query(query, "removing timeout: %p timeoutfd=%d", timeout, timeout->fd);
-
- netresolve_watch_remove(query, timeout, true);
-}
-
-void
-netresolve_dispatch(netresolve_t context, netresolve_watch_t watch, int events)
-{
- assert(watch);
- assert(watch->query);
-
- debug_query(watch->query, "dispatching: fd=%d events=%d watch=%p", watch->fd, events, watch);
-
- netresolve_query_dispatch(watch->query, watch, watch->fd, events, watch->data);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-
-static enum netresolve_log_level log_level = 0;
-
-enum netresolve_log_level
-netresolve_get_log_level(void)
-{
- return log_level;
-}
-
-void
-netresolve_set_log_level(enum netresolve_log_level new_log_level)
-{
- log_level = new_log_level;
-}
-
-void
-netresolve_log(int level, const char *fmt, ...)
-{
- if (level <= netresolve_get_log_level()) {
- va_list ap;
- size_t len = strlen(fmt);
- char fmtnl[len + 2];
-
- memcpy(fmtnl, fmt, len);
- fmtnl[len] = '\n';
- fmtnl[len + 1] = '\0';
-
- va_start(ap, fmt);
- vfprintf(stderr, fmtnl, ap);
- va_end(ap);
- }
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <unistd.h>
-#include <string.h>
-#include <poll.h>
-#include <sys/eventfd.h>
-
-const char *
-netresolve_query_state_to_string(enum netresolve_state state)
-{
- switch (state) {
- case NETRESOLVE_STATE_NONE:
- return "none";
- case NETRESOLVE_STATE_SETUP:
- return "setup";
- case NETRESOLVE_STATE_WAITING:
- return "waiting";
- case NETRESOLVE_STATE_WAITING_MORE:
- return "waiting-more";
- case NETRESOLVE_STATE_RESOLVED:
- return "resolved";
- case NETRESOLVE_STATE_DONE:
- return "done";
- case NETRESOLVE_STATE_ERROR:
- return "error";
- case NETRESOLVE_STATE_FAILED:
- return "failed";
- }
-
- abort();
-}
-
-static void
-clear_timeout(netresolve_query_t query, netresolve_timeout_t *timeout)
-{
- if (!*timeout)
- return;
-
- netresolve_timeout_remove(query, *timeout);
- *timeout = NULL;
-}
-
-static void
-cleanup_query(netresolve_query_t query)
-{
- struct netresolve_backend *backend = query->backend ? *query->backend : NULL;
-
- clear_timeout(query, &query->delayed);
- clear_timeout(query, &query->request_timeout);
- clear_timeout(query, &query->result_timeout);
-
- if (backend) {
- if (backend->cleanup)
- backend->cleanup(backend->data);
- if (backend->data)
- free(backend->data);
- backend->data = NULL;
- }
-}
-
-static void
-dispatch_timeout(netresolve_query_t query, netresolve_timeout_t *timeout, enum netresolve_state state)
-{
- assert(timeout && *timeout);
-
- clear_timeout(query, timeout);
- netresolve_query_set_state(query, state);
-}
-
-static void
-dispatch_request_timeout(netresolve_query_t query, netresolve_timeout_t timeout, void *data)
-{
- assert(query->state == NETRESOLVE_STATE_WAITING || query->state == NETRESOLVE_STATE_WAITING_MORE);
-
- debug_query(query, "timeout: request is cancelled");
-
- dispatch_timeout(query, &query->request_timeout, NETRESOLVE_STATE_FAILED);
-}
-
-static void
-dispatch_result_timeout(netresolve_query_t query, netresolve_timeout_t timeout, void *data)
-{
- assert(query->state == NETRESOLVE_STATE_WAITING_MORE);
-
- debug_query(query, "timeout: result result will be served");
-
- dispatch_timeout(query, &query->result_timeout, NETRESOLVE_STATE_DONE);
-}
-
-static void
-dispatch_delayed(netresolve_query_t query, netresolve_timeout_t timeout, void *data)
-{
- assert(query->state == NETRESOLVE_STATE_RESOLVED);
-
- debug_query(query, "delayed state change triggered");
-
- dispatch_timeout(query, &query->delayed, NETRESOLVE_STATE_DONE);
-}
-
-void
-netresolve_query_set_state(netresolve_query_t query, enum netresolve_state state)
-{
- enum netresolve_state old_state = query->state;
-
- if (state == old_state)
- return;
-
- debug_query(query, "state: %s -> %s",
- netresolve_query_state_to_string(old_state), netresolve_query_state_to_string(state));
-
- query->state = state;
-
- /* Entering state... */
- switch (state) {
- case NETRESOLVE_STATE_NONE:
- free(query->request.dns_name);
- free(query->response.paths);
- free(query->response.nodename);
- free(query->response.servname);
- netresolve_service_list_free(query->services);
- memset(&query->response, 0, sizeof query->response);
- break;
- case NETRESOLVE_STATE_SETUP:
- {
- struct netresolve_backend *backend = *query->backend;
- void (*setup)(netresolve_query_t query, char **settings);
-
- if (query->request.dns_srv_lookup && !query->request.protocol)
- query->request.protocol = IPPROTO_TCP;
-
- setup = backend->setup[query->request.type];
- if (setup) {
- setup(query, backend->settings + 1);
- if (query->state == NETRESOLVE_STATE_SETUP)
- netresolve_query_set_state(query, query->request.request_timeout ? NETRESOLVE_STATE_WAITING : NETRESOLVE_STATE_FAILED);
- if (query->state == NETRESOLVE_STATE_ERROR)
- netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
- } else
- netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
- }
- break;
- case NETRESOLVE_STATE_WAITING:
- if (query->request.request_timeout > 0)
- query->request_timeout = netresolve_timeout_add_ms(query, query->request.request_timeout, dispatch_request_timeout, NULL);
- break;
- case NETRESOLVE_STATE_WAITING_MORE:
- if (query->request.result_timeout == 0)
- netresolve_query_set_state(query, NETRESOLVE_STATE_DONE);
- if (query->request.result_timeout > 0)
- query->result_timeout = netresolve_timeout_add_ms(query, query->request.result_timeout, dispatch_result_timeout, NULL);
- break;
- case NETRESOLVE_STATE_RESOLVED:
- if (old_state == NETRESOLVE_STATE_SETUP) {
- int fd;
-
- if ((fd = eventfd(1, EFD_NONBLOCK)) == -1) {
- error("can't create eventfd");
- abort();
- }
- /* FIXME: should also work with zero! */
- /* FIXME: might not even be needed any more! */
- query->delayed = netresolve_timeout_add_ms(query, 0, dispatch_delayed, NULL);
- }
- break;
- case NETRESOLVE_STATE_DONE:
- cleanup_query(query);
-
- /* Restart with the next *mandatory* backend. */
- while (*++query->backend) {
- if ((*query->backend)->mandatory) {
- netresolve_query_set_state(query, NETRESOLVE_STATE_SETUP);
- break;
- }
- }
-
- if (query->callback)
- query->callback(query, query->user_data);
- break;
- case NETRESOLVE_STATE_ERROR:
- break;
- case NETRESOLVE_STATE_FAILED:
- if (query->response.pathcount)
- error("Failed reply has data.");
-
- cleanup_query(query);
-
- /* Restart with the next backend. */
- if (*++query->backend) {
- netresolve_query_set_state(query, NETRESOLVE_STATE_SETUP);
- break;
- }
-
- if (query->callback)
- query->callback(query, query->user_data);
- break;
- }
-}
-
-netresolve_query_t
-netresolve_query_new(netresolve_t context, enum netresolve_request_type type)
-{
- struct netresolve_query *queries = &context->queries;
- netresolve_query_t query;
-
- if (!(query = calloc(1, sizeof *query)))
- return NULL;
-
- query->previous = queries->previous;
- query->next = queries;
- query->previous->next = query->next->previous = query;
-
- query->context = context;
- query->watches.previous = query->watches.next = &query->watches;
-
- if (!context->backends)
- netresolve_set_backend_string(context, secure_getenv("NETRESOLVE_BACKENDS"));
- if (!context->backends || !*context->backends)
- abort();
-
- query->backend = context->backends;
- memcpy(&query->request, &context->request, sizeof context->request);
-
- query->request.type = type;
-
- debug_query(query, "created", type);
-
- return query;
-}
-
-netresolve_query_t
-netresolve_query( netresolve_t context, netresolve_query_callback callback, void *user_data,
- enum netresolve_option type, ...)
-{
- static netresolve_t default_context = NULL;
- netresolve_query_t query;
- va_list ap;
-
- /* Use a static context if none is provided. */
- if (!context) {
- if (!default_context)
- default_context = netresolve_context_new();
- context = default_context;
- }
- if (!context)
- return NULL;
-
- if (!(query = netresolve_query_new(context, type)))
- return NULL;
-
- query->callback = callback;
- query->user_data = user_data;
-
- va_start(ap, type);
- if (!netresolve_request_set_options_from_va(&query->request, ap)) {
- netresolve_query_free(query);
- va_end(ap);
- return NULL;
- }
- va_end(ap);
-
- if (context->config.force_family)
- query->request.family = context->config.force_family;
-
- /* Install default callbacks for first query in blocking mode. */
- if (!context->callbacks.add_watch)
- netresolve_epoll_install(context, &context->epoll, true);
-
- netresolve_query_set_state(query, NETRESOLVE_STATE_SETUP);
-
- /* Wait for the context in blocking mode. */
- if (context->callbacks.user_data == &context->epoll)
- netresolve_epoll_wait(context);
-
- return query;
-}
-
-netresolve_query_t
-netresolve_query_forward(netresolve_t context,
- const char *nodename, const char *servname,
- netresolve_query_callback callback, void *user_data)
-{
- return netresolve_query(context, callback, user_data,
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_OPTION_NODE_NAME, nodename,
- NETRESOLVE_OPTION_SERVICE_NAME, servname,
- NULL);
-}
-
-netresolve_query_t
-netresolve_query_reverse(netresolve_t context,
- int family, const void *address, int ifindex, int protocol, int port,
- netresolve_query_callback callback, void *user_data)
-{
- enum netresolve_option address_option;
-
- switch (family) {
- case AF_INET:
- address_option = NETRESOLVE_OPTION_IP4_ADDRESS;
- break;
- case AF_INET6:
- address_option = NETRESOLVE_OPTION_IP6_ADDRESS;
- break;
- default:
- return NULL;
- }
-
- return netresolve_query(context, callback, user_data,
- NETRESOLVE_REQUEST_REVERSE,
- address_option, address,
- NETRESOLVE_OPTION_IFINDEX, ifindex,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NETRESOLVE_OPTION_PORT, port,
- NULL);
-}
-
-netresolve_query_t
-netresolve_query_dns(netresolve_t context,
- const char *dname, int cls, int type,
- netresolve_query_callback callback, void *user_data)
-{
- return netresolve_query(context, callback, user_data,
- NETRESOLVE_REQUEST_DNS,
- NETRESOLVE_OPTION_DNS_NAME, dname,
- NETRESOLVE_OPTION_DNS_CLASS, cls,
- NETRESOLVE_OPTION_DNS_TYPE, type,
- NULL);
-}
-
-/* netresolve_query_dispatch:
- *
- * This internal function is called by the netresolve context object to hand
- * over file descriptor events to a query.
- */
-void
-netresolve_query_dispatch(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- assert(watch->callback);
-
- debug_query(query, "dispatching watch %p", watch);
-
- watch->callback(query, watch, fd, events, data);
-
- /* Check for state changes. */
- if (query->state == NETRESOLVE_STATE_RESOLVED)
- netresolve_query_set_state(query, NETRESOLVE_STATE_DONE);
- if (query->state == NETRESOLVE_STATE_ERROR)
- netresolve_query_set_state(query, NETRESOLVE_STATE_FAILED);
-}
-
-/* netresolve_query_free:
- *
- * Call this function when you are finished with the netresolve query and
- * don't need to access it any more. It cancels the query if it hasn't been
- * finished yet, and performs internal cleanups. Don't use the query handle
- * after calling it.
- */
-void
-netresolve_query_free(netresolve_query_t query)
-{
- debug_query(query, "destroying query");
-
- cleanup_query(query);
-
- netresolve_query_set_state(query, NETRESOLVE_STATE_NONE);
-
- assert(query->nfds == 0);
- assert(query->watches.next == &query->watches);
- assert(query->watches.previous == &query->watches);
-
- query->previous->next = query->next;
- query->next->previous = query->previous;
-
- assert(query->nfds == 0);
-
- free(query->request.nodename);
- free(query->request.servname);
- free(query->request.dns_name);
- free(query);
-}
-
-/* netresolve_query_get_count:
- *
- * Forward query: Retrieve a number of address objects available in the query
- * result.
- */
-size_t
-netresolve_query_get_count(netresolve_query_t query)
-{
- return query->response.pathcount;
-}
-
-/* netresolve_query_get_node_info:
- *
- * Forward query: Retrieve node related address information.
- */
-void
-netresolve_query_get_node_info(netresolve_query_t query, size_t idx,
- int *family, const void **address, int *ifindex)
-{
- assert (idx < query->response.pathcount);
-
- if (family)
- *family = query->response.paths[idx].node.family;
- if (address)
- *address = &query->response.paths[idx].node.address;
- if (ifindex)
- *ifindex = query->response.paths[idx].node.ifindex;
-}
-
-/* netresolve_query_get_service_info:
- *
- * Forward query: Retrieve service related address information.
- */
-void
-netresolve_query_get_service_info(netresolve_query_t query, size_t idx,
- int *socktype, int *protocol, int *port)
-{
- assert (idx < query->response.pathcount);
-
- if (socktype)
- *socktype = query->response.paths[idx].service.socktype;
- if (protocol)
- *protocol = query->response.paths[idx].service.protocol;
- if (port)
- *port = query->response.paths[idx].service.port;
-}
-
-/* netresolve_query_get_aux_info:
- *
- * Forward query: Retreive auxiliary address information.
- */
-void
-netresolve_query_get_aux_info(netresolve_query_t query, size_t idx,
- int *priority, int *weight, int *ttl)
-{
- assert (idx < query->response.pathcount);
-
- if (priority)
- *priority = query->response.paths[idx].priority;
- if (weight)
- *weight = query->response.paths[idx].weight;
- if (ttl)
- *ttl = query->request.clamp_ttl >= 0 ? query->request.clamp_ttl : query->response.paths[idx].ttl;
-}
-
-/* netresolve_query_get_node_name:
- *
- * Forward query: Retrieve the canonical name.
- *
- * Reverse query: Retrieve the node name.
- */
-const char *
-netresolve_query_get_node_name(const netresolve_query_t query)
-{
- if (query->response.nodename)
- return query->response.nodename;
- if (query->state != NETRESOLVE_STATE_DONE)
- return NULL;
- if (query->request.type != NETRESOLVE_REQUEST_FORWARD)
- return NULL;
- return query->request.nodename ?: "localhost";
-}
-
-/* netresolve_query_get_service_name:
- *
- * Reverse query: Retrieve the service name.
- */
-const char *
-netresolve_query_get_service_name(const netresolve_query_t query)
-{
- return query->response.servname;
-}
-
-/* netresolve_query_get_dns_answer:
- *
- * DNS query: Retrieve the DNS answer.
- */
-const void *
-netresolve_query_get_dns_answer(const netresolve_query_t query, size_t *size)
-{
- if (size)
- *size = query->response.dns.length;
-
- return query->response.dns.answer;
-}
-
-bool
-netresolve_query_get_secure(const netresolve_query_t query)
-{
- return query->response.security == NETRESOLVE_SECURITY_SECURE;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-
-static void
-copy_string(char **target, const char *source)
-{
- free(*target);
- *target = source ? strdup(source) : NULL;
-}
-
-static void
-copy_nonnegative(int *target, int source)
-{
- if (source >= 0)
- *target = source;
-}
-
-bool
-netresolve_request_set_options_from_va(struct netresolve_request *request, va_list ap)
-{
- enum netresolve_option option;
-
- while ((option = va_arg(ap, enum netresolve_option))) {
- switch (option) {
- case NETRESOLVE_OPTION_NODE_NAME:
- copy_string(&request->nodename, va_arg(ap, const char *));
- break;
- case NETRESOLVE_OPTION_SERVICE_NAME:
- copy_string(&request->servname, va_arg(ap, const char *));
- break;
- case NETRESOLVE_OPTION_FAMILY:
- copy_nonnegative(&request->family, va_arg(ap, int));
- break;
- case NETRESOLVE_OPTION_SOCKTYPE:
- copy_nonnegative(&request->socktype, va_arg(ap, int));
- break;
- case NETRESOLVE_OPTION_PROTOCOL:
- copy_nonnegative(&request->protocol, va_arg(ap, int));
- break;
- case NETRESOLVE_OPTION_IFINDEX:
- copy_nonnegative(&request->ifindex, va_arg(ap, int));
- break;
- case NETRESOLVE_OPTION_IP4_ADDRESS:
- request->family = AF_INET;
- memcpy(request->address, va_arg(ap, const void *), sizeof (struct in_addr));
- break;
- case NETRESOLVE_OPTION_IP6_ADDRESS:
- request->family = AF_INET6;
- memcpy(request->address, va_arg(ap, const void *), sizeof (struct in6_addr));
- break;
- case NETRESOLVE_OPTION_PORT:
- request->port = va_arg(ap, int);
- break;
- case NETRESOLVE_OPTION_DNS_NAME:
- copy_string(&request->dns_name, va_arg(ap, const char *));
- break;
- case NETRESOLVE_OPTION_DNS_CLASS:
- request->dns_class = va_arg(ap, int);
- break;
- case NETRESOLVE_OPTION_DNS_TYPE:
- request->dns_type = va_arg(ap, int);
- break;
- case NETRESOLVE_OPTION_DEFAULT_LOOPBACK:
- request->default_loopback = va_arg(ap, int);
- break;
- case NETRESOLVE_OPTION_DNS_SRV_LOOKUP:
- request->dns_srv_lookup = va_arg(ap, int);
- break;
- default:
- return false;
- }
- }
-
- return true;
-}
-
-static bool
-get_option(struct netresolve_request *request, int option, void *argument)
-{
- switch (option) {
- case NETRESOLVE_OPTION_DEFAULT_LOOPBACK:
- *(bool *) argument = request->default_loopback;
- break;
- case NETRESOLVE_OPTION_DNS_SRV_LOOKUP:
- *(bool *) argument = request->dns_srv_lookup;
- break;
- case NETRESOLVE_OPTION_NODE_NAME:
- *(const char **) argument = request->nodename;
- break;
- case NETRESOLVE_OPTION_SERVICE_NAME:
- *(const char **) argument = request->servname;
- break;
- case NETRESOLVE_OPTION_FAMILY:
- *(int *) argument = request->family;
- break;
- case NETRESOLVE_OPTION_SOCKTYPE:
- *(int *) argument = request->socktype;
- break;
- case NETRESOLVE_OPTION_PROTOCOL:
- *(int *) argument = request->protocol;
- break;
- case NETRESOLVE_OPTION_IFINDEX:
- *(int *) argument = request->ifindex;
- break;
- case NETRESOLVE_OPTION_IP4_ADDRESS:
- case NETRESOLVE_OPTION_IP6_ADDRESS:
- *(const void **) argument = request->address;
- break;
- case NETRESOLVE_OPTION_PORT:
- *(int *) argument = request->port;
- break;
- case NETRESOLVE_OPTION_DNS_NAME:
- *(const char **) argument = request->dns_name;
- break;
- case NETRESOLVE_OPTION_DNS_CLASS:
- *(int *) argument = request->dns_class;
- break;
- case NETRESOLVE_OPTION_DNS_TYPE:
- *(int *) argument = request->dns_type;
- break;
- default:
- return false;
- }
-
- return true;
-}
-
-bool
-netresolve_request_get_options_from_va(struct netresolve_request *request, va_list ap)
-{
- enum netresolve_option option;
-
- while ((option = va_arg(ap, enum netresolve_option)))
- if (!get_option(request, option, va_arg(ap, void *)))
- return false;
-
- return true;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-select.h>
-#include <netresolve-private.h>
-#include <sys/poll.h>
-#include <assert.h>
-
-struct netresolve_select {
- fd_set rfds, wfds;
- int nfds;
- netresolve_watch_t *sources;
-};
-
-static void *
-add_watch(netresolve_t context, int fd, int events, netresolve_watch_t source)
-{
- struct netresolve_select *loop = netresolve_get_user_data(context);
-
- assert(fd >= 0);
- assert(!FD_ISSET(fd, &loop->rfds) && !FD_ISSET(fd, &loop->wfds));
- assert(events & (POLLIN | POLLOUT));
-
- if (events & POLLIN)
- FD_SET(fd, &loop->rfds);
- if (events & POLLOUT)
- FD_SET(fd, &loop->wfds);
-
- if (fd >= loop->nfds)
- loop->nfds = fd + 1;
-
- loop->sources = realloc(loop->sources, loop->nfds * sizeof *loop->sources);
- assert(loop->sources);
-
- loop->sources[fd] = source;
-
- return NULL;
-}
-
-static void
-remove_watch(netresolve_t context, int fd, void *handle)
-{
- struct netresolve_select *loop = netresolve_get_user_data(context);
-
- assert(fd >= 0);
- assert(FD_ISSET(fd, &loop->rfds) || FD_ISSET(fd, &loop->wfds));
- assert(handle == NULL);
- assert(loop->nfds >= 0);
-
- FD_CLR(fd, &loop->rfds);
- FD_CLR(fd, &loop->wfds);
-
- while (loop->nfds > 0 && !FD_ISSET(loop->nfds - 1, &loop->rfds) && !FD_ISSET(loop->nfds - 1, &loop->wfds))
- loop->nfds--;
-
- loop->sources = realloc(loop->sources, loop->nfds * sizeof *loop->sources);
-}
-
-static void
-cleanup(void *user_data)
-{
- struct netresolve_select *loop = user_data;
-
- assert(!loop->nfds);
-
- free(loop);
-}
-
-netresolve_t
-netresolve_select_new()
-{
- netresolve_t context;
- struct netresolve_select *loop;
-
- if (!(loop = calloc(1, sizeof *loop)))
- goto fail;
- if (!(context = netresolve_context_new()))
- goto fail_context;
-
- netresolve_set_fd_callbacks(context, add_watch, remove_watch, cleanup, loop);
-
- return context;
-fail_context:
- free(loop);
-fail:
- return NULL;
-}
-
-int
-netresolve_select_apply_fds(netresolve_t context, fd_set *rfds, fd_set *wfds)
-{
- struct netresolve_select *loop = netresolve_get_user_data(context);
-
- for (int fd = 0; fd < loop->nfds; fd++) {
- if (FD_ISSET(fd, &loop->rfds))
- FD_SET(fd, rfds);
- if (FD_ISSET(fd, &loop->wfds))
- FD_SET(fd, wfds);
- }
-
- return loop->nfds;
-}
-
-void
-netresolve_select_dispatch_read(netresolve_t context, int fd)
-{
- struct netresolve_select *loop = netresolve_get_user_data(context);
- assert(fd >= 0);
- assert(fd < loop->nfds);
- assert(FD_ISSET(fd, &loop->rfds));
-
- netresolve_dispatch(context, loop->sources[fd], POLLIN);
-}
-
-void
-netresolve_select_dispatch_write(netresolve_t context, int fd)
-{
- struct netresolve_select *loop = netresolve_get_user_data(context);
-
- assert(fd >= 0);
- assert(fd < loop->nfds);
- assert(FD_ISSET(fd, &loop->wfds));
-
- netresolve_dispatch(context, loop->sources[fd], POLLOUT);
-}
-
-int
-netresolve_select_wait(netresolve_t context, struct timeval *timeout)
-{
- fd_set rfds, wfds;
- int nfds, status;
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- nfds = netresolve_select_apply_fds(context, &rfds, &wfds);
-
- status = select(nfds, &rfds, &wfds, NULL, timeout);
-
- for (int fd = 0; fd < nfds; fd++) {
- if (FD_ISSET(fd, &rfds))
- netresolve_select_dispatch_read(context, fd);
- if (FD_ISSET(fd, &wfds))
- netresolve_select_dispatch_write(context, fd);
- }
-
- return status;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <arpa/inet.h>
-
-struct netresolve_protocol {
- int socktype;
- int protocol;
- bool defaultpair;
- const char *name;
-};
-
-/* Order of socktype/protocol pairs is the same as in glibc's getaddrinfo()
- * implementation.
- */
-static const struct netresolve_protocol protocols[] = {
- { SOCK_STREAM, IPPROTO_TCP, true, "tcp" },
- { SOCK_DGRAM, IPPROTO_UDP, true, "udp" },
- { SOCK_DCCP, IPPROTO_DCCP, false, "dccp" },
- { SOCK_DGRAM, IPPROTO_UDPLITE, false, "udplite" },
- { SOCK_STREAM, IPPROTO_SCTP, false, "sctp" },
- { SOCK_SEQPACKET, IPPROTO_SCTP, false, "sctp" },
- { SOCK_RAW, 0, true, "raw" },
- { 0, 0, false, NULL }
-};
-
-struct netresolve_service {
- int protocol;
- int port;
- char *name;
-};
-
-struct netresolve_service_list {
- struct netresolve_service *items;
- size_t count;
- size_t reserved;
-
-};
-
-static int
-protocol_from_string(const char *str)
-{
- const struct netresolve_protocol *protocol;
-
- if (!str)
- return 0;
- for (protocol = protocols; protocol->name; protocol++)
- if (!strcmp(str, protocol->name))
- return protocol->protocol;
- return 0;
-}
-
-static void
-add_service(struct netresolve_service_list *services, int protocol, int port, const char *name)
-{
- struct netresolve_service service;
-
- memset(&service, 0, sizeof service);
- service.protocol = protocol;
- service.port = port;
- if (name)
- service.name = strdup(name);
-
- if (services->count == services->reserved) {
- if (!services->reserved)
- services->reserved = 256;
- else
- services->reserved *= 2;
- services->items = realloc(services->items, services->reserved * sizeof service);
- }
-
- memcpy(&services->items[services->count++], &service, sizeof service);
-}
-
-static void
-read_service(struct netresolve_service_list *services, char *line)
-{
- int protocol, port;
- const char *name, *alias;
- char *saveptr;
-
- if (!(name = strtok_r(line, " \t", &saveptr)))
- return;
- if (!(port = strtol(strtok_r(NULL, "/", &saveptr), NULL, 10)))
- return;
- if (!(protocol = protocol_from_string(strtok_r(NULL, " \t", &saveptr))))
- return;
- add_service(services, protocol, port, name);
- while ((alias = strtok_r(NULL, " \t", &saveptr)))
- add_service(services, protocol, port, alias);
-}
-
-#define SIZE 1024
-
-static void
-read_services(struct netresolve_service_list *services, const char *path)
-{
- int fd;
- char buffer[SIZE];
- char *current = buffer;
- char *end = buffer + sizeof buffer;
- char *new;
- size_t size;
-
- if (path) {
- if ((fd = open(path, O_RDONLY)) == -1)
- return;
- } else {
- if ((fd = open("/etc/netresolve/services", O_RDONLY)) == -1 && (fd = open("/etc/services", O_RDONLY)) == -1)
- return;
- }
-
- while (true) {
- if (current == end)
- goto out;
-
- size = read(fd, current, end-current);
-
- if (size == 0)
- goto out;
- if (size == -1)
- goto out;
-
- current += size;
-
- /* buffer ...record... new ...next... current ...empty... end */
- for (new = buffer; new < current; new++) {
- /* Comment */
- if (*new == '#')
- *new = '\0';
- /* New line */
- if (*new == '\n') {
- *new++ = '\0';
- read_service(services, buffer);
- memmove(buffer, new, current - new);
- current = buffer + (current - new);
- new = buffer - 1;
- }
- }
- }
-out:
- close(fd);
- add_service(services, 0, 0, NULL);
- services->reserved = services->count;
- services->items = realloc(services->items, services->reserved * sizeof *services->items);
-}
-
-struct netresolve_service_list *
-netresolve_service_list_new(const char *path)
-{
- struct netresolve_service_list *services;
-
- if (!path)
- path = secure_getenv("NETRESOLVE_SERVICES");
-
- if (!(services = calloc(1, sizeof *services)))
- return NULL;
-
- read_services(services, path);
-
- return services;
-}
-
-void
-netresolve_service_list_free(struct netresolve_service_list *services)
-{
- if (!services)
- return;
-
- for (struct netresolve_service *item = services->items; item->name; item++)
- free(item->name);
-
- free(services->items);
- free(services);
-}
-
-static void
-found_port(const char *name, int socktype, int proto, int port,
- netresolve_service_callback callback, void *user_data)
-{
- const struct netresolve_protocol *protocol;
-
- for (protocol = protocols; protocol->name; protocol++) {
- if (socktype && socktype != protocol->socktype)
- continue;
- if (proto && proto != protocol->protocol)
- continue;
- if ((!socktype || !proto) && !protocol->defaultpair)
- continue;
- callback(name, protocol->socktype, protocol->protocol, port, user_data);
- }
-}
-
-void
-netresolve_service_list_query(struct netresolve_service_list **services,
- const char *name, int socktype, int protocol, int port,
- netresolve_service_callback callback, void *user_data)
-{
- const struct netresolve_service *service;
- int count = 0;
-
- if (name && !port) {
- char *endptr;
-
- port = strtol(name, &endptr, 10);
- if (!*endptr) {
- found_port(name, socktype, protocol, port, callback, user_data);
- return;
- }
- }
-
- *services = netresolve_service_list_new(NULL);
-
- if (*services && (*services)->items) {
- for (service = (*services)->items; service->name; service++) {
- if (name && strcmp(name, service->name))
- continue;
- if (protocol && protocol != service->protocol)
- continue;
- if ((port || !name) && port != service->port)
- continue;
- count++;
- found_port(service->name, socktype, service->protocol, service->port, callback, user_data);
- }
- }
-
- if (!count) {
- char buffer[128] = { 0 };
-
- snprintf(buffer, sizeof buffer, "%d", (int) port);
- found_port(port ? buffer : NULL, socktype, protocol, port, callback, user_data);
- }
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <unistd.h>
-
-#include "netresolve-private.h"
-
-#define PRIORITY_TIMEOUT 1
-
-struct netresolve_socket {
- netresolve_query_t query;
- netresolve_socket_callback_t callback;
- void *user_data;
- int flags;
- netresolve_timeout_t priority_timeout;
- bool skip_scheduled;
-};
-
-static void pickup_connected_socket(struct netresolve_socket *priv);
-
-static void
-connection_callback(netresolve_query_t query, netresolve_watch_t watch, int fd, int events, void *data)
-{
- struct netresolve_socket *priv = query->user_data;
- struct netresolve_path *path = data;
-
- assert(fd == path->socket.fd);
- assert(events & POLLOUT);
- assert(path->socket.state == SOCKET_STATE_SCHEDULED);
- assert(path->socket.watch);
-
- socklen_t len = sizeof(errno);
- getsockopt(path->socket.fd, SOL_SOCKET, SO_ERROR, &errno, &len);
-
- debug_query(query, "socket: connection %s", errno ? "failed" : "succeeded");
-
- netresolve_watch_remove(priv->query, path->socket.watch, !!errno);
-
- path->socket.state = errno ? SOCKET_STATE_DONE : SOCKET_STATE_READY;
- path->socket.watch = NULL;
-
- /* See whether we can pass back a ready connection. */
- pickup_connected_socket(priv);
-}
-
-void
-timeout_callback(netresolve_query_t query, netresolve_timeout_t timeout, void *data)
-{
- struct netresolve_socket *priv = data;
-
- debug_query(query, "socket: priority timeout occured");
-
- priv->skip_scheduled = true;
-
- pickup_connected_socket(priv);
-}
-
-static void
-setup_socket(struct netresolve_socket *priv, struct netresolve_path *path)
-{
- static const int flags = O_NONBLOCK;
- int socktype;
- int protocol;
- const struct sockaddr *sa;
- socklen_t salen;
- int idx = path - priv->query->response.paths;
-
- assert(path->socket.state == SOCKET_STATE_NONE);
-
- sa = netresolve_query_get_sockaddr(priv->query, idx, &salen, &socktype, &protocol, NULL);
- if (!sa)
- goto fail;
- path->socket.fd = socket(sa->sa_family, socktype | flags, protocol);
- if (path->socket.fd == -1)
- goto fail;
-
- errno = 0;
- if (connect(path->socket.fd, sa, salen) == -1 && errno != EINPROGRESS)
- goto fail_connect;
-
- if (errno) {
- debug_query(priv->query, "socket: connection %d via %s scheduled", idx, sa->sa_family == AF_INET ? "IPv4" : "IPv6");
-
- path->socket.state = SOCKET_STATE_SCHEDULED;
- path->socket.watch = netresolve_watch_add(priv->query, path->socket.fd, POLLOUT, connection_callback, path);
- } else {
- /* FIXME: Is it at all possible for non-blocking sockets to connect
- * immediately?
- */
- debug_query(priv->query, "socket: connection %d via %s immediately succeeded", idx, sa->sa_family == AF_INET ? "IPv4" : "IPv6");
-
- path->socket.state = SOCKET_STATE_READY;
- pickup_connected_socket(priv);
- }
-
- return;
-fail_connect:
- close(path->socket.fd);
- path->socket.fd = -1;
-fail:
- path->socket.state = SOCKET_STATE_DONE;
-
- error("socket: connection %d failed", idx);
-}
-
-static void
-enable_sockets(struct netresolve_socket *priv)
-{
- netresolve_query_t query = priv->query;
- int ip4 = 0, ip6 = 0;
-
- /* Attempt to connect to one IPv4 and one IPv6 address in parallel. It is a
- * „happy eyeballs“ style optimization that removes a delay when packets
- * of the preferred protocol (typically IPvy) are dropped on the way which
- * is a very common network misconfiguration.
- */
- for (int i = 0; i < query->response.pathcount; i++) {
- struct netresolve_path *path = &query->response.paths[i];
-
- /* Skip already attempted sockets. */
- if (path->socket.state == SOCKET_STATE_DONE)
- continue;
-
- /* Skip all but first address for each protocol. */
- if (path->node.family == AF_INET && ip4++)
- continue;
- if (path->node.family == AF_INET6 && ip6++)
- continue;
-
- if (path->socket.state == SOCKET_STATE_NONE)
- setup_socket(priv, path);
- else if (path->socket.state == SOCKET_STATE_SCHEDULED && !path->socket.watch) {
- debug_query(priv->query, "socket: resuming connection %d", i);
- path->socket.watch = netresolve_watch_add(priv->query, path->socket.fd, POLLOUT, connection_callback, path);
- }
- }
-
- if (!ip4 && !ip6)
- error("socket: no connection paths available");
-}
-
-static void
-pickup_connected_socket(struct netresolve_socket *priv)
-{
- struct netresolve_path *paths = priv->query->response.paths;
- struct netresolve_path *found;
-
- /* Find first scheduled or ready socket. */
- for (found = paths; found->node.family; found++) {
- if (found->socket.state == SOCKET_STATE_SCHEDULED && !priv->skip_scheduled)
- break;
- if (found->socket.state == SOCKET_STATE_READY)
- break;
- }
-
- /* Pass a ready socket to the application and return. */
- if (found->socket.state == SOCKET_STATE_READY) {
- int fd = found->socket.fd;
-
- debug_query(priv->query, "socket: passing successful connection %d to the application", found - paths);
-
- found->socket.state = SOCKET_STATE_DONE;
- found->socket.fd = -1;
-
- /* Pause all scheduled sockets. */
- for (struct netresolve_path *path = paths; path->node.family; path++) {
- if (path->socket.state == SOCKET_STATE_SCHEDULED) {
- assert(path->socket.watch);
-
- debug_query(priv->query, "socket: pausing scheduled connection %d", path - paths);
-
- netresolve_watch_remove(priv->query, path->socket.watch, false);
- path->socket.watch = NULL;
- }
- }
-
- /* Reset priority timeout. */
- if (priv->priority_timeout) {
- netresolve_timeout_remove(priv->query, priv->priority_timeout);
- priv->priority_timeout = NULL;
- priv->skip_scheduled = false;
- }
-
- fcntl(fd, F_SETFL, (fcntl(fd, F_GETFL, 0) & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) | priv->flags);
- priv->callback(priv->query, found - paths, fd, priv->user_data);
-
- return;
- }
-
- /* Schedule priority timeout if there is a priority socket waiting and
- * another socket ready and continue.
- */
- if (found->socket.state == SOCKET_STATE_SCHEDULED) {
- for (struct netresolve_path *path = paths; path->node.family; path++) {
- if (path->socket.state == SOCKET_STATE_READY) {
- if (priv->priority_timeout)
- debug_query(priv->query, "socket: priority timeout already set");
- else {
- debug_query(priv->query, "socket: setting up priority timeout of %d seconds", PRIORITY_TIMEOUT);
- priv->priority_timeout = netresolve_timeout_add(priv->query, PRIORITY_TIMEOUT, 0, timeout_callback, priv);
- }
- break;
- }
- }
- }
-
- /* Make sure connections are scheduled. */
- enable_sockets(priv);
-}
-
-static void
-query_callback(netresolve_query_t query, void *user_data)
-{
- struct netresolve_socket *priv = user_data;
-
- debug_query(query, "socket: name resolution done");
-
- priv->query = query;
-
- enable_sockets(priv);
-}
-
-static void
-bind_callback(netresolve_query_t query, void *data)
-{
- struct netresolve_socket *priv = data;
- size_t count = netresolve_query_get_count(query);
-
- for (size_t idx = 0; idx < count; idx++) {
- int flags = O_NONBLOCK;
- int socktype;
- int protocol;
- const struct sockaddr *sa;
- socklen_t salen;
- int sock;
-
- sa = netresolve_query_get_sockaddr(query, idx, &salen, &socktype, &protocol, NULL);
- if (!sa)
- return;
- sock = socket(sa->sa_family, socktype | flags, protocol);
- if (sock == -1)
- return;
- if (bind(sock, sa, salen) == -1) {
- close(sock);
- return;
- }
- fcntl(sock, F_SETFL, (fcntl(sock, F_GETFL, 0) & ~(SOCK_NONBLOCK | SOCK_CLOEXEC)) | priv->flags);
-
- priv->callback(query, idx, sock, priv->user_data);
- }
-
- free(priv);
- netresolve_query_free(query);
-}
-
-static void *
-memdup(const void *source, size_t len)
-{
- void *target = malloc(len);
-
- if (target)
- memcpy(target, source, len);
-
- return target;
-}
-
-/* netresolve_connect:
- *
- * Perform name resolution and connect to a host. The callback is called
- * once, with the first successfully connected socket. If you want to
- * retry with another address, use `netresolve_connect_next()`. The caller
- * is responsible for closing any sockets received through the callback.
- *
- * You should call `netresolve_connect_free()` once you know you're not
- * going to call `netresolve_connect_free()` or any other API functions
- * on the query to free all resources associated with the connection
- * request.
- */
-netresolve_query_t
-netresolve_connect(netresolve_t context,
- const char *nodename, const char *servname,
- int family, int socktype, int protocol,
- netresolve_socket_callback_t callback, void *user_data)
-{
- int flags = socktype & (SOCK_NONBLOCK | SOCK_CLOEXEC);
-
- struct netresolve_socket priv = { .callback = callback, .user_data = user_data, .flags = socktype & (SOCK_NONBLOCK | SOCK_CLOEXEC) };
-
- return netresolve_query(context, query_callback, memdup(&priv, sizeof priv),
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_OPTION_NODE_NAME, nodename,
- NETRESOLVE_OPTION_SERVICE_NAME, servname,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype & ~flags,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NETRESOLVE_OPTION_DEFAULT_LOOPBACK, true,
- NULL);
-}
-
-/* netresolve_connect_next:
- *
- * When multiple addresses have been found for the target, retry connection
- * with the next available address.
- */
-void
-netresolve_connect_next(netresolve_query_t query)
-{
- struct netresolve_socket *priv = query->user_data;
-
- enable_sockets(priv);
-}
-
-/* netresolve_connect_free:
- *
- * Destroys the query object and releases any related resources.
- */
-void
-netresolve_connect_free(netresolve_query_t query)
-{
- struct netresolve_socket *priv = query->user_data;
-
- debug("socket: cleaning up...");
-
- for (int i = 0; i < query->response.pathcount; i++) {
- struct netresolve_path *path = &query->response.paths[i];
-
- switch (path->socket.state) {
- case SOCKET_STATE_SCHEDULED:
- if (path->socket.watch)
- netresolve_watch_remove(query, path->socket.watch, true);
- break;
- case SOCKET_STATE_READY:
- close(path->socket.fd);
- break;
- default:
- break;
- }
-
- memset(&path->socket, 0, sizeof path->socket);
- }
-
- if (priv->priority_timeout)
- netresolve_timeout_remove(query, priv->priority_timeout);
-
- memset(priv, 0, sizeof *priv);
- free(priv);
-
- netresolve_query_free(query);
-}
-
-/* netresolve_bind:
- *
- * Perform name resolution, bind to all discovered addresses. Resulting
- * file descriptors are passed to the caller via a series of calls to
- * the provided callback.
- */
-netresolve_query_t
-netresolve_bind(netresolve_t context,
- const char *nodename, const char *servname,
- int family, int socktype, int protocol,
- netresolve_socket_callback_t callback, void *user_data)
-{
- struct netresolve_socket priv = { .callback = callback, .user_data = user_data, .flags = socktype & (SOCK_NONBLOCK | SOCK_CLOEXEC) };
-
- return netresolve_query(context, bind_callback, memdup(&priv, sizeof priv),
- NETRESOLVE_REQUEST_FORWARD,
- NETRESOLVE_OPTION_NODE_NAME, nodename,
- NETRESOLVE_OPTION_SERVICE_NAME, servname,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype & ~priv.flags,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NETRESOLVE_OPTION_DEFAULT_LOOPBACK, false,
- NULL);
-}
-
-/* netresolve_bind_free:
- *
- * Destroys the query object and releases any related resources.
- */
-void
-netresolve_bind_free(netresolve_query_t query)
-{
- netresolve_query_free(query);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <netinet/in.h>
-
-#ifdef USE_LDNS
-#include <ldns/ldns.h>
-#endif
-
-static const char *
-socktype_to_string(int socktype)
-{
- switch (socktype) {
- case 0:
- return "any";
- case SOCK_DGRAM:
- return "dgram";
- case SOCK_STREAM:
- return "stream";
- case SOCK_SEQPACKET:
- return "seqpacket";
- case SOCK_RAW:
- return "raw";
- default:
- return "unknown";
- }
-}
-
-static const char *
-protocol_to_string(int proto)
-{
- switch (proto) {
- case 0:
- return "any";
- case IPPROTO_UDP:
- return "udp";
- case IPPROTO_TCP:
- return "tcp";
- case IPPROTO_SCTP:
- return "sctp";
- default:
- return "unknown";
- }
-}
-
-int
-netresolve_family_from_string(const char *str)
-{
- if (!str)
- return AF_UNSPEC;
- if (!strcmp(str, "ip4"))
- return AF_INET;
- if (!strcmp(str, "ip6"))
- return AF_INET6;
- if (!strcmp(str, "unix"))
- return AF_UNIX;
- /* "any" */
- return AF_UNSPEC;
-}
-
-int
-netresolve_socktype_from_string(const char *str)
-{
- if (!strcmp(str, "raw"))
- return SOCK_RAW;
- if (!strcmp(str, "stream"))
- return SOCK_STREAM;
- if (!strcmp(str, "dgram"))
- return SOCK_DGRAM;
- if (!strcmp(str, "seqpacket"))
- return SOCK_SEQPACKET;
- return 0;
-}
-
-int
-netresolve_protocol_from_string(const char *str)
-{
- if (!strcmp(str, "tcp"))
- return IPPROTO_TCP;
- if (!strcmp(str, "udp"))
- return IPPROTO_UDP;
- if (!strcmp(str, "sctp"))
- return IPPROTO_SCTP;
- return 0;
-}
-
-static int
-bprintf(char **current, char *end, const char *fmt, ...)
-{
- va_list ap;
- ssize_t size;
-
- va_start(ap, fmt);
- size = vsnprintf(*current, end - *current, fmt, ap);
- if (size > 0)
- (*current) += size;
- va_end(ap);
-
- return size;
-}
-
-static void
-add_path(char **start, char *end, netresolve_query_t query, int i)
-{
- int family, ifindex, socktype, protocol, port, priority, weight, ttl;
- const void *address;
- char ifname[IF_NAMESIZE+1+1] = {0};
- char addrstr[1024] = {0};
- const char *socktypestr;
- const char *protocolstr;
-
- netresolve_query_get_node_info(query, i, &family, &address, &ifindex);
- netresolve_query_get_service_info(query, i, &socktype, &protocol, &port);
- netresolve_query_get_aux_info(query, i, &priority, &weight, &ttl);
-
- socktypestr = socktype_to_string(socktype);
- protocolstr = protocol_to_string(protocol);
-
- if (family == AF_INET || family == AF_INET6)
- inet_ntop(family, address, addrstr, sizeof addrstr);
-
- if (family == AF_UNIX)
- bprintf(start, end, "unix %s %s", address, socktypestr);
- else {
- if (ifindex) {
- ifname[0] = '%';
- if (!if_indextoname(ifindex, ifname + 1))
- snprintf(ifname + 1, sizeof ifname - 1, "%d", ifindex);
- }
- bprintf(start, end, "ip %s%s %s %s %d %d %d %d",
- addrstr, ifname,
- socktypestr, protocolstr, port,
- priority, weight, ttl);
- }
-}
-
-const char *
-netresolve_get_request_string(netresolve_query_t query)
-{
- const char *node = netresolve_backend_get_nodename(query);
- const char *service = netresolve_backend_get_servname(query);
- char *start = query->buffer;
- char *end = query->buffer + sizeof query->buffer;
-
- bprintf(&start, end, "request %s %s\n", PACKAGE_NAME, VERSION);
- if (node)
- bprintf(&start, end, "node %s\n", node);
- if (service)
- bprintf(&start, end, "service %s\n", service);
- bprintf(&start, end, "\n");
-
- return query->buffer;
-}
-
-const char *
-netresolve_get_path_string(netresolve_query_t query, int i)
-{
- char *start = query->buffer;
- char *end = query->buffer + sizeof query->buffer;
-
- add_path(&start, end, query, i);
-
- return query->buffer;
-}
-
-const char *
-netresolve_get_response_string(netresolve_query_t query)
-{
- char *start = query->buffer;
- char *end = query->buffer + sizeof query->buffer;
-
- const char *nodename = netresolve_query_get_node_name(query);
- const char *servname = netresolve_query_get_service_name(query);
- size_t npaths = netresolve_query_get_count(query);
- size_t i;
- size_t length;
- const uint8_t *answer = netresolve_query_get_dns_answer(query, &length);
- bool secure = netresolve_query_get_secure(query);
-
- bprintf(&start, end, "response %s %s\n", PACKAGE_NAME, VERSION);
- if (nodename)
- bprintf(&start, end, "name %s\n", nodename);
- if (servname)
- bprintf(&start, end, "service %s\n", servname);
- for (i = 0; i < npaths; i++) {
- add_path(&start, end, query, i);
- bprintf(&start, end, "\n");
- }
- if (length) {
- bprintf(&start, end, "dns %d 0x", length);
- for (i = 0; i < length; i++)
- bprintf(&start, end, "%02hhx", answer[i]);
- bprintf(&start, end, "\n", length);
-
-#ifdef USE_LDNS
- ldns_pkt *pkt;
- int status = ldns_wire2pkt(&pkt, answer, length);
- if (status) {
- error("ldns: %s", ldns_get_errorstr_by_id(status));
- return NULL;
- } else {
- bprintf(&start, end, "%s\n", ldns_pkt2str(pkt));
- ldns_pkt_free(pkt);
- }
-#endif
- }
- if (secure)
- bprintf(&start, end, "secure\n");
- bprintf(&start, end, "\n");
-
- return query->buffer;
-}
+++ /dev/null
-#include "common.h"
-
-void
-check_address(netresolve_query_t query, int exp_family, const char *exp_address_str, int exp_ifindex)
-{
- unsigned char exp_address[16] = { 0 };
- int family;
- const void *address;
- int ifindex;
-
- inet_pton(exp_family, exp_address_str, exp_address);
-
- assert(query);
- assert(netresolve_query_get_count(query) == 1);
-
- netresolve_query_get_node_info(query, 0, &family, &address, &ifindex);
- assert(family = exp_family);
- assert(!memcmp(address, exp_address, family == AF_INET6 ? 16 : 4));
- assert(ifindex == exp_ifindex);
-}
-
-void
-callback1(netresolve_query_t query, void *user_data)
-{
- struct priv_common *priv = user_data;
-
- check_address(query, AF_INET6, "1:2:3:4:5:6:7:8", 999999);
-
- priv->finished++;
-}
-
-void
-callback2(netresolve_query_t query, void *user_data)
-{
- struct priv_common *priv = user_data;
-
- check_address(query, AF_INET, "1.2.3.4", 999999);
-
- priv->finished++;
-}
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve.h>
-#include <arpa/inet.h>
-#include <assert.h>
-#include <errno.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-struct priv_common {
- int finished;
-};
-
-void check_address(netresolve_query_t query, int exp_family, const char *exp_address_str, int exp_ifindex);
-void callback1(netresolve_query_t query, void *user_data);
-void callback2(netresolve_query_t query, void *user_data);
-
-netresolve_t context_new();
-void context_wait();
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip :: any any 0 0 0 0
-ip 0.0.0.0 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip :: stream tcp 0 0 0 0
-ip :: dgram udp 0 0 0 0
-ip :: raw any 0 0 0 0
-ip 0.0.0.0 stream tcp 0 0 0 0
-ip 0.0.0.0 dgram udp 0 0 0 0
-ip 0.0.0.0 raw any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name www.nic.cz
-ip 2001:1488:0:3::2 any any 0 0 0 1
-ip 217.31.205.50 any any 0 0 0 1
-
+++ /dev/null
-response netresolve 0.0.1
-name info.nix.cz
-
+++ /dev/null
-response netresolve 0.0.1
-name perseus.jabber.org
-ip 2001:4800:7810:512:14e1:b81:ff05:8bb stream tcp 5269 1 1 1
-ip 64.49.234.240 stream tcp 5269 1 1 1
-
+++ /dev/null
-response netresolve 0.0.1
-name perseus.jabber.org
-ip 2001:4800:7810:512:14e1:b81:ff05:8bb stream tcp 5269 0 0 1
-ip 64.49.234.240 stream tcp 5269 0 0 1
-
+++ /dev/null
-response netresolve 0.0.1
-name ds0039.flosoft-servers.net
-ip 91.121.109.155 dgram udp 0 40 10 1
-
+++ /dev/null
-response netresolve 0.0.1
-
+++ /dev/null
-response netresolve 0.0.1
-name www.nic.cz
-ip 2001:1488:0:3::2 any any 0 0 0 1
-ip 217.31.205.50 any any 0 0 0 1
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name info.nix.cz
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-
+++ /dev/null
-query:
- nodename = localhost
- servname = (null)
-status = 0
-#0:
- family = 10
- socktype = 1
- protocol = 6
- addrlen = 28
- address:
- family = 10
- port = 0
- flowinfo = 0x00000000
- address = 0x00000000000000000000000000000001
- scope_id = 0
-#1:
- family = 10
- socktype = 2
- protocol = 17
- addrlen = 28
- address:
- family = 10
- port = 0
- flowinfo = 0x00000000
- address = 0x00000000000000000000000000000001
- scope_id = 0
-#2:
- family = 10
- socktype = 3
- addrlen = 28
- address:
- family = 10
- port = 0
- flowinfo = 0x00000000
- address = 0x00000000000000000000000000000001
- scope_id = 0
-#3:
- family = 2
- socktype = 1
- protocol = 6
- addrlen = 16
- address:
- family = 2
- port = 0
- address = 0x7f000001
-#4:
- family = 2
- socktype = 2
- protocol = 17
- addrlen = 16
- address:
- family = 2
- port = 0
- address = 0x7f000001
-#5:
- family = 2
- socktype = 3
- addrlen = 16
- address:
- family = 2
- port = 0
- address = 0x7f000001
+++ /dev/null
-query:
- address = 127.0.0.1
-result:
- name = localhost
- aliases:
- addrtype = 2
- length = 4
- address = 7f000001
- addresses:
- #0 = 7f000001
+++ /dev/null
-query:
- api = gethostbyname
- nodename = localhost
-result:
- name = localhost
- aliases:
- addrtype = 2
- length = 4
- address = 7f000001
- addresses:
- #0 = 7f000001
- #1 = 7f000001
+++ /dev/null
-query:
- address = 127.0.0.1
- port = 80
-status = 0
-result:
- host = localhost
- serv = http
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip ::1 any any 0 0 0 0
-ip 127.0.0.1 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip ::1 stream tcp 80 0 0 0
-ip ::1 dgram udp 80 0 0 0
-ip 127.0.0.1 stream tcp 80 0 0 0
-ip 127.0.0.1 dgram udp 80 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip ::1 stream tcp 0 0 0 0
-ip ::1 dgram udp 0 0 0 0
-ip ::1 raw any 0 0 0 0
-ip 127.0.0.1 stream tcp 0 0 0 0
-ip 127.0.0.1 dgram udp 0 0 0 0
-ip 127.0.0.1 raw any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip 127.0.0.1 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip 127.0.0.1 stream tcp 80 0 0 0
-ip 127.0.0.1 dgram udp 80 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip ::1 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-ip ::1 stream tcp 80 0 0 0
-ip ::1 dgram udp 80 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1.2.3.4
-ip 1.2.3.4 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1.2.3.4%lo
-ip 1.2.3.4%lo any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1.2.3.4%999999
-ip 1.2.3.4%999999 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1:2:3:4:5:6:7:8
-ip 1:2:3:4:5:6:7:8 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-ip 1:2:3:4:5:6:7:8%lo any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1:2:3:4:5:6:7:8%lo
-ip 1:2:3:4:5:6:7:8%lo any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name 1:2:3:4:5:6:7:8%999999
-ip 1:2:3:4:5:6:7:8%999999 any any 0 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name localhost
-ip :: stream tcp 80 0 0 0
-ip :: dgram udp 80 0 0 0
-ip 0.0.0.0 stream tcp 80 0 0 0
-ip 0.0.0.0 dgram udp 80 0 0 0
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name /path/to/socket
-unix /path/to/socket stream
-unix /path/to/socket dgram
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name /path/to/socket
-unix /path/to/socket dgram
-secure
-
+++ /dev/null
-response netresolve 0.0.1
-name /path/to/socket
-unix /path/to/socket stream
-secure
-
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-epoll.h>
-#include "common.h"
-
-netresolve_t
-context_new(struct priv_common *priv)
-{
- netresolve_t context = netresolve_context_new();
- netresolve_epoll_fd(context);
-
- return context;
-}
-
-void
-context_wait(netresolve_t context)
-{
- netresolve_epoll_wait(context);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-select.h>
-#include "common.h"
-
-netresolve_t
-context_new(struct priv_common *priv)
-{
- return netresolve_select_new();
-}
-
-void
-context_wait(netresolve_t context)
-{
- netresolve_select_wait(context, NULL);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve.h>
-#include "common.h"
-
-int
-main(int argc, char **argv)
-{
- struct priv_common priv = { 0 };
- netresolve_t context;
- netresolve_query_t query1, query2;
- const char *node1 = "1:2:3:4:5:6:7:8%999999";
- const char *node2 = "1.2.3.4%999999";
- const char *service = "80";
- int family = AF_UNSPEC;
- int socktype = 0;
- int protocol = IPPROTO_TCP;
-
- /* Create a context. */
- context = context_new(&priv);
- if (!context) {
- perror("netresolve_context_new");
- abort();
- }
-
- /* Resolver configuration. */
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NETRESOLVE_OPTION_DONE);
-
- /* Start name resolution. */
- query1 = netresolve_query_forward(context, node1, service, callback1, &priv);
- query2 = netresolve_query_forward(context, node2, service, callback2, &priv);
- assert(query1 && query2);
-
- usleep(100000);
- context_wait(context);
- assert(priv.finished == 2);
-
- /* Clean up. */
- netresolve_context_free(context);
-
- exit(EXIT_SUCCESS);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <asyncns.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <unistd.h>
-
-int
-main(int argc, char **argv)
-{
- asyncns_t *asyncns;
- asyncns_query_t *query;
- struct addrinfo *result;
- struct pollfd pollfd = { .events = POLLIN };
- int status;
-
- asyncns = asyncns_new(10);
- assert(asyncns);
- assert(asyncns_getnqueries(asyncns) == 0);
- assert(asyncns_getnext(asyncns) == NULL);
-
- pollfd.fd = asyncns_fd(asyncns);
- assert(pollfd.fd > 2);
-
- query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
- assert(query);
- assert(asyncns_getnqueries(asyncns) == 1);
- assert(asyncns_getnext(asyncns) == NULL);
-
- asyncns_cancel(asyncns, query);
- query = NULL;
- assert(asyncns_getnqueries(asyncns) == 0);
- assert(asyncns_getnext(asyncns) == NULL);
-
- query = asyncns_getaddrinfo(asyncns, "127.0.0.1", NULL, NULL);
- assert(query);
- assert(asyncns_getnqueries(asyncns) == 1);
- assert(asyncns_getnext(asyncns) == NULL);
-
- usleep(100000);
- status = poll(&pollfd, 1, 0);
- assert(status == 1);
- status = asyncns_wait(asyncns, 0);
- assert(status == 0);
- assert(asyncns_isdone(asyncns, query));
- assert(asyncns_getnqueries(asyncns) == 1);
- assert(asyncns_getnext(asyncns) == query);
-
- status = poll(&pollfd, 1, 100);
- assert(status == 0);
-
- status = asyncns_getaddrinfo_done(asyncns, query, &result);
- assert(asyncns_getnqueries(asyncns) == 0);
-
- /* Intuitively, this should not be needed but the docs state that
- * a call to `asyncns_wait()` is necessary so that `asyncns_getnext()`
- * provides meaningful results.
- */
- status = asyncns_wait(asyncns, 0);
- assert(status == 0);
-
- /* There were two queries issued, one of which has been cancelled
- * and the other has been freed afterwards. As none of them can be
- * returned, the only meaningful result of `asyncns_getnext()` is
- * NULL.
- */
- assert(asyncns_getnext(asyncns) == NULL);
-
- asyncns_free(asyncns);
- asyncns_freeaddrinfo(result);
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <asyncns.h>
-#include <poll.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <stdbool.h>
-#include <unistd.h>
-
-static void
-check(int status, struct addrinfo *result, int family, const char *nodename)
-{
- assert(status == 0);
- assert(result);
- struct { struct addrinfo ai; struct sockaddr_in sa4; struct sockaddr_in6 sa6; } expected = {
- .ai = {
- .ai_family = family,
- .ai_socktype = SOCK_STREAM,
- .ai_protocol = IPPROTO_TCP,
- .ai_addr = result->ai_addr,
- .ai_addrlen = family == AF_INET6 ? sizeof expected.sa6 : sizeof expected.sa4,
- .ai_canonname = result->ai_canonname
- },
- .sa4 = {
- .sin_family = AF_INET,
- .sin_port = htons(80),
- .sin_addr = { htonl(0x01020304) }
- },
- .sa6 = {
- .sin6_family = AF_INET6,
- .sin6_port = htons(80),
- .sin6_addr = { .s6_addr = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 } },
- .sin6_scope_id = 999999
- }
- };
- /* getaddrinfo returns original ai_flags */
- if (result->ai_flags == 2)
- result->ai_flags = 0;
-
- assert(!memcmp(result, &expected.ai, sizeof expected.ai));
- assert(result->ai_canonname && !strcmp(result->ai_canonname, nodename));
- assert(!memcmp(result->ai_addr, family == AF_INET6 ? (void *) &expected.sa6 : (void *) &expected.sa4, expected.ai.ai_addrlen));
-}
-
-int
-main(int argc, char **argv)
-{
- const char *nodename1 = "1:2:3:4:5:6:7:8%999999";
- const char *nodename2 = "1.2.3.4";
- const char *servname = "80";
- struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = 0,
- .ai_protocol = IPPROTO_TCP,
- .ai_flags = AI_CANONNAME,
- };
- struct addrinfo *result1 = NULL, *result2 = NULL;
- int status, status1, status2;
- asyncns_t *asyncns;
- asyncns_query_t *q1, *q2;
- struct pollfd pollfd = { .fd = -1, .events = POLLIN };
-
- /* Create the thread pool */
- asyncns = asyncns_new(10);
- assert(asyncns);
- assert(asyncns_getnqueries(asyncns) == 0);
- assert(asyncns_getnext(asyncns) == NULL);
-
- /* Acquire the file descriptor */
- pollfd.fd = asyncns_fd(asyncns);
- assert(pollfd.fd > 2);
-
- /* Check that there are no events */
- status = poll(&pollfd, 1, 100);
- assert(status == 0);
-
- /* Start first query */
- q1 = asyncns_getaddrinfo(asyncns, nodename1, servname, &hints);
- assert(asyncns_getnqueries(asyncns) == 1);
- assert(asyncns_getnext(asyncns) == NULL);
- assert(!asyncns_isdone(asyncns, q1));
-
- /* Start second query */
- q2 = asyncns_getaddrinfo(asyncns, nodename2, servname, &hints);
- assert(q2 != q1);
- assert(asyncns_getnqueries(asyncns) == 2);
- assert(asyncns_getnext(asyncns) == NULL);
- assert(!asyncns_isdone(asyncns, q2));
-
- /* Make sure the results are ready */
- usleep(100000);
- status = poll(&pollfd, 1, 0);
- assert(status == 1);
- status = asyncns_wait(asyncns, 0);
- assert(status == 0);
-
- /* Both queries are finished and one is available via `asyncns_getnext()` */
- assert(asyncns_getnqueries(asyncns) == 2);
- assert(asyncns_isdone(asyncns, q1) && asyncns_isdone(asyncns, q2));
- assert(asyncns_getnext(asyncns) == q1 || asyncns_getnext(asyncns) == q2);
-
- /* Destroy the first query */
- status1 = asyncns_getaddrinfo_done(asyncns, q1, &result1);
- assert(asyncns_getnqueries(asyncns) == 1);
-
- /* Now second query should be available via `asycns_getnext()` */
- assert(asyncns_getnext(asyncns) == q2);
-
- /* Destry the second query */
- status2 = asyncns_getaddrinfo_done(asyncns, q2, &result2);
- assert(asyncns_getnqueries(asyncns) == 0);
-
- /* Now no more queries should be available via `asycns_getnext()` */
- assert(asyncns_getnext(asyncns) == NULL);
-
- /* Destroy the pool */
- asyncns_free(asyncns);
-
- /* Check result data and destroy it */
- check(status1, result1, AF_INET6, nodename1);
- check(status2, result2, AF_INET, nodename2);
- asyncns_freeaddrinfo(result1);
- asyncns_freeaddrinfo(result2);
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-socket.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-
-
-static void
-on_bind(netresolve_query_t query, int idx, int sock, void *user_data)
-{
- int *psock = user_data;
-
- if (*psock == -1)
- *psock = sock;
- else
- close(sock);
-}
-
-int
-do_bind(const char *node, const char *service, int family, int socktype, int protocol)
-{
- netresolve_query_t query;
- int sock = -1;
-
- query = netresolve_bind(NULL, node, service, family, socktype, protocol, on_bind, &sock);
- assert(query);
-
- return sock;
-}
-
-static void
-on_connect(netresolve_query_t query, int idx, int sock, void *user_data)
-{
- int *psock = user_data;
-
- assert(*psock == -1);
- *psock = sock;
-
- if (idx == 0) {
- close(*psock);
- *psock = -1;
- netresolve_connect_next(query);
- }
-}
-
-int
-do_connect(const char *node, const char *service, int family, int socktype, int protocol)
-{
- netresolve_query_t query;
- int sock = -1;
-
- query = netresolve_connect(NULL, node, service, family, socktype, protocol, on_connect, &sock);
- assert(query);
-
- return sock;
-}
-
-int
-main(int argc, char **argv)
-{
- int sock_server, sock_client, sock_accept;
- const char *node = NULL;
- const char *service = "1024";
- int family = AF_UNSPEC;
- int socktype = SOCK_STREAM;
- int protocol = IPPROTO_TCP;
- int status;
- char outbuf[6] = "asdf\n";
- char inbuf[6] = {0};
-
- sock_server = do_bind(node, service, family, socktype, protocol);
- assert(sock_server > 0);
- status = listen(sock_server, 10);
- assert(status == 0);
-
- sock_client = do_connect(node, service, family, socktype, protocol);
- assert(sock_client > 0);
-
- sock_accept = accept(sock_server, NULL, 0);
- assert(sock_accept != -1);
- close(sock_accept);
- sock_accept = accept(sock_server, NULL, 0);
- assert(sock_accept != -1);
- status = send(sock_client, outbuf, strlen(outbuf), 0);
- assert(status == strlen(outbuf));
- status = recv(sock_accept, inbuf, sizeof inbuf, 0);
- assert(status == strlen(outbuf));
- assert(!strcmp(inbuf, outbuf));
-
- status = close(sock_server);
- assert(status == 0);
- status = close(sock_client);
- assert(status == 0);
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
-#!/bin/bash -e
-
-DIFF="diff -u"
-DATA="${srcdir:-.}/tests/data"
-
-test_command() {
- $DIFF <(./$@ | grep -vE 'localhost[46]|localdomain') tests/data/$1
- $DIFF <(./wrapresolve ./"$@") tests/data/$1
-}
-
-for name in getaddrinfo gethostbyname{,2,_r,2_r} asyncns; do
- ./test-$name
- ./wrapresolve ./test-$name
-done
-
-./wrapresolve ./test-asyncns-cancel
-
-test_command getaddrinfo --node localhost
-# disabled due to bug in glibc
-#test_command gethostbyname --node localhost
-test_command getnameinfo --address 127.0.0.1 --port 80
-test_command gethostbyaddr --address 127.0.0.1
+++ /dev/null
-#!/bin/bash -e
-
-DIFF="diff -u"
-NR="./netresolve"
-DATA="${srcdir:-.}/tests/data/dns"
-
-export NETRESOLVE_CLAMP_TTL=1
-
-for backend in {ub,ares}dns; do
- $DIFF <($NR --backends $backend --node www.nic.cz) $DATA/dns-forward
- $DIFF <($NR --backends $backend --srv --node xmpp.org --service xmpp-server) $DATA/dns-srv
- $DIFF <($NR --backends $backend --srv --node perseus.jabber.org --service xmpp-server) $DATA/dns-srv-fallback
- $DIFF <($NR --backends $backend --srv --node jabber.org --service stun --protocol udp) $DATA/dns-srv-udp
- $DIFF <($NR --backends $backend --address 195.47.235.3) $DATA/dns-reverse
- $DIFF <($NR --backends $backend --address 2a02:38::1001) $DATA/dns-reverse
-done
+++ /dev/null
-#!/bin/bash -e
-
-DIFF="diff -u"
-NR="./netresolve"
-DATA="${srcdir:-.}/tests/data/dnssec"
-
-export NETRESOLVE_CLAMP_TTL=1
-
-for backend in ubdns:validate aresdns:trust; do
- $DIFF <($NR --backends $backend --node www.nic.cz) $DATA/dns-forward
- $DIFF <($NR --backends $backend --address 195.47.235.3) $DATA/dns-reverse
- $DIFF <($NR --backends $backend --address 2a02:38::1001) $DATA/dns-reverse
-done
-
-for backend in ubdns ubdns:validate aresdns aresdns:trust; do
- $DIFF <($NR --backends $backend --node www.rhybar.cz) $DATA/bogus
- $DIFF <($NR --backends $backend --node nonsense.rhybar.cz) $DATA/bogus
-done
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-int
-main(int argc, char **argv)
-{
- const char *node = "1:2:3:4:5:6:7:8%999999";
- const char *service = "80";
- struct addrinfo hints = {
- .ai_family = AF_UNSPEC,
- .ai_socktype = 0,
- .ai_protocol = IPPROTO_TCP,
- .ai_flags = AI_CANONNAME,
- };
- struct addrinfo *result = NULL;
- int status;
-
- /* run getaddrinfo */
- status = getaddrinfo(node, service, &hints, &result);
-
- assert(status == 0);
- assert(result);
- struct { struct addrinfo ai; struct sockaddr_in6 sa; } expected = {
- .ai = {
- /* FIXME: getaddrinfo sets .flags to 3 */
- .ai_flags = result->ai_flags,
- .ai_family = AF_INET6,
- .ai_socktype = SOCK_STREAM,
- .ai_protocol = IPPROTO_TCP,
- .ai_addr = result->ai_addr,
- .ai_addrlen = sizeof expected.sa,
- .ai_canonname = result->ai_canonname
- },
- .sa = {
- .sin6_family = AF_INET6,
- .sin6_port = htons(80),
- .sin6_addr = { .s6_addr = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 } },
- .sin6_scope_id = 999999
- }
- };
- assert(!memcmp(result, &expected.ai, sizeof expected.ai));
- assert(result->ai_canonname && !strcmp(result->ai_canonname, node));
- assert(!memcmp(result->ai_addr, &expected.sa, sizeof expected.sa));
-
- freeaddrinfo(result);
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <netdb.h>
-
-int
-main(int argc, char **argv)
-{
-#ifdef GETHOSTBYNAME2
- const char *node = "1:2:3:4:5:6:7:8";
-#else
- const char *node = "1.2.3.4";
-#endif
- struct hostent *result = NULL;
-
-#ifdef REENTRANT
- struct hostent he;
- size_t buflen = 1024;
- char buffer[buflen];
- int my_errno, my_h_errno;
-#ifdef GETHOSTBYNAME2
- my_errno = gethostbyname2_r(node, AF_INET6, &he, buffer, buflen, &result, &my_h_errno);
-#else
- my_errno = gethostbyname_r(node, &he, buffer, buflen, &result, &my_h_errno);
-#endif
- assert(!my_errno);
- assert(result == &he);
-#else
-#ifdef GETHOSTBYNAME2
- result = gethostbyname2(node, AF_INET6);
-#else
- result = gethostbyname(node);
-#endif
-#endif
- assert(result && result->h_addr_list[0]);
-
- struct {
- struct hostent he;
- char *ha[1];
- char *al[2];
-#ifdef GETHOSTBYNAME2
- struct in6_addr ia;
-#else
- struct in_addr ia;
-#endif
- } expected = {
- .he = {
- .h_name = result->h_name,
- .h_aliases = result->h_aliases,
-#ifdef GETHOSTBYNAME2
- .h_addrtype = AF_INET6,
-#else
- .h_addrtype = AF_INET,
-#endif
- .h_length = sizeof expected.ia,
- .h_addr_list = result->h_addr_list,
- },
- .ha = { NULL },
- .al = { *result->h_addr_list, NULL },
-#ifdef GETHOSTBYNAME2
- .ia = { .s6_addr = { 0, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8} }
-#else
- .ia = { .s_addr = htonl(0x01020304) }
-#endif
- };
- assert(!memcmp(result, &expected.he, sizeof expected.he));
- assert(result->h_name && !strcmp(result->h_name, node));
- assert(!memcmp(result->h_aliases, &expected.ha, sizeof expected.ha));
- assert(!memcmp(result->h_addr_list, &expected.al, sizeof expected.al));
- assert(!memcmp(result->h_addr_list[0], &expected.ia, sizeof expected.ia));
-
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* Copyright (c) 2013-2014 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-glib.h>
-
-#include "common.h"
-
-int
-main(int argc, char **argv)
-{
- netresolve_t context = netresolve_glib_new();
- netresolve_query_t query1, query2;
- struct priv_common priv = { 0 };
- const char *node1 = "1:2:3:4:5:6:7:8%999999";
- const char *node2 = "1.2.3.4%999999";
- const char *service = "80";
- int family = AF_UNSPEC;
- int socktype = 0;
- int protocol = IPPROTO_TCP;
-
- /* Resolver configuration. */
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NULL);
-
- /* Start name resolution. */
- query1 = netresolve_query_forward(context, node1, service, callback1, &priv);
- query2 = netresolve_query_forward(context, node2, service, callback2, &priv);
- assert(query1 && query2);
-
- /* Run the main loop. */
- while (priv.finished < 2)
- g_main_context_iteration(NULL, true);
- assert(priv.finished == 2);
-
- /* Clean up. */
- netresolve_context_free(context);
-
- exit(EXIT_SUCCESS);
-}
+++ /dev/null
-/* Copyright (c) 2013-2014 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-event.h>
-
-#include "common.h"
-
-int
-main(int argc, char **argv)
-{
- struct event_base *base;
- netresolve_t context;
- netresolve_query_t query1, query2;
- struct priv_common priv = { 0 };
- const char *node1 = "1:2:3:4:5:6:7:8%999999";
- const char *node2 = "1.2.3.4%999999";
- const char *service = "80";
- int family = AF_UNSPEC;
- int socktype = 0;
- int protocol = IPPROTO_TCP;
-
- /* Create an event base. */
- base = event_base_new();
- if (!base) {
- perror("event_base_new");
- abort();
- }
-
- /* Create a context. */
- context = netresolve_event_new(base);
- if (!context) {
- perror("netresolve_context_new");
- abort();
- }
-
- /* Resolver configuration. */
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NETRESOLVE_OPTION_DONE);
-
- /* Start name resolution. */
- query1 = netresolve_query_forward(context, node1, service, callback1, &priv);
- query2 = netresolve_query_forward(context, node2, service, callback2, &priv);
- assert(query1 && query2);
-
- /* Run the main loop. */
- event_base_dispatch(base);
- assert(priv.finished == 2);
-
- /* Clean up. */
- netresolve_context_free(context);
- event_base_free(base);
-
- exit(EXIT_SUCCESS);
-}
+++ /dev/null
-#!/bin/bash -xe
-
-DIFF="diff -u"
-NR="${NETRESOLVE_TEST_COMMAND:-./netresolve}"
-DATA="${srcdir:-.}/tests/data"
-
-# empty
-$DIFF <($NR) $DATA/any
-$DIFF <($NR --backends any) $DATA/any
-$DIFF <($NR --backends any --service '' | grep -v sctp) $DATA/any-listing
-$DIFF <($NR --backends numerichost) $DATA/failed
-$DIFF <($NR --backends loopback) $DATA/localhost
-$DIFF <($NR --backends hosts) $DATA/failed
-$DIFF <($NR --backends ubdns) $DATA/failed
-$DIFF <($NR --backends aresdns) $DATA/failed
-$DIFF <($NR --backends libc) $DATA/failed
-$DIFF <($NR --backends "nss files") $DATA/failed
-$DIFF <($NR --backends "nss bogusbogus") $DATA/failed
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so") <(grep -v '^secure$' $DATA/any-listing)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so getaddrinfo") <(grep -v '^secure$' $DATA/any-listing)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname4") $DATA/failed
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname3") $DATA/failed
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname2") $DATA/failed
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname") $DATA/failed
-
-# empty (passive)
-$DIFF <(NETRESOLVE_FLAG_DEFAULT_LOOPBACK=yes $NR) $DATA/localhost
-
-# empty/http
-$DIFF <($NR --service http) $DATA/services
-$DIFF <($NR --backend libc --service http | grep -v sctp) <(grep -v '^secure$' $DATA/services)
-
-# numeric
-$DIFF <($NR --node 1.2.3.4) $DATA/numeric4
-$DIFF <($NR --node 1.2.3.4%lo) $DATA/numeric4lo
-$DIFF <($NR --node 1.2.3.4%999999) $DATA/numeric4nines
-$DIFF <($NR --node 1.2.3.4%999999x) $DATA/failed
-$DIFF <($NR --node 1:2:3:4:5:6:7:8) $DATA/numeric6
-$DIFF <($NR --node 1:2:3:4:5:6:7:8%lo) $DATA/numeric6lo
-$DIFF <($NR --node 1:2:3:4:5:6:7:8%999999) $DATA/numeric6nines
-$DIFF <($NR --node 1:2:3:4:5:6:7:8%999999x) $DATA/failed
-
-# localhost
-$DIFF <($NR --node localhost) $DATA/localhost
-$DIFF <($NR --node localhost --service '') $DATA/localhost-listing
-$DIFF <($NR --backends hosts --node localhost) $DATA/localhost
-$DIFF <($NR --backends "nss files" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss files gethostbyname4" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss files gethostbyname3" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss files gethostbyname2" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss files gethostbyname" --node localhost) <(grep -v '^secure$' $DATA/localhost4)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so" --node localhost) <(grep -v '^secure$' $DATA/localhost-listing)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so getaddrinfo" --node localhost) <(grep -v '^secure$' $DATA/localhost-listing)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname4" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname3" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname2" --node localhost) <(grep -v '^secure$' $DATA/localhost)
-$DIFF <($NR --backends "nss ./.libs/libnss_netresolve.so gethostbyname" --node localhost) <(grep -v '^secure$' $DATA/localhost4)
-
-# localhost/http
-$DIFF <($NR --node localhost) $DATA/localhost
-$DIFF <($NR --backends libc --node localhost --service http | grep -v sctp) <(grep -v '^secure$' $DATA/localhost-http)
-$DIFF <($NR --backends "nss files" --node localhost --service http) <(grep -v '^secure$' $DATA/localhost-http)
-$DIFF <($NR --backends "nss files gethostbyname4" --node localhost --service http) <(grep -v '^secure$' $DATA/localhost-http)
-$DIFF <($NR --backends "nss files gethostbyname3" --node localhost --service http) <(grep -v '^secure$' $DATA/localhost-http)
-$DIFF <($NR --backends "nss files gethostbyname2" --node localhost --service http) <(grep -v '^secure$' $DATA/localhost-http)
-$DIFF <($NR --backends "nss files gethostbyname" --node localhost --service http) <(grep -v '^secure$' $DATA/localhost4-http)
-
-# localhost (ip4)
-$DIFF <($NR --node localhost --family ip4) $DATA/localhost4
-$DIFF <($NR --backends "nss files" --node localhost --family ip4) <(grep -v '^secure$' $DATA/localhost4)
-$DIFF <($NR --backends "nss files gethostbyname4" --node localhost --family ip4) $DATA/failed
-$DIFF <($NR --backends "nss files gethostbyname3" --node localhost --family ip4) <(grep -v '^secure$' $DATA/localhost4)
-$DIFF <($NR --backends "nss files gethostbyname2" --node localhost --family ip4) <(grep -v '^secure$' $DATA/localhost4)
-$DIFF <($NR --backends "nss files gethostbyname" --node localhost --family ip4) <(grep -v '^secure$' $DATA/localhost4)
-
-# localhost (ip6)
-$DIFF <($NR --node localhost --family ip6) $DATA/localhost6
-$DIFF <($NR --backends "nss files" --node localhost --family ip6) <(grep -v '^secure$' $DATA/localhost6)
-$DIFF <($NR --backends "nss files gethostbyname4" --node localhost --family ip6) <(grep -v '^secure$' $DATA/failed)
-$DIFF <($NR --backends "nss files gethostbyname3" --node localhost --family ip6) <(grep -v '^secure$' $DATA/localhost6)
-$DIFF <($NR --backends "nss files gethostbyname2" --node localhost --family ip6) <(grep -v '^secure$' $DATA/localhost6)
-$DIFF <($NR --backends "nss files gethostbyname" --node localhost --family ip6) <(grep -v '^secure$' $DATA/empty)
-
-# localhost4
-$DIFF <($NR --node localhost4) $DATA/localhost4
-
-# localhost6
-$DIFF <($NR --node localhost6) $DATA/localhost6
-
-# bogus
-$DIFF <($NR --node x-x-x-x-x-x-x-x-x) $DATA/failed
-
-# unix
-$DIFF <($NR --node /path/to/socket --family unix) $DATA/unix
-$DIFF <($NR --node /path/to/socket --family unix --socktype stream) $DATA/unix-stream
-$DIFF <($NR --node /path/to/socket --family unix --socktype dgram) $DATA/unix-dgram
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "common.h"
-
-int
-main(int argc, char **argv)
-{
- netresolve_t context;
- netresolve_query_t query;
- const char *service = "80";
- int family = AF_UNSPEC;
- int socktype = 0;
- int protocol = IPPROTO_TCP;
-
- /* Create a context. */
- context = netresolve_context_new();
- if (!context) {
- perror("netresolve_context_new");
- abort();
- }
-
- /* Resolver configuration. */
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_FAMILY, family,
- NETRESOLVE_OPTION_SOCKTYPE, socktype,
- NETRESOLVE_OPTION_PROTOCOL, protocol,
- NULL);
-
- /* First query */
- query = netresolve_query_forward(context, "1:2:3:4:5:6:7:8%999999", service, NULL, NULL);
- check_address(query, AF_INET6, "1:2:3:4:5:6:7:8", 999999);
- netresolve_query_free(query);
-
- /* Second query */
- query = netresolve_query_forward(context, "1.2.3.4%999999", service, NULL, NULL);
- check_address(query, AF_INET, "1.2.3.4", 999999);
- netresolve_query_free(query);
-
- /* Check results */
-
- /* Clean up. */
- netresolve_context_free(context);
-
- exit(EXIT_SUCCESS);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <arpa/inet.h>
-#include <net/if.h>
-
-#include "compat.h"
-
-/*
- * struct hostent {
- * char *h_name;
- * char **h_aliases;
- * int h_addrtype;
- * int h_length;
- * char **h_addr_list;
- * }
- * #define h_addr h_addr_list[0]
- */
-
-void
-print_hostent(struct hostent *item)
-{
- if (item->h_name)
- printf(" name = %s\n", item->h_name);
- if (item->h_aliases) {
- int count = 0;
- printf(" aliases:\n");
- for (char **alias = item->h_aliases; *alias; alias++)
- printf(" #%d = %s\n", count++, *alias);
- }
- if (item->h_addrtype)
- printf(" addrtype = %d\n", item->h_addrtype);
- if (item->h_length)
- printf(" length = %d\n", item->h_length);
- if (item->h_addr) {
- printf(" address = ");
- for (int i = 0; i < item->h_length; i++)
- printf("%02x", item->h_addr[i]);
- printf("\n");
- }
- if (item->h_addr_list) {
- int count = 0;
- printf(" addresses:\n");
- for (char **address = item->h_addr_list; *address; address++) {
- printf(" #%d = ", count++);
- for (int i = 0; i < item->h_length; i++)
- printf("%02x", (*address)[i]);
- printf("\n");
- }
- }
-}
-
-/* struct addrinfo {
- * int ai_flags;
- * int ai_family;
- * int ai_socktype;
- * int ai_protocol;
- * socklen_t ai_addrlen;
- * struct sockaddr *ai_addr;
- * char *ai_canonname;
- * struct addrinfo *ai_next;
- * };
- *
- * struct sockaddr_in {
- * sa_family_t sin_family;
- * in_port_t sin_port;
- * struct in_addr sin_addr;
- * };
- *
- * struct sockaddr_in6 {
- * sa_family_t sin6_family;
- * in_port_t sin6_port;
- * uint32_t sin6_flowinfo;
- * struct in6_addr sin6_addr;
- * uint32_t sin6_scope_id;
- * };
- */
-
-void
-print_addrinfo(struct addrinfo *item)
-{
- if (item->ai_flags)
- printf(" flags = %d\n", item->ai_flags);
- if (item->ai_family)
- printf(" family = %d\n", item->ai_family);
- if (item->ai_socktype)
- printf(" socktype = %d\n", item->ai_socktype);
- if (item->ai_protocol)
- printf(" protocol = %d\n", item->ai_protocol);
- if (item->ai_addrlen)
- printf(" addrlen = %d\n", item->ai_addrlen);
- if (item->ai_addr) {
- printf(" address:\n");
- printf(" family = %d\n", item->ai_addr->sa_family);
- switch (item->ai_addr->sa_family) {
- case AF_INET:
- {
- struct sockaddr_in *sa4 = (void *) item->ai_addr;
-
- printf(" port = %d\n", ntohs(sa4->sin_port));
- printf(" address = 0x%x\n", ntohl(sa4->sin_addr.s_addr));
- }
- break;
- case AF_INET6:
- {
- struct sockaddr_in6 *sa6 = (void *) item->ai_addr;
-
- printf(" port = %d\n", ntohs(sa6->sin6_port));
- printf(" flowinfo = 0x%08x\n", ntohs(sa6->sin6_flowinfo));
- printf(" address = 0x");
- for (int i = 0; i < 16; i++)
- printf("%02x", sa6->sin6_addr.s6_addr[i]);
- printf("\n");
- printf(" scope_id = %d\n", sa6->sin6_scope_id);
- }
- break;
- default:
- break;
- }
- }
- if (item->ai_canonname)
- printf(" nodename = %s\n", item->ai_canonname);
-}
-
-bool
-parse_address(const char *string_orig, void *address, int *family, int *ifindex)
-{
- char *string;
- char *ifname;
-
- if (!string_orig)
- return false;
-
- string = strdupa(string_orig);
-
- ifname = strchr(string, '%');
- if (ifname)
- *ifname++ = '\0';
- if (!ifname)
- ifname = "";
- if (ifindex) {
- *ifindex = if_nametoindex(ifname);
- if (!*ifindex) {
- char *endptr = NULL;
-
- *ifindex = strtol(ifname, &endptr, 10);
- if (*endptr)
- return false;
- }
- }
-
- if (inet_pton(AF_INET, string, address) == 1) {
- *family = AF_INET;
- return true;
- }
- if (inet_pton(AF_INET6, string, address) == 1) {
- *family = AF_INET6;
- return true;
- }
-
- return false;
-}
+++ /dev/null
-/* Copyright (c) 2013 Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdbool.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <errno.h>
-
-/* Input */
-bool parse_address(const char *string_orig, void *address, int *family, int *ifindex);
-
-/* Output */
-void print_hostent(struct hostent *item);
-void print_addrinfo(struct addrinfo *item);
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-
-#include "compat.h"
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "node", 1, 0, 'n' },
- { "host", 1, 0, 'n' },
- { "service", 0, 0, 's' },
- { "ipv4", 0, 0, '4' },
- { "ipv6", 0, 0, '6' },
- { "raw", 0, 0, 'R' },
- { "stream", 0, 0, 'S' },
- { "dgram", 0, 0, 'D' },
- { "datagram", 0, 0, 'D' },
- { "tcp", 0, 0, 'T' },
- { "udp", 0, 0, 'U' },
- { "passive", 0, 0, 'p' },
- { "addrconfig", 0, 0, 'a' },
- { "canonname", 0, 0, 'c' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hvn:s:46RSDTUpac";
- int opt, idx = 0;
- char *nodename = NULL, *servname = NULL;
- struct addrinfo hints = { 0 };
- struct addrinfo *result;
-
- while ((opt = getopt_long(argc, argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- fprintf(stderr,
- "-h,--help -- help\n"
- "-n,--node <nodename> -- node name\n"
- "-s,--service <servname> -- service name\n"
- "-4,--ipv4 -- IPv4 only query\n"
- "-6,--ipv6 -- IPv6 only query\n"
- "--raw -- raw socket type (SOCK_RAW)\n"
- "--stream -- stream socket type (SOCK_STREAM)\n"
- "--dgram -- datagram socket type (SOCK_DGRAM)\n"
- "--tcp -- TCP protocol (IPPROTO_TCP)\n"
- "--udp -- UDP protocol (IPPROTO_UDP)\n"
- "--passive -- AI_PASSIVE\n"
- "--addrconfig -- AI_ADDRCONFIG\n"
- "--canonname -- AI_CANONNAME\n");
- exit(EXIT_SUCCESS);
- case 'n':
- nodename = optarg;
- break;
- case 's':
- servname = optarg;
- break;
- case '4':
- hints.ai_family = AF_INET;
- break;
- case '6':
- hints.ai_family = AF_INET6;
- break;
- case 'R':
- hints.ai_socktype = SOCK_RAW;
- break;
- case 'S':
- hints.ai_socktype = SOCK_STREAM;
- break;
- case 'D':
- hints.ai_socktype = SOCK_DGRAM;
- break;
- case 'T':
- hints.ai_protocol = IPPROTO_TCP;
- break;
- case 'U':
- hints.ai_protocol = IPPROTO_UDP;
- break;
- case 'p':
- hints.ai_flags |= AI_PASSIVE;
- break;
- case 'a':
- hints.ai_flags |= AI_ADDRCONFIG;
- break;
- case 'c':
- hints.ai_flags |= AI_CANONNAME;
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind])
- nodename = argv[optind++];
- if (argv[optind])
- servname = argv[optind++];
- if (argv[optind]) {
- fprintf(stderr, "Too many arguments.");
- exit(1);
- }
-
- printf("query:\n");
- printf(" nodename = %s\n", nodename);
- printf(" servname = %s\n", servname);
- print_addrinfo(&hints);
-
- int status = getaddrinfo(nodename, servname, &hints, &result);
-
- printf("status = %d\n", status);
- if (status)
- exit(1);
- int count = 0;
- for (struct addrinfo *item = result; item; item = item->ai_next) {
- printf("#%d:\n", count++);
- print_addrinfo(item);
- }
-
- freeaddrinfo(result);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "compat.h"
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "address", 1, 0, 'a' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hva:";
- int opt, idx = 0;
- char *address_str = NULL;
- char address[16];
- int family, ifindex;
-
-
- while ((opt = getopt_long(argc, argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- fprintf(stderr,
- "-h,--help -- help\n"
- "-a,--address <address> -- node name\n");
- exit(EXIT_SUCCESS);
- case 'a':
- address_str = optarg;
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind])
- address_str = argv[optind++];
- if (argv[optind]) {
- fprintf(stderr, "Too many arguments.");
- exit(1);
- }
-
- printf("query:\n");
- printf(" address = %s\n", address_str);
-
- if (!address_str) {
- fprintf(stderr, "Cannot query an empty address.\n");
- exit(1);
- }
-
- parse_address(address_str, &address, &family, &ifindex);
-
- if (ifindex) {
- fprintf(stderr, "No ifindex/scope_id support in `gethostbyaddr()`.");
- exit(1);
- }
-
- struct hostent *result = gethostbyaddr(&address, family == AF_INET ? 4 : 16, family);
-
- if (!result) {
- printf("errno = %d\n", errno);
- printf("h_errno = %d\n", h_errno);
- exit(1);
- }
-
- printf("result:\n");
- print_hostent(result);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "compat.h"
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "node", 1, 0, 'n' },
- { "host", 1, 0, 'n' },
- { "ipv4", 0, 0, '4' },
- { "ipv6", 0, 0, '6' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hvn:46";
- int opt, idx = 0;
- char *nodename = NULL;
- int family = 0;
-
- while ((opt = getopt_long(argc, argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- fprintf(stderr,
- "-h,--help -- help\n"
- "-n,--node <nodename> -- node name\n"
- "-4,--ipv4 -- IPv4 only query\n"
- "-6,--ipv6 -- IPv6 only query\n");
- exit(EXIT_SUCCESS);
- case 'n':
- nodename = optarg;
- break;
- case '4':
- family = AF_INET;
- break;
- case '6':
- family = AF_INET6;
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind])
- nodename = argv[optind++];
- if (argv[optind]) {
- fprintf(stderr, "Too many arguments.");
- exit(1);
- }
-
- printf("query:\n");
- printf(" api = %s\n", family ? "gethostbyname2" : "gethostbyname");
- if (family)
- printf(" family = %d\n", family);
- printf(" nodename = %s\n", nodename);
-
- if (!nodename) {
- fprintf(stderr, "Cannot query an empty nodename\n");
- exit(1);
- }
-
- struct hostent *result = family ? gethostbyname2(nodename, family) : gethostbyname(nodename);
-
- if (!result) {
- printf("errno = %d\n", errno);
- printf("h_errno = %d\n", h_errno);
- exit(1);
- }
-
- printf("result:\n");
- print_hostent(result);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include "compat.h"
-
-#define SIZE 1024
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "udp", 0, 0, 'u' },
- { "address", 1, 0, 'a' },
- { "port", 1, 0, 'p' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hvua:46";
- int opt, idx = 0;
- char *address_str = NULL;
- char address[16];
- int family = 0, ifindex = 0;
- uint16_t port = 0;
- int flags = 0;
- union {
- struct sockaddr sa;
- struct sockaddr_in sa4;
- struct sockaddr_in6 sa6;
- } sa;
- socklen_t salen;
- char host[SIZE], serv[SIZE];
-
- memset(&sa, 0, sizeof sa);
-
- while ((opt = getopt_long(argc, argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- fprintf(stderr,
- "-h,--help -- help\n"
- "-u,--udp -- query UDP instead of TCP\n"
- "-a,--address <address> -- node name\n"
- "-p,--port <port>\n");
- exit(EXIT_SUCCESS);
- case 'u':
- flags |= NI_DGRAM;
- break;
- case 'a':
- address_str = optarg;
- break;
- case 'p':
- port = strtoll(optarg, NULL, 10);
- break;
- case '4':
- family = AF_INET;
- break;
- case '6':
- family = AF_INET6;
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind])
- address_str = argv[optind++];
- if (argv[optind])
- port = strtoll(argv[optind++], NULL, 10);
- if (argv[optind]) {
- fprintf(stderr, "Too many arguments.");
- exit(1);
- }
-
- printf("query:\n");
- printf(" address = %s\n", address_str);
- if (port)
- printf(" port = %d\n", port);
-
- if (!address_str) {
- fprintf(stderr, "Cannot query an empty address.\n");
- exit(1);
- }
-
- parse_address(address_str, &address, &family, &ifindex);
-
- switch (family) {
- case AF_INET:
- if (ifindex) {
- fprintf(stderr, "No IPv4 ifindex/scope_id support in `gethostbyaddr()`.");
- exit(1);
- }
- memcpy(&sa.sa4.sin_addr, &address, sizeof sa.sa4.sin_addr);
- sa.sa4.sin_port = htons(port);
- salen = sizeof sa.sa4;
- break;
- case AF_INET6:
- memcpy(&sa.sa6.sin6_addr, &address, sizeof sa.sa6.sin6_addr);
- sa.sa6.sin6_scope_id = ifindex;
- sa.sa6.sin6_port = htons(port);
- salen = sizeof sa.sa6;
- break;
- default:
- fprintf(stderr, "Cannot parse address.\n");
- exit(1);
- }
-
- sa.sa.sa_family = family;
-
- int status = getnameinfo(&sa.sa, salen, host, sizeof host, serv, sizeof serv, flags);
-
- printf("status = %d\n", status);
- if (status)
- exit(1);
- printf("result:\n");
- printf(" host = %s\n", host);
- printf(" serv = %s\n", serv);
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <netresolve-private.h>
-#include <getopt.h>
-#include <arpa/nameser.h>
-#include <netinet/ip_icmp.h>
-#include <linux/icmpv6.h>
-#include <sys/socket.h>
-
-#ifdef USE_LDNS
-#include <ldns/ldns.h>
-#endif
-
-static int
-count_argv(char **argv)
-{
- int count = 0;
-
- while (*argv++)
- count++;
-
- return count;
-}
-
-static void
-read_and_write(int rfd, int wfd)
-{
- char buffer[1024];
- ssize_t rsize, wsize, offset;
-
- rsize = read(rfd, buffer, sizeof(buffer));
- if (rsize == -1) {
- error("read: %s", strerror(errno));
- abort();
- }
- if (rsize == 0) {
- debug("end of input\n");
- exit(0);
- }
- for (offset = 0; offset < rsize; offset += wsize) {
- debug("%s: <<<%*s>>>\n",
- (rfd == 0) ? "sending" : "receiving",
- (int) (rsize - offset), buffer + offset);
- wsize = write(wfd, buffer + offset, rsize - offset);
- if (wsize <= 0) {
- debug("write: %s\n", strerror(errno));
- abort();
- }
- }
-}
-
-static void
-on_socket(netresolve_query_t context, int idx, int sock, void *user_data)
-{
- int *fd = user_data;;
-
- if (*fd == -1)
- *fd = sock;
-}
-
-static char *
-get_dns_string(netresolve_query_t query)
-{
-#ifdef USE_LDNS
- const uint8_t *answer;
- size_t length;
-
- if (!(answer = netresolve_query_get_dns_answer(query, &length)))
- return NULL;
-
- ldns_pkt *pkt;
-
- int status = ldns_wire2pkt(&pkt, answer, length);
-
- if (status) {
- fprintf(stderr, "ldns: %s", ldns_get_errorstr_by_id(status));
- return NULL;
- }
-
- char *result = ldns_pkt2str(pkt);
-
- ldns_pkt_free(pkt);
- return result;
-#else
- return NULL;
-#endif
-}
-
-static const char *
-sa_to_string(struct sockaddr *sender)
-{
- static char buffer[1024];
-
- switch (sender->sa_family) {
- case AF_INET:
- return inet_ntop(AF_INET, &((struct sockaddr_in *) sender)->sin_addr, buffer, sizeof buffer);
- case AF_INET6:
- return inet_ntop(AF_INET6, &((struct sockaddr_in6 *) sender)->sin6_addr, buffer, sizeof buffer);
- default:
- return NULL;
- }
-}
-
-bool
-run_ping(netresolve_query_t query, size_t idx)
-{
- struct pollfd sock = { .fd = -1, .events = POLLIN };
- const struct sockaddr *sa;
- socklen_t salen;
- struct icmphdr data4 = { .type = ICMP_ECHO };
- struct icmp6hdr data6 = { .icmp6_type = ICMPV6_ECHO_REQUEST };
- int status;
- char buffer[4096];
- struct sockaddr_storage sender;
-
- sa = netresolve_query_get_sockaddr(query, idx, &salen, NULL, NULL, NULL);
- if (!sa)
- return false;
-
- sock.fd = socket(sa->sa_family, SOCK_DGRAM, sa->sa_family == AF_INET ? IPPROTO_ICMP : IPPROTO_ICMPV6);
- if (sock.fd == -1)
- return false;
-
- while (true) {
- if (sa->sa_family == AF_INET)
- status = sendto(sock.fd, &data4, sizeof data4, 0, sa, salen);
- else
- status = sendto(sock.fd, &data6, sizeof data6, 0, sa, salen);
- if (status == -1)
- return false;
- fprintf(stderr, "echo request\n");
-
- status = poll(&sock, 1, -1);
- if (status != 1)
- return false;
- status = recvfrom(sock.fd, buffer, sizeof buffer, 0, (struct sockaddr *) &sender, &salen);
- if (status == -1)
- return false;
- query = netresolve_query_getnameinfo(NULL, (struct sockaddr *) &sender, salen, 0, NULL, NULL);
- if (!query)
- return false;
- fprintf(stderr, "reply from %s (%s)\n", netresolve_query_get_node_name(query), sa_to_string((struct sockaddr *) &sender));
-
- sleep(1);
- }
-
- return true;
-}
-
-void
-usage(void)
-{
- fprintf(stderr,
- "netresolve [ OPTIONS ]\n"
- "\n"
- "Forward query:\n"
- " -n,--node <nodename> -- node name\n"
- " -s,--service <servname> -- service name\n"
- " -f,--family any|ip4|ip6 -- family name\n"
- " -t,--socktype any|stream|dgram|seqpacket -- socket type\n"
- " -p,--protocol any|tcp|udp|sctp -- transport protocol\n"
- " -S,--srv -- use SRV records\n"
- "\n"
- "Reverse query:\n"
- " -a,--address -- IPv4/IPv6 address (reverse query)\n"
- " -P,--port -- TCP/UDP port\n"
- "\n"
- "DNS query:\n"
- " -C,--class -- DNS record class\n"
- " -T,--type -- DNS record type\n"
- "\n"
- "Socket API:\n"
- " -l,--listen -- attempt to listen on a port like netcat/socat\n"
- " -c,--connect -- attempt to connect to a host like netcat/socat\n"
- " --ping -- perform an ICMP ping"
- "\n"
- "Miscellaneous:\n"
- " -b,--backends <backends> -- comma-separated list of backends\n"
- " -h,--help -- help\n"
- " -v,--verbose -- show more verbose output\n"
- "\n"
- "Examples:\n"
- " netresolve --node www.sourceforge.net --service http\n"
- " netresolve --address 8.8.8.8 --port 80\n"
- " netresolve --node jabber.org --type SRV\n");
- exit(EXIT_SUCCESS);
-}
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "listen", 0, 0, 'l' },
- { "connect", 0, 0, 'c' },
- { "node", 1, 0, 'n' },
- { "host", 1, 0, 'n' },
- { "service", 1, 0, 's' },
- { "family", 1, 0, 'f' },
- { "socktype", 1, 0, 't' },
- { "ping", 0, 0, 'I' },
- { "protocol", 1, 0, 'p' },
- { "backends", 1, 0, 'b' },
- { "srv", 0, 0, 'S' },
- { "address", 1, 0, 'a' },
- { "port", 1, 0, 'P' },
- { "class", 1, 0, 'C' },
- { "type", 1, 0, 'T' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hvcn::s:f:t:p:b:Sa:P:";
- int opt, idx = 0;
- bool do_connect = false;
- bool do_listen = false;
- bool ping = false;
- char *nodename = NULL, *servname = NULL;
- char *address_str = NULL, *port_str = NULL;
- int cls = ns_c_in, type = 0;
- netresolve_t context;
- netresolve_query_t query;
-
- netresolve_set_log_level(NETRESOLVE_LOG_LEVEL_ERROR);
-
- context = netresolve_context_new();
- if (!context) {
- error("netresolve: %s\n", strerror(errno));
- return EXIT_FAILURE;
- }
-
- while ((opt = getopt_long(count_argv(argv), argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- usage();
- case 'v':
- netresolve_set_log_level(NETRESOLVE_LOG_LEVEL_DEBUG);
- break;
- case 'l':
- do_listen = true;
- break;
- case 'c':
- do_connect = true;
- break;
- case 'I':
- ping = true;
- break;
- case 'n':
- nodename = optarg;
- break;
- case 's':
- servname = optarg;
- break;
- case 'f':
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_FAMILY, netresolve_family_from_string(optarg),
- NETRESOLVE_OPTION_DONE);
- break;
- case 't':
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_SOCKTYPE, netresolve_socktype_from_string(optarg),
- NETRESOLVE_OPTION_DONE);
- break;
- case 'p':
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_PROTOCOL, netresolve_protocol_from_string(optarg),
- NETRESOLVE_OPTION_DONE);
- break;
- case 'b':
- netresolve_set_backend_string(context, optarg);
- break;
- case 'S':
- netresolve_context_set_options(context,
- NETRESOLVE_OPTION_DNS_SRV_LOOKUP, (int) true,
- NETRESOLVE_OPTION_DONE);
- break;
- case 'a':
- address_str = optarg;
- break;
- case 'P':
- port_str = optarg;
- break;
- case 'C':
-#ifdef USE_LDNS
- cls = ldns_get_rr_class_by_name(optarg);
-#else
- cls = strtoll(optarg, NULL, 10);
-#endif
- break;
- case 'T':
-#ifdef USE_LDNS
- type = ldns_get_rr_type_by_name(optarg);
-#else
- type = strtoll(optarg, NULL, 10);
-#endif
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind])
- usage();
-
- if (do_listen || do_connect) {
- netresolve_query_t query;
- int sock = -1;
- struct pollfd fds[2];
-
- if (do_listen) {
- query = netresolve_bind(context, nodename, servname, 0, 0, 0, on_socket, &sock);
-
- if (sock == -1) {
- error("netresolve: Socket creation failed: %s", strerror(errno));
- return EXIT_FAILURE;
- }
-
- netresolve_bind_free(query);
-
- listen(sock, 10);
-
- debug("Listening.");
-
- sock = accept(sock, NULL, NULL);
-
- if (sock == -1) {
- error("netresolve: Socket accept failed: %s", strerror(errno));
- return EXIT_FAILURE;
- }
- } else {
- query = netresolve_connect(context, nodename, servname, 0, 0, 0, on_socket, &sock);
-
- if (sock == -1) {
- error("netresolve: Socket connection failed: %s", strerror(errno));
- return EXIT_FAILURE;
- }
-
- netresolve_connect_free(query);
- }
-
- debug("Connected.");
-
- fds[0].fd = 0;
- fds[0].events = POLLIN;
- fds[1].fd = sock;
- fds[1].events = POLLIN;
-
- while (true) {
- if (poll(fds, 2, -1) == -1) {
- fprintf(stderr, "poll: %s\n", strerror(errno));
- break;
- }
-
- if (fds[0].revents & POLLIN)
- read_and_write(0, sock);
- if (fds[1].revents & POLLIN)
- read_and_write(sock, 1);
- }
-
- return EXIT_SUCCESS;
- } else if (type)
- query = netresolve_query_dns(context, nodename, cls, type, NULL, NULL);
- else if (address_str || port_str) {
- Address address;
- int family, ifindex;
-
- if (!netresolve_backend_parse_address(address_str, &address, &family, &ifindex))
- return EXIT_FAILURE;
- query = netresolve_query_reverse(context, family, &address, ifindex, -1, port_str ? strtol(port_str, NULL, 10) : 0, NULL, NULL);
- } else
- query = netresolve_query_forward(context, nodename, servname, NULL, NULL);
-
- if (!query) {
- fprintf(stderr, "netresolve: %s\n", strerror(errno));
- return EXIT_FAILURE;
- }
-
- debug("%s", netresolve_get_request_string(query));
-
- if (ping) {
- for (int i = 0; i < netresolve_query_get_count(query); i++)
- if (run_ping(query, i))
- goto out;
- error("netresolve: ping failed");
- goto out;
- }
-
- const char *response_string = netresolve_get_response_string(query);
- char *dns_string = get_dns_string(query);
-
- if (response_string)
- printf("%s", response_string);
- if (dns_string) {
- printf("%s", dns_string);
- free(dns_string);
- }
-
-out:
- netresolve_context_free(context);
- return EXIT_SUCCESS;
-}
+++ /dev/null
-/* Copyright (c) 2013+ Pavel Šimerda, Red Hat, Inc. (psimerda at redhat.com) and others
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- *
- * 1. Redistributions of source code must retain the above copyright notice, this
- * list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright notice,
- * this list of conditions and the following disclaimer in the documentation
- * and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-#include <stdlib.h>
-#include <stdio.h>
-#include <getopt.h>
-#include <string.h>
-#include <netdb.h>
-#include <arpa/nameser.h>
-#include <resolv.h>
-
-#ifdef USE_LDNS
-#include <ldns/ldns.h>
-#endif
-
-#include "compat.h"
-
-#define SIZE 8192
-
-int
-main(int argc, char **argv)
-{
- static const struct option longopts[] = {
- { "help", 0, 0, 'h' },
- { "verbose", 0, 0, 'v' },
- { "search", 0, 0, 's' },
- { "dname", 1, 0, 'n' },
- { "class", 1, 0, 'c' },
- { "type", 1, 0, 't' },
- { NULL, 0, 0, 0 }
- };
- static const char *opts = "hvsn:c:t:";
- int opt, idx = 0;
- bool search = false;
- const char *dname = NULL;
- int class = ns_c_in;
- int type = ns_t_a;
- uint8_t answer[SIZE];
- int length = 0;
-
- while ((opt = getopt_long(argc, argv, opts, longopts, &idx)) != -1) {
- switch (opt) {
- case 'h':
- fprintf(stderr,
- "-h,--help -- help\n"
- "-s,--search <servname> -- service name\n"
- "-n,--dname <name> -- domain name\n"
- "-c,--class <class> -- class\n"
- "-t,--type <type> -- type\n");
- exit(EXIT_SUCCESS);
- case 's':
- search = true;
- break;
- case 'n':
- dname = optarg;
- break;
- case 'c':
- class = strtoll(optarg, NULL, 10);
- break;
- case 't':
- type = strtoll(optarg, NULL, 10);
- break;
- default:
- exit(EXIT_FAILURE);
- }
- }
-
- if (argv[optind]) {
- fprintf(stderr, "Too many arguments.\n");
- exit(1);
- }
-
- printf("query:\n");
- printf(" search = %s\n", search ? "yes" : "no");
- printf(" dname = %s\n", dname);
- printf(" class = %d\n", class);
- printf(" type = %d\n", type);
-
- if (!dname) {
- fprintf(stderr, "Cannot query NULL dname.\n");
- exit(EXIT_FAILURE);
- }
-
- length = (search ? res_search : res_query)(dname, class, type, answer, sizeof answer);
-
- printf("result:\n");
- printf(" length = %d\n", length);
-
-#ifdef USE_LDNS
- ldns_pkt *pkt;
-
- if (length > 0 && !ldns_wire2pkt(&pkt, answer, length)) {
- printf(" answer:\n%s\n", ldns_pkt2str(pkt));
-
- ldns_pkt_free(pkt);
- }
-#endif
-
- exit(EXIT_SUCCESS);
-}
+++ /dev/null
-#!/bin/sh
-#
-# Compatibility wrapper for netresolve that runs a program with libc functions
-# replaced by netresolve based implementations.
-
-export LD_PRELOAD="libnetresolve-libc.so libnetresolve-asyncns.so"
-
-while [ $# -gt 0 ]; do
- case "$1" in
- (-v|--verbose)
- export NETRESOLVE_VERBOSE=yes
- ;;
- (-b|--backends)
- shift
- export NETRESOLVE_BACKENDS="$1"
- ;;
- (-4)
- export NETRESOLVE_FORCE_FAMILY=ip4
- ;;
- (-6)
- export NETRESOLVE_FORCE_FAMILY=ip6
- ;;
- (-*)
- echo "unknown option: $1" >&2
- exit 1
- ;;
- (*)
- exec libtool execute "$@"
- ;;
- esac
- shift
-done
+++ /dev/null
-#!/bin/sh
-#
-# Wrapper over the real netresolve compatibility wrapper that can be run
-# within the source tree.
-
-dirname=$(dirname $0)
-
-export LD_LIBRARY_PATH="$dirname/.libs"
-source "$dirname/tools/wrapresolve.in"