Browse Source

- removed msg->repl_add_rm (msg->add_rm is used now both for replies & requests)
- tcp code now always tries to add bind address info even for temporary "sending" sockets (it tries to find first match in the listening sockets list)
- new lump function: insert_subst_lump_after, insert_subst_lump_before
(you can add now lumps that will be substituted with the rcv/sending ip addr,
port or proto: see SUBST_{SND,RCV}_{IP,PORT,PROTO})

Andrei Pelinescu-Onciul 22 năm trước cách đây
mục cha
commit
f15bede127
8 tập tin đã thay đổi với 334 bổ sung35 xóa
  1. 1 1
      Makefile.defs
  2. 2 0
      TODO
  3. 53 1
      data_lump.c
  4. 17 3
      data_lump.h
  5. 212 18
      msg_translator.c
  6. 4 4
      parser/msg_parser.c
  7. 6 6
      parser/msg_parser.h
  8. 39 2
      tcp_main.c

+ 1 - 1
Makefile.defs

@@ -18,7 +18,7 @@
 VERSION = 0
 PATCHLEVEL = 8
 SUBLEVEL =   11
-EXTRAVERSION = pre8-mem
+EXTRAVERSION = pre9-repl_add_rm
 
 RELEASE=$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(EXTRAVERSION)
 OS = $(shell uname -s | sed -e s/SunOS/solaris/ | tr "[A-Z]" "[a-z]")

+ 2 - 0
TODO

@@ -16,6 +16,8 @@ x (different way) add request header bitmap field for the modules
 - ? variable number of params functions in script (no longer limited to 2)?
 - kill bind_idx
 - fix bind_address for tcp (in some  way)
+- add conflict in debs/rpms/etc (conflict w/ older ser-mysql, ser-jabber)
+- new packages ser-radius etc
 
 
 High priority:

+ 53 - 1
data_lump.c

@@ -26,7 +26,8 @@
  *
  * History:
  * --------
- * 2003-01-19 support for duplication lump lists added (jiri)
+ *  2003-01-19  support for duplication lump lists added (jiri)
+ *  2003-03-31  added subst lumps -- they expand in ip addr, port a.s.o (andrei)
  */
 
 
