ソースを参照

- ipv6 reference parsing support

Andrei Pelinescu-Onciul 22 年 前
コミット
80c4012487
2 ファイル変更95 行追加22 行削除
  1. 2 0
      TODO
  2. 93 22
      test/p_uri.c

+ 2 - 0
TODO

@@ -90,6 +90,8 @@ optimizations:
 tcp stuff:
 x tcp disable nagle 
 - tcp locking/atomic ops review
+- tcp fix simultaneous connects (ser process is blocked until connect timeouts
+ => possible DOS)
 
 tm optimizations:
 

+ 93 - 22
test/p_uri.c

@@ -20,7 +20,8 @@ struct sip_uri {
 
 int parse_uri(char* buf, int len, struct sip_uri* uri)
 {
-	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_HOST, URI_PORT,
+	enum states  {	URI_INIT, URI_USER, URI_PASSWORD, URI_HOST, URI_HOST_P,
+					URI_HOST6_P, URI_HOST6_END, URI_PORT,
 					URI_PARAM, URI_HEADERS };
 	enum states state;
 	char* s;
@@ -54,8 +55,31 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 							found_user=1;\
 							error_headers=0; \
 							state=URI_HOST; \
-						}else goto error_bad_char; 
-	 
+						}else goto error_bad_char 
+#define check_host_end \
+					case ':': \
+						/* found the host */ \
+						uri->host.s=s; \
+						uri->host.len=p-s; \
+						state=URI_PORT; \
+						s=p+1; \
+						break; \
+					case ';': \
+						uri->host.s=s; \
+						uri->host.len=p-s; \
+						state=URI_PARAM; \
+						s=p+1; \
+						break; \
+					case '?': \
+						uri->host.s=s; \
+						uri->host.len=p-s; \
+						state=URI_HEADERS; \
+						s=p+1; \
+						break; \
+					case '&': \
+					case '@': \
+						goto error_bad_char 
+	
 	end=buf+len;
 	p=buf+4;
 	found_user=0;
@@ -69,9 +93,26 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 		     (buf[3]==':') ) ) goto error_bad_uri;
 	
 	s=p;
-	state=URI_USER;
 	for(;p<end; p++){
 		switch(state){
+			case URI_INIT:
+				switch(*p){
+					case '[':
+						/* uri =  [ipv6address]... */
+						state=URI_HOST6_P;
+						s=p;
+						break;
+					case ']':
+						/* invalid, no uri can start with ']' */
+					case ':':
+						/* the same as above for ':' */
+						goto error_bad_char;
+					case '@': /* error no user part, or
+								 be forgiving and accept it ? */
+					default:
+						state=URI_USER;
+				}
+				break; 
 			case URI_USER:
 				switch(*p){
 					case '@':
@@ -104,6 +145,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						s=p+1;
 						break;
 						/* almost anything permitted in the user part */
+					case '[':
+					case ']': /* the user part cannot contain "[]" */
+						goto error_bad_char;
 				}
 				break;
 			case URI_PASSWORD: /* this can also be the port (missing user)*/
@@ -142,34 +186,50 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 						found_user=1; /*  there is no user part */
 						s=p+1;
 						break;
+					case '[':
+					case ']':
 					case ':':
 						goto error_bad_char;
 				}
 				break;
 			case URI_HOST:
 				switch(*p){
-					case ':':
-						/* found the host */
-						uri->host.s=s;
-						uri->host.len=p-s;
-						state=URI_PORT;
-						s=p+1;
+					case '[':
+						state=URI_HOST6_P;
 						break;
+					case ':': 
 					case ';':
-						uri->host.s=s;
-						uri->host.len=p-s;
-						state=URI_PARAM;
-						s=p+1;
-						break;
-					case '?':
-						uri->host.s=s;
-						uri->host.len=p-s;
-						state=URI_HEADERS;
-						s=p+1;
+					case '?': /* null host name ->invalid */
+					case '&':
+					case '@': /*chars not allowed in hosts names */
+						goto error_bad_host;
+					default:
+						state=URI_HOST_P;
+				}
+				break;
+			case URI_HOST_P:
+				switch(*p){
+					check_host_end;
+				}
+				break;
+			case URI_HOST6_END:
+				switch(*p){
+					check_host_end;
+					default: /*no chars allowed after [ipv6] */
+						goto error_bad_host;
+				}
+				break;
+			case URI_HOST6_P:
+				switch(*p){
+					case ']':
+						state=URI_HOST6_END;
 						break;
+					case '[':
 					case '&':
 					case '@':
-						goto error_bad_char;
+					case ';':
+					case '?':
+						goto error_bad_host;
 				}
 				break;
 			case URI_PORT:
@@ -271,6 +331,8 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 	}
 	/*end of uri */
 	switch (state){
+		case URI_INIT: /* error empy uri */
+			goto error_too_short;
 		case URI_USER:
 			/* this is the host, it can't be the user */
 			if (found_user) goto error_bad_uri;
@@ -287,10 +349,14 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
 			uri->user.s=0;
 			uri->user.len=0;
 			break;
-		case URI_HOST:
+		case URI_HOST_P:
+		case URI_HOST6_END:
 			uri->host.s=s;
 			uri->host.len=p-s;
 			break;
+		case URI_HOST: /* error: null host */
+		case URI_HOST6_P: /* error: unterminated ipv6 reference*/
+			goto error_bad_host;
 		case URI_PORT:
 			uri->port.s=s;
 			uri->port.len=p-s;
@@ -329,6 +395,11 @@ error_bad_char:
 			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
 			*p, state, (p-buf), buf, (p-buf), len, buf, len);
 	return -1;
+error_bad_host:
+	LOG(L_ERR, "ERROR: parse_uri: bad host in uri (error at char %c in"
+			" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
+			*p, state, (p-buf), buf, (p-buf), len, buf, len);
+	return -1;
 error_bad_uri:
 	LOG(L_ERR, "ERROR: parse_uri: bad uri,  state %d"
 			" parsed: <%.*s> (%d) / <%.*s> (%d)\n",