Browse code

- tcp add alias policy changes (experimental): now new aliases are added even if matching aliases for different connections exists. Until now an existing alias pointing to some other connection would trigger an error, the reason being that someone could try to "steal" a connection. However this turned out to affect also normal usage, like UAs behind nats that change the ip, or rebooted UAs (that didn't have a chance to close the tcp connection).

Andrei Pelinescu-Onciul authored on 05/09/2007 17:20:35
Showing 2 changed files
... ...
@@ -37,6 +37,13 @@ struct tcp_child{
37 37
 	int n_reqs; /* number of requests serviced so far */
38 38
 };
39 39
 
40
+#define TCP_ALIAS_FORCE_ADD 1
41
+#define TCP_ALIAS_REPLACE   2
42
+
43
+/* flags used for adding new aliases */
44
+extern int tcp_alias_flags;
45
+/* flags used for adding the default aliases of a new tcp connection */
46
+extern int tcp_new_conn_alias_flags;
40 47
 
41 48
 int init_tcp();
42 49
 void destroy_tcp();
... ...
@@ -145,6 +145,7 @@
145 145
 #include "io_wait.h"
146 146
 #include <fcntl.h> /* must be included after io_wait.h if SIGIO_RT is used */
147 147
 
148
+
148 149
 #define TCP_PASS_NEW_CONNECTION_ON_DATA /* don't pass a new connection
149 150
 										   immediately to a child, wait for
150 151
 										   some data on it first */
... ...
@@ -173,6 +174,10 @@ enum fd_types { F_NONE, F_SOCKINFO /* a tcp_listen fd */,
173 174
 static int is_tcp_main=0;
174 175
 
175 176
 int tcp_accept_aliases=0; /* by default don't accept aliases */
177
+/* flags used for adding new aliases */
178
+int tcp_alias_flags=TCP_ALIAS_FORCE_ADD;
179
+/* flags used for adding the default aliases of a new tcp connection */
180
+int tcp_new_conn_alias_flags=TCP_ALIAS_REPLACE;
176 181
 int tcp_connect_timeout=DEFAULT_TCP_CONNECT_TIMEOUT;
177 182
 int tcp_send_timeout=DEFAULT_TCP_SEND_TIMEOUT;
178 183
 int tcp_con_lifetime=DEFAULT_TCP_CONNECTION_LIFETIME;
... ...
@@ -209,7 +214,8 @@ static io_wait_h io_h;
209 214
 
210 215
 
211 216
 inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
212
-										struct ip_addr* l_ip, int l_port);
217
+										struct ip_addr* l_ip, int l_port,
218
+										int flags);
213 219
 
214 220
 
215 221
 
... ...
@@ -666,10 +672,12 @@ inline static struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
666 672
 		 *  finding any conenction to peer_ip, peer_port from local_addr 
667 673
 		 * the third alias is for (peer_ip, peer_port, local_addr, local_port) 
668 674
 		 *   -- for finding if a fully specified connection exists */
669
-		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &zero_ip, 0);
670
-		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0);
675
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &zero_ip, 0,
676
+													tcp_new_conn_alias_flags);
677
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0,
678
+													tcp_new_conn_alias_flags);
671 679
 		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
672
-														c->rcv.dst_port);
680
+									c->rcv.dst_port, tcp_new_conn_alias_flags);
673 681
 		/* ignore add_alias errors, there are some valid cases when one
674 682
 		 *  of the add_alias would fail (e.g. first add_alias for 2 connections
675 683
 		 *   with the same destination but different src. ip*/
