repo: ngircd
action: commit
revision: 
path_from: 
revision_from: 684e50f0a4d827965b61c4b9feeda403ec3c3b87:
path_to: 
revision_to: 
git.thebackupbox.net
ngircd
git clone git://git.thebackupbox.net/ngircd
commit 684e50f0a4d827965b61c4b9feeda403ec3c3b87
Author: Alexander Barton 
Date:   Sat Jun 9 01:03:48 2012 +0200

    Correctly handle asynchronously re-established server links

    Don't try to establish an outgoing server link after DNS lookup when this
    server re-connected on its own in the meantime.
    In addition, log a warning message if we try to update the connection
    index of an already connected server structure -- and ignore it.

    Up to now, both behaviour could lead to a race when the remote server
    connects to this daemon while it still prepares the outgoing connection:

     - The local server prepares the new outgoing connection ...
     - in the meantime the remote server becomes connected and registered.
     - Now the new outgoing connection overwrites the (correct) socket handle,
     - then the 2nd connection becomes disconnected: "already registered",
     - and the 1st connection becomes unhandled ("gets lost") because the
       configuration structure is reset because of the wrong socket handle.

    This patch hopefully fixes all these problems.

diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c
index 54269009d1ee433bb537fa1c4ef140f34ea2cb57..
index ..f274eb826391dd3c0975383f77c48963a64ef4c1 100644
--- a/src/ngircd/conf.c
+++ b/src/ngircd/conf.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -492,6 +492,14 @@ Conf_SetServer( int ConfServer, CONN_ID Idx )
 	assert( ConfServer > NONE );
 	assert( Idx > NONE );

+	if (Conf_Server[ConfServer].conn_id > NONE &&
+	    Conf_Server[ConfServer].conn_id != Idx) {
+		Log(LOG_ALERT,
+			"Trying to update connection index for already registered server \"%s\": %d/%d - ignored.",
+			Conf_Server[ConfServer].name,
+			Conf_Server[ConfServer].conn_id, Idx);
+		return;
+	}
 	Conf_Server[ConfServer].conn_id = Idx;
 }

diff --git a/src/ngircd/conn.c b/src/ngircd/conn.c
index 09f726ca2bf91016d54a8d2b2c7c10029943fa68..
index ..06236fd43e2ab1269e91e1065efa11786da0ed40 100644
--- a/src/ngircd/conn.c
+++ b/src/ngircd/conn.c
@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2011 Alexander Barton (alex@barton.de) and Contributors.
+ * Copyright (c)2001-2012 Alexander Barton (alex@barton.de) and Contributors.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -1935,6 +1935,14 @@ New_Server( int Server , ng_ipaddr_t *dest)

 	assert( Server > NONE );

+	/* Make sure that the remote server hasn't re-linked to this server
+	 * asynchronously on its own */
+	if (Conf_Server[Server].conn_id > NONE) {
+		Log(LOG_INFO,
+			"Connection to \"%s\" meanwhile re-established, aborting preparation.");
+		return;
+	}
+
 	if (!ng_ipaddr_tostr_r(dest, ip_str)) {
 		Log(LOG_WARNING, "New_Server: Could not convert IP to string");
 		return;
@@ -2008,7 +2016,7 @@ New_Server( int Server , ng_ipaddr_t *dest)
 	Client_SetToken( c, TOKEN_OUTBOUND );

 	/* Register connection */
-	Conf_Server[Server].conn_id = new_sock;
+	Conf_SetServer(Server, new_sock);
 	My_Connections[new_sock].sock = new_sock;
 	My_Connections[new_sock].addr = *dest;
 	My_Connections[new_sock].client = c;

-----END OF PAGE-----