|
@@ -1254,7 +1254,7 @@ struct hostent* srv_sip_resolvehost(str* name, int zt, unsigned short* port,
|
|
don't find another */
|
|
don't find another */
|
|
/* check if it's an ip address */
|
|
/* check if it's an ip address */
|
|
if (((ip=str2ip(name))!=0)
|
|
if (((ip=str2ip(name))!=0)
|
|
- || ((ip=str2ip6(name))!=0)
|
|
|
|
|
|
+ || ((ip=str2ip6(name))!=0)
|
|
){
|
|
){
|
|
/* we are lucky, this is an ip address */
|
|
/* we are lucky, this is an ip address */
|
|
he=ip_addr2he(name, ip);
|
|
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",
|
|
LM_WARN("domain name too long (%d), unable to perform SRV lookup\n",
|
|
name->len);
|
|
name->len);
|
|
}else{
|
|
}else{
|
|
-
|
|
|
|
|
|
+
|
|
switch(srv_proto){
|
|
switch(srv_proto){
|
|
case PROTO_UDP:
|
|
case PROTO_UDP:
|
|
case PROTO_TCP:
|
|
case PROTO_TCP:
|
|
@@ -1691,7 +1691,7 @@ int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
|
|
char* proto)
|
|
char* proto)
|
|
{
|
|
{
|
|
struct hostent* he;
|
|
struct hostent* he;
|
|
-
|
|
|
|
|
|
+
|
|
he=sip_resolvehost(name, &port, proto);
|
|
he=sip_resolvehost(name, &port, proto);
|
|
if (he==0){
|
|
if (he==0){
|
|
ser_error=E_BAD_ADDRESS;
|
|
ser_error=E_BAD_ADDRESS;
|
|
@@ -1708,3 +1708,209 @@ int sip_hostport2su(union sockaddr_union* su, str* name, unsigned short port,
|
|
error:
|
|
error:
|
|
return -1;
|
|
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;
|
|
|
|
+}
|