Rahul, thanks for the report and for the investigation. Remarks and
some answers inline:
On Sun, 30 Aug 2026 11:12:44 +0100
Rahul
Hi,
I'm seeing DNS requests being dropped when using pasta 20250217. As far as I can tell, UDP flows where the source port chosen in the namespace is already in use in the init namespace get dropped.
All three fwd_nat_from_*() preserve the source port for UDP:
tgt->oport = 0; if (proto == IPPROTO_UDP) /* But for UDP preserve the source port */ tgt->oport = ini->eport;
This is intended, to offer compatibility with applications or protocols that might rely on UDP source ports to be preserved, and, in general, to be as transparent as possible. But:
That forces a bind() to it, and udp_flow_sock() treats bind failure as fatal, so the flow is cancelled and the datagram dropped with no error to the sender.
...this is not, that is, it would definitely be desirable to have a fallback for bind() failures.
I don't think I ever hit this with slirp4netns, it looks like libslirp's udp_attach() never binds a port, so the kernel just gives it a random free port.
Right, yes, slirp4netns doesn't attempt to preserve UDP source ports outside the namespace. It's a feature we added in pasta.
I'm not sure whether this is intended, but if it is, is there any way to work around it?
I see two ways of implementing this fallback mechanism, roughly: 1. pass all the way to _sock_l4() via udp_flow_sock() an additional argument to entirely ignore bind() failures (like we do for ICMP ping sockets). It might be a rather mechanical change but not my preferred approach as we would need an extra argument in a large number of functions just for a corner case 2. I think preferable: detect the failure on bind() here (it should be EADDRINUSE, did you check?) and try again from udp_flow_sock() with tgt->oport as 0. Here, "tgt" means the target namespace of the connection, and "oport" means "our port", implying the source port (because it's an outbound connection from pasta's side). I think it would be good to try and sketch a solution (maybe starting from 1.) to understand what approach would be more elegant and viable. I don't have much time on my hands right now but I'll definitely provide pointers and support if you feel like proposing a patch for this. As a first test / workaround for your usage: did you already check that keeping tgt->oport as 0 in the relevant function in fwd.c works? -- Stefano