Bug 6953 - spamd: could not create IO::Socket::INET6 socket on [::]:783: Address already in use
Summary: spamd: could not create IO::Socket::INET6 socket on [::]:783: Address already...
Status: RESOLVED FIXED
Alias: None
Product: Spamassassin
Classification: Unclassified
Component: spamc/spamd (show other bugs)
Version: 3.4 SVN branch
Hardware: All Linux
: P2 normal
Target Milestone: 3.4.1
Assignee: SpamAssassin Developer Mailing List
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2013-07-04 11:43 UTC by Mark Martinec
Modified: 2015-02-24 00:02 UTC (History)
0 users



Attachment Type Modified Status Actions Submitter/CLA Status

Note You need to log in before you can comment on or make changes to this bug.
Description Mark Martinec 2013-07-04 11:43:09 UTC
Got the following problem report in a private communication
from Nejc Porenta:

Linux/Centos, SA 3.4 trunk: 1498432
# spamd -c -m500 -i --allowed-ips=x.x.x.x/25,y.y.y.y/26,127.0.0.1 -x --sql-config /etc/mail/spamassassin/local.cf -u nobody -D
[21291] dbg: logger: adding facilities: all
[21291] dbg: logger: logging level is DBG
[21291] dbg: logger: calling setlogsock(unix)
[21291] dbg: logger: opening syslog with unix socket
[21291] dbg: logger: successfully connected to syslog/unix
[21291] dbg: logger: successfully added syslog method
[21291] dbg: spamd: will perform setuids? 0
[21291] dbg: spamd: socket module of choice: IO::Socket::INET6 2.56, Socket 1.82, have PF_INET, have PF_INET6, using legacy Socket6::getaddrinfo, AI_ADDRCONFIG is supported
[21291] dbg: spamd: socket specification: "*", IP address: *, port: 783
[21291] dbg: spamd: attempting to listen on IP addresses: 0.0.0.0, ::, port 783
[21291] dbg: spamd: creating IO::Socket::INET6 socket: Listen: 128, LocalAddr: 0.0.0.0, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 1
[21291] dbg: spamd: creating IO::Socket::INET6 socket: Listen: 128, LocalAddr: ::, LocalPort: 783, Proto: tcp, ReuseAddr: 1, Type: 1
server socket setup failed, retry 1: spamd: could not create IO::Socket::INET6 socket on [::]:783: Address already in use
Comment 1 Mark Martinec 2013-07-04 13:04:15 UTC
This can happen when a socket of a protocol family INET6 is bound
to ANY IP address and is allowed to also accept INET connections, in
which case it is *not* possible to create another ANY socket even
if a different protocol family is specified.

There exists a socket option IPV6_V6ONLY, which determined if an
INET6 socket can also accept INET sessions. Its default value is
derived from a global setting (e.g. net.inet6.ip6.v6only), and
defaults to 1 on BSD systems (and Solaris I believe), but defaults
to 0 on Linux systems.

When a socket is created, it is possible to override a global
default for IPV6_V6ONLY for each socket. The perl module
IO::Socket::IP offers this control since version 0.09 and
spamd does turn it off where possible.

Unfortunately the older module IO::Socket::INET6 does not
recognize this option, which leads to the reported problem.

So the situation occurs in a specific situation where all of
the following applies:

- a module IO::Socket::INET6 is installed and the IO::Socket::IP
is not installed or is too old

- the host is a dual-stack host (supports IPv4 and IPv6)

- the global default for IPV6_V6ONLY is off (i.e. Linux, not BSD)

- the spamd option --listen (or -i) is specified without argument,
i.e. spamd is instructed to listen on any interface (not just loopback)


Conversely, the situation does *not* occur if any of the following
is true:

- the OS supports only IPv4 or only IPv6

- the systemwide default setting for IPV6_V6ONLY is true,
typical for a non-linux host

- the module IO::Socket::INET6 is not installed

- the --listen option is left at its default (i.e. bind to a loopback
interface only), or specifies explicitly just one IP address,
e.g. 0.0.0.0 or :: , which tells spamd to only create one listen socket
on one protocol family.

So workarounds are:
- specify 0.0.0.0 or :: explicitly with a --listen (-i) spamd option
- or, install module IO::Socket::IP version 0.09 or later
- or, deinstall IO::Socket::INET6
Comment 2 Mark Martinec 2013-07-04 13:16:29 UTC
So, there should be a better way to chose to which sockets spamd should
bind by default when --listen=* .  Testing the socket option is not
doable, as the old IP::Socket::INET6 does not support it;  testing and
guessing on the environment could be an unreliable fudge. Perhaps
turning the second bind attempt into a warning and discarding the failed
socket could be an easy way out.
Comment 3 Mark Martinec 2014-12-18 01:36:32 UTC
See also Bug 7106.
(not exactly a duplicate, but closely related)
Comment 4 Mark Martinec 2015-01-27 23:58:00 UTC
> See also Bug 7106. (not exactly a duplicate, but closely related)

I think the change in Bug 7106 also provides a workaround for the
case described in this bug. Needs to be tested...
Comment 5 Mark Martinec 2015-01-28 14:44:47 UTC
> > See also Bug 7106. (not exactly a duplicate, but closely related) 
> I think the change in Bug 7106 also provides a workaround for the
> case described in this bug. Needs to be tested...

Now with less stringent checks put in place by Bug 7106#c4,
we can afford to swap the order of bindings
in pairs 0.0.0.0 with ::, and 127.0.0.1 with ::1 .
Previously we tried binding to an IPv4 socket first, followed
by an IPv6, with the following small change we do the reverse:

  Bug 6953: spamd: could not create IO::Socket::INET6 socket
    on [::]:783: Address already in use' spamd/spamd.raw
    Sending spamd/spamd.raw
  Committed revision 1655345.


In many cases the order does not matter:
  - when one or the other protocol family is not supported
    in the kernel at all, or
  - when IO::Socket::IP version 0.09 or newer is installed, or
  - when IO::Socket::INET6 is not installed, or
  - when a binding address is explicitly provided by a
    spamd --listen (or -i) option, or
  - when option -4 or -6 is given to spamd, or
  - when sysctl setting net.ipv6.bindv6only (Linux) or
    net.inet6.ip6.v6only (BSD) is set to 1 (which is a default
    on FreeBSD, and configurable in any OS)

It only matters if none of the above applies. In this case,
prior to the Bug 7106#c4 change and the above swap we'd get a
fatal error as is the topic of this problem report. Now spamd
successfully binds to ::  (i.e. an 'any' address') and because
of the sysctl setting it is willing to accept also connections
to this IPv6 socket over an IPv4 protocol family. When it
tries next to bind to 0.0.0.0 (i.e. an IPv4-only 'any' address),
this fails with: "Address already in use", but thanks to the
change in Bug 7106 this is now only a warning issued on a
spamd start, but later it works fine, accepting both protocol
families over a single IPv6 socket.

Perhaps the only detail to be considered is whether a warning
issued during a spamd start would upset some startup script.
If this is an issue, the warning could be downgraded to an info.
The warning can also be avoided by any of the measures in the
above list.
Comment 6 Mark Martinec 2015-02-24 00:02:58 UTC
The change in Bug 7106 turned this failure into a warning.
Should do for now, closing.