Browse code

command line support for address lists (-l)

Support for specifying and address list for -l (e.g. -l (foo, bar)). For
sctp all the address in the list will be used for multi-homing.

Andrei Pelinescu-Onciul authored on 19/08/2008 18:37:52
Showing 1 changed files
... ...
@@ -76,6 +76,8 @@
76 76
  *              scheduling policies (andrei)
77 77
  * 2007-07-30  dst blacklist and DNS cache measurements added (Gergo)
78 78
  * 2008-08-08  sctp support (andrei)
79
+ * 2008-08-19  -l support for mmultihomed addresses/addresses lists
80
+ *                (e.g. -l (eth0, 1.2.3.4, foo.bar) ) (andrei)
79 81
  */
80 82
 
81 83
 
... ...
@@ -196,10 +198,12 @@ Options:\n\
196 196
     -c           Check configuration file for errors\n\
197 197
     -l address   Listen on the specified address/interface (multiple -l\n\
198 198
                   mean listening on more addresses).  The address format is\n\
199
-                  [proto:]addr[:port], where proto=udp|tcp and \n\
200
-                  addr= host|ip_address|interface_name. E.g: -l locahost, \n\
201
-                  -l udp:127.0.0.1:5080, -l eth0:5062 The default behavior\n\
202
-                  is to listen on all the interfaces.\n\
199
+                  [proto:]addr_lst[:port], where proto=udp|tcp|tls|sctp, \n\
200
+                  addr_lst= addr|(addr, addr_lst) and \n\
201
+                  addr= host|ip_address|interface_name. \n\
202
+                  E.g: -l locahost, -l udp:127.0.0.1:5080, -l eth0:5062,\n\
203
+                  -l \"sctp:(eth0)\", -l \"(eth0, eth1, 127.0.0.1):5065\".\n\
204
+                  The default behaviour is to listen on all the interfaces.\n\
203 205
     -n processes Number of child processes to fork per interface\n\
204 206
                   (default: 8)\n\
205 207
     -r           Use dns to check if is necessary to add a \"received=\"\n\
... ...
@@ -845,13 +849,116 @@ static int parse_proto(unsigned char* s, long len, int* proto)
845 845
 
846 846
 
847 847
 
848
+static struct name_lst* mk_name_lst_elem(char* name, int name_len, int flags)
849
+{
850
+	struct name_lst* l;
851
+	
852
+	l=pkg_malloc(sizeof(struct name_lst)+name_len+1/* 0 */);
853
+	if (l){
854
+		l->name=((char*)l)+sizeof(struct name_lst);
855
+		memcpy(l->name, name, name_len);
856
+		l->name[name_len]=0;
857
+		l->flags=flags;
858
+		l->next=0;
859
+	}
860
+	return l;
861
+}
862
+
863
+
864
+
865
+/* free a name_lst list with elements allocated with mk_name_lst_elem
866
+ * (single block both for the structure and for the name) */
867
+static void free_name_lst(struct name_lst* lst)
868
+{
869
+	struct name_lst* l;
870
+	
871
+	while(lst){
872
+		l=lst;
873
+		lst=lst->next;
874
+		pkg_free(l);
875
+	}
876
+}
877
+
878
+
879
+
880
+/* parse h and returns a name lst (flags are set to SI_IS_MHOMED if
881
+ * h contains more then one name or contains a name surrounded by '(' ')' )
882
+ * valid formats:    "hostname"
883
+ *                   "(hostname, hostname1, hostname2)"
884
+ *                   "(hostname hostname1 hostname2)"
885
+ *                   "(hostname)"
886
+ */
887
+static struct name_lst* parse_name_lst(char* h, int h_len)
888
+{
889
+	char* last;
890
+	char* p;
891
+	struct name_lst* n_lst;
892
+	struct name_lst* l;
893
+	struct name_lst** tail;
894
+	int flags;
895
+	
896
+	n_lst=0;
897
+	tail=&n_lst;
898
+	last=h+h_len-1;
899
+	flags=0;
900
+	/* eat whitespace */
901
+	for(; h<=last && ((*h==' ') || (*h=='\t')); h++);
902
+	for(; last>h && ((*last==' ') || (*last=='\t')); last--);
903
+	/* catch empty strings and invalid lens */
904
+	if (h>last) goto error;
905
+	
906
+	if (*h=='('){
907
+		/* list mode */
908
+		if (*last!=')' || ((h+1)>(last-1)))
909
+			goto error;
910
+		h++;
911
+		last--;
912
+		flags=SI_IS_MHOMED;
913
+		for(p=h; p<=last; p++)
914
+			switch (*p){
915
+				case ',':
916
+				case ';':
917
+				case ' ':
918
+				case '\t':
919
+					if ((int)(p-h)>0){
920
+						l=mk_name_lst_elem(h, (int)(p-h), flags);
921
+						if (l==0) 
922
+							goto error;
923
+						*tail=l;
924
+						tail=&l->next;
925
+					}
926
+					h=p+1;
927
+					break;
928
+			}
929
+	}else{
930
+		/* single addr. mode */
931
+		flags=0;
932
+		p=last+1;
933
+	}
934
+	if ((int)(p-h)>0){
935
+		l=mk_name_lst_elem(h, (int)(p-h), flags);
936
+		if (l==0) 
937
+			goto error;
938
+		*tail=l;
939
+		tail=&l->next;
940
+	}
941
+	return n_lst;
942
+error:
943
+	if (n_lst) free_name_lst(n_lst);
944
+	return 0;
945
+}
946
+
947
+
948
+
848 949
 /*
849
- * parses [proto:]host[:port]
950
+ * parses [proto:]host[:port]  or
951
+ *  [proto:](host_1, host_2, ... host_n)[:port]
850 952
  * where proto= udp|tcp|tls
851
- * returns 0 on success and -1 on failure
953
+ * returns  fills proto, port, host and returns list of addresses on success
954
+ * (pkg malloc'ed) and 0 on failure
852 955
  */
