Bug 7106 - Failed IPv6 port create blocks good IPv4 port create.
Summary: Failed IPv6 port create blocks good IPv4 port create.
Status: RESOLVED FIXED
Alias: None
Product: Spamassassin
Classification: Unclassified
Component: spamc/spamd (show other bugs)
Version: 3.4.0
Hardware: Sun Solaris
: P2 normal
Target Milestone: 3.4.1
Assignee: SpamAssassin Developer Mailing List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-11-26 16:36 UTC by Tom Schulz
Modified: 2015-02-23 23:43 UTC (History)
0 users



Attachment Type Modified Status Actions Submitter/CLA Status
suggested patch patch None Mark Martinec [HasCLA]

Note You need to log in before you can comment on or make changes to this bug.
Description Tom Schulz 2014-11-26 16:36:38 UTC
From the users mailing list I will enter this as two comments.

>> Tom Schulz wrote:
>>> I have been running spamd on Solaris 10 and Perl v5.8.9 for years,
>>> starting it with the command:
>>> spamd -d -c -m 18 --min-spare=1 --max-spare=4 --syslog-socket=inet
>>>
>>> I upgraded Perl to v5.20.1 and installed the current modules. When I
>>> try to start spamd with that command, I get the following errors:
>>>
>>> server socket setup failed, retry 1: spamd: could not create
>>> IO::Socket::IP socket on [::1]:783: Cannot assign requested address
>>> server socket setup failed, retry 2: spamd: could not create
>>> IO::Socket::IP socket on [127.0.0.1]:783: Address already in use
>>>
>>> And spamd does not start. If I add '-4' to the above command [...]
>>> And spamd does start.
>>>
>>> I conclude that the failed attempt to create an IPv6 socket blocks
>>> the ability to later create IPv4 sockets to the same port.
>>
>> Yes, so it seems.
>>
>> Please start spamd without option '-d' (daemonize) and with '-D spamd',
>> and note the logged order of socket bind attempts. Mine shows:
>>
>> dbg: spamd: socket module of choice: IO::Socket::IP 0.32, Socket 2.015,
>> have PF_INET, have PF_INET6, using Socket::getaddrinfo, AI_ADDRCONFIG
>> is supported
>> dbg: spamd: socket specification: "localhost", IP address: localhost,
>> port: 783
>> dbg: spamd: attempting to listen on IP addresses: 127.0.0.1, ::1, port
>> 783
>> dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr:
>> 127.0.0.1, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 1, V6Only: 1
>> dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr: ::1,
>> LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 1, V6Only: 1
>>
>> Note the order: tries 127.0.0.1 first, only then the ::1.
>> Note also the reported 'V6Only: 1' and a version of IO::Socket::IP
>> (or maybe it's IO::Socket::INET6 in your case???).
>>
>>> But note that with
>>> Perl v5.8.9 and the module versions available in Dec 2013, there was no
>>> problem without the '-4' switch. This sounds like it could be a bug
>>> somewhere.
>>
>>    Mark
Comment 1 Tom Schulz 2014-11-26 16:38:25 UTC
Tom Schulz wrote:
> Here is my debug output. It looks like the socket is created for
> 127.0.0.1 and then an attempt is also made for ::1. That fails as
> expected. But in my case that failure causes a retry that includes
> retrying for 127.0.0.1. This now fails because the port has already
> been created (as noted in the error message). Retries then continue
> until the retry limit is reached.
>
> dbg: spamd: socket module of choice: IO::Socket::IP 0.32, Socket 2.013,
> have PF_INET, have PF_INET6, using Socket::getaddrinfo, AI_ADDRCONFIG
> is supported
> dbg: spamd: socket specification: "localhost", IP address: localhost,
> port: 783
> dbg: spamd: attempting to listen on IP addresses: 127.0.0.1, ::1, port
> 783
> dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr:
> 127.0.0.1, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 2, V6Only: 1
> dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr:
> ::1, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 2, V6Only: 1
> server socket setup failed, retry 1: spamd: could not create
> IO::Socket::IP socket on [::1]:783: Cannot assign requested address
> dbg: spamd: attempting to listen on IP addresses: 127.0.0.1, ::1, port
> 783
> dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr:
> 127.0.0.1, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 2, V6Only: 1
> server socket setup failed, retry 2: spamd: could not create
> IO::Socket::IP socket on [127.0.0.1]:783: Address already in use

Thanks, that explains how we get to 'Address already in use'.

This opens up a couple of questions:

- creating a socket listening on '::' apparently does work
(it is tested in the BEGIN phase, and reported by 'have PF_INET6'),
but creating a socket listening on '::1' (i.e. a loopback address)
fails. Are you running spamd in jail? Does a loopback interface
have an IPv6 address assigned? Is it '::1'? Or if you think the
IPv6 is not supported on that host, why then does creating a
socket listening on '::' succeed?

- why did it work with older versions of perl and modules

- this chain of events shows that the logic in server_sock_setup_inet()
and/or its caller is flawed. When multiple sockets are to be created
and not all succeed, we'd need to undo the successfully created
sockets before bailing out on error - or alternatively, make do
with partially fulfilling the request.

Please open up a ticket on the bugzilla.

   Mark
Comment 2 Tom Schulz 2014-11-26 16:48:38 UTC
The operating system (Solaris 10) supports IPV6 but there are no IPV6
interfaces defined. So binding to ::1 can not succeed.
Here is the debug output with the old Perl and old modules:

dbg: spamd: socket module of choice: IO::Socket::IP 0.27, Socket 2.013, have PF_INET, no PF_INET6, using Socket::getaddrinfo, AI_ADDRCONFIG is supovported
dbg: spamd: socket specification: "localhost", IP address: localhost, port: 783
dbg: spamd: attempting to listen on IP addresses: 127.0.0.1, port 783
dbg: spamd: creating IO::Socket::IP socket: Listen: 128, LocalAddr: 127.0.0.1, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 2, V6Only: 1
Comment 3 Mark Martinec 2014-12-18 01:37:35 UTC
See also Bug 6953.
Comment 4 Mark Martinec 2015-01-27 20:21:23 UTC
Created attachment 5269 [details]
suggested patch

Bug 7106: Failed IPv6 port create blocks good IPv4 port create
  Sending spamd/spamd.raw
Committed revision 1655145.
Comment 5 Mark Martinec 2015-01-27 23:55:08 UTC
The change above takes a fairly minimalistic approach. When a single socket
specification implies more than one IP address (like when a given hostname
in a --listen option results in multiple A or AAAA records, or when a
default 'localhost' expands to two addresses ::1 and 127.0.0.1, or when
a --listen '*' expands to :: and 0.0.0.0), then as long as binding to one
of these IP addresses is successful, bind failures on other IP addresses
belonging to the same specification entry are not considered fatal - they
are reported as warnings, but allow the spamd program to proceed.

If even a warning needs to be avoided, one can always explicitly specify
an IP address to bind to in a --listen option and avoid guesswork by spamd.
Comment 6 Mark Martinec 2015-02-23 23:43:27 UTC
Should do for now, closing.