From 7533d802229c182177369193a25d0bc9795564c7 Mon Sep 17 00:00:00 2001 From: Ihor Olkhovskyi Date: Mon, 4 May 2026 16:15:00 +0200 Subject: [PATCH] add ip.resolve4/resolve6 transformations --- resolve.c | 25 ++++++++++++++++--------- resolve.h | 2 ++ transformations.c | 15 ++++++++++++++- transformations.h | 2 +- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/resolve.c b/resolve.c index 3e9b84b42c1..52b7c982229 100644 --- a/resolve.c +++ b/resolve.c @@ -492,7 +492,7 @@ struct hostent* own_gethostbyname2(char *name,int af) return &global_he; } -inline struct hostent* resolvehost(char* name, int no_ip_test) +inline struct hostent* resolvehost_af(char* name, int no_ip_test, int af) { static struct hostent *he = NULL; #ifdef HAVE_GETIPNODEBYNAME @@ -508,15 +508,15 @@ inline struct hostent* resolvehost(char* name, int no_ip_test) s.len = strlen(name); /* check if it's an ip address */ - if ((ip = str2ip(&s)) || (ip = str2ip6(&s))) { - /* we are lucky, this is an ip address */ + if (af != AF_INET6 && (ip = str2ip(&s))) + return ip_addr2he(&s, ip); + if (af != AF_INET && (ip = str2ip6(&s))) return ip_addr2he(&s, ip); - } } start_expire_timer(start, execdnsthreshold); - if (dns_try_ipv6) { + if (af == AF_INET6 || (af == 0 && dns_try_ipv6)) { /* try ipv6 */ #ifdef HAVE_GETHOSTBYNAME2 if (dnscache_fetch_func) @@ -538,10 +538,12 @@ inline struct hostent* resolvehost(char* name, int no_ip_test) goto out; } - if (dnscache_fetch_func) - he = own_gethostbyname2(name,AF_INET); - else - he = gethostbyname(name); + if (af != AF_INET6) { + if (dnscache_fetch_func) + he = own_gethostbyname2(name,AF_INET); + else + he = gethostbyname(name); + } out: _stop_expire_timer(start, execdnsthreshold, "dns", @@ -549,6 +551,11 @@ inline struct hostent* resolvehost(char* name, int no_ip_test) return he; } +inline struct hostent* resolvehost(char* name, int no_ip_test) +{ + return resolvehost_af(name, no_ip_test, 0); +} + struct hostent * own_gethostbyaddr(void *addr, socklen_t len, int af) { const unsigned char *uaddr = (const u_char *)addr; diff --git a/resolve.h b/resolve.h index 6c5f84c8485..cef6524aff5 100644 --- a/resolve.h +++ b/resolve.h @@ -173,6 +173,8 @@ struct hostent* sip_resolvehost(str* name, unsigned short* port, struct hostent* resolvehost(char* name, int no_ip_test); +struct hostent* resolvehost_af(char* name, int no_ip_test, int af); + struct hostent* rev_resolvehost(struct ip_addr *ip); /*! \brief free the DNS resolver state machine */ diff --git a/transformations.c b/transformations.c index 037f8f39b8d..8d997d5cddb 100644 --- a/transformations.c +++ b/transformations.c @@ -1937,6 +1937,8 @@ int tr_eval_ip(struct sip_msg *msg, tr_param_t *tp,int subtype, val->flags = PV_VAL_STR; break; case TR_IP_RESOLVE: + case TR_IP_RESOLVE_V4: + case TR_IP_RESOLVE_V6: val->flags = PV_VAL_STR; if (val->rs.len + 1 > TR_BUFFER_SIZE) { LM_ERR("failed to resolve host, length too large (%d)\n", @@ -1946,7 +1948,12 @@ int tr_eval_ip(struct sip_msg *msg, tr_param_t *tp,int subtype, memcpy(_tr_buffer, val->rs.s, val->rs.len); _tr_buffer[val->rs.len] = '\0'; - server = resolvehost(_tr_buffer, 0); + if (subtype == TR_IP_RESOLVE_V4) + server = resolvehost_af(_tr_buffer, 0, AF_INET); + else if (subtype == TR_IP_RESOLVE_V6) + server = resolvehost_af(_tr_buffer, 0, AF_INET6); + else + server = resolvehost(_tr_buffer, 0); if (!server || !server->h_addr) { val->flags = PV_VAL_NULL; @@ -3810,6 +3817,12 @@ int tr_parse_ip(str *in, trans_t *t) } else if (name.len == 7 && strncasecmp(name.s,"resolve",7) == 0) { t->subtype = TR_IP_RESOLVE; return 0; + } else if (name.len == 8 && strncasecmp(name.s,"resolve4",8) == 0) { + t->subtype = TR_IP_RESOLVE_V4; + return 0; + } else if (name.len == 8 && strncasecmp(name.s,"resolve6",8) == 0) { + t->subtype = TR_IP_RESOLVE_V6; + return 0; } else if (name.len == 7 && strncasecmp(name.s,"matches",5) == 0) { t->subtype = TR_IP_MATCHES; if(*p!=TR_PARAM_MARKER) diff --git a/transformations.h b/transformations.h index 626790fd89f..67e62722b74 100644 --- a/transformations.h +++ b/transformations.h @@ -71,7 +71,7 @@ enum _tr_param_type { TR_PARAM_NONE=0, TR_PARAM_STRING, TR_PARAM_NUMBER, enum _tr_csv_subtype {TR_CSV_NONE=0, TR_CSV_COUNT,TR_CSV_VALUEAT}; enum _tr_sdp_subtype {TR_SDP_NONE=0, TR_SDP_LINEAT, TR_SDP_STREAM_DEL, TR_SDP_STREAM}; -enum _tr_ip_subtype {TR_IP_NONE=0,TR_IP_FAMILY,TR_IP_NTOP,TR_IP_RESOLVE, +enum _tr_ip_subtype {TR_IP_NONE=0,TR_IP_FAMILY,TR_IP_NTOP,TR_IP_RESOLVE,TR_IP_RESOLVE_V4,TR_IP_RESOLVE_V6, TR_IP_ISIP, TR_IP_ISIP4, TR_IP_ISIP6, TR_IP_PTON, TR_IP_MATCHES, TR_IP_ISPRIVATE}; enum _tr_re_subtype {TR_RE_NONE=0,TR_RE_SUBST};