Bug #3858
closedDynDNS errno 47: Address family not supported by protocol family
0%
Description
I'm on pfSense 2.1.3-RELEASE amd64 (seems to be missing from affected version). Upon configuring the custom (v4, not v6, although v6 had the same issue) DynDNS service, I was met with the following in my logs (when verbose logging was enabled, and yes, I masked the full script URL and my IP address):
Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDns: updatedns() starting Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDns (): XX.XXX.XX.XXX extracted from local system. Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDNS (): running get_failover_interface for wan. found em1 Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDNS (): DynDns _update() starting. Sep 10 23:14:41 php: /services_dyndns_edit.php: Custom DDNS (): DNS update() starting. Sep 10 23:14:41 php: /services_dyndns_edit.php: Sending request to: http://myhost.example.com/dyndns/index.php?type=v4&ip=67.169.59.123 Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDNS (): DynDns _checkStatus() starting. Sep 10 23:14:41 php: /services_dyndns_edit.php: DynDNS (): Current Service: custom Sep 10 23:14:41 php: /services_dyndns_edit.php: Curl error occurred: bind failed with errno 47: Address family not supported by protocol family
and the request would fail to complete. I started digging around, and found that if I commented line 277 (https://github.com/pfsense/pfsense/blob/master/etc/inc/dyndns.class#L277) of /etc/inc/dyndns.class
, the request would complete. I checked the output of $this->_dnsRequestIfIP
and found that it correctly output the IPv4 address assigned to my em1
interface (I only have a simple single WAN/single LAN setup). I checked the PHP Curl documentation, which stated that CURLOPT_INTERFACE
will accept an IP address or interface name. I tried giving it em1
instead of the IP address provided in $this->_dnsRequestIfIP
but that hung the webconfigurator.
So, current easiest fix is commenting line 277, because PHP is unable to send the request if bound to a specific interface.
Updated by Chris Buechler over 9 years ago
- Status changed from New to Confirmed
- Target version set to 2.3
- Affected Version changed from 2.1.2 to All
- Affected Architecture added
- Affected Architecture deleted (
amd64)
that's what happens when you're dual stack, the URL has an AAAA, and it's updating a v4 IP.
Updated by Jonathon Reinhart over 9 years ago
Chris Buechler wrote:
that's what happens when you're dual stack, the URL has an AAAA, and it's updating a v4 IP.
I'm still trying to understand what exactly is going on this bug. Clearly it's an issue for people, as IPv6 becomes more prevalent.
For the record, the line Robbie commented out is here :
curl_setopt($ch, CURLOPT_INTERFACE, $this->_dnsRequestIfIP);
which comes from:
$this->_dnsRequestIfIP = get_interface_ip($dnsRequestIf);
So I'm guessing that we're binding to the IPv4 address of the interface, but the URL has an AAAA, so we're trying to connect() to an IPv6 address, and curl doesn't like that?
I'm curious why Robbie's method of passing the interface name doesn't seem to work. I'm also curious why we even have to bind to an interface at all?
Updated by Jonathon Reinhart over 9 years ago
I put together a quick test on Linux (using pycurl) that basically does:
c = pycurl.Curl() c.setopt(c.INTERFACE, my_interface_ipv4_addr) c.setopt(c.URL, 'http://[' + google_ipv6_addr + ']/')
to try and force a situation like you've described. (When I tried it with just the URL it worked just fine, and connect()ed to an IPv4 address).
Interestingly, I see the following in strace:
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 3 ... bind(3, {sa_family=AF_UNSPEC, sa_data="\0\0\0\0\0\0\0\0\0\0\0\0\0\0"}, 28) = -1 EAFNOSUPPORT (Address family not supported by protocol)
Why is curl trying to bind() to an AF_UNSPEC address? Seems like a bug in curl.
Updated by Chris Buechler about 9 years ago
- Status changed from Confirmed to Feedback
- Target version changed from 2.3 to 2.2.5
It's bound to an interface name to ensure it egresses via its associated interface (ensures reachability where system routing table wouldn't, because of 'pass out ... route-to ...').
This should just need CURL_IPRESOLVE_V4 set in these cases. That wasn't being done for the dynamic DNS updates. What I just pushed should resolve this.
Updated by Chris Buechler about 9 years ago
- Status changed from Feedback to Resolved
confirmed fixed