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 173
 static int is_tcp_main=0;
174 174
 
175 175
 int tcp_accept_aliases=0; /* by default don't accept aliases */
176
+/* flags used for adding new aliases */
177
+int tcp_alias_flags=TCP_ALIAS_FORCE_ADD;
178
+/* flags used for adding the default aliases of a new tcp connection */
179
+int tcp_new_conn_alias_flags=TCP_ALIAS_REPLACE;
176 180
 int tcp_connect_timeout=DEFAULT_TCP_CONNECT_TIMEOUT;
177 181
 int tcp_send_timeout=DEFAULT_TCP_SEND_TIMEOUT;
178 182
 int tcp_con_lifetime=DEFAULT_TCP_CONNECTION_LIFETIME;
... ...
@@ -209,7 +214,8 @@ static io_wait_h io_h;
209 209
 
210 210
 
211 211
 inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
212
-										struct ip_addr* l_ip, int l_port);
212
+										struct ip_addr* l_ip, int l_port,
213
+										int flags);
213 214
 
214 215
 
215 216
 
... ...
@@ -666,10 +672,12 @@ inline static struct tcp_connection*  tcpconn_add(struct tcp_connection *c)
666 666
 		 *  finding any conenction to peer_ip, peer_port from local_addr 
667 667
 		 * the third alias is for (peer_ip, peer_port, local_addr, local_port) 
668 668
 		 *   -- 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);
669
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &zero_ip, 0,
670
+													tcp_new_conn_alias_flags);
671
+		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip, 0,
672
+													tcp_new_conn_alias_flags);
671 673
 		_tcpconn_add_alias_unsafe(c, c->rcv.src_port, &c->rcv.dst_ip,
672
-														c->rcv.dst_port);
674
+									c->rcv.dst_port, tcp_new_conn_alias_flags);
673 675
 		/* ignore add_alias errors, there are some valid cases when one
674 676
 		 *  of the add_alias would fail (e.g. first add_alias for 2 connections
675 677
 		 *   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 809
 
810 810
 
811 811
 /* add c->dst:port, local_addr as an alias for the "id" connection, 
812
+ * flags: TCP_ALIAS_FORCE_ADD  - add an alias even if a previous one exists
813
+ *        TCP_ALIAS_REPLACE    - if a prev. alias exists, replace it with the
814
+ *                                new one
812 815
  * returns 0 on success, <0 on failure ( -1  - null c, -2 too many aliases,
813 816
  *  -3 alias already present and pointing to another connection)
814 817
  * WARNING: must be called with TCPCONN_LOCK held */
815 818
 inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
816
-										struct ip_addr* l_ip, int l_port)
819
+										struct ip_addr* l_ip, int l_port,
820
+										int flags)
817 821
 {
818 822
 	unsigned hash;
819 823
 	struct tcp_conn_alias* a;
824
+	struct tcp_conn_alias* nxt;
820 825
 	int is_local_ip_any;
821 826
 	
822 827
 	a=0;
... ...
@@ -824,7 +837,8 @@ inline static int _tcpconn_add_alias_unsafe(struct tcp_connection* c, int port,
824 824
 	if (c){
825 825
 		hash=tcp_addr_hash(&c->rcv.src_ip, port, l_ip, l_port);
826 826
 		/* search the aliases for an already existing one */
827
-		for (a=tcpconn_aliases_hash[hash]; a; a=a->next){
827
+		for (a=tcpconn_aliases_hash[hash], nxt=a?a->next:0; a;
828
+					a=nxt, nxt=a->next){
828 829
 			if ( (a->parent->state!=S_CONN_BAD) && (port==a->port) &&
829 830
 					( (l_port==0) || (l_port==a->parent->rcv.dst_port)) &&
830 831
 					(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 832
 					  ip_addr_cmp(&a->parent->rcv.dst_ip, l_ip))
833 833
 					){
834 834
 				/* found */
835
-				if (a->parent!=c) goto error_sec;
836
-				else goto ok;
835
+				if (a->parent!=c){
836
+					if (flags & TCP_ALIAS_FORCE_ADD)
837
+						/* still have to walk the whole list to check if
838
+						 * the alias was not already added */
839
+						continue;
840
+					else if (flags & TCP_ALIAS_REPLACE){
841
+						/* remove the current one */
842
+						tcpconn_listrm(tcpconn_aliases_hash[hash],
843
+														a, next, prev);
844
+						a->next=0;
845
+						a->prev=0;
846
+					}else
847
+						goto error_sec;
848
+				}else goto ok;
837 849
 			}
838 850
 		}
839 851
 		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 882
 		ip_addr_mk_any(c->rcv.src_ip.af, &zero_ip);
883 883
 		
884 884
 		/* alias src_ip:port, 0, 0 */
885
-		ret=_tcpconn_add_alias_unsafe(c, port,  &zero_ip, 0);
885
+		ret=_tcpconn_add_alias_unsafe(c, port,  &zero_ip, 0, 
886
+										tcp_alias_flags);
886 887
 		if (ret<0 && ret!=-3) goto error;
887 888
 		/* alias src_ip:port, local_ip, 0 */
888
-		ret=_tcpconn_add_alias_unsafe(c, port,  &c->rcv.dst_ip, 0);
889
+		ret=_tcpconn_add_alias_unsafe(c, port,  &c->rcv.dst_ip, 0, 
890
+										tcp_alias_flags);
889 891
 		if (ret<0 && ret!=-3) goto error;
890 892
 		/* 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);
893
+		ret=_tcpconn_add_alias_unsafe(c, port, &c->rcv.dst_ip, c->rcv.dst_port,
894
+										tcp_alias_flags);
893 895
 		if (ret<0) goto error;
894 896
 	}else goto error_not_found;
895 897
 	TCPCONN_UNLOCK;