Browse code

core: helper functions to lookup local socket from proto:host:port

Daniel-Constantin Mierla authored on 17/07/2013 10:22:31
Showing 3 changed files
... ...
@@ -924,7 +924,7 @@ error:
924 924
 
925 925
 /* returns -1 on error, 0 on success
926 926
  * sets proto */
927
-static int parse_proto(unsigned char* s, long len, int* proto)
927
+int parse_proto(unsigned char* s, long len, int* proto)
928 928
 {
929 929
 #define PROTO2UINT3(a, b, c) ((	(((unsigned int)(a))<<16)+ \
930 930
 								(((unsigned int)(b))<<8)+  \
... ...
@@ -2057,3 +2057,97 @@ void init_proto_order()
2057 2057
 }
2058 2058
 
2059 2059
 
2060
+/**
2061
+ * parse '[port:]host[:port]' string to a broken down structure
2062
+ */
2063
+int parse_protohostport(str* ins, sr_phostp_t *r)
2064
+{
2065
+	char* first; /* first ':' occurrence */
2066
+	char* second; /* second ':' occurrence */
2067
+	char* p;
2068
+	int bracket;
2069
+	char* tmp;
2070
+
2071
+	first=second=0;
2072
+	bracket=0;
2073
+	memset(r, 0, sizeof(sr_phostp_t));
2074
+
2075
+	/* find the first 2 ':', ignoring possible ipv6 addresses
2076
+	 * (substrings between [])
2077
+	 */
2078
+	for(p=ins->s; p<ins->s+ins->len; p++){
2079
+		switch(*p){
2080
+			case '[':
2081
+				bracket++;
2082
+				if (bracket>1) goto error_brackets;
2083
+				break;
2084
+			case ']':
2085
+				bracket--;
2086
+				if (bracket<0) goto error_brackets;
2087
+				break;
2088
+			case ':':
2089
+				if (bracket==0){
2090
+					if (first==0) first=p;
2091
+					else if( second==0) second=p;
2092
+					else goto error_colons;
2093
+				}
2094
+				break;
2095
+		}
2096
+	}
2097
+	if (p==ins->s) return -1;
2098
+	if (*(p-1)==':') goto error_colons;
2099
+
2100
+	if (first==0) { /* no ':' => only host */
2101
+		r->host.s=ins->s;
2102
+		r->host.len=(int)(p-ins->s);
2103
+		goto end;
2104
+	}
2105
+	if (second) { /* 2 ':' found => check if valid */
2106
+		if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
2107
+			goto error_proto;
2108
+		r->port=strtol(second+1, &tmp, 10);
2109
+		if ((tmp==0)||(*tmp)||(tmp==second+1)) goto error_port;
2110
+		r->host.s=first+1;
2111
+		r->host.len=(int)(second-r->host.s);
2112
+		goto end;
2113
+	}
2114
+	/* only 1 ':' found => it's either proto:host or host:port */
2115
+	r->port=strtol(first+1, &tmp, 10);
2116
+	if ((tmp==0)||(*tmp)||(tmp==first+1)){
2117
+		/* invalid port => it's proto:host */
2118
+		if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0)
2119
+			goto error_proto;
2120
+		r->host.s=first+1;
2121
+		r->host.len=(int)(p-r->host.s);
2122
+	}else{
2123
+		/* valid port => its host:port */
2124
+		r->host.s=ins->s;
2125
+		r->host.len=(int)(first-r->host.s);
2126
+	}
2127
+end:
2128
+	return 0;
2129
+error_brackets:
2130
+	LOG(L_ERR, "too many brackets in %.*s\n", ins->len, ins->s);
2131
+	return -1;
2132
+error_colons:
2133
+	LOG(L_ERR, "too many colons in %.*s\n", ins->len, ins->s);
2134
+	return -1;
2135
+error_proto:
2136
+	LOG(L_ERR, "bad protocol in %.*s\n", ins->len, ins->s);
2137
+	return -1;
2138
+error_port:
2139
+	LOG(L_ERR, "bad port number in %.*s\n", ins->len, ins->s);
2140
+	return -1;
2141
+}
2142
+
2143
+/**
2144
+ * lookup a local socket by '[port:]host[:port]' string
2145
+ */
2146
+struct socket_info* lookup_local_socket(str *phostp)
2147
+{
2148
+	sr_phostp_t r;
2149
+	if(parse_protohostport(phostp, &r)<0)
2150
+		return NULL;
2151
+	return grep_sock_info(&r.host, (unsigned short)r.port,
2152
+			(unsigned short)r.proto);
2153
+}
... ...
@@ -105,6 +105,8 @@ struct socket_info** get_sock_info_list(unsigned short proto);
105 105
 int parse_phostport(char* s, char** host, int* hlen,
106 106
 								 int* port, int* proto);
107 107
 
108
+int parse_proto(unsigned char* s, long len, int* proto);
109
+
108 110
 char* get_valid_proto_name(unsigned short proto);
109 111
 
110 112
 /* helper function:
... ...
@@ -142,5 +144,13 @@ inline static struct socket_info* get_first_socket(void)
142 142
 	return 0;
143 143
 }
144 144
 
145
+/* structure to break down 'proto:host:port' */
146
+typedef struct _sr_phostp {
147
+	int proto;
148
+	str host;
149
+	int port;
150
+} sr_phostp_t;
151
+
152
+struct socket_info* lookup_local_socket(str *phostp);
145 153
 
146 154
 #endif