make Listen parameter a comma-seperated list of addresses.

this also obsoletes ListenIPv4 and ListenIPv6 options.
If Listen is unset, it is treated as Listen="::,0.0.0.0".

Note: ListenIPv4 and ListenIPv6 options are still recognized,
but ngircd will print a warning if they are used in the config file.

Also, some plattforms require that ai_socktype
is set in the getaddrinfo() hints structure.
This commit is contained in:
Florian Westphal 2008-05-19 00:12:41 +02:00
parent 818a206a42
commit 4ed2cb1a02
7 changed files with 129 additions and 106 deletions

View File

@ -40,9 +40,11 @@
# one port, separated with ",". (Default: 6667)
;Ports = 6667, 6668, 6669
# IP address on which the server should listen. (Default: empty,
# so the server listens on all IP addresses of the system)
;Listen = 1.2.3.4
# comma seperated list of IP addresses on which the server should
# listen. Default values are:
# "0.0.0.0" or (if compiled with IPv6 support) "::,0.0.0.0"
# so the server listens on all IP addresses of the system by default.
;Listen = 127.0.0.1,192.168.0.1
# Text file with the "message of the day" (MOTD). This message will
# be shown to all users connecting to the server:
@ -103,11 +105,6 @@
# Don't do any DNS lookups when a client connects to the server.
;NoDNS = no
# allow both ipv4 and ipv6 clients to connect by opening both
# ipv4 and ipv6 sockets
;ListenIPv6 = yes
;ListenIPv4 = yes
# try to connect to other irc servers using ipv4 and ipv6, if possible
;ConnectIPv6 = yes
;ConnectIPv4 = yes

View File

@ -73,8 +73,10 @@ Ports on which the server should listen. There may be more than one port,
separated with ','. Default: 6667.
.TP
\fBListen\fR
The IP address on which the server should listen. Default is empty, so
the server listens on all configured IP addresses and interfaces.
A comma seperated list of IP address on which the server should listen.
If unset, the defaults value is "0.0.0.0", or, if ngircd was compiled
with IPv6 support, "::,0.0.0.0", so the server listens on all configured
IP addresses and interfaces by default.
.TP
\fBMotdFile\fR
Text file with the "message of the day" (MOTD). This message will be shown
@ -160,15 +162,6 @@ If you configure ngircd to connect to other servers, ngircd may still
perform a DNS lookup if required.
Default: No.
.TP
\fBListenIPv4\fR
Set this to no if you do not want ngircd to accept clients using the standard internet protocol, ipv4.
This allows use of ngircd in ipv6-only setups.
Default: Yes.
.TP
\fBListenIPv6\fR
Set this to no if you do not want ngircd to accept clients using the new internet protocol, ipv6.
Default: Yes.
.TP
\fBConnectIPv4\fR
Set this to no if you do not want ngircd to connect to other irc servers using ipv4.
This allows use of ngircd in ipv6-only setups.

View File

@ -24,18 +24,19 @@ ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
int ret;
char portstr[64];
struct addrinfo *res0;
struct addrinfo hints = {
#ifndef WANT_IPV6 /* only accept v4 addresses */
.ai_family = AF_INET,
#endif
.ai_flags = AI_NUMERICHOST
};
struct addrinfo hints;
if (ip_str == NULL)
hints.ai_flags |= AI_PASSIVE;
assert(ip_str);
memset(&hints, 0, sizeof(hints));
hints.ai_flags = AI_NUMERICHOST;
/* some getaddrinfo implementations require that ai_socktype is set. */
hints.ai_socktype = SOCK_STREAM;
/* silly, but ngircd stores UINT16 in server config, not string */
snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port);
ret = getaddrinfo(ip_str, portstr, &hints, &res0);
assert(ret == 0);
if (ret != 0)
@ -49,8 +50,7 @@ ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
freeaddrinfo(res0);
return ret == 0;
#else /* HAVE_GETADDRINFO */
if (ip_str == NULL)
ip_str = "0.0.0.0";
assert(ip_str);
addr->sin4.sin_family = AF_INET;
# ifdef HAVE_INET_ATON
if (inet_aton(ip_str, &addr->sin4.sin_addr) == 0)

View File

