diff --git a/main/kamailio/APKBUILD b/main/kamailio/APKBUILD
index 5498eb7ae484f9fa87b670de4f31ede805364c9b..a5802c2d17539d79d5104e7e76d6a2a391d06600 100644
--- a/main/kamailio/APKBUILD
+++ b/main/kamailio/APKBUILD
@@ -13,7 +13,7 @@ _gittag=HEAD
 
 
 pkgver=4.2.3
-pkgrel=0
+pkgrel=1
 [ -z "${_gitcommit}" ] && _suffix="_src" || _suffix="-${_gitcommit}"
 
 pkgdesc="Open Source SIP Server"
@@ -225,6 +225,8 @@ done
 source="http://www.kamailio.org/pub/kamailio/$pkgver/src/kamailio-${pkgver}${_suffix}.tar.gz
 	kamailio-4.2-backslash.patch
 	0001-musl-fixes.patch
+	kamailio-4.2-ipops-srv-query.patch
+
 	kamailio.cfg
 	kamailio.initd
 	"
@@ -489,15 +491,18 @@ redis() {
 md5sums="f94eb1db3820dba22bd3fdae464e93b3  kamailio-4.2.3_src.tar.gz
 bad1ac2d4c95043df271d2ea6d37627a  kamailio-4.2-backslash.patch
 4685288dc54680597b00f956dc95d4d6  0001-musl-fixes.patch
+5b7ecf5c4ae06420c028e03721cb9e89  kamailio-4.2-ipops-srv-query.patch
 a3c959ec568c43a905710e7d25cd8c25  kamailio.cfg
 0e0a271fd3ddb7e87c01c26c7d041d59  kamailio.initd"
 sha256sums="7dbbca4a515778d3e903380adcc49f727ddc4853238cb905e14c811a5671ed80  kamailio-4.2.3_src.tar.gz
 d7e59be721ed0ad4621d404493b9a519708d801e9d4914b0164b819fa1abcd13  kamailio-4.2-backslash.patch
 b98555ff304b51b82c6cf7e01d757b15ea4f05bd2e603c84d4384df6a6be62b6  0001-musl-fixes.patch
+cfe645fc80eaed8a9e4bd56047f75555b2a9e3edcb3e2b6c6cece1547ab0a574  kamailio-4.2-ipops-srv-query.patch
 8024266849033a917147827c3579a382f10f3796989bebc6de3d7c80c965fb72  kamailio.cfg
 a90d3ab09a3ed58892e94710a1f80492a61ffad1ccf7ccb5b851bb8f538d32c4  kamailio.initd"
 sha512sums="2f42499fe84eefac236fe3d4aa3c7bc424944236f00b95a7071feaa816b3df5764f84076d57b2137908dab7ff06a2440cc7a53a799216befd9511f8718a2eee5  kamailio-4.2.3_src.tar.gz
 a9bb1e8f9f373264b8351ddae099a36a46ddd46fdec09e468d297ba4f64bb4896e7d6e599da70a424e8a28695ab3f3b4ac940afab534593a6b9d08ae462f001a  kamailio-4.2-backslash.patch
 dea7ef2ccf01357576045ba375d41301e2447b4454324007c7ca1862322835c57045852017192ca5434b32dd1b7a2e9669209b7111889dab335b74f042d0f11f  0001-musl-fixes.patch
+3a9bb5d05b4628f6146b824b8916db259f1da51415398ba420900311d73986d21cab653079080c0e8c55ef512909f542279ca7da944b5ef14520331584ca958f  kamailio-4.2-ipops-srv-query.patch
 0b666bfa10fd0af97b62749f8691cb3f76d9b40d1abe0a33e810e367bd733d2e8189c89f7f23010ec591116aada6e1a8a403b17449fe775038917617f281ad4d  kamailio.cfg
 5ddaa059cdef10462c904f061f7bb085e62ad7501e2ed41f797d9e68822bce4e0e5ca09c1586c3901c920f8ce563c8c3ede860752c2b9bdb8f09908388ef337f  kamailio.initd"
diff --git a/main/kamailio/kamailio-4.2-ipops-srv-query.patch b/main/kamailio/kamailio-4.2-ipops-srv-query.patch
new file mode 100644
index 0000000000000000000000000000000000000000..450215e112df4a3311bb87814aab592bc49bbc5e
--- /dev/null
+++ b/main/kamailio/kamailio-4.2-ipops-srv-query.patch
@@ -0,0 +1,658 @@
+--- a/modules/ipops/ipops_mod.c
++++ b/modules/ipops/ipops_mod.c
+@@ -21,6 +21,7 @@
+  *
+  * History:
+  * -------
++ *  2015-02-04: Added srv_query function (rboisvert)
+  *  2011-07-29: Added a function to detect RFC1918 private IPv4 addresses (ibc)
+  *  2011-04-27: Initial version (ibc)
+  */
+@@ -92,10 +93,13 @@
+ static int w_dns_int_match_ip(sip_msg_t*, char*, char*);
+ 
+ static int w_dns_query(struct sip_msg* msg, char* str1, char* str2);
++static int w_srv_query(struct sip_msg* msg, char* str1, char* str2);
+ 
+ static pv_export_t mod_pvs[] = {
+ 	{ {"dns", sizeof("dns")-1}, PVT_OTHER, pv_get_dns, 0,
+ 		pv_parse_dns_name, 0, 0, 0 },
++	{ {"srvquery", sizeof("srvquery")-1}, PVT_OTHER, pv_get_srv, 0,
++		pv_parse_srv_name, 0, 0, 0 },
+ 	{ {"HN", sizeof("HN")-1}, PVT_OTHER, pv_get_hn, 0,
+ 		pv_parse_hn_name, 0, 0, 0 },
+ 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
+@@ -132,6 +136,8 @@
+   ANY_ROUTE },
+   { "dns_query", (cmd_function)w_dns_query, 2, fixup_spve_spve, 0,
+   ANY_ROUTE },
++  { "srv_query", (cmd_function)w_srv_query, 2, fixup_spve_spve, 0,
++  ANY_ROUTE },
+   { "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
+   { 0, 0, 0, 0, 0, 0 }
+ };
+@@ -772,4 +778,32 @@
+ 	}
+ 
+ 	return dns_update_pv(&hostname, &name);
++}
++
++/**
++ *
++ */
++static int w_srv_query(struct sip_msg* msg, char* str1, char* str2)
++{
++	str srvcname;
++	str name;
++
++	if(msg==NULL)
++	{
++		LM_ERR("received null msg\n");
++		return -1;
++	}
++
++	if(fixup_get_svalue(msg, (gparam_t*)str1, &srvcname)<0)
++	{
++		LM_ERR("cannot get the srvcname\n");
++		return -1;
++	}
++	if(fixup_get_svalue(msg, (gparam_t*)str2, &name)<0)
++	{
++		LM_ERR("cannot get the pvid name\n");
++		return -1;
++	}
++
++	return srv_update_pv(&srvcname, &name);
+ }
+--- a/modules/ipops/ipops_pv.c
++++ b/modules/ipops/ipops_pv.c
+@@ -32,6 +32,7 @@
+ #include <netinet/in.h>
+ 
+ #include "../../dprint.h"
++#include "../../rand/fastrand.h"
+ #include "../../hashes.h"
+ #include "../../resolve.h"
+ #include "../../pvar.h"
+@@ -66,7 +67,6 @@
+ 	int nidx;
+ } dns_pv_t;
+ 
+-
+ static sr_dns_item_t *_sr_dns_list = NULL;
+ 
+ /**
+@@ -132,7 +132,6 @@
+ 	return it;
+ }
+ 
+-
+ /**
+  *
+  */
+@@ -431,7 +430,6 @@
+ 	return 1;
+ }
+ 
+-
+ struct _hn_pv_data {
+ 	str data;
+ 	str fullname;
+@@ -594,4 +592,545 @@
+ 				return pv_get_null(msg, param, res);;
+ 			return pv_get_strval(msg, param, res, &_hn_data->hostname);
+ 	}
++}
++
++/**********
++* srvquery PV
++**********/
++
++static char *srvqrylst []
++  = {"count", "port", "priority", "target", "weight", NULL};
++
++#define PV_SRV_MAXSTR 64
++#define PV_SRV_MAXRECS 32
++
++typedef struct _sr_srv_record {
++  unsigned short priority;
++  unsigned short weight;
++  unsigned short port;
++  char target [PV_SRV_MAXSTR + 1];
++} sr_srv_record_t;
++
++typedef struct _sr_srv_item {
++  str pvid;
++  unsigned int hashid;
++  int count;
++  sr_srv_record_t rr [PV_SRV_MAXRECS];
++  struct _sr_srv_item *next;
++} sr_srv_item_t;
++
++typedef struct _srv_pv {
++  sr_srv_item_t *item;
++  int type;
++  int flags;
++  pv_spec_t *pidx;
++  int nidx;
++} srv_pv_t;
++
++static sr_srv_item_t *_sr_srv_list = NULL;
++
++/**********
++* Add srvquery Item
++*
++* INPUT:
++*   Arg (1) = pvid string pointer
++*   Arg (2) = find flag; <>0=search only
++* OUTPUT: srv record pointer; NULL=not found
++**********/
++
++sr_srv_item_t *sr_srv_add_item (str *pvid, int findflg)
++
++{
++sr_srv_item_t *pitem;
++unsigned int hashid;
++
++/**********
++* o get hash
++* o already exists?
++**********/
++
++hashid = get_hash1_raw (pvid->s, pvid->len);
++for (pitem = _sr_srv_list; pitem; pitem = pitem->next) {
++  if (pitem->hashid == hashid
++    && pitem->pvid.len == pvid->len
++    && !strncmp (pitem->pvid.s, pvid->s, pvid->len))
++    return pitem;
++}
++if (findflg)
++  return NULL;
++
++/**********
++* o alloc/init item structure
++* o link in new item
++**********/
++
++pitem = (sr_srv_item_t *) pkg_malloc (sizeof (sr_srv_item_t));
++if (!pitem) {
++  LM_ERR ("No more pkg memory!\n");
++  return NULL;
++}
++memset (pitem, 0, sizeof (sr_srv_item_t));
++pitem->pvid.s = (char *) pkg_malloc (pvid->len + 1);
++if (!pitem->pvid.s) {
++  LM_ERR ("No more pkg memory!\n");
++  pkg_free (pitem);
++  return NULL;
++}
++memcpy (pitem->pvid.s, pvid->s, pvid->len);
++pitem->pvid.len = pvid->len;
++pitem->hashid = hashid;
++pitem->next = _sr_srv_list;
++_sr_srv_list = pitem;
++return pitem;
++}
++
++/**********
++* Skip Over
++*
++* INPUT:
++*   Arg (1) = string pointer
++*   Arg (2) = starting position
++*   Arg (3) = whitespace flag
++* OUTPUT: position past skipped
++**********/
++
++int skip_over (str *pstr, int pos, int bWS)
++
++{
++char *pchar;
++
++/**********
++* o string exists?
++* o skip over
++**********/
++
++if (pos >= pstr->len)
++  return pstr->len;
++for (pchar = &pstr->s [pos]; pos < pstr->len; pchar++, pos++) {
++  if (*pchar == ' ' || *pchar == '\t' || *pchar == '\n' || *pchar == '\r') {
++    if (bWS)
++      continue;
++  }
++  if ((*pchar>='A' && *pchar<='Z') || (*pchar>='a' && *pchar<='z')
++    || (*pchar>='0' && *pchar<='9')) {
++    if (!bWS)
++      continue;
++  }
++  break;
++}
++return pos;
++}
++
++/**********
++* Sort SRV Records by Weight (RFC 2782)
++*
++* INPUT:
++*   Arg (1) = pointer to array of SRV records
++*   Arg (2) = first record in range
++*   Arg (3) = last record in range
++* OUTPUT: position past skipped
++**********/
++
++void sort_weights (struct srv_rdata **plist, int pos1, int pos2)
++
++{
++int idx1, idx2, idx3, lastfound;
++struct srv_rdata *wlist [PV_SRV_MAXRECS];
++unsigned int rand, sum, sums [PV_SRV_MAXRECS];
++
++/**********
++* place zero weights in the unordered list and then non-zero
++**********/
++
++idx2 = 0;
++for (idx1 = pos1; idx1 <= pos2; idx1++) {
++  if (!plist [idx1]->weight) {
++    wlist [idx2++] = plist [idx1];
++  }
++}
++for (idx1 = pos1; idx1 <= pos2; idx1++) {
++  if (plist [idx1]->weight) {
++    wlist [idx2++] = plist [idx1];
++  }
++}
++
++/**********
++* generate running sum list
++**********/
++
++sum = 0;
++for (idx1 = pos1; idx1 <= pos2; idx1++) {
++  sum += wlist [idx1]->weight;
++  sums [pos1 - idx1] = sum;
++}
++
++/**********
++* resort randomly
++**********/
++
++idx3 = pos1;
++lastfound = 0;
++for (idx1 = pos2 - pos1; idx1; --idx1) {
++  /**********
++  * o calculate a random number in range
++  * o find first unsorted
++  **********/
++
++  rand = fastrand_max (sum);
++  for (idx2 = 0; idx2 < pos2 - pos1; idx2++) {
++    if (!wlist [idx2]) {
++      continue;
++    }
++    if (sums [idx2] >= rand) {
++      plist [idx3++] = wlist [idx2];
++      wlist [idx2] = 0;
++      break;
++    }
++    lastfound = idx2;
++  }
++  if (idx2 == pos2 - pos1) {
++    plist [idx3++] = wlist [lastfound];
++    wlist [lastfound] = 0;
++  }
++}
++return;
++}
++
++/**********
++* Sort SRV Records by Priority/Weight
++*
++* INPUT:
++*   Arg (1) = pointer to array of SRV records
++*   Arg (2) = record count
++* OUTPUT: position past skipped
++**********/
++
++void sort_srv (struct srv_rdata **plist, int rcount)
++
++{
++int idx1, idx2;
++struct srv_rdata *pswap;
++
++/**********
++* sort by priority
++**********/
++
++for (idx1 = 1; idx1 < rcount; idx1++) {
++  pswap = plist [idx1];
++  for (idx2 = idx1;
++    idx2 && (plist [idx2 - 1]->priority > pswap->priority); --idx2) {
++    plist [idx2] = plist [idx2 - 1];
++  }
++  plist [idx2] = pswap;
++}
++
++/**********
++* check for multiple priority
++**********/
++
++idx2 = 0;
++pswap = plist [0];
++for (idx1 = 1; idx1 <= rcount; idx1++) {
++  if ((idx1 == rcount) || (pswap->priority != plist [idx1]->priority)) {
++    /**********
++    * o range has more than one element?
++    * o restart range
++    **********/
++
++    if (idx1 - idx2 - 1) {
++      sort_weights (plist, idx2, idx1 - 1);
++    }
++    idx2 = idx1;
++    pswap = plist [idx2];
++  }
++}
++return;
++}
++
++/**********
++* Parse srvquery Name
++*
++* INPUT:
++*   Arg (1) = pv spec pointer
++*   Arg (2) = input string pointer
++* OUTPUT: 0=success
++**********/
++
++int pv_parse_srv_name (pv_spec_t *sp, str *in)
++
++{
++char *pstr;
++int i, pos, sign;
++srv_pv_t *dpv;
++str pvi, pvk, pvn;
++
++/**********
++* o alloc/init pvid structure
++* o extract pvid name
++* o check separator
++**********/
++
++if (!sp || !in || in->len<=0)
++  return -1;
++dpv = (srv_pv_t *) pkg_malloc (sizeof (srv_pv_t));
++if (!dpv) {
++  LM_ERR ("No more pkg memory!\n");
++  return -1;
++}
++memset (dpv, 0, sizeof (srv_pv_t));
++pos = skip_over (in, 0, 1);
++if (pos == in->len)
++  goto error;
++pvn.s = &in->s [pos];
++pvn.len = pos;
++pos = skip_over (in, pos, 0);
++pvn.len = pos - pvn.len;
++if (!pvn.len)
++  goto error;
++pos = skip_over (in, pos, 1);
++if ((pos + 2) > in->len)
++  goto error;
++if (strncmp (&in->s [pos], "=>", 2))
++  goto error;
++
++/**********
++* o extract key name
++* o check key name
++* o count?
++**********/
++
++pos = skip_over (in, pos + 2, 1);
++pvk.s = &in->s [pos];
++pvk.len = pos;
++pos = skip_over (in, pos, 0);
++pvk.len = pos - pvk.len;
++if (!pvk.len)
++  goto error;
++for (i = 0; srvqrylst [i]; i++) {
++  if (strlen (srvqrylst [i]) != pvk.len)
++    continue;
++  if (!strncmp (pvk.s, srvqrylst [i], pvk.len)) {
++    dpv->type = i;
++    break;
++  }
++}
++if (!srvqrylst [i])
++  goto error;
++if (!i)
++  goto noindex;
++
++/**********
++* o check for array
++* o extract array index and check
++**********/
++
++pos = skip_over (in, pos, 1);
++if ((pos + 3) > in->len)
++  goto error;
++if (in->s [pos] != '[')
++  goto error;
++pos = skip_over (in, pos + 1, 1);
++if ((pos + 2) > in->len)
++  goto error;
++pvi.s = &in->s [pos];
++pvi.len = pos;
++if (in->s [pos] == PV_MARKER) {
++  /**********
++  * o search from the end back to array close
++  * o get PV value
++  **********/
++
++  for (i = in->len - 1; i != pos; --i) {
++    if (in->s [i] == ']')
++      break;
++  }
++  if (i == pos)
++    goto error;
++  pvi.len = i - pvi.len;
++  pos = i + 1;
++  dpv->pidx = pv_cache_get (&pvi);
++  if (!dpv->pidx)
++    goto error;
++  dpv->flags |= SR_DNS_PVIDX;
++} else {
++  /**********
++  * o get index value
++  * o check for reverse index
++  * o convert string to number
++  **********/
++
++  pos = skip_over (in, pos, 0);
++  pvi.len = pos - pvi.len;
++  sign = 1;
++  i = 0;
++  pstr = pvi.s;
++  if (*pstr == '-') {
++    sign = -1;
++    i++;
++    pstr++;
++  }
++  for (dpv->nidx = 0; i < pvi.len; i++) {
++    if (*pstr >= '0' && *pstr <= '9')
++      dpv->nidx = (dpv->nidx * 10) + *pstr++ - '0';
++  }
++  if (i != pvi.len)
++    goto error;
++  dpv->nidx *= sign;
++  pos = skip_over (in, pos, 1);
++  if (pos == in->len)
++    goto error;
++  if (in->s [pos++] != ']')
++    goto error;
++}
++
++/**********
++* o check for trailing whitespace
++* o add data to PV
++**********/
++
++noindex:
++if (skip_over (in, pos, 1) != in->len)
++  goto error;
++LM_DBG ("srvquery (%.*s => %.*s [%.*s])\n",
++  pvn.len, pvn.s, pvk.len, pvk.s, pvi.len, pvi.s);
++dpv->item = sr_srv_add_item (&pvn, 0);
++if (!dpv->item)
++  goto error;
++sp->pvp.pvn.u.dname = (void *)dpv;
++sp->pvp.pvn.type = PV_NAME_OTHER;
++return 0;
++
++error:
++LM_ERR ("error at PV srvquery: %.*s@%d\n", in->len, in->s, pos);
++pkg_free (dpv);
++return -1;
++}
++
++int srv_update_pv (str *srvcname, str *pvid)
++
++{
++int idx1, idx2, rcount;
++struct rdata *phead, *psrv;
++struct srv_rdata *plist [PV_SRV_MAXRECS];
++sr_srv_item_t *pitem;
++sr_srv_record_t *prec;
++
++/**********
++* o service name missing?
++* o find pvid
++**********/
++
++if (!srvcname->len) {
++  LM_DBG ("service name missing: %.*s\n", srvcname->len, srvcname->s);
++  return -2;
++}
++pitem = sr_srv_add_item (pvid, 1);
++if (!pitem) {
++  LM_DBG ("pvid not found: %.*s\n", pvid->len, pvid->s);
++  return -3;
++}
++
++/**********
++* o get records
++* o sort by priority/weight
++* o save to PV
++**********/
++
++LM_DBG ("attempting to query: %.*s\n", srvcname->len, srvcname->s);
++phead = get_record (srvcname->s, T_SRV, RES_ONLY_TYPE);
++rcount = 0;
++for (psrv = phead; psrv; psrv = psrv->next) {
++  if (rcount < PV_SRV_MAXRECS) {
++    plist [rcount++] = (struct srv_rdata *) psrv->rdata;
++  } else {
++    LM_WARN ("truncating srv_query list to %d records!", PV_SRV_MAXRECS);
++    break;
++  }
++}
++pitem->count = rcount;
++if (rcount)
++  sort_srv (plist, rcount);
++for (idx1 = 0; idx1 < rcount; idx1++) {
++  prec = &pitem->rr [idx1];
++  prec->priority = plist [idx1]->priority;
++  prec->weight = plist [idx1]->weight;
++  prec->port = plist [idx1]->port;
++  idx2 = plist [idx1]->name_len;
++  if (idx2 > PV_SRV_MAXSTR) {
++    LM_WARN ("truncating srv_query target (%.*s)!", idx2, plist [idx1]->name);
++    idx2 = PV_SRV_MAXSTR;
++  }
++  strncpy (prec->target, plist [idx1]->name, idx2);
++  prec->target [idx2] = '\0';
++}
++if (phead)
++  free_rdata_list (phead);
++LM_DBG ("srvquery PV updated for: %.*s (%d)\n",
++  srvcname->len, srvcname->s, rcount);
++return 1;
++}
++
++/**********
++* Get srvquery Values
++*
++* INPUT:
++*   Arg (1) = SIP message pointer
++*   Arg (2) = parameter pointer
++*   Arg (3) = PV value pointer
++* OUTPUT: 0=success
++**********/
++
++int pv_get_srv (sip_msg_t *pmsg, pv_param_t *param, pv_value_t *res)
++
++{
++pv_value_t val;
++srv_pv_t *dpv;
++
++/**********
++* o sipmsg and param exist?
++* o PV name exists?
++* o count?
++**********/
++
++if(!pmsg || !param)
++  return -1;
++dpv = (srv_pv_t *) param->pvn.u.dname;
++if(!dpv || !dpv->item)
++  return -1;
++if (!dpv->type)
++  return pv_get_sintval (pmsg, param, res, dpv->item->count);
++
++/**********
++* o get index value
++* o reverse index?
++* o extract data
++**********/
++
++if (!dpv->pidx) {
++  val.ri = dpv->nidx;
++} else {
++  if (pv_get_spec_value (pmsg, dpv->pidx, &val) < 0
++    || !(val.flags & PV_VAL_INT)) {
++    LM_ERR ("failed to evaluate index variable!\n");
++    return pv_get_null (pmsg, param, res);
++  }
++}
++if (val.ri < 0) {
++  if ((dpv->item->count + val.ri) < 0)
++    return pv_get_null (pmsg, param, res);
++  val.ri = dpv->item->count + val.ri;
++}
++if (val.ri >= dpv->item->count)
++  return pv_get_null(pmsg, param, res);
++switch (dpv->type) {
++  case 1: /* port */
++    return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].port);
++  case 2: /* priority */
++    return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].priority);
++  case 3: /* target */
++    return pv_get_strzval (pmsg, param, res, dpv->item->rr [val.ri].target);
++  case 4: /* weight */
++    return pv_get_sintval (pmsg, param, res, dpv->item->rr [val.ri].weight);
++}
++return pv_get_null (pmsg, param, res);
+ }
+--- a/modules/ipops/ipops_pv.h
++++ b/modules/ipops/ipops_pv.h
+@@ -39,5 +39,9 @@
+ int pv_get_hn(struct sip_msg *msg, pv_param_t *param,
+ 		pv_value_t *res);
+ 
++int pv_parse_srv_name(pv_spec_t *, str *);
++int pv_get_srv(sip_msg_t *, pv_param_t *, pv_value_t *);
++int srv_update_pv(str *, str *);
++
+ #endif
+