853
-static int parse_phostport(char* s, char** host, int* hlen, int* port,
854
-							int* proto)
956
+static struct name_lst* parse_phostport(char* s, char** host, int* hlen,
957
+										int* port, int* proto)
855 958
 {
856 959
 	char* first; /* first ':' occurrence */
857 960
 	char* second; /* second ':' occurrence */
... ...
@@ -884,7 +991,7 @@ static int parse_phostport(char* s, char** host, int* hlen, int* port,
884 884
 				break;
885 885
 		}
886 886
 	}
887
-	if (p==s) return -1;
887
+	if (p==s) return 0;
888 888
 	if (*(p-1)==':') goto error_colons;
889 889
 
890 890
 	if (first==0){ /* no ':' => only host */
... ...
@@ -892,7 +999,7 @@ static int parse_phostport(char* s, char** host, int* hlen, int* port,
892 892
 		*hlen=(int)(p-s);
893 893
 		*port=0;
894 894
 		*proto=0;
895
-		return 0;
895
+		goto end;
896 896
 	}
897 897
 	if (second){ /* 2 ':' found => check if valid */
898 898
 		if (parse_proto((unsigned char*)s, first-s, proto)<0) goto error_proto;
... ...
@@ -900,7 +1007,7 @@ static int parse_phostport(char* s, char** host, int* hlen, int* port,
900 900
 		if ((tmp==0)||(*tmp)||(tmp==second+1)) goto error_port;
901 901
 		*host=first+1;
902 902
 		*hlen=(int)(second-*host);
903
-		return 0;
903
+		goto end;
904 904
 	}
905 905
 	/* only 1 ':' found => it's either proto:host or host:port */
906 906
 	*port=strtol(first+1, &tmp, 10);
... ...
@@ -916,19 +1023,20 @@ static int parse_phostport(char* s, char** host, int* hlen, int* port,
916 916
 		*host=s;
917 917
 		*hlen=(int)(first-*host);
918 918
 	}
919
-	return 0;
919
+end:
920
+	return parse_name_lst(*host, *hlen);
920 921
 error_brackets:
921 922
 	LOG(L_ERR, "ERROR: parse_phostport: too many brackets in %s\n", s);
922
-	return -1;
923
+	return 0;
923 924
 error_colons:
924 925
 	LOG(L_ERR, "ERROR: parse_phostport: too many colons in %s\n", s);
925
-	return -1;
926
+	return 0;
926 927
 error_proto:
927 928
 	LOG(L_ERR, "ERROR: parse_phostport: bad protocol in %s\n", s);
928
-	return -1;
929
+	return 0;
929 930
 error_port:
930 931
 	LOG(L_ERR, "ERROR: parse_phostport: bad port number in %s\n", s);
931
-	return -1;
932
+	return 0;
932 933
 }
933 934
 
934 935
 
... ...
@@ -1366,6 +1474,7 @@ int main(int argc, char** argv)
1366 1366
 	int rfd;
1367 1367
 	int debug_save, debug_flag;
1368 1368
 	int dont_fork_cnt;
1369
+	struct name_lst* n_lst;
1369 1370
 
1370 1371
 	/*init*/
1371 1372
 	time(&up_since);
... ...
@@ -1563,18 +1672,20 @@ try_again:
1563 1563
 					}
1564 1564
 					break;
1565 1565
 			case 'l':
1566
-					if (parse_phostport(optarg, &tmp, &tmp_len,
1567
-											&port, &proto)<0){
1566
+					if ((n_lst=parse_phostport(optarg, &tmp, &tmp_len,
1567
+											&port, &proto))==0){
1568 1568
 						fprintf(stderr, "bad -l address specifier: %s\n",
1569 1569
 										optarg);
1570 1570
 						goto error;
1571 1571
 					}
1572
-					tmp[tmp_len]=0; /* null terminate the host */
1573 1572
 					/* add a new addr. to our address list */
1574
-					if (add_listen_iface(tmp,0,  port, proto, 0)!=0){
1573
+					if (add_listen_iface(n_lst->name, n_lst->next,  port,
1574
+											proto, n_lst->flags)!=0){
1575 1575
 						fprintf(stderr, "failed to add new listen address\n");
1576
+						free_name_lst(n_lst);
1576 1577
 						goto error;
1577 1578
 					}
1579
+					free_name_lst(n_lst);
1578 1580
 					break;
1579 1581
 			case 'n':
1580 1582
 					children_no=strtol(optarg, &tmp, 10);