@ -84,7 +84,6 @@ ng_ipaddr_getport(const ng_ipaddr_t *a)
* init a ng_ipaddr_t object.
* @param addr: pointer to ng_ipaddr_t to initialize.
* @param ip_str: ip address in dotted-decimal (ipv4) or hexadecimal (ipv6) notation
* if ip_str is NULL it is treated as 0.0.0.0/[::]
* @param port: transport layer port number to use.
*/
GLOBAL bool ng_ipaddr_init PARAMS((ng_ipaddr_t *addr, const char *ip_str, UINT16 port));

View File

@ -56,6 +56,18 @@ static CONF_SERVER New_Server;
static int New_Server_Idx;
#ifdef WANT_IPV6
/*
* these options appeared in ngircd 0.12; they are here
* for backwards compatibility. They should be removed
* in the future. Instead of setting these options,
* the "Listen" option should be set accordingly.
*/
static bool Conf_ListenIPv6;
static bool Conf_ListenIPv4;
#endif
static void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool ngircd_starting ));
static void Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
@ -199,8 +211,7 @@ Conf_Test( void )
fputs(" Ports = ", stdout);
ports_puts(&Conf_ListenPorts);
printf( " Listen = %s\n", Conf_ListenAddress );
printf(" Listen = %s\n", Conf_ListenAddress);
pwd = getpwuid( Conf_UID );
if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name );
else printf( " ServerUID = %ld\n", (long)Conf_UID );
@ -216,8 +227,11 @@ Conf_Test( void )
printf( " NoDNS = %s\n", yesno_to_str(Conf_NoDNS));
#ifdef WANT_IPV6
printf(" ListenIPv6 = %s\n", yesno_to_str(Conf_ListenIPv6));
printf(" ListenIPv4 = %s\n", yesno_to_str(Conf_ListenIPv4));
/* both are deprecated, only mention them if their default value changed. */
if (!Conf_ListenIPv6)
puts(" ListenIPv6 = no");
if (!Conf_ListenIPv4)
puts(" ListenIPv4 = no");
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
#endif
@ -448,8 +462,8 @@ Set_Defaults( bool InitServers )
strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile ));
strcpy( Conf_ListenAddress, "" );
free(Conf_ListenAddress);
Conf_ListenAddress = NULL;
Conf_UID = Conf_GID = 0;
Conf_PingTimeout = 120;
@ -650,6 +664,23 @@ Read_Config( bool ngircd_starting )
exit( 1 );
}
}
if (!Conf_ListenAddress) {
/* no Listen addresses configured, use default */
#ifdef WANT_IPV6
/* Conf_ListenIPv6/4 should no longer be used */
if (Conf_ListenIPv6 && Conf_ListenIPv4)
Conf_ListenAddress = strdup_warn("::,0.0.0.0");
else if (Conf_ListenIPv6)
Conf_ListenAddress = strdup_warn("::");
else
#endif
Conf_ListenAddress = strdup_warn("0.0.0.0");
}
if (!Conf_ListenAddress) {
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
exit(1);
}
return true;
} /* Read_Config */
@ -840,17 +871,25 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
}
#ifdef WANT_IPV6
/* the default setting for all the WANT_IPV6 special options is 'true' */
if( strcasecmp( Var, "ListenIPv6" ) == 0 ) {
/* listen on ipv6 sockets, if available? */
if (strcasecmp(Var, "ListenIPv6") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/*
* listen on ipv6 sockets, if available?
* Deprecated use "Listen = 0.0.0.0" (or, rather, do not list "::")
*/
Conf_ListenIPv6 = Check_ArgIsTrue( Arg );
Config_Error(LOG_WARNING, "%s, line %d: %s=%s is deprecated, %sinclude '::' in \"Listen =\" option instead",
NGIRCd_ConfFile, Line, Var, yesno_to_str(Conf_ListenIPv6), Conf_ListenIPv6 ? " ":"do not ");
return;
}
if( strcasecmp( Var, "ListenIPv4" ) == 0 ) {
if (strcasecmp(Var, "ListenIPv4") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/*
* listen on ipv4 sockets, if available?
* this allows "ipv6-only" setups.
* this allows "ipv6-only" setups
* Deprecated use "Listen = ::" (or, rather, do not list "0.0.0.0")
*/
Conf_ListenIPv4 = Check_ArgIsTrue( Arg );
Config_Error(LOG_WARNING, "%s, line %d: %s=%s is deprecated, %sinclude '0.0.0.0' in \"Listen =\" option instead",
NGIRCd_ConfFile, Line, Var, yesno_to_str(Conf_ListenIPv4), Conf_ListenIPv4 ? " ":"do not ");
return;
}
if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
@ -911,14 +950,24 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
if( strcasecmp( Var, "Listen" ) == 0 ) {
/* IP-Address to bind sockets */
len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress ));
if (len >= sizeof( Conf_ListenAddress ))
Config_Error_TooLong( Line, Var );
if (Conf_ListenAddress) {
Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
return;
}
Conf_ListenAddress = strdup_warn(Arg);
/*
* if allocation fails, we're in trouble:
* we cannot ignore the error -- otherwise ngircd
* would listen on all interfaces.
*/
if (!Conf_ListenAddress) {
Config_Error(LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME);
exit(1);
}
return;
}
Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var );
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var);
} /* Handle_GLOBAL */
@ -1186,16 +1235,6 @@ Validate_Config(bool Configtest, bool Rehash)
"No administrative information configured but required by RFC!");
}
#ifdef WANT_IPV6
if (!Conf_ListenIPv4 && !Conf_ListenIPv6)
Config_Error(LOG_ALERT,
"Both \"ListenIPv4\" and \"ListenIPv6\" are set to 'no'; no network protocol available!");
if (!Conf_ConnectIPv4 && !Conf_ConnectIPv6)
Config_Error(LOG_ALERT,
"Both \"ConnectIPv4\" and \"ConnectIPv6\" are set to 'no'; ngircd will fail to connect to other irc servers");
#endif
#ifdef DEBUG
servers = servers_once = 0;
for (i = 0; i < MAX_SERVERS; i++) {

View File

@ -86,7 +86,7 @@ GLOBAL char Conf_MotdPhrase[LINE_LEN];
GLOBAL array Conf_ListenPorts;
/* Address to which the socket should be bound or empty (=all) */
GLOBAL char Conf_ListenAddress[16];
GLOBAL char *Conf_ListenAddress;
/* User and group ID the server should run with */
GLOBAL uid_t Conf_UID;
@ -124,12 +124,6 @@ GLOBAL bool Conf_OperCanMode;
/* Disable all DNS functions? */
GLOBAL bool Conf_NoDNS;
/* listen for incoming ipv6 connections if OS supports it (default: yes)? */
GLOBAL bool Conf_ListenIPv6;
/* listen for incoming ipv4 connections if OS supports it (default: yes)? */
GLOBAL bool Conf_ListenIPv4;
/*
* try to connect to remote systems using the ipv6 protocol,
* if they have an ipv6 address? (default yes)

View File

@ -88,7 +88,7 @@ static void Init_Conn_Struct PARAMS(( CONN_ID Idx ));
static bool Init_Socket PARAMS(( int Sock ));
static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest ));
static void Simple_Message PARAMS(( int Sock, const char *Msg ));
static int NewListener PARAMS(( int af, const UINT16 Port ));
static int NewListener PARAMS(( const char *listen_addr, UINT16 Port ));
static array My_Listeners;
static array My_ConnArray;
@ -272,7 +272,7 @@ Conn_Exit( void )
static unsigned int
ports_initlisteners(array *a, int af, void (*func)(int,short))
ports_initlisteners(array *a, const char *listen_addr, void (*func)(int,short))
{
unsigned int created = 0;
size_t len;
@ -281,15 +281,15 @@ ports_initlisteners(array *a, int af, void (*func)(int,short))
len = array_length(a, sizeof (UINT16));
port = array_start(a);
while(len--) {
fd = NewListener(af, *port);
while (len--) {
fd = NewListener(listen_addr, *port);
if (fd < 0) {
port++;
continue;
}
if (!io_event_create( fd, IO_WANTREAD, func )) {
Log( LOG_ERR, "io_event_create(): Could not add listening fd %d (port %u): %s!",
fd, (unsigned int) *port, strerror(errno));
fd, (unsigned int) *port, strerror(errno));
close(fd);
port++;
continue;
@ -297,7 +297,6 @@ ports_initlisteners(array *a, int af, void (*func)(int,short))
created++;
port++;
}
return created;
}
@ -306,21 +305,39 @@ GLOBAL unsigned int
Conn_InitListeners( void )
{
/* Initialize ports on which the server should accept connections */
unsigned int created = 0;
char *copy, *listen_addr;
if (!io_library_init(CONNECTION_POOL)) {
Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
return -1;
}
#ifdef WANT_IPV6
if (Conf_ListenIPv6)
created = ports_initlisteners(&Conf_ListenPorts, AF_INET6, cb_listen);
#endif
if (Conf_ListenIPv4)
created += ports_initlisteners(&Conf_ListenPorts, AF_INET, cb_listen);
assert(Conf_ListenAddress);
/* can't use Conf_ListenAddress directly, see below */
copy = strdup(Conf_ListenAddress);
if (!copy) {
Log(LOG_CRIT, "Cannot copy %s: %s", Conf_ListenAddress, strerror(errno));
return 0;
}
listen_addr = strtok(copy, ",");
while (listen_addr) {
ngt_TrimStr(listen_addr);
if (*listen_addr)
created += ports_initlisteners(&Conf_ListenPorts, listen_addr, cb_listen);
listen_addr = strtok(NULL, ",");
}
/*
* can't free() Conf_ListenAddress here. On /REHASH, if the config file
* cannot be re-loaded, we'd end up with a NULL Conf_ListenAddress.
* Instead, free() takes place in conf.c, before the config file
* is being parsed.
*/
free(copy);
return created;
} /* Conn_InitListeners */
@ -350,25 +367,15 @@ Conn_ExitListeners( void )
static bool
InitSinaddrListenAddr(int af, ng_ipaddr_t *addr, UINT16 Port)
InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
{
bool ret;
const char *listen_addrstr = NULL;
#ifdef WANT_IPV6
if (af == AF_INET)
listen_addrstr = "0.0.0.0";
#else
(void)af;
#endif
if (Conf_ListenAddress[0]) /* overrides V4/V6 atm */
listen_addrstr = Conf_ListenAddress;
ret = ng_ipaddr_init(addr, listen_addrstr, Port);
if (!ret) {
if (!listen_addrstr)
listen_addrstr = "";
Log(LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"",
listen_addrstr, Port, listen_addrstr);
assert(listen_addrstr);
Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
listen_addrstr, Port, listen_addrstr);
}
return ret;
}
@ -394,24 +401,23 @@ set_v6_only(int af, int sock)
/* return new listening port file descriptor or -1 on failure */
static int
NewListener(int af, const UINT16 Port)
NewListener(const char *listen_addr, UINT16 Port)
{
/* Create new listening socket on specified port */
ng_ipaddr_t addr;
int sock;
int sock, af;
#ifdef ZEROCONF
char name[CLIENT_ID_LEN], *info;
#endif
if (!InitSinaddrListenAddr(af, &addr, Port))
if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
return -1;
sock = socket(ng_ipaddr_af(&addr), SOCK_STREAM, 0);
if( sock < 0 ) {
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
return -1;
}
af = ng_ipaddr_af(&addr);
sock = socket(af, SOCK_STREAM, 0);
if( sock < 0 ) {
Log(LOG_CRIT, "Can't create socket (af %d) : %s!", af, strerror(errno));
return -1;
}
set_v6_only(af, sock);
@ -438,12 +444,7 @@ NewListener(int af, const UINT16 Port)
return -1;
}
#ifdef WANT_IPV6
if (af == AF_INET6)
Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
else
#endif
Log(LOG_INFO, "Now listening on %s:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
Log(LOG_INFO, "Now listening on [%s]:%d (socket %d).", ng_ipaddr_tostr(&addr), Port, sock);
#ifdef ZEROCONF
/* Get best server description text */
@ -1461,7 +1462,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
af_dest = ng_ipaddr_af(dest);
new_sock = socket(af_dest, SOCK_STREAM, 0);
if (new_sock < 0) {
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
Log( LOG_CRIT, "Can't create socket (af %d) : %s!", af_dest, strerror( errno ));
return;
}