浏览代码

sctp multi-homing config support

- config support for sctp multi-homing (listen on multiple addresses in the
   same time).
   Format:  sctp:(addr1, addr2, addr3)
            sctp:(eth0)   -> will listen on all eth0 addresses in the same
                             time
           (eth0,lo) -> sctp will listen on all addresses from eth0 & lo
                        in the same time, while the other protocols will
                        create different socket for each of the addresses
                        (e.g.: for udp it would be equivalent with:
                        listen= udp:eth0 udp:lo)
   The first address is always the main one.
   Conflicts are resolved automatically, by removing the duplicates. Main
   addresses have priority (e.g: sctp:(lo,eth0) sctp:(eth0,eth1) after
   duplicate removal will become sctp:(lo) sctp:(eth0,eth1)).

- try to always keep the order in which listen addresses were given in
  config (fixes reordering between interface names and hostnames, e.g.
  listen= eth0 foo.bar resulted in ip(foo.bar) , ip(eth0) )
Andrei Pelinescu-Onciul 17 年之前
父节点
当前提交
eb321e3ffe
共有 7 个文件被更改,包括 802 次插入187 次删除
  1. 125 9
      cfg.y
  2. 26 3
      ip_addr.h
  3. 1 1
      main.c
  4. 13 8
      route.c
  5. 3 3
      route_struct.c
  6. 628 161
      socket_info.c
  7. 6 2
      socket_info.h

+ 125 - 9
cfg.y

@@ -175,6 +175,7 @@ static void yyerror(char* s);
 static char* tmp;
 static int i_tmp;
 static struct socket_id* lst_tmp;
+static struct name_lst*  nl_tmp;
 static int rt;  /* Type of route block for find_export */
 static str* str_tmp;
 static str s_tmp;
@@ -186,6 +187,10 @@ static struct action *mod_func_action;
 
 static void warn(char* s);
 static struct socket_id* mk_listen_id(char*, int, int);
+static struct name_lst* mk_name_lst(char* name, int flags);
+static struct socket_id* mk_listen_id2(struct name_lst*, int, int);
+static void free_name_lst(struct name_lst* lst);
+static void free_socket_id_lst(struct socket_id* i);
 
 %}
 
@@ -198,6 +203,7 @@ static struct socket_id* mk_listen_id(char*, int, int);
 	struct net* ipnet;
 	struct ip_addr* ipaddr;
 	struct socket_id* sockid;
+	struct name_lst* name_l;
 	struct avp_spec* attr;
 	select_t* select;
 }
@@ -466,8 +472,11 @@ static struct socket_id* mk_listen_id(char*, int, int);
 %type <ipnet> ipnet
 %type <strval> host
 %type <strval> listen_id
+%type <name_l> listen_id_lst
+%type <name_l> listen_id2
 %type <sockid>  id_lst
 %type <sockid>  phostport
+%type <sockid>  listen_phostport
 %type <intval> proto port
 %type <intval> equalop strop intop binop
 %type <strval> host_sep
@@ -550,6 +559,20 @@ listen_id:
 		}
 	}
 	;
+
+
+listen_id_lst:
+	listen_id	{ $$=mk_name_lst($1, SI_IS_MHOMED); }
+	| listen_id COMMA listen_id_lst	{ $$=mk_name_lst($1, SI_IS_MHOMED); 
+										if ($$) $$->next=$3;
+									}
+	;
+
+listen_id2:
+	LPAREN listen_id_lst RPAREN { $$=$2; }
+	| listen_id	{ $$=mk_name_lst($1, 0); }
+	;
+
 proto:
 	UDP	{ $$=PROTO_UDP; }
 	| TCP	{ $$=PROTO_TCP; }
@@ -568,9 +591,18 @@ phostport:
 	| proto COLON listen_id COLON port	{ $$=mk_listen_id($3, $1, $5);}
 	| listen_id COLON error { $$=0; yyerror(" port number expected"); }
 	;
+
+listen_phostport:
+	listen_id2		{ $$=mk_listen_id2($1, 0, 0); }
+	| listen_id2 COLON port	{ $$=mk_listen_id2($1, 0, $3); }
+	| proto COLON listen_id2	{ $$=mk_listen_id2($3, $1, 0); }
+	| proto COLON listen_id2 COLON port	{ $$=mk_listen_id2($3, $1, $5);}
+	| listen_id2 COLON error { $$=0; yyerror(" port number expected"); }
+	;
+
 id_lst:
