1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-01-23 13:56:51 +00:00

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) # one port, separated with ",". (Default: 6667)
;Ports = 6667, 6668, 6669 ;Ports = 6667, 6668, 6669
# IP address on which the server should listen. (Default: empty, # comma seperated list of IP addresses on which the server should
# so the server listens on all IP addresses of the system) # listen. Default values are:
;Listen = 1.2.3.4 # "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 # Text file with the "message of the day" (MOTD). This message will
# be shown to all users connecting to the server: # 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. # Don't do any DNS lookups when a client connects to the server.
;NoDNS = no ;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 # try to connect to other irc servers using ipv4 and ipv6, if possible
;ConnectIPv6 = yes ;ConnectIPv6 = yes
;ConnectIPv4 = 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. separated with ','. Default: 6667.
.TP .TP
\fBListen\fR \fBListen\fR
The IP address on which the server should listen. Default is empty, so A comma seperated list of IP address on which the server should listen.
the server listens on all configured IP addresses and interfaces. 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 .TP
\fBMotdFile\fR \fBMotdFile\fR
Text file with the "message of the day" (MOTD). This message will be shown 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. perform a DNS lookup if required.
Default: No. Default: No.
.TP .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 \fBConnectIPv4\fR
Set this to no if you do not want ngircd to connect to other irc servers using ipv4. 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. 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; int ret;
char portstr[64]; char portstr[64];
struct addrinfo *res0; struct addrinfo *res0;
struct addrinfo hints = { struct addrinfo hints;
#ifndef WANT_IPV6 /* only accept v4 addresses */
.ai_family = AF_INET,
#endif
.ai_flags = AI_NUMERICHOST
};
if (ip_str == NULL) assert(ip_str);
hints.ai_flags |= AI_PASSIVE;
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 */ /* silly, but ngircd stores UINT16 in server config, not string */
snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port); snprintf(portstr, sizeof(portstr), "%u", (unsigned int) port);
ret = getaddrinfo(ip_str, portstr, &hints, &res0); ret = getaddrinfo(ip_str, portstr, &hints, &res0);
assert(ret == 0); assert(ret == 0);
if (ret != 0) if (ret != 0)
@ -49,8 +50,7 @@ ng_ipaddr_init(ng_ipaddr_t *addr, const char *ip_str, UINT16 port)
freeaddrinfo(res0); freeaddrinfo(res0);
return ret == 0; return ret == 0;
#else /* HAVE_GETADDRINFO */ #else /* HAVE_GETADDRINFO */
if (ip_str == NULL) assert(ip_str);
ip_str = "0.0.0.0";
addr->sin4.sin_family = AF_INET; addr->sin4.sin_family = AF_INET;
# ifdef HAVE_INET_ATON # ifdef HAVE_INET_ATON
if (inet_aton(ip_str, &addr->sin4.sin_addr) == 0) 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. * init a ng_ipaddr_t object.
* @param addr: pointer to ng_ipaddr_t to initialize. * @param addr: pointer to ng_ipaddr_t to initialize.
* @param ip_str: ip address in dotted-decimal (ipv4) or hexadecimal (ipv6) notation * @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. * @param port: transport layer port number to use.
*/ */
GLOBAL bool ng_ipaddr_init PARAMS((ng_ipaddr_t *addr, const char *ip_str, UINT16 port)); 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; 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 void Set_Defaults PARAMS(( bool InitServers ));
static bool Read_Config PARAMS(( bool ngircd_starting )); static bool Read_Config PARAMS(( bool ngircd_starting ));
static void Validate_Config PARAMS(( bool TestOnly, bool Rehash )); static void Validate_Config PARAMS(( bool TestOnly, bool Rehash ));
@ -199,7 +211,6 @@ Conf_Test( void )
fputs(" Ports = ", stdout); fputs(" Ports = ", stdout);
ports_puts(&Conf_ListenPorts); ports_puts(&Conf_ListenPorts);
printf(" Listen = %s\n", Conf_ListenAddress); printf(" Listen = %s\n", Conf_ListenAddress);
pwd = getpwuid( Conf_UID ); pwd = getpwuid( Conf_UID );
if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name ); if( pwd ) printf( " ServerUID = %s\n", pwd->pw_name );
@ -216,8 +227,11 @@ Conf_Test( void )
printf( " NoDNS = %s\n", yesno_to_str(Conf_NoDNS)); printf( " NoDNS = %s\n", yesno_to_str(Conf_NoDNS));
#ifdef WANT_IPV6 #ifdef WANT_IPV6
printf(" ListenIPv6 = %s\n", yesno_to_str(Conf_ListenIPv6)); /* both are deprecated, only mention them if their default value changed. */
printf(" ListenIPv4 = %s\n", yesno_to_str(Conf_ListenIPv4)); if (!Conf_ListenIPv6)
puts(" ListenIPv6 = no");
if (!Conf_ListenIPv4)
puts(" ListenIPv4 = no");
printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6)); printf(" ConnectIPv4 = %s\n", yesno_to_str(Conf_ConnectIPv6));
printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4)); printf(" ConnectIPv6 = %s\n", yesno_to_str(Conf_ConnectIPv4));
#endif #endif
@ -448,8 +462,8 @@ Set_Defaults( bool InitServers )
strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile )); strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile ));
strcpy( Conf_ListenAddress, "" ); free(Conf_ListenAddress);
Conf_ListenAddress = NULL;
Conf_UID = Conf_GID = 0; Conf_UID = Conf_GID = 0;
Conf_PingTimeout = 120; Conf_PingTimeout = 120;
@ -650,6 +664,23 @@ Read_Config( bool ngircd_starting )
exit( 1 ); 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; return true;
} /* Read_Config */ } /* Read_Config */
@ -840,17 +871,25 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
} }
#ifdef WANT_IPV6 #ifdef WANT_IPV6
/* the default setting for all the WANT_IPV6 special options is 'true' */ /* the default setting for all the WANT_IPV6 special options is 'true' */
if( strcasecmp( Var, "ListenIPv6" ) == 0 ) { if (strcasecmp(Var, "ListenIPv6") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/* listen on ipv6 sockets, if available? */ /*
* listen on ipv6 sockets, if available?
* Deprecated use "Listen = 0.0.0.0" (or, rather, do not list "::")
*/
Conf_ListenIPv6 = Check_ArgIsTrue( Arg ); 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; return;
} }
if( strcasecmp( Var, "ListenIPv4" ) == 0 ) { if (strcasecmp(Var, "ListenIPv4") == 0) { /* DEPRECATED, option appeared in 0.12.0 */
/* /*
* listen on ipv4 sockets, if available? * 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 ); 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; return;
} }
if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) { if( strcasecmp( Var, "ConnectIPv6" ) == 0 ) {
@ -911,12 +950,22 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
if( strcasecmp( Var, "Listen" ) == 0 ) { if( strcasecmp( Var, "Listen" ) == 0 ) {
/* IP-Address to bind sockets */ /* IP-Address to bind sockets */
len = strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress )); if (Conf_ListenAddress) {
if (len >= sizeof( Conf_ListenAddress )) Config_Error(LOG_ERR, "Multiple Listen= options, ignoring: %s", Arg);
Config_Error_TooLong( Line, Var ); 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; return;
} }
Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", Config_Error(LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!",
NGIRCd_ConfFile, Line, Var); NGIRCd_ConfFile, Line, Var);
} /* Handle_GLOBAL */ } /* Handle_GLOBAL */
@ -1186,16 +1235,6 @@ Validate_Config(bool Configtest, bool Rehash)
"No administrative information configured but required by RFC!"); "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 #ifdef DEBUG
servers = servers_once = 0; servers = servers_once = 0;
for (i = 0; i < MAX_SERVERS; i++) { for (i = 0; i < MAX_SERVERS; i++) {

View File

@ -86,7 +86,7 @@ GLOBAL char Conf_MotdPhrase[LINE_LEN];
GLOBAL array Conf_ListenPorts; GLOBAL array Conf_ListenPorts;
/* Address to which the socket should be bound or empty (=all) */ /* 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 */ /* User and group ID the server should run with */
GLOBAL uid_t Conf_UID; GLOBAL uid_t Conf_UID;
@ -124,12 +124,6 @@ GLOBAL bool Conf_OperCanMode;
/* Disable all DNS functions? */ /* Disable all DNS functions? */
GLOBAL bool Conf_NoDNS; 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, * try to connect to remote systems using the ipv6 protocol,
* if they have an ipv6 address? (default yes) * 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 bool Init_Socket PARAMS(( int Sock ));
static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest )); static void New_Server PARAMS(( int Server, ng_ipaddr_t *dest ));
static void Simple_Message PARAMS(( int Sock, const char *Msg )); 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_Listeners;
static array My_ConnArray; static array My_ConnArray;
@ -272,7 +272,7 @@ Conn_Exit( void )
static unsigned int 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; unsigned int created = 0;
size_t len; size_t len;
@ -282,7 +282,7 @@ ports_initlisteners(array *a, int af, void (*func)(int,short))
len = array_length(a, sizeof (UINT16)); len = array_length(a, sizeof (UINT16));
port = array_start(a); port = array_start(a);
while (len--) { while (len--) {
fd = NewListener(af, *port); fd = NewListener(listen_addr, *port);
if (fd < 0) { if (fd < 0) {
port++; port++;
continue; continue;
@ -297,7 +297,6 @@ ports_initlisteners(array *a, int af, void (*func)(int,short))
created++; created++;
port++; port++;
} }
return created; return created;
} }
@ -306,21 +305,39 @@ GLOBAL unsigned int
Conn_InitListeners( void ) Conn_InitListeners( void )
{ {
/* Initialize ports on which the server should accept connections */ /* Initialize ports on which the server should accept connections */
unsigned int created = 0; unsigned int created = 0;
char *copy, *listen_addr;
if (!io_library_init(CONNECTION_POOL)) { if (!io_library_init(CONNECTION_POOL)) {
Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno)); Log(LOG_EMERG, "Cannot initialize IO routines: %s", strerror(errno));
return -1; return -1;
} }
#ifdef WANT_IPV6 assert(Conf_ListenAddress);
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);
/* 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; return created;
} /* Conn_InitListeners */ } /* Conn_InitListeners */
@ -350,24 +367,14 @@ Conn_ExitListeners( void )
static bool static bool
InitSinaddrListenAddr(int af, ng_ipaddr_t *addr, UINT16 Port) InitSinaddrListenAddr(ng_ipaddr_t *addr, const char *listen_addrstr, UINT16 Port)
{ {
bool ret; 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); ret = ng_ipaddr_init(addr, listen_addrstr, Port);
if (!ret) { if (!ret) {
if (!listen_addrstr) assert(listen_addrstr);
listen_addrstr = ""; Log(LOG_CRIT, "Can't bind to [%s]:%u: can't convert ip address \"%s\"",
Log(LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"",
listen_addrstr, Port, listen_addrstr); listen_addrstr, Port, listen_addrstr);
} }
return ret; return ret;
@ -394,24 +401,23 @@ set_v6_only(int af, int sock)
/* return new listening port file descriptor or -1 on failure */ /* return new listening port file descriptor or -1 on failure */
static int static int
NewListener(int af, const UINT16 Port) NewListener(const char *listen_addr, UINT16 Port)
{ {
/* Create new listening socket on specified port */ /* Create new listening socket on specified port */
ng_ipaddr_t addr; ng_ipaddr_t addr;
int sock; int sock, af;
#ifdef ZEROCONF #ifdef ZEROCONF
char name[CLIENT_ID_LEN], *info; char name[CLIENT_ID_LEN], *info;
#endif #endif
if (!InitSinaddrListenAddr(af, &addr, Port)) if (!InitSinaddrListenAddr(&addr, listen_addr, Port))
return -1; 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); 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); set_v6_only(af, sock);
@ -438,12 +444,7 @@ NewListener(int af, const UINT16 Port)
return -1; 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); 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);
#ifdef ZEROCONF #ifdef ZEROCONF
/* Get best server description text */ /* Get best server description text */
@ -1461,7 +1462,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
af_dest = ng_ipaddr_af(dest); af_dest = ng_ipaddr_af(dest);
new_sock = socket(af_dest, SOCK_STREAM, 0); new_sock = socket(af_dest, SOCK_STREAM, 0);
if (new_sock < 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; return;
} }