summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorFlorian Westphal <fw@strlen.de>2007-11-23 16:26:03 +0000
committerFlorian Westphal <fw@strlen.de>2007-11-23 16:26:03 +0000
commit82d32ffb28262b302fb435739e4c81bd3c1a1b85 (patch)
tree2949b21f9691c7f3bd5718a5dd20341a83a555ce /src
parent024588dbe72e25b49439602670be7d8164183a74 (diff)
downloadngircd-82d32ffb28262b302fb435739e4c81bd3c1a1b85.tar.gz
ngircd-82d32ffb28262b302fb435739e4c81bd3c1a1b85.zip
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.
Diffstat (limited to 'src')
-rw-r--r--src/ngircd/conf.c11
-rw-r--r--src/ngircd/conf.h3
-rw-r--r--src/ngircd/conn.c73
-rw-r--r--src/tool/tool.c25
-rw-r--r--src/tool/tool.h6
5 files changed, 88 insertions, 30 deletions
diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c
index c55aaf53..7ca5567d 100644
--- a/src/ngircd/conf.c
+++ b/src/ngircd/conf.c
@@ -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 */
 
 
diff --git a/src/ngircd/conf.h b/src/ngircd/conf.h
index 371f94db..9e152266 100644
--- a/src/ngircd/conf.h
+++ b/src/ngircd/conf.h
@@ -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
diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index 95ed3088..07c80783 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -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)",
diff --git a/src/tool/tool.c b/src/tool/tool.c
index 01d892fd..dc238451 100644
--- a/src/tool/tool.c
+++ b/src/tool/tool.c
@@ -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- */
diff --git a/src/tool/tool.h b/src/tool/tool.h
index 5b386e59..bdd846f7 100644
--- a/src/tool/tool.h
+++ b/src/tool/tool.h
@@ -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