bind ListenAddress for outgoing connections

ngircd would always use INADDR_ANY for outgoing connections;
which might not be desirable. Added new [Server] option
"Bind" to set source ip.
This commit is contained in:
Florian Westphal 2007-11-23 16:26:03 +00:00
parent 024588dbe7
commit 82d32ffb28
7 changed files with 98 additions and 32 deletions

View File

@ -1,4 +1,4 @@
# $Id: sample-ngircd.conf,v 1.42 2007/11/21 12:16:35 alex Exp $
# $Id: sample-ngircd.conf,v 1.43 2007/11/23 16:26:03 fw Exp $
#
# This is a sample configuration file for the ngIRCd, which must be adepted
@ -154,6 +154,10 @@
# this server should establish the connection).
;Host = connect-to-host.the.net
# IP address to use as _source_ address for the connection. if unspecified,
# ngircd will let the operating system pick an address.
;Bind = 10.0.0.1
# Port of the server to which the ngIRCd should connect. If you
# assign no port the ngIRCd waits for incoming connections.
;Port = 6667

View File

@ -1,5 +1,5 @@
.\"
.\" $Id: ngircd.conf.5.tmpl,v 1.6 2007/11/21 12:16:36 alex Exp $
.\" $Id: ngircd.conf.5.tmpl,v 1.7 2007/11/23 16:26:03 fw Exp $
.\"
.TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual"
.SH NAME
@ -212,6 +212,10 @@ IRC name of the server
\fBHost\fR
Internet host name of the peer
.TP
\fBBind\fR
IP address to use as source IP for the outgoing connection. Default ist
to let the operating system decide.
.TP
\fBPort\fR
Port of the server to which the ngIRCd should connect. If you assign no port
the ngIRCd waits for incoming connections.

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: conf.c,v 1.102 2007/11/21 12:16:36 alex Exp $";
static char UNUSED id[] = "$Id: conf.c,v 1.103 2007/11/23 16:26:04 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -937,6 +937,14 @@ Handle_SERVER( int Line, char *Var, char *Arg )
Config_Error_TooLong( Line, Var );
return;
}
if (strcasecmp(Var, "Bind") == 0) {
if (ngt_IPStrToBin(Arg, &New_Server.bind_addr))
return;
Config_Error(LOG_ERR, "%s, line %d (section \"Server\"): Can't parse IP address \"%s\"",
NGIRCd_ConfFile, Line, Arg);
return;
}
if( strcasecmp( Var, "MyPassword" ) == 0 ) {
/* Password of this server which is sent to the peer */
if (*Arg == ':') {
@ -1205,6 +1213,7 @@ Init_Server_Struct( CONF_SERVER *Server )
Resolve_Init(&Server->res_stat);
Server->conn_id = NONE;
Server->bind_addr.s_addr = htonl(INADDR_ANY);
} /* Init_Server_Struct */

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: conf.h,v 1.45 2007/11/21 12:16:36 alex Exp $
* $Id: conf.h,v 1.46 2007/11/23 16:26:04 fw Exp $
*
* Configuration management (header)
*/
@ -43,6 +43,7 @@ typedef struct _Conf_Server
RES_STAT res_stat; /* Status of the resolver */
int flags; /* Flags */
CONN_ID conn_id; /* ID of server connection or NONE */
struct in_addr bind_addr; /* source address to use for outgoing connections */
} CONF_SERVER;
typedef struct _Conf_Channel

View File