-	phostport		{  $$=$1 ; }
-	| phostport id_lst	{ $$=$1; $$->next=$2; }
+	listen_phostport		{  $$=$1 ; }
+	| listen_phostport id_lst	{ $$=$1; $$->next=$2; }
 	;
 
 flags_decl:		FLAGS_DECL	flag_list
@@ -1107,16 +1139,28 @@ assign_stm:
 	| REPLY_TO_VIA EQUAL error { yyerror("boolean value expected"); }
 	| LISTEN EQUAL id_lst {
 		for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next) {
-			if (add_listen_iface(lst_tmp->name, lst_tmp->port, lst_tmp->proto, 0)!=0) {
-				LOG(L_CRIT,  "ERROR: cfg. parser: failed to add listen address\n");
+			if (add_listen_iface(	lst_tmp->addr_lst->name,
+									lst_tmp->addr_lst->next,
+									lst_tmp->port, lst_tmp->proto,
+									lst_tmp->flags)!=0) {
+				LOG(L_CRIT,  "ERROR: cfg. parser: failed to add listen"
+								" address\n");
 				break;
 			}
 		}
+		free_socket_id_lst($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->name, strlen(lst_tmp->name), lst_tmp->port, lst_tmp->proto);
+		for(lst_tmp=$3; lst_tmp; lst_tmp=lst_tmp->next){
+			add_alias(	lst_tmp->addr_lst->name,
+						strlen(lst_tmp->addr_lst->name),
+						lst_tmp->port, lst_tmp->proto);
+			for (nl_tmp=lst_tmp->addr_lst->next; nl_tmp; nl_tmp=nl_tmp->next)
+				add_alias(nl_tmp->name, strlen(nl_tmp->name),
+							lst_tmp->port, lst_tmp->proto);
+		}
+		free_socket_id_lst($3);
 	}
 	| ALIAS  EQUAL error  { yyerror(" hostname expected"); }
 	| ADVERTISED_ADDRESS EQUAL listen_id {
@@ -2289,8 +2333,12 @@ cmd:
 	}
 	| SET_ADV_PORT LPAREN error RPAREN { $$=0; yyerror("bad argument, string expected"); }
 	| SET_ADV_PORT  error {$$=0; yyerror("missing '(' or ')' ?"); }
-	| FORCE_SEND_SOCKET LPAREN phostport RPAREN { $$=mk_action(FORCE_SEND_SOCKET_T, 1, SOCKID_ST, $3); }
-	| FORCE_SEND_SOCKET LPAREN error RPAREN { $$=0; yyerror("bad argument, [proto:]host[:port] expected"); }
+	| FORCE_SEND_SOCKET LPAREN phostport RPAREN { 
+		$$=mk_action(FORCE_SEND_SOCKET_T, 1, SOCKID_ST, $3);
+	}
+	| FORCE_SEND_SOCKET LPAREN error RPAREN {
+		$$=0; yyerror("bad argument, [proto:]host[:port] expected");
+	}
 	| FORCE_SEND_SOCKET error {$$=0; yyerror("missing '(' or ')' ?"); }
 	| ID {mod_func_action = mk_action(MODULE_T, 2, MODEXP_ST, NULL, NUMBER_ST, 0); } LPAREN func_params RPAREN	{
 		mod_func_action->val[0].u.data = find_export_record($1, mod_func_action->val[1].u.number, rt);
@@ -2352,6 +2400,21 @@ static void yyerror(char* s)
 }
 
 
