Переглянути джерело

- myself matches now also the uri port
- modified check_self, add_alias & grep_alias to accept port numbers
- added loopback check
- modified get_send_socket to return the first non loopback ipv4 interface if
bind_address==0

Andrei Pelinescu-Onciul 23 роки тому
батько
коміт
1baa06b5df
11 змінених файлів з 94 додано та 67 видалено
  1. 1 14
      action.c
  2. 2 2
      cfg.y
  3. 12 8
      forward.c
  4. 1 1
      forward.h
  5. 1 0
      ip_addr.h
  6. 47 32
      main.c
  7. 9 5
      name_alias.h
  8. 1 0
      parser/msg_parser.h
  9. 10 1
      parser/parse_uri.c
  10. 8 4
      route.c
  11. 2 0
      test/test-throughput.cfg

+ 1 - 14
action.c

@@ -71,7 +71,6 @@ int do_action(struct action* a, struct sip_msg* msg)
 	char *new_uri, *end, *crt;
 	int len;
 	int user;
-	int err;
 	struct sip_uri uri;
 	struct sip_uri* u;
 	unsigned short port;
@@ -100,19 +99,7 @@ int do_action(struct action* a, struct sip_msg* msg)
 				u=&msg->parsed_uri;
 				switch (a->p2_type){
 					case URIPORT_ST:
-									if (u->port.s){
-									 /*port=strtol(uri.port.s,&end,10);*/
-										port=str2s((unsigned char*)u->port.s,
-													u->port.len, &err);
-										/*if ((end)&&(*end)){*/
-										if (err){
-											LOG(L_ERR, "ERROR: do_action: "
-												"forward: bad port in "
-												"uri: <%s>\n", u->port.s);
-											ret=E_BAD_URI;
-											goto error_fwd_uri;
-										}
-									}else port=0;
+									port=u->port_no;
 									break;
 					case NUMBER_ST:
 									port=a->p2.number;

+ 2 - 2
cfg.y

@@ -315,8 +315,8 @@ assign_stm:	DEBUG EQUAL NUMBER { debug=$3; }
 		| LISTEN EQUAL  error { yyerror("ip address or hostname"
 						"expected"); }
 		| ALIAS EQUAL  id_lst { 
-								for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next)
-									add_alias(lst_tmp->s, strlen(lst_tmp->s));
+							for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next)
+								add_alias(lst_tmp->s, strlen(lst_tmp->s), 0);
 							  }
 		| ALIAS  EQUAL error  { yyerror(" hostname expected"); }
 		| error EQUAL { yyerror("unknown config variable"); }

+ 12 - 8
forward.c

@@ -70,7 +70,7 @@ struct socket_info* get_send_socket(union sockaddr_union* to)
 	send_sock=0;
 	/* check if we need to change the socket (different address families -
 	 * eg: ipv4 -> ipv6 or ipv6 -> ipv4) */