@ -17,7 +17,7 @@
#include "portab.h"
#include "io.h"
static char UNUSED id[] = "$Id: conn.c,v 1.214 2007/11/18 15:05:35 alex Exp $";
static char UNUSED id[] = "$Id: conn.c,v 1.215 2007/11/23 16:26:04 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -333,6 +333,42 @@ Conn_ExitListeners( void )
} /* Conn_ExitListeners */
static void
InitSinaddr(struct sockaddr_in *addr, UINT16 Port)
{
struct in_addr inaddr;
memset(addr, 0, sizeof(*addr));
memset( &inaddr, 0, sizeof(inaddr));
addr->sin_family = AF_INET;
addr->sin_port = htons(Port);
inaddr.s_addr = htonl(INADDR_ANY);
addr->sin_addr = inaddr;
}
static bool
InitSinaddrListenAddr(struct sockaddr_in *addr, UINT16 Port)
{
struct in_addr inaddr;
InitSinaddr(addr, Port);
if (!Conf_ListenAddress[0])
return true;
if (!ngt_IPStrToBin(Conf_ListenAddress, &inaddr)) {
Log( LOG_CRIT, "Can't bind to %s:%u: can't convert ip address \"%s\"",
Conf_ListenAddress, Port, Conf_ListenAddress);
return false;
}
addr->sin_addr = inaddr;
return true;
}
/* return new listening port file descriptor or -1 on failure */
static int
NewListener( const UINT16 Port )
@ -340,33 +376,15 @@ NewListener( const UINT16 Port )
/* Create new listening socket on specified port */
struct sockaddr_in addr;
struct in_addr inaddr;
int sock;
#ifdef ZEROCONF
char name[CLIENT_ID_LEN], *info;
#endif
/* Server-"Listen"-Socket initialisieren */
memset( &addr, 0, sizeof( addr ));
memset( &inaddr, 0, sizeof( inaddr ));
InitSinaddrListenAddr(&addr, Port);
addr.sin_family = AF_INET;
addr.sin_port = htons( Port );
if( Conf_ListenAddress[0] )
{
#ifdef HAVE_INET_ATON
if( inet_aton( Conf_ListenAddress, &inaddr ) == 0 )
#else
inaddr.s_addr = inet_addr( Conf_ListenAddress );
if( inaddr.s_addr == (unsigned)-1 )
#endif
{
Log( LOG_CRIT, "Can't listen on %s:%u: can't convert ip address %s!",
Conf_ListenAddress, Port, Conf_ListenAddress );
return -1;
}
}
else inaddr.s_addr = htonl( INADDR_ANY );
addr.sin_addr = inaddr;
sock = socket( PF_INET, SOCK_STREAM, 0);
if( sock < 0 ) {
@ -1358,7 +1376,7 @@ static void
New_Server( int Server )
{
/* Establish new server link */
struct sockaddr_in local_addr;
struct sockaddr_in new_addr;
struct in_addr inaddr;
int res, new_sock;
@ -1382,11 +1400,12 @@ New_Server( int Server )
return;
}
memset( &new_addr, 0, sizeof( new_addr ));
memset(&new_addr, 0, sizeof( new_addr ));
new_addr.sin_family = AF_INET;
new_addr.sin_addr = inaddr;
new_addr.sin_port = htons( Conf_Server[Server].port );
new_sock = socket( PF_INET, SOCK_STREAM, 0 );
if ( new_sock < 0 ) {
Log( LOG_CRIT, "Can't create socket: %s!", strerror( errno ));
@ -1395,6 +1414,12 @@ New_Server( int Server )
if( ! Init_Socket( new_sock )) return;
/* if we fail to bind, just continue and let connect() pick a source address */
InitSinaddr(&local_addr, 0);
local_addr.sin_addr = Conf_Server[Server].bind_addr;
if (bind(new_sock, (struct sockaddr *)&local_addr, (socklen_t)sizeof(local_addr)))
Log(LOG_WARNING, "Can't bind socket to %s!", Conf_ListenAddress, strerror( errno ));
res = connect(new_sock, (struct sockaddr *)&new_addr,
(socklen_t)sizeof(new_addr));
if(( res != 0 ) && ( errno != EINPROGRESS )) {
@ -1402,7 +1427,7 @@ New_Server( int Server )
close( new_sock );
return;
}
if (!array_alloc(&My_ConnArray, sizeof(CONNECTION), (size_t)new_sock)) {
Log(LOG_ALERT,
"Cannot allocate memory for server connection (socket %d)",

View File

@ -14,7 +14,7 @@
#include "portab.h"
static char UNUSED id[] = "$Id: tool.c,v 1.6 2006/04/09 12:53:07 alex Exp $";
static char UNUSED id[] = "$Id: tool.c,v 1.7 2007/11/23 16:26:05 fw Exp $";
#include "imp.h"
#include <assert.h>
@ -22,6 +22,11 @@ static char UNUSED id[] = "$Id: tool.c,v 1.6 2006/04/09 12:53:07 alex Exp $";
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#ifdef HAVE_ARPA_INET_H
# include <arpa/inet.h>
#endif
#include "exp.h"
#include "tool.h"
@ -105,4 +110,22 @@ ngt_TrimLastChr( char *String, const char Chr)
} /* ngt_TrimLastChr */
GLOBAL bool
ngt_IPStrToBin(const char *ip_str, struct in_addr *inaddr)
{
/* AF is always AF_INET for now */
#ifdef HAVE_INET_ATON
if (inet_aton(ip_str, inaddr) == 0)
return false;
#else
inaddr->s_addr = inet_addr(ip_str);
if (inaddr->s_addr == (unsigned)-1)
return false;
#endif
return true;
}
/* -eof- */

View File

@ -8,7 +8,7 @@
* (at your option) any later version.
* Please read the file COPYING, README and AUTHORS for more information.
*
* $Id: tool.h,v 1.3 2005/03/19 18:43:53 fw Exp $
* $Id: tool.h,v 1.4 2007/11/23 16:26:05 fw Exp $
*
* Tool functions (Header)
*/
@ -16,7 +16,7 @@
#ifndef __tool_h__
#define __tool_h__
#include "portab.h"
GLOBAL void ngt_TrimLastChr PARAMS((char *String, const char Chr ));
@ -24,7 +24,7 @@ GLOBAL void ngt_TrimStr PARAMS((char *String ));
GLOBAL char *ngt_LowerStr PARAMS((char *String ));
GLOBAL bool ngt_IPStrToBin PARAMS((const char *ip_str, struct in_addr *inaddr));
#endif