... ...
@@ -809,14 +817,19 @@ struct tcp_connection* tcpconn_get(int id, struct ip_addr* ip, int port,
809 817
 
810 818
 
811 819
 /* add c->dst:port, local_addr as an alias for the "id" connection, 
820
+ * flags: TCP_ALIAS_FORCE_ADD  - add an alias even if a previous one exists
821
+ *        TCP_ALIAS_REPLACE    - if a prev. alias exists, replace it with the
822
+ *                                new one
812 823
  * returns 0 on success, <0 on failure ( -1  - null c, -2 too many aliases,
813 824
  *  -3 alias already present and pointing to another connection)
814 825
  * WARNING: must be called with TCPCONN_LOCK held */
815 826
 inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
816
-										struct ip_addr* l_ip, int l_port)
827
+										struct ip_addr* l_ip, int l_port,
828
+										int flags)
817 829
 {
818 830
 	unsigned hash;
819 831
 	struct tcp_conn_alias* a;
832
+	struct tcp_conn_alias* nxt;
820 833
 	int is_local_ip_any;
821 834
 	
822 835
 	a=0;
... ...
@@ -824,7 +837,8 @@ inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
824 837
 	if (c){
825 838
 		hash=tcp_addr_hash(&c->rcv.src_ip, port, l_ip, l_port);
826 839
 		/* search the aliases for an already existing one */
827
-		for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
840
+		for (a=tcpconn_aliases_hash[hash], nxt=a?a->next:0; a;
841
+					a=nxt, nxt=a->next){
828 842
 			if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
829 843
 					( (l_port==0) || (l_port==a->parent->rcv.dst_port)) &&
830 844
 					(ip_addr_cmp(&c->rcv.src_ip, &a->parent->rcv.src_ip)) &&
... ...
@@ -832,8 +846,20 @@ inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
832 846
 					  ip_addr_cmp(&a->parent->rcv.dst_ip, l_ip))
833 847
 					){
834 848
 				/* found */
835
-				if (a->parent!=c) goto error_sec;
836
-				else goto ok;
849
+				if (a->parent!=c){
850
+					if (flags & TCP_ALIAS_FORCE_ADD)
851
+						/* still have to walk the whole list to check if
852
+						 * the alias was not already added */
853
+						continue;
854
+					else if (flags & TCP_ALIAS_REPLACE){
855
+						/* remove the current one */
856
+						tcpconn_listrm(tcpconn_aliases_hash[hash],
857
+														a, next, prev);
858
+						a->next=0;
859
+						a->prev=0;
860
+					}else
861
+						goto error_sec;
862
+				}else goto ok;
837 863
 			}
838 864
 		}
839 865
 		if (c->aliases>=TCP_CON_MAX_ALIASES) goto error_aliases;
... ...
@@ -882,14 +908,16 @@ int tcpconn_add_alias(int id, int port, int proto)
882 908
 		ip_addr_mk_any(c->rcv.src_ip.af, &zero_ip);
883 909
 		
884 910
 		/* alias src_ip:port, 0, 0 */
885
-		ret=_tcpconn_add_alias_unsafe(c, port,  &zero_ip, 0);
911
+		ret=_tcpconn_add_alias_unsafe(c, port,  &zero_ip, 0, 
912
+										tcp_alias_flags);
886 913
 		if (ret<0 && ret!=-3) goto error;
887 914
 		/* alias src_ip:port, local_ip, 0 */
888
-		ret=_tcpconn_add_alias_unsafe(c, port,  &c->rcv.dst_ip, 0);
915
+		ret=_tcpconn_add_alias_unsafe(c, port,  &c->rcv.dst_ip, 0, 
916
+										tcp_alias_flags);
889 917
 		if (ret<0 && ret!=-3) goto error;
890 918
 		/* alias src_ip:port, local_ip, local_port */
891
-		ret=_tcpconn_add_alias_unsafe(c, port,  &c->rcv.dst_ip,
892
-															c->rcv.dst_port);
919
+		ret=_tcpconn_add_alias_unsafe(c, port, &c->rcv.dst_ip, c->rcv.dst_port,
920
+										tcp_alias_flags);
893 921
 		if (ret<0) goto error;
894 922
 	}else goto error_not_found;
895 923
 	TCPCONN_UNLOCK;