-	if (to->s.sa_family!=bind_address->address.af){
+	if ((bind_address==0) ||(to->s.sa_family!=bind_address->address.af)){
 		switch(to->s.sa_family){
 			case AF_INET:	send_sock=sendipv4;
 							break;
@@ -87,10 +87,11 @@ struct socket_info* get_send_socket(union sockaddr_union* to)
 
 
 
-/* checks if the host is one of the address we listen on
-* returns 1 if true, 0 if false, -1 on error
+/* checks if the host:port is one of the address we listen on;
+ * if port==0, the  port number is ignored
+ * returns 1 if true, 0 if false, -1 on error
 */
-int check_self(str* host)
+int check_self(str* host, unsigned short port)
 {
 	int r;
 	
@@ -102,6 +103,7 @@ int check_self(str* host)
 					host->len, host->s,
 					sock_info[r].name.len, sock_info[r].name.s
 			);
+		if  ((port)&&(sock_info[r].port_no!=port)) continue;
 		if ( (host->len==sock_info[r].name.len) && 
 	#ifdef USE_IPV6
 			(strncasecmp(host->s, sock_info[r].name.s,
@@ -127,7 +129,7 @@ int check_self(str* host)
 	}
 	if (r==sock_no){
 		/* try to look into the aliases*/
-		if (grep_aliases(host->s, host->len)==0){
+		if (grep_aliases(host->s, host->len, port)==0){
 			DBG("check_self: host != me\n");
 			return 0;
 		}
@@ -312,9 +314,11 @@ int forward_reply(struct sip_msg* msg)
 	new_buf=0;
 	/*check if first via host = us */
 	if (check_via){
-		if (check_self(&(msg->via1->host))!=1){
+		if (check_self(&msg->via1->host,
+					msg->via1->port?msg->via1->port:SIP_PORT)!=1){
 			LOG(L_NOTICE, "ERROR: forward_reply: host in first via!=me :"
-					" %.*s\n", msg->via1->host.len, msg->via1->host.s);
+					" %.*s:%d\n", msg->via1->host.len, msg->via1->host.s
+									msg->via1->port);
 			/* send error msg back? */
 			goto error;
 		}
@@ -367,7 +371,7 @@ int forward_reply(struct sip_msg* msg)
 #endif
 	}
 
-	DBG(" reply forwarded to %s:%d\n",msg->via2->host.s,
+	DBG(" reply forwarded to %s:%d\n", msg->via2->host.s,
 		(unsigned short) msg->via2->port);
 
 	pkg_free(new_buf);

+ 1 - 1
forward.h

@@ -37,7 +37,7 @@
 
 
 struct socket_info* get_send_socket(union sockaddr_union* su);
-int check_self(str* host);
+int check_self(str* host, unsigned short port);
 int forward_request( struct sip_msg* msg,  struct proxy_l* p);
 int update_sock_struct_from_via( union sockaddr_union* to,
 								struct via_body* via );

+ 1 - 0
ip_addr.h

@@ -78,6 +78,7 @@ struct socket_info{
 	unsigned short port_no;  /* port number */
 	str port_no_str; /* port number converted to string -- optimization*/
 	int is_ip; /* 1 if name is an ip address, 0 if not  -- optimization*/
+	int is_lo; /* 1 if is a loopback, 0 if not */
 	union sockaddr_union su; 
 };
 

+ 47 - 32
main.c

@@ -266,7 +266,7 @@ int addresses_no=0;                   /* number of names/ips */
 #endif
 struct socket_info sock_info[MAX_LISTEN];/*all addresses we listen/send from*/
 int sock_no=0; /* number of addresses/open sockets*/
-struct socket_info* bind_address; /* pointer to the crt. proc.
+struct socket_info* bind_address=0; /* pointer to the crt. proc.
 									 listening address*/
 int bind_idx; /* same as above but index in the bound[] array */
 struct socket_info* sendipv4; /* ipv4 socket to use when msg. comes from ipv6*/
@@ -588,7 +588,8 @@ int main_loop()
 			/* create the listening socket (for each address)*/
 			if (udp_init(&sock_info[r])==-1) goto error;
 			/* get first ipv4/ipv6 socket*/
-			if ((sendipv4==0)&&(sock_info[r].address.af==AF_INET))
+			if ((sock_info[r].address.af==AF_INET)&&
+					((sendipv4==0)||(sendipv4->is_lo)))
 				sendipv4=&sock_info[r];
 	#ifdef USE_IPV6
 			if((sendipv6==0)&&(sock_info[r].address.af==AF_INET6))
@@ -803,10 +804,11 @@ int add_interfaces(char* if_name, int family, unsigned short port)
 			continue;
 		}
 		
-		if (if_name==0){ /* ignore down ifs only if listening on all of them*/
-			memcpy(&ifrcopy, ifr, sizeof(ifrcopy));
-			/*get flags*/
-			if (ioctl(s, SIOCGIFFLAGS,  &ifrcopy)!=-1){ /* ignore errors */
+		/*get flags*/
+		memcpy(&ifrcopy, ifr, sizeof(ifrcopy));
+		if (ioctl(s, SIOCGIFFLAGS,  &ifrcopy)!=-1){ /* ignore errors */
+			/* ignore down ifs only if listening on all of them*/
+			if (if_name==0){ 
 				/* if if not up, skip it*/
 				if (!(ifrcopy.ifr_flags & IFF_UP)) continue;
 			}
@@ -832,6 +834,9 @@ int add_interfaces(char* if_name, int family, unsigned short port)
 				strncpy(sock_info[sock_no].name.s, tmp, 
 							sock_info[sock_no].name.len+1);
 				sock_info[sock_no].port_no=port;
+				/* mark if loopback */
+				if (ifrcopy.ifr_flags & IFF_LOOPBACK) 
+					sock_info[sock_no].is_lo=1;
 				sock_no++;
 				ret=0;
 			}else{
@@ -1194,6 +1199,29 @@ int main(int argc, char** argv)
 	printf("Listening on \n");
 #endif
 	for (r=0; r<sock_no;r++){
+		/* fix port number, port_no should be !=0 here */
+		if (sock_info[r].port_no==0) sock_info[r].port_no=port_no;
+		port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
+									(unsigned short) sock_info[r].port_no);
+		if (port_no_str_len<0){
+			fprintf(stderr, "ERROR: bad port number: %d\n", 
+						sock_info[r].port_no);
+			goto error;
+		}
+		/* on some systems snprintf returns really strange things if it does 
+		  not have  enough space */
+		port_no_str_len=
+				(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
+		sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1);
+		if (sock_info[r].port_no_str.s==0){
+			fprintf(stderr, "Out of memory.\n");
+			goto error;
+		}
+		strncpy(sock_info[r].port_no_str.s, port_no_str,
+					strlen(port_no_str)+1);
+		sock_info[r].port_no_str.len=strlen(port_no_str);
+		
+		/* get "official hostnames", all the aliases etc. */
 		he=resolvehost(sock_info[r].name.s);
 		if (he==0){
 			DPrint("ERROR: could not resolve %s\n", sock_info[r].name.s);
@@ -1201,7 +1229,8 @@ int main(int argc, char** argv)
 		}
 		/* check if we got the official name */
 		if (strcasecmp(he->h_name, sock_info[r].name.s)!=0){
-			if (add_alias(sock_info[r].name.s, sock_info[r].name.len)<0){
+			if (add_alias(sock_info[r].name.s, sock_info[r].name.len,
+							sock_info[r].port_no)<0){
 				LOG(L_ERR, "ERROR: main: add_alias failed\n");
 			}
 			/* change the oficial name */
@@ -1216,7 +1245,7 @@ int main(int argc, char** argv)
 		}
 		/* add the aliases*/
 		for(h=he->h_aliases; h && *h; h++)
-			if (add_alias(*h, strlen(*h))<0){
+			if (add_alias(*h, strlen(*h), sock_info[r].port_no)<0){
 				LOG(L_ERR, "ERROR: main: add_alias failed\n");
 			}
 		hostent2ip_addr(&sock_info[r].address, he, 0); /*convert to ip_addr 
@@ -1242,36 +1271,17 @@ int main(int argc, char** argv)
 							sock_info[r].name.s);
 				}else{
 					/* add the aliases*/
-					if (add_alias(he->h_name, strlen(he->h_name))<0){
+					if (add_alias(he->h_name, strlen(he->h_name),
+									sock_info[r].port_no)<0){
 						LOG(L_ERR, "ERROR: main: add_alias failed\n");
 					}
 					for(h=he->h_aliases; h && *h; h++)
-						if (add_alias(*h, strlen(*h))<0){
+						if (add_alias(*h,strlen(*h),sock_info[r].port_no)<0){
 							LOG(L_ERR, "ERROR: main: add_alias failed\n");
 						}
 				}
 		}else{ sock_info[r].is_ip=0; };
 			
-		if (sock_info[r].port_no==0) sock_info[r].port_no=port_no;
-		port_no_str_len=snprintf(port_no_str, MAX_PORT_LEN, ":%d", 
-									(unsigned short) sock_info[r].port_no);
-		if (port_no_str_len<0){
-			fprintf(stderr, "ERROR: bad port number: %d\n", 
-						sock_info[r].port_no);
-			goto error;
-		}
-		/* on some systems snprintf returns really strange things if it does 
-		  not have  enough space */
-		port_no_str_len=
-				(port_no_str_len<MAX_PORT_LEN)?port_no_str_len:MAX_PORT_LEN;
-		sock_info[r].port_no_str.s=(char*)malloc(strlen(port_no_str)+1);
-		if (sock_info[r].port_no_str.s==0){
-			fprintf(stderr, "Out of memory.\n");
-			goto error;
-		}
-		strncpy(sock_info[r].port_no_str.s, port_no_str, strlen(port_no_str)+1);
-		sock_info[r].port_no_str.len=strlen(port_no_str);
-		
 #ifdef EXTRA_DEBUG
 		printf("              %.*s [%s]:%s\n", sock_info[r].name.len, 
 				sock_info[r].name.s,
@@ -1298,7 +1308,8 @@ int main(int argc, char** argv)
 						(strncmp(sock_info[t].name.s, sock_info[r].name.s,
 								 sock_info[r].name.len)!=0))
 					)
-					add_alias(sock_info[t].name.s, sock_info[t].name.len);
+					add_alias(sock_info[t].name.s, sock_info[t].name.len,
+								sock_info[t].port_no);
 						
 				/* free space*/
 				free(sock_info[t].name.s);
@@ -1320,7 +1331,11 @@ int main(int argc, char** argv)
 				sock_info[r].address_str.s, sock_info[r].port_no_str.s);
 
 	printf("Aliases: ");
-	for(a=aliases; a; a=a->next) printf("%.*s ", a->alias.len, a->alias.s);
+	for(a=aliases; a; a=a->next) 
+		if (a->port)
+			printf("%.*s:%d ", a->alias.len, a->alias.s, a->port);
+		else
+			printf("%.*s:* ", a->alias.len, a->alias.s);
 	printf("\n");
 	if (sock_no==0){
 		fprintf(stderr, "ERROR: no listening sockets");

+ 9 - 5
name_alias.h

@@ -35,6 +35,7 @@
 
 struct host_alias{
 	str alias;
+	unsigned short port;
 	struct host_alias* next;
 };
 
@@ -43,13 +44,14 @@ extern struct host_alias* aliases;
 
 
 
-/* returns 1 if  name is in the alias list*/
-static inline int grep_aliases(char* name, int len)
+/* returns 1 if  name is in the alias list; if port=0, port no is ignored*/
+static inline int grep_aliases(char* name, int len, unsigned short port)
 {
 	struct  host_alias* a;
 	
 	for(a=aliases;a;a=a->next)
-		if ((a->alias.len==len) && (strncasecmp(a->alias.s, name, len)==0))
+		if ((a->alias.len==len) && ((a->port==0) || (port==0) || 
+				(a->port==port)) && (strncasecmp(a->alias.s, name, len)==0))
 			return 1;
 	return 0;
 }
@@ -57,13 +59,14 @@ static inline int grep_aliases(char* name, int len)
 
 
 /* adds an alias to the list (only if it isn't already there)
+ * if port==0, the alias will match all the ports
  * returns 1 if a new alias was added, 0 if the alias was already on the list
  * and  -1 on error */
-static inline int add_alias(char* name, int len)
+static inline int add_alias(char* name, int len, unsigned short port)
 {
 	struct host_alias* a;
 	
-	if (grep_aliases(name,len)) return 0;
+	if ((port) && grep_aliases(name,len, port)) return 0;
 	a=0;
 	a=(struct host_alias*)malloc(sizeof(struct host_alias));
 	if(a==0) goto error;
@@ -72,6 +75,7 @@ static inline int add_alias(char* name, int len)
 	a->alias.len=len;
 	memcpy(a->alias.s, name, len);
 	a->alias.s[len]=0; /* null terminate for easier printing*/
+	a->port=port;
 	a->next=aliases;
 	aliases=a;
 	return 1;

+ 1 - 0
parser/msg_parser.h

@@ -72,6 +72,7 @@ struct sip_uri {
 	str port;     /* Port number */
 	str params;   /* Parameters */
 	str headers;  
+	unsigned short port_no;
 };
 
 

+ 10 - 1
parser/parse_uri.c

@@ -42,6 +42,7 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 	char* next, *end;
 	char *user, *passwd, *host, *port, *params, *headers, *ipv6;
 	int host_len, port_len, params_len, headers_len;
+	int err;
 	int ret;
 	
 	
@@ -208,7 +209,15 @@ int parse_uri(char *buf, int len, struct sip_uri* uri)
 		uri->headers.len=headers_len;
 		uri->headers.s[headers_len]=0;
 	}else uri->headers.s=0;
-	
+
+	err=0;
+	if (uri->port.s) uri->port_no=str2s(uri->port.s, uri->port.len, &err);
+	if (err){
+		LOG(L_DBG, "ERROR: parse_uri: bad port number in sip uri: %s\n",
+				uri->port.s);
+		ser_error=ret=E_BAD_URI;
+		goto error;
+	}
 	return ret;
 error:
 	free_uri(uri);

+ 8 - 4
route.c

@@ -262,7 +262,7 @@ error:
 
 
 
-/* eval_elem helping function, returns a op param */
+/* eval_elem helping function, returns an op param */
 static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
 {
 	struct hostent* he;
@@ -305,7 +305,7 @@ static int comp_ip(struct ip_addr* ip, void* param, int op, int subtype)
 		case MYSELF_ST: /* check if it's one of our addresses*/
 			tmp.s=ip_addr2a(ip);
 			tmp.len=strlen(tmp.s);
-			ret=check_self(&tmp);
+			ret=check_self(&tmp, 0);
 			break;
 		default:
 			LOG(L_CRIT, "BUG: comp_ip: invalid type for "
@@ -338,7 +338,9 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				if(msg->new_uri.s){
 					if (e->subtype==MYSELF_ST){
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
-						else	ret=check_self(&msg->parsed_uri.host);
+						else	ret=check_self(&msg->parsed_uri.host,
+									msg->parsed_uri.port_no?
+									msg->parsed_uri.port_no:SIP_PORT);
 					}else{
 						ret=comp_str(msg->new_uri.s, e->r.param,
 										e->op, e->subtype);
@@ -346,7 +348,9 @@ static int eval_elem(struct expr* e, struct sip_msg* msg)
 				}else{
 					if (e->subtype==MYSELF_ST){
 						if (parse_sip_msg_uri(msg)<0) ret=-1;
-						else	ret=check_self(&msg->parsed_uri.host);
+						else	ret=check_self(&msg->parsed_uri.host,
+									msg->parsed_uri.port_no?
+									msg->parsed_uri.port_no:SIP_PORT);
 					}else{
 						ret=comp_str(msg->first_line.u.request.uri.s,
 										 e->r.param, e->op, e->subtype);

+ 2 - 0
test/test-throughput.cfg

@@ -6,6 +6,8 @@ rev_dns=off
 log_stderror=yes
 #children=8
 fifo=""
+alias=foo.bar
+alias=testing
 
 route{