~aasg/nixexprs

91955ef6d35f8c91182fcd7c32b01ee5b4d96112 — Aluísio Augusto Silva Gonçalves a month ago 33cad4b
trust-dns: Patch to set SO_REUSEADDR on UDP sockets

I really don't like messing with generated files (Cargo.nix here), but I
haven't been unable to add the socket2 dependency otherwise.

If this fixed the issue I'm having on behemoth, I should upstream it
ASAP.
M pkgs/servers/dns/trust-dns/Cargo.nix => pkgs/servers/dns/trust-dns/Cargo.nix +4 -0
@@ 3099,6 3099,10 @@ rec {
            optional = true;
          }
          {
            name = "socket2";
            packageId = "socket2";
          }
          {
            name = "tokio";
            packageId = "tokio";
            features = [ "rt-core" "rt-threaded" "time" ];

M pkgs/servers/dns/trust-dns/default.nix => pkgs/servers/dns/trust-dns/default.nix +19 -12
@@ 3,18 3,25 @@
, defaultCrateOverrides
, features ? [ ]
}:
let
  attrs = {
    patches = [ ./udp-reuseaddr.patch ];

(callPackage ./Cargo.nix { }).workspaceMembers.trust-dns.build.override {
  inherit features;
  crateOverrides = defaultCrateOverrides // {
    trust-dns = attrs: {
      meta = with lib; {
        description = "Rust-based DNS client, server, and resolver";
        homepage = "https://github.com/bluejekyll/trust-dns";
        license = licenses.mit;
        maintainers = with maintainers; [ AluisioASG ];
        platforms = platforms.all;
      };
    meta = with lib; {
      description = "Rust-based DNS client, server, and resolver";
      homepage = "https://github.com/bluejekyll/trust-dns";
      license = licenses.mit;
      maintainers = with maintainers; [ AluisioASG ];
      platforms = platforms.all;
    };
  };
}

  crates = callPackage ./Cargo.nix {
    rootFeatures = features;
    defaultCrateOverrides = defaultCrateOverrides // {
      trust-dns = oldAttrs: attrs;
    };
  };

in
crates.rootCrate.build

A pkgs/servers/dns/trust-dns/udp-reuseaddr.patch => pkgs/servers/dns/trust-dns/udp-reuseaddr.patch +35 -0
@@ 0,0 1,35 @@
diff --git i/src/named.rs w/src/named.rs
index 7d11e5c..ee79f50 100644
--- i/src/named.rs
+++ w/src/named.rs
@@ -33,6 +33,7 @@ extern crate futures;
 extern crate log;
 #[cfg(feature = "dns-over-rustls")]
 extern crate rustls;
+extern crate socket2;
 extern crate tokio;
 extern crate trust_dns_client;
 #[cfg(feature = "dns-over-openssl")]
@@ -410,9 +411,20 @@ fn main() {
     // load all the listeners
     for udp_socket in &sockaddrs {
         info!("binding UDP to {:?}", udp_socket);
+        use socket2::{Domain, Protocol, Socket, Type};
+        let base_socket = match udp_socket {
+            SocketAddr::V4(..) => Socket::new(Domain::ipv4(), Type::dgram(), Some(Protocol::udp())),
+            SocketAddr::V6(..) => Socket::new(Domain::ipv6(), Type::dgram(), Some(Protocol::udp())),
+        }.unwrap_or_else(|_| panic!("could not create udp socket: {}", udp_socket));
+        if base_socket.set_reuse_address(true).is_err() {
+            error!("failed to enable address reuse for udp socket: {}", udp_socket);
+        }
+        if base_socket.bind(&udp_socket.clone().into()).is_err() {
+            panic!("could not bind to udp: {}", udp_socket);
+        }
         let udp_socket = runtime
-            .block_on(UdpSocket::bind(udp_socket))
-            .unwrap_or_else(|_| panic!("could not bind to udp: {}", udp_socket));
+            .block_on(async move { UdpSocket::from_std(base_socket.into()) })
+            .unwrap_or_else(|_| panic!("bad handle for udp socket: {}", udp_socket));

         info!(
             "listening for UDP on {:?}",