@@ -149,6 +150,57 @@ struct lump* insert_new_lump_before( struct lump* before, char* new_hdr,
 
 
 
+/* inserts a  subst lump immediately after hdr 
+ * returns pointer on success, 0 on error */
+struct lump* insert_subst_lump_after( struct lump* after, enum lump_subst subst,
+										int type)
+{
+	struct lump* tmp;
+
+	tmp=pkg_malloc(sizeof(struct lump));
+	if (tmp==0){
+		ser_error=E_OUT_OF_MEM;
+		LOG(L_ERR, "ERROR: insert_new_lump_after: out of memory\n");
+		return 0;
+	}
+	memset(tmp,0,sizeof(struct lump));
+	tmp->after=after->after;
+	tmp->type=type;
+	tmp->op=LUMP_ADD_SUBST;
+	tmp->u.subst=subst;
+	tmp->len=0;
+	after->after=tmp;
+	return tmp;
+}
+
+
+
+/* inserts a  subst lump immediately before "before" 
+ * returns pointer on success, 0 on error */
+struct lump* insert_subst_lump_before(	struct lump* before, 
+										enum lump_subst subst,
+										int type)
+{
+	struct lump* tmp;
+
+	tmp=pkg_malloc(sizeof(struct lump));
+	if (tmp==0){
+		ser_error=E_OUT_OF_MEM;
+		LOG(L_ERR,"ERROR: insert_new_lump_before: out of memory\n");
+		return 0;
+	}
+	memset(tmp,0,sizeof(struct lump));
+	tmp->before=before->before;
+	tmp->type=type;
+	tmp->op=LUMP_ADD_SUBST;
+	tmp->u.subst=subst;
+	tmp->len=0;
+	before->before=tmp;
+	return tmp;
+}
+
+
+
 /* removes an already existing header/data lump */
 struct lump* del_lump(struct lump** list, int offset, int len, int type)
 {

+ 17 - 3
data_lump.h

@@ -25,8 +25,11 @@
  * You should have received a copy of the GNU General Public License 
  * along with this program; if not, write to the Free Software 
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
- * 2003-01-29 s/int/enum ... more convenient for gdb (jiri)
+ */
+/* History:
+ * --------
+ *  2003-01-29  s/int/enum ... more convenient for gdb (jiri)
+ *  2003-03-31  added subst lumps -- they expand in ip addr, port a.s.o (andrei)
  */
 
 
@@ -34,7 +37,12 @@
 #define data_lump_h
 
 
-enum lump_op { LUMP_NOP=0, LUMP_DEL, LUMP_ADD };
+enum lump_op { LUMP_NOP=0, LUMP_DEL, LUMP_ADD, LUMP_ADD_SUBST };
+enum lump_subst{ SUBST_NOP=0,
+				 SUBST_RCV_IP,    SUBST_SND_IP,
+				 SUBST_RCV_PORT,  SUBST_SND_PORT,
+				 SUBST_RCV_PROTO, SUBST_SND_PROTO
+				};
 enum lump_flag { LUMPFLAG_NONE=0, LUMPFLAG_DUPED=1, LUMPFLAG_SHMEM=2 };
 
 struct lump{
@@ -43,6 +51,7 @@ struct lump{
 	
 	union{
 		int offset; /* used for DEL, MODIFY */
+		enum lump_subst subst; /*what to subst: ip addr, port, proto*/
 		char * value; /* used for ADD */
 	}u;
 	int len; /* length of this header field */
@@ -89,6 +98,11 @@ struct lump* insert_new_lump_after(struct lump* after,
 									char* new_hdr, int len, int type);
 struct lump* insert_new_lump_before(struct lump* before, char* new_hdr,
 									int len,int type);
+/* substitutions (replace with ip address, port etc) */
+struct lump* insert_subst_lump_after(struct lump* after,  enum lump_subst subst,
+									int type);
+struct lump* insert_subst_lump_before(struct lump* before,enum lump_subst subst,
+									int type);
 
 
 /* removes an already existing header */

+ 212 - 18
msg_translator.c

@@ -42,6 +42,7 @@
  * 2003-01-27  more rport fixes (make use of new via_param->start)  (andrei)
  * 2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
  * 2003-01-29  scratchpad removed (jiri)
+ * 2003-03-31  added subst lump support (andrei)
  *
  */
 
@@ -357,24 +358,89 @@ char* clen_builder(struct sip_msg* msg, unsigned int *clen_len)
 
 /* computes the "unpacked" len of a lump list,
    code moved from build_req_from_req */
-static inline int lumps_len(struct lump* l)
+static inline int lumps_len(struct sip_msg* msg, struct socket_info* send_sock)
 {
 	int s_offset;
 	int new_len;
 	struct lump* t;
 	struct lump* r;
 
+#define SUBST_LUMP_LEN(subst_l) \
+		switch((subst_l)->u.subst){ \
+			case SUBST_RCV_IP: \
+				if (msg->rcv.bind_address){ \
+					new_len+=msg->rcv.bind_address->address_str.len; \
+					if (msg->rcv.bind_address->address.af!=AF_INET) \
+						new_len+=2; \
+				}else{ \
+					/* FIXME */ \
+					LOG(L_CRIT, "FIXME: null bind_address\n"); \
+				}; \
+				break; \
+			case SUBST_RCV_PORT: \
+				if (msg->rcv.bind_address){ \
+					new_len+=msg->rcv.bind_address->port_no_str.len; \
+				}else{ \
+					/* FIXME */ \
+					LOG(L_CRIT, "FIXME: null bind_address\n"); \
+				}; \
+				break; \
+			case SUBST_RCV_PROTO: \
+				if (msg->rcv.bind_address){ \
+					new_len+=send_sock->port_no_str.len; \
+				}else{ \
+					/* FIXME */ \
+					LOG(L_CRIT, "FIXME: null bind_address\n"); \
+				}; \
+				break; \
+			case SUBST_SND_IP: \
+				if (send_sock){ \
+					new_len+=send_sock->address_str.len; \
+					if (send_sock->address.af!=AF_INET) \
+						new_len+=2; \
+				}else{ \
+					LOG(L_CRIT, "FIXME: lumps_len called with" \
+							" null send_sock\n"); \
+				}; \
+				break; \
+			case SUBST_SND_PORT: \
+				if (send_sock){ \
+					new_len+=send_sock->port_no_str.len; \
+				}else{ \
+					LOG(L_CRIT, "FIXME: lumps_len called with" \
+							" null send_sock\n"); \
+				}; \
+				break; \
+			case SUBST_SND_PROTO: \
+				if (send_sock){ \
+					new_len+=3; /* tcp, udp or tls*/ \
+				}else{ \
+					LOG(L_CRIT, "FIXME: lumps_len called with" \
+							" null send_sock\n"); \
+				}; \
+				break; \
+			case SUBST_NOP: /* do nothing */ \
+				break; \
+			default: \
+				LOG(L_CRIT, "BUG: unknown subst type %d\n", \
+						(subst_l)->u.subst); \
+		}
+	
 	s_offset=0;
 	new_len=0;
-	for(t=l;t;t=t->next){
+	
+	for(t=msg->add_rm;t;t=t->next){
 		for(r=t->before;r;r=r->before){
 			switch(r->op){
 				case LUMP_ADD:
 					new_len+=r->len;
 					break;
+				case LUMP_ADD_SUBST:
+					SUBST_LUMP_LEN(r);
+					break;
 				default:
 					/* only ADD allowed for before/after */
-					LOG(L_CRIT, "BUG: lumps_len: invalid op "
+						LOG(L_CRIT, "BUG: lumps_len: invalid op "
 							"for data lump (%x)\n", r->op);
 			}
 		}
@@ -382,6 +448,9 @@ static inline int lumps_len(struct lump* l)
 			case LUMP_ADD:
 				new_len+=t->len;
 				break;
+			case LUMP_ADD_SUBST:
+				SUBST_LUMP_LEN(t);
+				break;
 			case LUMP_DEL:
 				/* fix overlapping deleted zones */
 				if (t->u.offset < s_offset){
@@ -411,6 +480,9 @@ static inline int lumps_len(struct lump* l)
 				case LUMP_ADD:
 					new_len+=r->len;
 					break;
+				case LUMP_ADD_SUBST:
+					SUBST_LUMP_LEN(r);
+					break;
 				default:
 					/* only ADD allowed for before/after */
 					LOG(L_CRIT, "BUG:lumps_len: invalid"
@@ -426,22 +498,130 @@ static inline int lumps_len(struct lump* l)
 /* another helper functions, adds/Removes the lump,
 	code moved form build_req_from_req  */
 
-static inline void process_lumps(	struct lump* l,	char* new_buf, 
-									unsigned int* new_buf_offs, char* orig,
-									unsigned int* orig_offs)
+static inline void process_lumps(	struct sip_msg* msg,	
+									char* new_buf, 
+									unsigned int* new_buf_offs, 
+									unsigned int* orig_offs,
+									struct socket_info* send_sock)
 {
 	struct lump *t;
 	struct lump *r;
+	char* orig;
 	int size;
 	int offset;
 	int s_offset;
+
+#define SUBST_LUMP(subst_l) \
+	switch((subst_l)->u.subst){ \
+		case SUBST_RCV_IP: \
+			if (msg->rcv.bind_address){  \
+				memcpy(new_buf+offset, msg->rcv.bind_address->address_str.s, \
+						msg->rcv.bind_address->address_str.len); \
+				offset+=msg->rcv.bind_address->address_str.len; \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
+			}; \
+			break; \
+		case SUBST_RCV_PORT: \
+			if (msg->rcv.bind_address){  \
+				memcpy(new_buf+offset, msg->rcv.bind_address->port_no_str.s, \
+						msg->rcv.bind_address->port_no_str.len); \
+				offset+=msg->rcv.bind_address->port_no_str.len; \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process_lumps: null bind_address\n"); \
+			}; \
+			break; \
+		case SUBST_SND_IP: \
+			if (send_sock){  \
+				memcpy(new_buf+offset, send_sock->address_str.s, \
+									send_sock->address_str.len); \
+				offset+=send_sock->address_str.len; \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process_lumps: called with" \
+							" null send_sock\n"); \
+			}; \
+			break; \
+		case SUBST_SND_PORT: \
+			if (send_sock){  \
+				memcpy(new_buf+offset, send_sock->port_no_str.s, \
+									send_sock->port_no_str.len); \
+				offset+=send_sock->port_no_str.len; \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process_lumps: called with" \
+						" null send_sock\n"); \
+			}; \
+			break; \
+		case SUBST_RCV_PROTO: \
+			if (msg->rcv.bind_address){ \
+				switch(msg->rcv.bind_address->proto){ \
+					case PROTO_NONE: \
+					case PROTO_UDP: \
+						memcpy(new_buf+offset, "udp", 3); \
+						offset+=3; \
+						break; \
+					case PROTO_TCP: \
+						memcpy(new_buf+offset, "tcp", 3); \
+						offset+=3; \
+						break; \
+					case PROTO_TLS: \
+						memcpy(new_buf+offset, "tls", 3); \
+						offset+=3; \
+						break; \
+					default: \
+						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
+								msg->rcv.bind_address->proto); \
+				} \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process lumps: null bind_address\n"); \
+			}; \
+			break; \
+		case  SUBST_SND_PROTO: \
+			if (send_sock){ \
+				switch(send_sock->proto){ \
+					case PROTO_NONE: \
+					case PROTO_UDP: \
+						memcpy(new_buf+offset, "udp", 3); \
+						offset+=3; \
+						break; \
+					case PROTO_TCP: \
+						memcpy(new_buf+offset, "tcp", 3); \
+						offset+=3; \
+						break; \
+					case PROTO_TLS: \
+						memcpy(new_buf+offset, "tls", 3); \
+						offset+=3; \
+						break; \
+					default: \
+						LOG(L_CRIT, "BUG: process_lumps: unknown proto %d\n", \
+								send_sock->proto); \
+				} \
+			}else{  \
+				/*FIXME*/ \
+				LOG(L_CRIT, "FIXME: process_lumps: called with null" \
+							" send_sock \n"); \
+			}; \
+			break; \
+		default: \
+					LOG(L_CRIT, "BUG: process_lumps: unknown subst type %d\n", \
+							(subst_l)->u.subst); \
+	} \
+ \
+	
+	
 	
+	orig=msg->buf;
 	offset=*new_buf_offs;
 	s_offset=*orig_offs;
 	
-	for (t=l;t;t=t->next){
+	for (t=msg->add_rm;t;t=t->next){
 		switch(t->op){
 			case LUMP_ADD:
+			case LUMP_ADD_SUBST:
 				/* just add it here! */
 				/* process before  */
 				for(r=t->before;r;r=r->before){
@@ -451,6 +631,9 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 							memcpy(new_buf+offset, r->u.value, r->len);
 							offset+=r->len;
 							break;
+						case LUMP_ADD_SUBST:
+							SUBST_LUMP(r);
+							break;
 						default:
 							/* only ADD allowed for before/after */
 							LOG(L_CRIT, "BUG:process_lumps: "
@@ -458,8 +641,12 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 					}
 				}
 				/* copy "main" part */
-				memcpy(new_buf+offset, t->u.value, t->len);
-				offset+=t->len;
+				if(t->op==LUMP_ADD){
+					memcpy(new_buf+offset, t->u.value, t->len);
+					offset+=t->len;
+				}else{
+					SUBST_LUMP(t);
+				}
 				/* process after */
 				for(r=t->after;r;r=r->after){
 					switch (r->op){
@@ -468,6 +655,9 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 							memcpy(new_buf+offset, r->u.value, r->len);
 							offset+=r->len;
 							break;
+						case LUMP_ADD_SUBST:
+							SUBST_LUMP(r);
+							break;
 						default:
 							/* only ADD allowed for before/after */
 							LOG(L_CRIT, "BUG:process_lumps: "
@@ -499,6 +689,9 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 							memcpy(new_buf+offset, r->u.value, r->len);
 							offset+=r->len;
 							break;
+						case LUMP_ADD_SUBST:
+							SUBST_LUMP(r);
+							break;
 						default:
 							/* only ADD allowed for before/after */
 							LOG(L_CRIT, "BUG:process_lumps: "
@@ -518,6 +711,9 @@ static inline void process_lumps(	struct lump* l,	char* new_buf,
 							memcpy(new_buf+offset, r->u.value, r->len);
 							offset+=r->len;
 							break;
+						case LUMP_ADD_SUBST:
+							SUBST_LUMP(r);
+							break;
 						default:
 							/* only ADD allowed for before/after */
 							LOG(L_CRIT, "BUG:process_lumps: "
@@ -686,7 +882,7 @@ skip_clen:
 #endif
 
 	/* compute new msg len and fix overlapping zones*/
-	new_len=len+lumps_len(msg->add_rm);
+	new_len=len+lumps_len(msg, send_sock);
 
 	if (msg->new_uri.s){
 		uri_len=msg->new_uri.len;
@@ -713,7 +909,7 @@ skip_clen:
 	}
 	new_buf[new_len]=0;
 	/* copy msg adding/removing lumps */
-	process_lumps(msg->add_rm, new_buf, &offset, buf, &s_offset);
+	process_lumps(msg, new_buf, &offset, &s_offset, send_sock);
 	/* copy the rest of the message */
 	memcpy(new_buf+offset, buf+s_offset, len-s_offset);
 	new_buf[new_len]=0;
@@ -802,7 +998,7 @@ skip_clen:
 #endif
 	
 	/* remove the first via*/
-	if (del_lump( &(msg->repl_add_rm), via_offset, via_len, HDR_VIA)==0){
+	if (del_lump( &(msg->add_rm), via_offset, via_len, HDR_VIA)==0){
 		LOG(L_ERR, "build_res_buf_from_sip_res: error trying to remove first"
 					"via\n");
 		goto error;
@@ -812,7 +1008,7 @@ skip_clen:
 	if (clen_len){
 		/* msg->unparsed should point just before the final crlf,
 		 * parse_headers is called from clen_builder */
-		anchor=anchor_lump(&(msg->repl_add_rm), msg->unparsed-buf, 0, 
+		anchor=anchor_lump(&(msg->add_rm), msg->unparsed-buf, 0, 
 							HDR_CONTENTLENGTH);
 		DBG("build_res_from_sip_res: adding content-length: %.*s\n",
 				(int)clen_len, clen_buf);
@@ -822,8 +1018,8 @@ skip_clen:
 			goto error_clen; /* free clen_buf*/
 	}
 #endif
-	new_len=len+lumps_len(msg->repl_add_rm);
-
+	new_len=len+lumps_len(msg, 0); /*FIXME: we don't know the send sock */
+	
 	DBG(" old size: %d, new size: %d\n", len, new_len);
 	new_buf=(char*)pkg_malloc(new_len+1); /* +1 is for debugging 
 											 (\0 to print it )*/
@@ -833,9 +1029,7 @@ skip_clen:
 	}
 	new_buf[new_len]=0; /* debug: print the message */
 	offset=s_offset=0;
-	process_lumps(msg->repl_add_rm, new_buf, &offset, 
-		buf,
-		&s_offset);
+	process_lumps(msg, new_buf, &offset, &s_offset, 0); /*FIXME: no send sock*/
 	/* copy the rest of the message */
 	memcpy(new_buf+offset,
 		buf+s_offset, 

+ 4 - 4
parser/msg_parser.c

@@ -29,9 +29,10 @@
  *
  * History:
  * ---------
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-29 scrathcpad removed (jiri)
- * 2003-01-27 next baby-step to removing ZT - PRESERVE_ZT (jiri)
+ *  2003-02-28  scratchpad compatibility abandoned (jiri)
+ *  2003-01-29  scrathcpad removed (jiri)
+ *  2003-01-27  next baby-step to removing ZT - PRESERVE_ZT (jiri)
+ *  2003-03-31  removed msg->repl_add_rm (andrei)
  */
 
 
@@ -553,7 +554,6 @@ void free_sip_msg(struct sip_msg* msg)
 	if (msg->new_uri.s) { pkg_free(msg->new_uri.s); msg->new_uri.len=0; }
 	if (msg->headers)     free_hdr_field_lst(msg->headers);
 	if (msg->add_rm)      free_lump_list(msg->add_rm);
-	if (msg->repl_add_rm) free_lump_list(msg->repl_add_rm);
 	if (msg->reply_lump)   free_reply_lump(msg->reply_lump);
 	/* don't free anymore -- now a pointer to a static buffer */
 #	ifdef DYN_BUF

+ 6 - 6
parser/msg_parser.h

@@ -26,10 +26,11 @@
  *
  * History
  * -------
- * 2003-03-06 enum_request_method changed to begin with 1;
- *            0 reserved for invalid values; (jiri)
- * 2003-02-28 scratchpad compatibility abandoned (jiri)
- * 2003-01-28 removed scratchpad (jiri)
+ *  2003-03-06  enum_request_method changed to begin with 1;
+ *             0 reserved for invalid values; (jiri)
+ *  2003-02-28  scratchpad compatibility abandoned (jiri)
+ *  2003-01-28  removed scratchpad (jiri)
+ *  2003-03-31  removed sip_msg->repl_add_rm (andrei)
  */
 
 
@@ -141,8 +142,7 @@ struct sip_msg {
 	int parsed_uri_ok; /* 1 if parsed_uri is valid, 0 if not */
 	struct sip_uri parsed_uri; /* speed-up > keep here the parsed uri*/
 	
-	struct lump* add_rm;         /* used for all the forwarded requests */
-	struct lump* repl_add_rm;    /* used for all the forwarded replies */
+	struct lump* add_rm;       /* used for all the forwarded requests/replies */
 	struct lump_rpl *reply_lump; /* only for localy generated replies !!!*/
 
 	/* str add_to_branch; 

+ 39 - 2
tcp_main.c

@@ -34,7 +34,10 @@
  *  2003-02-25  Nagle is disabled if -DDISABLE_NAGLE (andrei)
  *  2003-03-29  SO_REUSEADDR before calling bind to allow
  *              server restart, Nagle set on the (hopefuly) 
- *              correct socket
+ *              correct socket (jiri)
+ *  2003-03-31  always try to find the corresponding tcp listen socket for
+ *               a temp. socket and store in in *->bind_address: added
+ *               find_tcp_si, modified tcpconn_connect (andrei)
  */
 
 
@@ -149,9 +152,28 @@ error:
 
 
 
+
+struct socket_info* find_tcp_si(union sockaddr_union* s)
+{
+	int r;
+	struct ip_addr ip;
+	
+	su2ip_addr(&ip, s);
+	for (r=0; r<sock_no; r++)
+		if (ip_addr_cmp(&ip, &tcp_info[r].address)){
+			/* found it, we use first match */
+			return &tcp_info[r];
+		}
+	return 0; /* no match */
+}
+
+
 struct tcp_connection* tcpconn_connect(union sockaddr_union* server)
 {
 	int s;
+	struct socket_info* si;
+	union sockaddr_union my_name;
+	int my_name_len;
 #ifdef DISABLE_NAGLE
 	int flag;
 #endif
@@ -179,7 +201,22 @@ struct tcp_connection* tcpconn_connect(union sockaddr_union* server)
 				errno, strerror(errno));
 		goto error;
 	}
-	return tcpconn_new(s, server, 0); /*FIXME: set sock idx! */
+	my_name_len=sizeof(my_name);
+	if (getsockname(s, &my_name.s, &my_name_len)!=0){
+		LOG(L_ERR, "ERROR: tcp_connect: getsockname failed: %s(%d)\n",
+				strerror(errno), errno);
+		si=0; /* try to go on */
+	}
+	si=find_tcp_si(&my_name);
+	if (si==0){
+		LOG(L_ERR, "ERROR: tcp_connect: could not find coresponding"
+				" listening socket, using default...\n");
+		if (server->s.sa_family==AF_INET) si=sendipv4_tcp;
+#ifdef USE_IPV6
+		else si=sendipv6_tcp;
+#endif
+	}
+	return tcpconn_new(s, server, si); /*FIXME: set sock idx! */
 error:
 	return 0;
 }