+static struct name_lst* mk_name_lst(char* host, int flags)
+{
+	struct name_lst* l;
+	l=pkg_malloc(sizeof(struct name_lst));
+	if (l==0) {
+		LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
+	} else {
+		l->name=host;
+		l->flags=flags;
+		l->next=0;
+	}
+	return l;
+}
+
+
 static struct socket_id* mk_listen_id(char* host, int proto, int port)
 {
 	struct socket_id* l;
@@ -2359,7 +2422,12 @@ static struct socket_id* mk_listen_id(char* host, int proto, int port)
 	if (l==0) {
 		LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
 	} else {
-		l->name=host;
+		l->addr_lst=mk_name_lst(host, 0);
+		if (l->addr_lst==0){
+			pkg_free(l);
+			return 0;
+		}
+		l->flags=0;
 		l->port=port;
 		l->proto=proto;
 		l->next=0;
@@ -2368,6 +2436,54 @@ static struct socket_id* mk_listen_id(char* host, int proto, int port)
 }
 
 
+static void free_name_lst(struct name_lst* lst)
+{
+	struct name_lst* tmp;
+	
+	while(lst){
+		tmp=lst;
+		lst=lst->next;
+		pkg_free(tmp);
+	}
+}
+
+
+static struct socket_id* mk_listen_id2(struct name_lst* addr_l, int proto,
+										int port)
+{
+	struct socket_id* l;
+	l=pkg_malloc(sizeof(struct socket_id));
+	if (l==0) {
+		LOG(L_CRIT,"ERROR: cfg. parser: out of memory.\n");
+	} else {
+		l->flags=addr_l->flags;
+		l->port=port;
+		l->proto=proto;
+		l->addr_lst=addr_l;
+		l->next=0;
+	}
+	return l;
+}
+
+
+static void free_socket_id(struct socket_id* i)
+{
+	free_name_lst(i->addr_lst);
+	pkg_free(i);
+}
+
+
+static void free_socket_id_lst(struct socket_id* lst)
+{
+	struct socket_id* tmp;
+	
+	while(lst){
+		tmp=lst;
+		lst=lst->next;
+		free_socket_id(tmp);
+	}
+}
+
 /*
 int main(int argc, char ** argv)
 {

+ 26 - 3
ip_addr.h

@@ -89,13 +89,23 @@ union sockaddr_union{
 
 
 enum si_flags { SI_NONE=0, SI_IS_IP=1, SI_IS_LO=2, SI_IS_MCAST=4,
-				 SI_IS_ANY=8 };
+				 SI_IS_ANY=8, SI_IS_MHOMED=16 };
+
+struct addr_info{
+	str name; /* name - eg.: foo.bar or 10.0.0.1 */
+	struct ip_addr address; /*ip address */
+	str address_str;        /*ip address converted to string -- optimization*/
+	enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
+	union sockaddr_union su;
+	struct addr_info* next;
+	struct addr_info* prev;
+};
 
 struct socket_info{
 	int socket;
 	str name; /* name - eg.: foo.bar or 10.0.0.1 */
 	struct ip_addr address; /* ip address */
-	str address_str;        /* ip address converted to string -- optimization*/
+	str address_str;        /*ip address converted to string -- optimization*/
 	str port_no_str; /* port number converted to string -- optimization*/
 	enum si_flags flags; /* SI_IS_IP | SI_IS_LO | SI_IS_MCAST */
 	union sockaddr_union su; 
@@ -103,6 +113,7 @@ struct socket_info{
 	struct socket_info* prev;
 	unsigned short port_no;  /* port number */
 	char proto; /* tcp or udp*/
+	struct addr_info* addr_info_lst; /* extra addresses (e.g. SCTP mh) */
 };
 
 
@@ -135,8 +146,20 @@ struct dest_info{
 };
 
 
-struct socket_id{
+/* list of names for multi-homed sockets that need to bind on
+ * multiple addresses in the same time (sctp ) */
+struct name_lst{
 	char* name;
+	struct name_lst* next;
+	int flags;
+};
+
+
+struct socket_id{
+	struct name_lst* addr_lst; /* address list, the first one must
+								  be present and is the main one
+								  (in case of multihoming sctp)*/
+	int flags;
 	int proto;
 	int port;
 	struct socket_id* next;

+ 1 - 1
main.c

@@ -1571,7 +1571,7 @@ try_again:
 					}
 					tmp[tmp_len]=0; /* null terminate the host */
 					/* add a new addr. to our address list */
-					if (add_listen_iface(tmp, port, proto, 0)!=0){
+					if (add_listen_iface(tmp,0,  port, proto, 0)!=0){
 						fprintf(stderr, "failed to add new listen address\n");
 						goto error;
 					}

+ 13 - 8
route.c

@@ -391,6 +391,7 @@ static int fix_actions(struct action* a)
 	struct hostent* he;
 	struct ip_addr ip;
 	struct socket_info* si;
+	char buf[30]; /* tmp buffer needed for module param fixups */
 
 	if (a==0){
 		LOG(L_CRIT,"BUG: fix_actions: null pointer\n");
@@ -506,15 +507,17 @@ static int fix_actions(struct action* a)
 				if (cmd && cmd->fixup) {
 					int i;
 					DBG("fixing %s()\n", cmd->name);
-					/* type cast NUMBER to STRING, old modules may expect all STRING params during fixup */
+					/* type cast NUMBER to STRING, old modules may expect
+					 * all STRING params during fixup */
 					for (i=0; i<t->val[1].u.number; i++) {
 						if (t->val[i+2].type == NUMBER_ST) {
-							char buf[30];
-							snprintf(buf, sizeof(buf)-1, "%ld", t->val[i+2].u.number);
-							/* fixup currently requires string pkg_malloc-aed */
+							snprintf(buf, sizeof(buf)-1, "%ld", 
+										t->val[i+2].u.number);
+							/* fixup currently requires string pkg_malloced*/
 							t->val[i+2].u.string = pkg_malloc(strlen(buf)+1);
 							if (!t->val[i+2].u.string) {
-								LOG(L_CRIT, "ERROR: cannot translate NUMBER to STRING\n");
+								LOG(L_CRIT, "ERROR: cannot translate NUMBER"
+											" to STRING\n");
 								return E_OUT_OF_MEM;
 							}
 							strcpy(t->val[i+2].u.string, buf);
@@ -539,11 +542,13 @@ static int fix_actions(struct action* a)
 								t->val[0].type);
 					return E_BUG;
 				}
-				he=resolvehost(((struct socket_id*)t->val[0].u.data)->name);
+				he=resolvehost(
+						((struct socket_id*)t->val[0].u.data)->addr_lst->name
+						);
 				if (he==0){
 					LOG(L_ERR, "ERROR: fix_actions: force_send_socket:"
 								" could not resolve %s\n",
-							((struct socket_id*)t->val[0].u.data)->name);
+						((struct socket_id*)t->val[0].u.data)->addr_lst->name);
 					return E_BAD_ADDRESS;
 				}
 				hostent2ip_addr(&ip, he, 0);
@@ -552,7 +557,7 @@ static int fix_actions(struct action* a)
 				if (si==0){
 					LOG(L_ERR, "ERROR: fix_actions: bad force_send_socket"
 							" argument: %s:%d (ser doesn't listen on it)\n",
-							((struct socket_id*)t->val[0].u.data)->name,
+						((struct socket_id*)t->val[0].u.data)->addr_lst->name,
 							((struct socket_id*)t->val[0].u.data)->port);
 					return E_BAD_ADDRESS;
 				}

+ 3 - 3
route_struct.c

@@ -404,7 +404,7 @@ void print_action(struct action* t)
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
-			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;
@@ -438,7 +438,7 @@ void print_action(struct action* t)
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
-			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;
@@ -470,7 +470,7 @@ void print_action(struct action* t)
 		case SOCKID_ST:
 			DBG("%d:%s:%d",
 			((struct socket_id*)t->val[0].u.data)->proto,
-			ZSW(((struct socket_id*)t->val[0].u.data)->name),
+			ZSW(((struct socket_id*)t->val[0].u.data)->addr_lst->name),
 			((struct socket_id*)t->val[0].u.data)->port
 			);
 			break;

文件差异内容过多而无法显示
+ 628 - 161
socket_info.c


+ 6 - 2
socket_info.h

@@ -42,6 +42,9 @@
 #include "ip_addr.h" 
 #include "dprint.h"
 #include "globals.h"
+
+
+
 /* struct socket_info is defined in ip_addr.h */
 
 extern struct socket_info* udp_listen;
@@ -71,8 +74,9 @@ extern int socket_types;
 
 void init_proto_order();
 
-int add_listen_iface(char* name, unsigned short port, unsigned short proto,
-							enum si_flags flags);
+int add_listen_iface(char* name, struct name_lst* nlst,
+						unsigned short port, unsigned short proto,
+						enum si_flags flags);
 int fix_all_socket_lists();
 void print_all_socket_lists();
 void print_aliases();

部分文件因为文件数量过多而无法显示