Hello Juha,

On 12/15/2011 01:22 PM, Juha Heinanen wrote:
>> Just realized that lcr module does not support IPv6 yet. Is there
>> already any work going on here? Otherwise we'd take this task over.
> 
> i don't know of such work.  if you decide to do it, try to not cause any
> performance hit for current ipv4 usage.

Please find attached the patch against git master, courtesy of my
colleague Richard Fuchs <rfuchs at sipwise.com>.

Please review and apply if acceptable.

Andreas
diff --git a/modules/lcr/hash.c b/modules/lcr/hash.c
index 4e24c94..2082ad8 100644
--- a/modules/lcr/hash.c
+++ b/modules/lcr/hash.c
@@ -88,7 +88,7 @@ int get_gw_index(struct gw_info *gws, unsigned int gw_id,
 {
     unsigned short gw_count, i;
 
-    gw_count = gws[0].ip_addr;
+    gw_count = gws[0].ip_addr.u.addr32[0];
 
     for (i = 1; i <= gw_count; i++) {
 	if (gws[i].gw_id == gw_id) {
diff --git a/modules/lcr/lcr_mod.c b/modules/lcr/lcr_mod.c
index dac5c7d..8f8d373 100644
--- a/modules/lcr/lcr_mod.c
+++ b/modules/lcr/lcr_mod.c
@@ -786,10 +786,11 @@ static int comp_gws(const void *_g1, const void *_g2)
     struct gw_info *g1 = (struct gw_info *)_g1;
     struct gw_info *g2 = (struct gw_info *)_g2;
 
-    if (g1->ip_addr < g2->ip_addr) return -1;
-    if (g1->ip_addr > g2->ip_addr) return 1;
-
-    return 0;
+    if (g1->ip_addr.af < g2->ip_addr.af)   return -1;
+    if (g1->ip_addr.af > g2->ip_addr.af)   return  1;
+    if (g1->ip_addr.len < g2->ip_addr.len) return -1;
+    if (g1->ip_addr.len > g2->ip_addr.len) return  1;
+    return memcmp(g1->ip_addr.u.addr, g2->ip_addr.u.addr, g1->ip_addr.len);
 }
 
 
@@ -798,7 +799,7 @@ static int comp_gws(const void *_g1, const void *_g2)
  */
 static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id,
 		     char *gw_name, unsigned int gw_name_len,
-		     unsigned int scheme, unsigned int ip_addr,
+		     unsigned int scheme, struct ip_addr *ip_addr,
 		     unsigned int port, unsigned int transport,
 		     char *params, unsigned int params_len,
 		     char *hostname, unsigned int hostname_len,
@@ -810,7 +811,7 @@ static int insert_gw(struct gw_info *gws, unsigned int i, unsigned int gw_id,
     if (gw_name_len) memcpy(&(gws[i].gw_name[0]), gw_name, gw_name_len);
     gws[i].gw_name_len = gw_name_len;
     gws[i].scheme = scheme;
-    gws[i].ip_addr = ip_addr;
+    gws[i].ip_addr = *ip_addr;
     gws[i].port = port;
     gws[i].transport = transport;
     if (params_len) memcpy(&(gws[i].params[0]), params, params_len);
@@ -885,10 +886,11 @@ int reload_tables()
 	tag_len, prefix_len, from_uri_len, stopper, enabled, flags, gw_cnt,
 	hostname_len, params_len, defunct_until, null_gw_ip_addr, priority,
 	weight, tmp;
-    struct in_addr ip_addr;
+    struct in_addr in_addr;
+    struct ip_addr ip_addr, *ip_p;
     uri_type scheme;
     uri_transport transport;
-    char *gw_name, *ip_string, *hostname, *tag, *prefix, *from_uri, *params;
+    char *gw_name, *hostname, *tag, *prefix, *from_uri, *params;
     db1_res_t* res = NULL;
     db_row_t* row;
     db_key_t key_cols[1];
@@ -900,6 +902,7 @@ int reload_tables()
     pcre *from_uri_re;
     struct gw_info *gws, *gw_pt_tmp;
     struct rule_info **rules, **rule_pt_tmp;
+    str ip_string;
 
     key_cols[0] = &lcr_id_col;
     op[0] = OP_EQ;
@@ -1152,14 +1155,32 @@ int reload_tables()
 		goto err;
 	    }
 	    if (VAL_NULL(ROW_VALUES(row) + 1)) {
-		ip_string = (char *)0;
-		ip_addr.s_addr = 0;
+		ip_string.s = (char *)0;
+		ip_addr.af = 0;
+		ip_addr.len = 0;
 		null_gw_ip_addr = 1;
 	    } else {
-		ip_string = (char *)VAL_STRING(ROW_VALUES(row) + 1);
-		if (inet_aton(ip_string, &ip_addr) == 0) {
+		ip_string.s = (char *)VAL_STRING(ROW_VALUES(row) + 1);
+		ip_string.len = strlen(ip_string.s);
+		if ((ip_p = str2ip(&ip_string))) {
+		    /* 123.123.123.123 */
+		    ip_addr = *ip_p;
+		}
+#ifdef USE_IPV6
+		else if ((ip_p = str2ip6(&ip_string))) {
+		    /* fe80::123:4567:89ab:cdef and [fe80::123:4567:89ab:cdef] */
+		    ip_addr = *ip_p;
+		}
+#endif
+		else if (inet_aton(ip_string.s, &in_addr) == 0) {
+		    /* backwards compatibility for integer or hex notations */
+		    ip_addr.u.addr32[0] = in_addr.s_addr;
+		    ip_addr.af = AF_INET;
+		    ip_addr.len = 4;
+		}
+		else {
 		    LM_ERR("lcr_gw ip_addr <%s> at row <%u> is invalid\n",
-			   ip_string, i);
+			   ip_string.s, i);
 		    goto err;
 		}
 	    }
@@ -1233,7 +1254,7 @@ int reload_tables()
 		goto err;
 	    }
 	    if (VAL_NULL(ROW_VALUES(row) + 6)) {
-		if (ip_string == 0) {
+		if (ip_string.s == 0) {
 		    LM_ERR("lcr_gw gw ip_addr and hostname are both null "
 			   "at row <%u>\n", i);
 		    goto err;
@@ -1307,9 +1328,9 @@ int reload_tables()
 	    }
 	    gw_cnt++;
 	    if (!insert_gw(gws, gw_cnt, gw_id, gw_name, gw_name_len,
-			   scheme, (unsigned int)ip_addr.s_addr, port,
+			   scheme, &ip_addr, port,
 			   transport, params, params_len, hostname,
-			   hostname_len, ip_string, strip, prefix, prefix_len,
+			   hostname_len, ip_string.s, strip, prefix, prefix_len,
 			   tag, tag_len, flags, defunct_until)) {
 		goto err;
 	    }
@@ -1319,7 +1340,7 @@ int reload_tables()
 	res = NULL;
 
 	qsort(&(gws[1]), gw_cnt, sizeof(struct gw_info), comp_gws);
-	gws[0].ip_addr = gw_cnt;
+	gws[0].ip_addr.u.addr32[0] = gw_cnt;
 	gws[0].port = null_gw_ip_addr;
 
 	/* Reload targets */
@@ -1438,7 +1459,7 @@ inline int encode_avp_value(char *value, unsigned int gw_index, uri_type scheme,
 			    unsigned int strip,
 			    char *prefix, unsigned int prefix_len,
 			    char *tag, unsigned int tag_len,
-			    unsigned int ip_addr, char *hostname, 
+			    struct ip_addr *ip_addr, char *hostname, 
 			    unsigned int hostname_len, unsigned int port,
 			    char *params, unsigned int params_len,
 			    uri_transport transport, unsigned int flags)
@@ -1467,10 +1488,17 @@ inline int encode_avp_value(char *value, unsigned int gw_index, uri_type scheme,
     append_str(at, tag, tag_len);
     append_chr(at, '|');
     /* ip_addr */
-    if (ip_addr > 0) {
-	string = int2str(ip_addr, &len);
+    if (ip_addr->af == AF_INET && ip_addr->u.addr32[0] > 0) {
+	string = int2str(ip_addr->u.addr32[0], &len);
 	append_str(at, string, len);
     }
+#ifdef USE_IPV6
+    else if (ip_addr->af == AF_INET6 && !ip_addr_any(ip_addr)) {
+	append_chr(at, '[');
+	at += ip6tosbuf(ip_addr->u.addr, at, MAX_URI_LEN - (at - value));
+	append_chr(at, ']');
+    }
+#endif
     append_chr(at, '|');
     /* hostname */
     append_str(at, hostname, hostname_len);
@@ -1496,12 +1524,13 @@ inline int encode_avp_value(char *value, unsigned int gw_index, uri_type scheme,
 
 inline int decode_avp_value(char *value, unsigned int *gw_index, str *scheme,
 			    unsigned int *strip, str *prefix, str *tag,
-			    unsigned int *addr, str *hostname, str *port,
+			    struct ip_addr *addr, str *hostname, str *port,
 			    str *params, str *transport, unsigned int *flags)
 {
     unsigned int u;
     str s;
     char *sep;
+    struct ip_addr *ip;
 
     /* gw index */
     s.s = value;
@@ -1562,9 +1591,20 @@ inline int decode_avp_value(char *value, unsigned int *gw_index, str *scheme,
     }
     s.len = sep - s.s;
     if (s.len > 0) {
-	str2int(&s, addr);
+	if ((ip = str2ip(&s)) != NULL)
+	    *addr = *ip;
+#ifdef USE_IPV6
+	else if ((ip = str2ip6(&s)) != NULL)
+	    *addr = *ip;
+#endif
+	else {
+	    str2int(&s, &u);
+	    addr->af = AF_INET;
+	    addr->len = 4;
+	    addr->u.addr32[0] = u;
+	}
     } else {
-	*addr = 0;
+	addr->af = 0;
     }
     /* hostname */
     hostname->s = sep + 1;
@@ -1659,7 +1699,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
 	tag_len = gws[index].tag_len;
 	if (5 /* gw_index */ + 5 /* scheme */ + 4 /* strip */ + prefix_len +
 	    tag_len + 1 /* @ */ +
-	    ((hostname_len > 15)?hostname_len:15) + 6 /* port */ +
+	    ((hostname_len > IP6_MAX_STR_SIZE+2)?hostname_len:IP6_MAX_STR_SIZE+2) + 6 /* port */ +
 	    params_len /* params */ + 15 /* transport */ + 10 /* flags */ +
 	    7 /* separators */ > MAX_URI_LEN) {
 	    LM_ERR("too long AVP value\n");
@@ -1669,7 +1709,7 @@ void add_gws_into_avps(struct gw_info *gws, struct matched_gw_info *matched_gws,
 	    encode_avp_value(encoded_value, index, gws[index].scheme,
 			     strip, gws[index].prefix, prefix_len,
 			     gws[index].tag, tag_len,
-			     gws[index].ip_addr,
+			     &gws[index].ip_addr,
 			     gws[index].hostname, hostname_len,
 			     gws[index].port, gws[index].params, params_len,
 			     gws[index].transport, gws[index].flags);
@@ -1834,7 +1874,7 @@ static int load_gws(struct sip_msg* _m, int argc, action_u_t argv[])
 /* Generate Request-URI and Destination URI */
 static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
 			 unsigned int *r_uri_len, char *dst_uri,
-			 unsigned int *dst_uri_len, unsigned int *addr,
+			 unsigned int *dst_uri_len, struct ip_addr *addr,
 			 unsigned int *gw_index, unsigned int *flags,
 			 str *tag)
 {
@@ -1844,7 +1884,6 @@ static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
 	tmp_tag;
     char *at;
     unsigned int strip;
-    struct ip_addr a;
     
     gu_avp = search_first_avp(gw_uri_avp_type, gw_uri_avp, &gw_uri_val, 0);
 
@@ -1854,18 +1893,15 @@ static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
 		     &tmp_tag, addr, &hostname, &port, &params, &transport,
 		     flags);
 
-    if (*addr > 0) {
-	a.af = AF_INET;
-	a.len = 4;
-	a.u.addr32[0] = *addr;
-	addr_str.s = ip_addr2a(&a);
+    if (addr->af != 0) {
+	addr_str.s = ip_addr2a(addr);
 	addr_str.len = strlen(addr_str.s);
     } else {
 	addr_str.len = 0;
     }
     
     if (scheme.len + r_uri_user->len - strip + prefix.len + 1 /* @ */ +
-	((hostname.len > 15)?hostname.len:15) + 1 /* : */ +
+	((hostname.len > IP6_MAX_STR_SIZE+2)?hostname.len:IP6_MAX_STR_SIZE+2) + 1 /* : */ +
 	port.len + params.len + transport.len + 1 /* null */ > MAX_URI_LEN) {
 	LM_ERR("too long Request URI or DST URI\n");
 	return -1;
@@ -1901,7 +1937,11 @@ static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
 	*r_uri_len = at - r_uri;
 	at = dst_uri;
 	append_str(at, scheme.s, scheme.len);
+	if (addr->af == AF_INET6)
+	    append_chr(at, '[');
 	append_str(at, addr_str.s, addr_str.len);
+	if (addr->af == AF_INET6)
+	    append_chr(at, ']');
 	if (port.len > 0) {
 	    append_chr(at, ':');
 	    append_str(at, port.s, port.len);
@@ -1915,7 +1955,11 @@ static int generate_uris(struct sip_msg* _m, char *r_uri, str *r_uri_user,
 	/* either ip_addr or hostname specified:
 	   place the given one in r-uri and leave dst-uri empty */
 	if (addr_str.len > 0) {
+	    if (addr->af == AF_INET6)
+		append_chr(at, '[');
 	    append_str(at, addr_str.s, addr_str.len);
+	    if (addr->af == AF_INET6)
+		append_chr(at, ']');
 	} else {
 	    append_str(at, hostname.s, hostname.len);
 	}
@@ -1990,7 +2034,7 @@ static int defunct_gw(struct sip_msg* _m, char *_defunct_period, char *_s2)
 	return -1;
     }
     gw_index = index_val.n;
-    if ((gw_index < 1) || (gw_index > gws[0].ip_addr)) {
+    if ((gw_index < 1) || (gw_index > gws[0].ip_addr.u.addr32[0])) {
 	LM_ERR("gw index <%u> is out of bounds\n", gw_index);
 	return -1;
     }
@@ -2023,8 +2067,9 @@ static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
     int rval;
     str uri_str, tag_str;
     char tag[MAX_TAG_LEN];
-    unsigned int flags, r_uri_len, dst_uri_len, addr, gw_index;
+    unsigned int flags, r_uri_len, dst_uri_len, gw_index;
     char r_uri[MAX_URI_LEN], dst_uri[MAX_URI_LEN];
+    struct ip_addr addr;
 
     tag_str.s = &(tag[0]);
 
@@ -2103,7 +2148,7 @@ static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
 	delete_avp(defunct_gw_avp_type, defunct_gw_avp);
 	val.n = gw_index;
 	add_avp(defunct_gw_avp_type, defunct_gw_avp, val);
-	LM_DBG("added defunct_gw_avp <%u>", addr);
+	LM_DBG("added defunct_gw_avp <%u>", addr.u.addr32[0]);
     }
     
     return 1;
@@ -2114,7 +2159,7 @@ static int next_gw(struct sip_msg* _m, char* _s1, char* _s2)
  * Checks if request comes from ip address of a gateway
  */
 static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
-		      unsigned int src_addr, uri_transport transport)
+		      struct ip_addr *src_addr, uri_transport transport)
 {
     struct gw_info *res, gw, *gws;
     int_str val;
@@ -2128,8 +2173,8 @@ static int do_from_gw(struct sip_msg* _m, unsigned int lcr_id,
     }
 
     /* Search for gw ip address */
-    gw.ip_addr = src_addr;
-    res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr,
+    gw.ip_addr = *src_addr;
+    res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
 				    sizeof(struct gw_info), comp_gws);
 
     /* Store tag and flags and return result */
@@ -2164,7 +2209,6 @@ static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
 {
     int lcr_id;
     char *tmp;
-    unsigned int src_addr;
     uri_transport transport;
 
     /* Get and check parameter value */
@@ -2178,12 +2222,11 @@ static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
 	return -1;
     }
 
-    /* Get source address and transport protocol */
-    src_addr = _m->rcv.src_ip.u.addr32[0];
+    /* Get transport protocol */
     transport = _m->rcv.proto;
 
     /* Do test */
-    return do_from_gw(_m, lcr_id, src_addr, transport);
+    return do_from_gw(_m, lcr_id, &_m->rcv.src_ip, transport);
 }
 
 
@@ -2194,7 +2237,7 @@ static int from_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
 static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
 		     char* _transport)
 {
-    unsigned int src_addr;
+    struct ip_addr src_addr;
     int lcr_id;
     char *tmp;
     struct ip_addr *ip;
@@ -2213,11 +2256,15 @@ static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
     }
     addr_str.s = _addr;
     addr_str.len = strlen(_addr);
-    if ((ip = str2ip(&addr_str)) == NULL) {
+    if ((ip = str2ip(&addr_str)) != NULL)
+	src_addr = *ip;
+#ifdef USE_IPV6
+    else if ((ip = str2ip6(&addr_str)) != NULL)
+	src_addr = *ip;
+#endif
+    else {
 	LM_ERR("addr param value %s is not an IP address\n", _addr);
 	return -1;
-    } else {
-	src_addr = ip->u.addr32[0];
     }
     transport = strtol(_transport, &tmp, 10);
     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
@@ -2230,7 +2277,7 @@ static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
     }
 
     /* Do test */
-    return do_from_gw(_m, lcr_id, src_addr, transport);
+    return do_from_gw(_m, lcr_id, &src_addr, transport);
 }
 
 
@@ -2240,14 +2287,13 @@ static int from_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
  */
 static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
 {
-    unsigned int src_addr, i;
+    unsigned int i;
     uri_transport transport;
 
-    src_addr = _m->rcv.src_ip.u.addr32[0];
     transport = _m->rcv.proto;
 
     for (i = 1; i <= lcr_count_param; i++) {
-	if (do_from_gw(_m, i, src_addr, transport) == 1) {
+	if (do_from_gw(_m, i, &_m->rcv.src_ip, transport) == 1) {
 	    return i;
 	}
     }
@@ -2261,20 +2307,24 @@ static int from_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
  */
 static int from_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
 {
-    unsigned int i, src_addr;
+    unsigned int i;
     char *tmp;
-    struct ip_addr *ip;
+    struct ip_addr *ip, src_addr;
     str addr_str;
     uri_transport transport;
 
     /* Get and check parameter values */
     addr_str.s = _addr;
     addr_str.len = strlen(_addr);
-    if ((ip = str2ip(&addr_str)) == NULL) {
+    if ((ip = str2ip(&addr_str)) != NULL)
+	src_addr = *ip;
+#ifdef USE_IPV6
+    else if ((ip = str2ip6(&addr_str)) != NULL)
+	src_addr = *ip;
+#endif
+    else {
 	LM_ERR("addr param value %s is not an IP address\n", _addr);
 	return -1;
-    } else {
-	src_addr = ip->u.addr32[0];
     }
     transport = strtol(_transport, &tmp, 10);
     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
@@ -2288,7 +2338,7 @@ static int from_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
 
     /* Do test */
     for (i = 1; i <= lcr_count_param; i++) {
-	if (do_from_gw(_m, i, src_addr, transport) == 1) {
+	if (do_from_gw(_m, i, &src_addr, transport) == 1) {
 	    return i;
 	}
     }
@@ -2300,7 +2350,7 @@ static int from_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
  * Checks if in-dialog request goes to ip address of a gateway.
  */
 static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
-		    unsigned int dst_addr, uri_transport transport)
+		    struct ip_addr *dst_addr, uri_transport transport)
 {
     struct gw_info *res, gw, *gws;
 
@@ -2313,8 +2363,8 @@ static int do_to_gw(struct sip_msg* _m, unsigned int lcr_id,
     }
 
     /* Search for gw ip address */
-    gw.ip_addr = dst_addr;
-    res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr,
+    gw.ip_addr = *dst_addr;
+    res = (struct gw_info *)bsearch(&gw, &(gws[1]), gws[0].ip_addr.u.addr32[0],
 				    sizeof(struct gw_info), comp_gws);
 
     /* Return result */
@@ -2339,8 +2389,7 @@ static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
 {
     int lcr_id;
     char *tmp;
-    unsigned int dst_addr;
-    struct ip_addr *ip;
+    struct ip_addr *ip, dst_addr;
     uri_transport transport;
 
     /* Get and check parameter value */
@@ -2359,22 +2408,26 @@ static int to_gw_1(struct sip_msg* _m, char* _lcr_id, char* _s2)
 	LM_ERR("while parsing Request-URI\n");
 	return -1;
     }
-    if (_m->parsed_uri.host.len > 15) {
+    if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
 	LM_DBG("request is not going to gw "
 	       "(Request-URI host is not an IP address)\n");
 	return -1;
     }
-    if ((ip = str2ip(&(_m->parsed_uri.host))) == NULL) {
+    if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
+	dst_addr = *ip;
+#ifdef USE_IPV6
+    else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
+	dst_addr = *ip;
+#endif
+    else {
 	LM_DBG("request is not going to gw "
 	       "(Request-URI host is not an IP address)\n");
 	return -1;
-    } else {
-	dst_addr = ip->u.addr32[0];
     }
     transport = _m->parsed_uri.proto;
 
     /* Do test */
-    return do_to_gw(_m, lcr_id, dst_addr, transport);
+    return do_to_gw(_m, lcr_id, &dst_addr, transport);
 }
 
 
@@ -2387,8 +2440,7 @@ static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
 {
     int lcr_id;
     char *tmp;
-    unsigned int dst_addr;
-    struct ip_addr *ip;
+    struct ip_addr *ip, dst_addr;
     str addr_str;
     uri_transport transport;
 
@@ -2404,11 +2456,15 @@ static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
     }
     addr_str.s = _addr;
     addr_str.len = strlen(_addr);
-    if ((ip = str2ip(&addr_str)) == NULL) {
+    if ((ip = str2ip(&addr_str)) != NULL)
+	dst_addr = *ip;
+#ifdef USE_IPV6
+    else if ((ip = str2ip(&addr_str)) != NULL)
+	dst_addr = *ip;
+#endif
+    else {
 	LM_ERR("addr param value %s is not an IP address\n", _addr);
 	return -1;
-    } else {
-	dst_addr = ip->u.addr32[0];
     }
     transport = strtol(_transport, &tmp, 10);
     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
@@ -2421,7 +2477,7 @@ static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
     }
     
     /* Do test */
-    return do_to_gw(_m, lcr_id, dst_addr, transport);
+    return do_to_gw(_m, lcr_id, &dst_addr, transport);
 }
 
 
@@ -2431,8 +2487,8 @@ static int to_gw_3(struct sip_msg* _m, char* _lcr_id, char* _addr,
  */
 static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
 {
-    unsigned int dst_addr, i;
-    struct ip_addr *ip;
+    unsigned int i;
+    struct ip_addr *ip, dst_addr;
     uri_transport transport;
 
     /* Get destination address and transport protocol from R-URI */
@@ -2440,23 +2496,27 @@ static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
 	LM_ERR("while parsing Request-URI\n");
 	return -1;
     }
-    if (_m->parsed_uri.host.len > 15) {
+    if (_m->parsed_uri.host.len > IP6_MAX_STR_SIZE+2) {
 	LM_DBG("request is not going to gw "
 	       "(Request-URI host is not an IP address)\n");
 	return -1;
     }
-    if ((ip = str2ip(&(_m->parsed_uri.host))) == NULL) {
+    if ((ip = str2ip(&(_m->parsed_uri.host))) != NULL)
+	dst_addr = *ip;
+#ifdef USE_IPV6
+    else if ((ip = str2ip6(&(_m->parsed_uri.host))) != NULL)
+	dst_addr = *ip;
+#endif
+    else {
 	LM_DBG("request is not going to gw "
 	       "(Request-URI host is not an IP address)\n");
 	return -1;
-    } else {
-	dst_addr = ip->u.addr32[0];
     }
     transport = _m->parsed_uri.proto;
 
     /* Do test */
     for (i = 1; i <= lcr_count_param; i++) {
-	if (do_to_gw(_m, i, dst_addr, transport) == 1) {
+	if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
 	    return i;
 	}
     }
@@ -2470,20 +2530,24 @@ static int to_any_gw_0(struct sip_msg* _m, char* _s1, char* _s2)
  */
 static int to_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
 {
-    unsigned int i, dst_addr;
+    unsigned int i;
     char *tmp;
-    struct ip_addr *ip;
+    struct ip_addr *ip, dst_addr;
     uri_transport transport;
     str addr_str;
 
     /* Get and check parameter values */
     addr_str.s = _addr;
     addr_str.len = strlen(_addr);
-    if ((ip = str2ip(&addr_str)) == NULL) {
+    if ((ip = str2ip(&addr_str)) != NULL)
+	dst_addr = *ip;
+#ifdef USE_IPV6
+    if ((ip = str2ip6(&addr_str)) != NULL)
+	dst_addr = *ip;
+#endif
+    else {
 	LM_ERR("addr param value %s is not an IP address\n", _addr);
 	return -1;
-    } else {
-	dst_addr = ip->u.addr32[0];
     }
     transport = strtol(_transport, &tmp, 10);
     if ((tmp == 0) || (*tmp) || (tmp == _transport)) {
@@ -2497,7 +2561,7 @@ static int to_any_gw_2(struct sip_msg* _m, char* _addr, char* _transport)
 
     /* Do test */
     for (i = 1; i <= lcr_count_param; i++) {
-	if (do_to_gw(_m, i, dst_addr, transport) == 1) {
+	if (do_to_gw(_m, i, &dst_addr, transport) == 1) {
 	    return i;
 	}
     }
diff --git a/modules/lcr/lcr_mod.h b/modules/lcr/lcr_mod.h
index 16c0b16..e544f68 100644
--- a/modules/lcr/lcr_mod.h
+++ b/modules/lcr/lcr_mod.h
@@ -42,6 +42,7 @@
 #include "../../lib/kmi/mi.h"
 #include "../../locking.h"
 #include "../../parser/parse_uri.h"
+#include "../../ip_addr.h"
 
 #define MAX_PREFIX_LEN 16
 #define MAX_URI_LEN 256
@@ -84,7 +85,7 @@ struct gw_info {
     char gw_name[MAX_NAME_LEN];
     unsigned short gw_name_len;
     uri_type scheme;
-    unsigned int ip_addr;
+    struct ip_addr ip_addr;
     char hostname[MAX_HOST_LEN];
     unsigned short hostname_len;
     unsigned int port;
diff --git a/modules/lcr/lcr_rpc.c b/modules/lcr/lcr_rpc.c
index b32b697..f70c042 100644
--- a/modules/lcr/lcr_rpc.c
+++ b/modules/lcr/lcr_rpc.c
@@ -72,7 +72,7 @@ static void dump_gws(rpc_t* rpc, void* c)
 
 	gws = gw_pt[j];
 
-	for (i = 1; i <= gws[0].ip_addr; i++) {
+	for (i = 1; i <= gws[0].ip_addr.u.addr32[0]; i++) {
 	    if (rpc->add(c, "{", &st) < 0) return;
 	    rpc->struct_add(st, "d", "lcr_id", j);
 	    rpc->struct_add(st, "d", "gw_id", gws[i].gw_id);
@@ -85,11 +85,22 @@ static void dump_gws(rpc_t* rpc, void* c)
 	    } else {
 		rpc->struct_add(st, "s", "scheme", "sips");
 	    }
-	    rpc->struct_printf(st, "ip_addr", "%d.%d.%d.%d",
-			       (gws[i].ip_addr << 24) >> 24,
-			       ((gws[i].ip_addr >> 8) << 24) >> 24,
-			       ((gws[i].ip_addr >> 16) << 24) >> 24,
-			       gws[i].ip_addr >> 24);
+	    if (gws[i].ip_addr.af == AF_INET)
+		rpc->struct_printf(st, "ip_addr", "%d.%d.%d.%d",
+					gws[i].ip_addr.u.addr32[0],
+					gws[i].ip_addr.u.addr32[1],
+					gws[i].ip_addr.u.addr32[2],
+					gws[i].ip_addr.u.addr32[3]);
+	    else /* AF_INET6 */
+		rpc->struct_printf(st, "ip_addr", "%x:%x:%x:%x:%x:%x:%x:%x",
+					gws[i].ip_addr.u.addr16[0],
+					gws[i].ip_addr.u.addr16[1],
+					gws[i].ip_addr.u.addr16[2],
+					gws[i].ip_addr.u.addr16[3],
+					gws[i].ip_addr.u.addr16[4],
+					gws[i].ip_addr.u.addr16[5],
+					gws[i].ip_addr.u.addr16[6],
+					gws[i].ip_addr.u.addr16[7]);
 	    hostname.s=gws[i].hostname;
 	    hostname.len=gws[i].hostname_len;
 	    rpc->struct_add(st, "S", "hostname", &hostname);

Attachment: signature.asc
Description: OpenPGP digital signature

_______________________________________________
SIP Express Router (SER) and Kamailio (OpenSER) - sr-users mailing list
sr-users@lists.sip-router.org
http://lists.sip-router.org/cgi-bin/mailman/listinfo/sr-users

Reply via email to