Forráskód Böngészése

core: added a few variants for parsing IPv4/6 addresses

- store parsed structure directly in a provided buffer
- wrapper for parsing either IPv4 or IPv6
Daniel-Constantin Mierla 6 éve
szülő
commit
fb75e90549
2 módosított fájl, 216 hozzáadás és 159 törlés
  1. 209 3
      src/core/resolve.c
  2. 7 156
      src/core/resolve.h

+ 209 - 3
src/core/resolve.c

@@ -1254,7 +1254,7 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
 														  don't find another */
 		/* check if it's an ip address */
 		if (((ip=str2ip(name))!=0)
-			  || ((ip=str2ip6(name))!=0) 
+			  || ((ip=str2ip6(name))!=0)
 			 ){
 			/* we are lucky, this is an ip address */
 			he=ip_addr2he(name, ip);
@@ -1264,7 +1264,7 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
 			LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
 						name->len);
 		}else{
-			
+
 			switch(srv_proto){
 				case PROTO_UDP:
 				case PROTO_TCP:
@@ -1691,7 +1691,7 @@ int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
 						char* proto)
 {
 	struct hostent* he;
-	
+
 	he=sip_resolvehost(name, &port, proto);
 	if (he==0){
 		ser_error=E_BAD_ADDRESS;
@@ -1708,3 +1708,209 @@ int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
 error:
 	return -1;
 }
+
+/* converts a str to an ipv4 address struct stored in ipb
+ * - ipb must be already allocated
+ * - return 0 on success; <0 on failure */
+int str2ipbuf(str* st, ip_addr_t* ipb)
+{
+	int i;
+	unsigned char *limit;
+	unsigned char* s;
+
+	/* just in case that e.g. the VIA parser get confused */
+	if(unlikely(!st->s || st->len <= 0)) {
+		LM_ERR("invalid name, no conversion to IP address possible\n");
+		return 0;
+	}
+	s=(unsigned char*)st->s;
+
+	/*init*/
+	ipb->u.addr32[0]=0;
+	i=0;
+	limit=(unsigned char*)(st->s + st->len);
+
+	for(;s<limit ;s++){
+		if (*s=='.'){
+				i++;
+				if (i>3) goto error_dots;
+		}else if ( (*s <= '9' ) && (*s >= '0') ){
+				ipb->u.addr[i]=ipb->u.addr[i]*10+*s-'0';
+		}else{
+				//error unknown char
+				goto error_char;
+		}
+	}
+	if (i<3) goto error_dots;
+	ipb->af=AF_INET;
+	ipb->len=4;
+
+	return 0;
+
+error_dots:
+	DBG("error - too %s dots in [%.*s]\n", (i>3)?"many":"few",
+			st->len, st->s);
+	return -1;
+ error_char:
+	/*
+	DBG("warning - unexpected char %c in [%.*s]\n", *s, st->len, st->s);
+	*/
+	return -2;
+}
+
+/* converts a str to an ipv4 address, returns the address or 0 on error
+   Warning: the result is a pointer to a statically allocated structure */
+ip_addr_t* str2ip(str* st)
+{
+	static ip_addr_t ip;
+
+	if(str2ipbuf(st, &ip)<0) {
+		return NULL;
+	}
+
+	return &ip;
+}
+
+/* converts a str to an ipv6 address struct stored in ipb
+ * - ipb must be already allocated
+ * - return 0 on success; <0 on failure */
+int str2ip6buf(str* st, ip_addr_t* ipb)
+{
+	int i, idx1, rest;
+	int no_colons;
+	int double_colon;
+	int hex;
+	unsigned short* addr_start;
+	unsigned short addr_end[8];
+	unsigned short* addr;
+	unsigned char* limit;
+	unsigned char* s;
+
+	/* just in case that e.g. the VIA parser get confused */
+	if(unlikely(!st->s || st->len <= 0)) {
+		LM_ERR("invalid name, no conversion to IP address possible\n");
+		return -1;
+	}
+	/* init */
+	if ((st->len) && (st->s[0]=='[')){
+		/* skip over [ ] */
+		if (st->s[st->len-1]!=']') goto error_char;
+		s=(unsigned char*)(st->s+1);
+		limit=(unsigned char*)(st->s+st->len-1);
+	}else{
+		s=(unsigned char*)st->s;
+		limit=(unsigned char*)(st->s+st->len);
+	}
+	i=idx1=rest=0;
+	double_colon=0;
+	no_colons=0;
+	ipb->af=AF_INET6;
+	ipb->len=16;
+	addr_start=ipb->u.addr16;
+	addr=addr_start;
+	memset(addr_start, 0 , 8*sizeof(unsigned short));
+	memset(addr_end, 0 , 8*sizeof(unsigned short));
+	for (; s<limit; s++){
+		if (*s==':'){
+			no_colons++;
+			if (no_colons>7) goto error_too_many_colons;
+			if (double_colon){
+				idx1=i;
+				i=0;
+				if (addr==addr_end) goto error_colons;
+				addr=addr_end;
+			}else{
+				double_colon=1;
+				addr[i]=htons(addr[i]);
+				i++;
+			}
+		}else if ((hex=HEX2I(*s))>=0){
+				addr[i]=addr[i]*16+hex;
+				double_colon=0;
+		}else{
+			/* error, unknown char */
+			goto error_char;
+		}
+	}
+	if (!double_colon){ /* not ending in ':' */
+		addr[i]=htons(addr[i]);
+		i++;
+	}
+	/* if address contained '::' fix it */
+	if (addr==addr_end){
+		rest=8-i-idx1;
+		memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
+	}else{
+		/* no double colons inside */
+		if (no_colons<7) goto error_too_few_colons;
+	}
+/*
+	DBG("idx1=%d, rest=%d, no_colons=%d, hex=%x\n",
+			idx1, rest, no_colons, hex);
+	DBG("address %x:%x:%x:%x:%x:%x:%x:%x\n",
+			addr_start[0], addr_start[1], addr_start[2],
+			addr_start[3], addr_start[4], addr_start[5],
+			addr_start[6], addr_start[7] );
+*/
+	return 0;
+
+error_too_many_colons:
+	DBG("error - too many colons in [%.*s]\n", st->len, st->s);
+	return -1;
+
+error_too_few_colons:
+	DBG("error - too few colons in [%.*s]\n", st->len, st->s);
+	return -2;
+
+error_colons:
+	DBG("error - too many double colons in [%.*s]\n", st->len, st->s);
+	return -3;
+
+error_char:
+	/*
+	DBG("warning - unexpected char %c in  [%.*s]\n", *s, st->len,
+			st->s);*/
+	return -4;
+}
+
+/* returns an ip_addr struct.; on error returns 0
+ * the ip_addr struct is static, so subsequent calls will destroy its content*/
+ip_addr_t* str2ip6(str* st)
+{
+	static ip_addr_t ip;
+
+	if(str2ip6buf(st, &ip)<0) {
+		return NULL;
+	}
+
+	return &ip;
+}
+
+/* converts a str to an ipvv/6 address struct stored in ipb
+ * - ipb must be already allocated
+ * - return 0 on success; <0 on failure */
+int str2ipxbuf(str* st, ip_addr_t* ipb)
+{
+	if (str2ipbuf(st, ipb)<0) {
+		if(str2ip6buf(st, ipb) < 0) {
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+/* returns an ip_addr struct converted from ipv4/6 str; on error returns 0
+ * the ip_addr struct is static, so subsequent calls will destroy its content*/
+struct ip_addr* str2ipx(str* st)
+{
+	static ip_addr_t ip;
+
+	if(str2ipbuf(st, &ip)<0) {
+		if(str2ip6buf(st, &ip)<0) {
+			return NULL;
+		}
+	}
+
+	return &ip;
+}

+ 7 - 156
src/core/resolve.h

@@ -212,161 +212,12 @@ void free_rdata_list(struct rdata* head);
 		(((c)>='a') && ((c)<='f'))? ((c)-'a')+10 : -1 )
 
 
-
-
-
-/* converts a str to an ipv4 address, returns the address or 0 on error
-   Warning: the result is a pointer to a statically allocated structure */
-static inline struct ip_addr* str2ip(str* st)
-{
-	int i;
-	unsigned char *limit;
-	static struct ip_addr ip;
-	unsigned char* s;
-
-	/* just in case that e.g. the VIA parser get confused */
-	if(unlikely(!st->s || st->len <= 0)) {
-		LM_ERR("invalid name, no conversion to IP address possible\n");
-		return 0;
-	}
-	s=(unsigned char*)st->s;
-
-	/*init*/
-	ip.u.addr32[0]=0;
-	i=0;
-	limit=(unsigned char*)(st->s + st->len);
-
-	for(;s<limit ;s++){
-		if (*s=='.'){
-				i++;
-				if (i>3) goto error_dots;
-		}else if ( (*s <= '9' ) && (*s >= '0') ){
-				ip.u.addr[i]=ip.u.addr[i]*10+*s-'0';
-		}else{
-				//error unknown char
-				goto error_char;
-		}
-	}
-	if (i<3) goto error_dots;
-	ip.af=AF_INET;
-	ip.len=4;
-	
-	return &ip;
-error_dots:
-	DBG("str2ip: ERROR: too %s dots in [%.*s]\n", (i>3)?"many":"few", 
-			st->len, st->s);
-	return 0;
- error_char:
-	/*
-	DBG("str2ip: WARNING: unexpected char %c in [%.*s]\n", *s, st->len, st->s);
-	*/
-	return 0;
-}
-
-
-/* returns an ip_addr struct.; on error returns 0
- * the ip_addr struct is static, so subsequent calls will destroy its content*/
-static inline struct ip_addr* str2ip6(str* st)
-{
-	int i, idx1, rest;
-	int no_colons;
-	int double_colon;
-	int hex;
-	static struct ip_addr ip;
-	unsigned short* addr_start;
-	unsigned short addr_end[8];
-	unsigned short* addr;
-	unsigned char* limit;
-	unsigned char* s;
-	
-	/* just in case that e.g. the VIA parser get confused */
-	if(unlikely(!st->s || st->len <= 0)) {
-		LM_ERR("invalid name, no conversion to IP address possible\n");
-		return 0;
-	}
-	/* init */
-	if ((st->len) && (st->s[0]=='[')){
-		/* skip over [ ] */
-		if (st->s[st->len-1]!=']') goto error_char;
-		s=(unsigned char*)(st->s+1);
-		limit=(unsigned char*)(st->s+st->len-1);
-	}else{
-		s=(unsigned char*)st->s;
-		limit=(unsigned char*)(st->s+st->len);
-	}
-	i=idx1=rest=0;
-	double_colon=0;
-	no_colons=0;
-	ip.af=AF_INET6;
-	ip.len=16;
-	addr_start=ip.u.addr16;
-	addr=addr_start;
-	memset(addr_start, 0 , 8*sizeof(unsigned short));
-	memset(addr_end, 0 , 8*sizeof(unsigned short));
-	for (; s<limit; s++){
-		if (*s==':'){
-			no_colons++;
-			if (no_colons>7) goto error_too_many_colons;
-			if (double_colon){
-				idx1=i;
-				i=0;
-				if (addr==addr_end) goto error_colons;
-				addr=addr_end;
-			}else{
-				double_colon=1;
-				addr[i]=htons(addr[i]);
-				i++;
-			}
-		}else if ((hex=HEX2I(*s))>=0){
-				addr[i]=addr[i]*16+hex;
-				double_colon=0;
-		}else{
-			/* error, unknown char */
-			goto error_char;
-		}
-	}
-	if (!double_colon){ /* not ending in ':' */
-		addr[i]=htons(addr[i]);
-		i++; 
-	}
-	/* if address contained '::' fix it */
-	if (addr==addr_end){
-		rest=8-i-idx1;
-		memcpy(addr_start+idx1+rest, addr_end, i*sizeof(unsigned short));
-	}else{
-		/* no double colons inside */
-		if (no_colons<7) goto error_too_few_colons;
-	}
-/*
-	DBG("str2ip6: idx1=%d, rest=%d, no_colons=%d, hex=%x\n",
-			idx1, rest, no_colons, hex);
-	DBG("str2ip6: address %x:%x:%x:%x:%x:%x:%x:%x\n", 
-			addr_start[0], addr_start[1], addr_start[2],
-			addr_start[3], addr_start[4], addr_start[5],
-			addr_start[6], addr_start[7] );
-*/
-	return &ip;
-
-error_too_many_colons:
-	DBG("str2ip6: ERROR: too many colons in [%.*s]\n", st->len, st->s);
-	return 0;
-
-error_too_few_colons:
-	DBG("str2ip6: ERROR: too few colons in [%.*s]\n", st->len, st->s);
-	return 0;
-
-error_colons:
-	DBG("str2ip6: ERROR: too many double colons in [%.*s]\n", st->len, st->s);
-	return 0;
-
-error_char:
-	/*
-	DBG("str2ip6: WARNING: unexpected char %c in  [%.*s]\n", *s, st->len,
-			st->s);*/
-	return 0;
-}
-
-
+int str2ipbuf(str* st, ip_addr_t* ipb);
+int str2ip6buf(str* st, ip_addr_t* ipb);
+int str2ipxbuf(str* st, ip_addr_t* ipb);
+ip_addr_t* str2ip(str* st);
+ip_addr_t* str2ip6(str* st);
+ip_addr_t* str2ipx(str* st);
 
 struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto);
 
@@ -376,7 +227,7 @@ struct hostent* _sip_resolvehost(str* name, unsigned short* port, char* proto);
 static inline struct hostent* _resolvehost(char* name)
 {
 	static struct hostent* he=0;
-#ifdef HAVE_GETIPNODEBYNAME 
+#ifdef HAVE_GETIPNODEBYNAME
 	int err;
 	static struct hostent* he2=0;
 #endif