#include "fd-util.h"
#include "iovec-util.h"
#include "log.h"
+#include "main-func.h"
#include "resolved-dns-packet.h"
#include "resolved-manager.h"
#include "socket-netlink.h"
return reply_append_edns(packet, reply, "\xF0\x9F\x90\xB1", DNS_RCODE_SERVFAIL, DNS_EDE_RCODE_OTHER);
}
-int main(int argc, char *argv[]) {
- _cleanup_close_ int fd = -EBADF;
+static int on_dns_packet(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
+ _cleanup_(dns_packet_unrefp) DnsPacket *packet = NULL;
+ _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
+ const char *name;
int r;
- log_parse_environment();
- log_open();
+ assert(fd >= 0);
- if (argc != 2)
- return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
- "This program takes one argument in format ip_address:port");
+ r = server_recv(fd, &packet);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to receive packet, ignoring: %m");
+ return 0;
+ }
- fd = make_socket_fd(LOG_DEBUG, argv[1], SOCK_DGRAM, SOCK_CLOEXEC);
- if (fd < 0)
- return log_error_errno(fd, "Failed to listen on address '%s': %m", argv[1]);
+ r = dns_packet_validate_query(packet);
+ if (r < 0) {
+ log_debug_errno(r, "Invalid DNS UDP packet, ignoring.");
+ return 0;
+ }
- (void) sd_notify(/* unset_environment=false */ false, "READY=1");
+ r = dns_packet_extract(packet);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to extract DNS packet, ignoring: %m");
+ return 0;
+ }
- for (;;) {
- _cleanup_(dns_packet_unrefp) DnsPacket *packet = NULL;
- _cleanup_(dns_packet_unrefp) DnsPacket *reply = NULL;
- const char *name;
+ name = dns_question_first_name(packet->question);
+ log_info("Processing question for name '%s'", name);
- r = server_recv(fd, &packet);
- if (r < 0) {
- log_debug_errno(r, "Failed to receive packet, ignoring: %m");
- continue;
- }
+ (void) dns_question_dump(packet->question, stdout);
- r = dns_packet_validate_query(packet);
- if (r < 0) {
- log_debug_errno(r, "Invalid DNS UDP packet, ignoring.");
- continue;
- }
+ r = make_reply_packet(packet, &reply);
+ if (r < 0) {
+ log_debug_errno(r, "Failed to make reply packet, ignoring: %m");
+ return 0;
+ }
- r = dns_packet_extract(packet);
- if (r < 0) {
- log_debug_errno(r, "Failed to extract DNS packet, ignoring: %m");
- continue;
- }
+ if (streq_ptr(name, "edns-bogus-dnssec.forwarded.test"))
+ r = server_handle_edns_bogus_dnssec(packet, reply);
+ else if (streq_ptr(name, "edns-extra-text.forwarded.test"))
+ r = server_handle_edns_extra_text(packet, reply);
+ else if (streq_ptr(name, "edns-invalid-code.forwarded.test"))
+ r = server_handle_edns_invalid_code(packet, reply, NULL);
+ else if (streq_ptr(name, "edns-invalid-code-with-extra-text.forwarded.test"))
+ r = server_handle_edns_invalid_code(packet, reply, "Hello [#]$%~ World");
+ else if (streq_ptr(name, "edns-code-zero.forwarded.test"))
+ r = server_handle_edns_code_zero(packet, reply);
+ else
+ r = log_debug_errno(SYNTHETIC_ERRNO(EFAULT), "Unhandled name '%s', ignoring.", name);
+ if (r < 0)
+ server_fail(packet, reply, DNS_RCODE_NXDOMAIN);
+
+ r = server_ipv4_send(fd, &packet->sender.in, packet->sender_port, &packet->destination.in, reply);
+ if (r < 0)
+ log_debug_errno(r, "Failed to send reply, ignoring: %m");
- name = dns_question_first_name(packet->question);
- log_info("Processing question for name '%s'", name);
+ return 0;
+}
- (void) dns_question_dump(packet->question, stdout);
+static int run(int argc, char *argv[]) {
+ _cleanup_(sd_event_unrefp) sd_event *event = NULL;
+ _cleanup_close_ int fd = -EBADF;
+ int r;
- r = make_reply_packet(packet, &reply);
- if (r < 0) {
- log_debug_errno(r, "Failed to make reply packet: %m");
- break;
- }
+ log_setup();
- if (streq_ptr(name, "edns-bogus-dnssec.forwarded.test"))
- r = server_handle_edns_bogus_dnssec(packet, reply);
- else if (streq_ptr(name, "edns-extra-text.forwarded.test"))
- r = server_handle_edns_extra_text(packet, reply);
- else if (streq_ptr(name, "edns-invalid-code.forwarded.test"))
- r = server_handle_edns_invalid_code(packet, reply, NULL);
- else if (streq_ptr(name, "edns-invalid-code-with-extra-text.forwarded.test"))
- r = server_handle_edns_invalid_code(packet, reply, "Hello [#]$%~ World");
- else if (streq_ptr(name, "edns-code-zero.forwarded.test"))
- r = server_handle_edns_code_zero(packet, reply);
- else
- r = log_debug_errno(SYNTHETIC_ERRNO(EFAULT), "Unhandled name '%s', ignoring.", name);
+ if (argc != 2)
+ return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
+ "This program takes one argument in format ip_address:port");
- if (r < 0)
- server_fail(packet, reply, DNS_RCODE_NXDOMAIN);
+ fd = make_socket_fd(LOG_DEBUG, argv[1], SOCK_DGRAM, SOCK_CLOEXEC);
+ if (fd < 0)
+ return log_error_errno(fd, "Failed to listen on address '%s': %m", argv[1]);
- r = server_ipv4_send(fd, &packet->sender.in, packet->sender_port, &packet->destination.in, reply);
- if (r < 0)
- log_debug_errno(r, "Failed to send reply: %m");
+ r = sd_event_default(&event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to allocate event: %m");
- }
+ r = sd_event_add_io(event, NULL, fd, EPOLLIN, on_dns_packet, NULL);
+ if (r < 0)
+ return log_error_errno(r, "Failed to add IO event source: %m");
+
+ r = sd_event_set_signal_exit(event, true);
+ if (r < 0)
+ return log_error_errno(r, "Failed to install SIGINT/SIGTERM handlers: %m");
+
+ (void) sd_notify(/* unset_environment=false */ false, "READY=1");
+
+ r = sd_event_loop(event);
+ if (r < 0)
+ return log_error_errno(r, "Failed to run event loop: %m");
return 0;
}
+
+DEFINE_MAIN_FUNCTION(run);