Browse code

ipops: new naptr_query function

Vitaliy Aleksandrov authored on 29/05/2017 08:42:27
Showing 4 changed files
... ...
@@ -962,6 +962,102 @@ if (srv_query ("_sip._udp.example.com", "udp") > 0) {
962 962
     $var(i) = $var(i) + 1;
963 963
   }
964 964
 }
965
+...
966
+        </programlisting>
967
+      </example>
968
+    </section>
969
+ 
970
+    <section id="ipops.f.naptr_query">
971
+      <title>
972
+        <function moreinfo="none">naptr_query(domain, pvid)</function>
973
+      </title>
974
+
975
+      <para>
976
+         Queries DNS NAPTR records to resolve a domain name into a list of orders, preferences, flags, services, regex, replaces sorted by orders and preferences as outlined in <ulink url="http://tools.ietf.org/html/rfc2915">RFC 2915</ulink>.
977
+      </para>
978
+
979
+      <para>Parameters:</para>
980
+
981
+      <itemizedlist>
982
+        <listitem>
983
+          <para>
984
+            <emphasis>domain</emphasis> - string or pseudo-variable containing the domain. For example, "example.com".
985
+          </para>
986
+        </listitem>
987
+        <listitem>
988
+          <para>
989
+            <emphasis>pvid</emphasis> - container id for script variable.
990
+          </para>
991
+        </listitem>
992
+      </itemizedlist>
993
+
994
+      <para>Output:</para>
995
+
996
+      <para>
997
+        Returns a positive number indicating success or a negative number when an error is encountered. It can be used from ANY_ROUTE.
998
+      </para>
999
+
1000
+      <para>
1001
+        The $naptrquery pseudo-variable (PV) is loaded with the results of the query. Multiple queries can be stored in the PV using the pvid key. Each query contains zero-indexed arrays sorted by order and preference that contain:
1002
+      </para>
1003
+
1004
+      <itemizedlist>
1005
+        <listitem>
1006
+          <para>
1007
+            <emphasis>count</emphasis> - number of records found
1008
+          </para>
1009
+        </listitem>
1010
+        <listitem>
1011
+          <para>
1012
+            <emphasis>order [index]</emphasis> - order as defined by <ulink url="http://tools.ietf.org/html/rfc2915">RFC 2915</ulink>
1013
+          </para>
1014
+        </listitem>
1015
+        <listitem>
1016
+          <para>
1017
+            <emphasis>pref [index]</emphasis> - preference as defined by <ulink url="http://tools.ietf.org/html/rfc2915">RFC 2915</ulink>
1018
+          </para>
1019
+        </listitem>
1020
+        <listitem>
1021
+          <para>
1022
+            <emphasis>flags [index]</emphasis> - flags
1023
+          </para>
1024
+        </listitem>
1025
+        <listitem>
1026
+          <para>
1027
+            <emphasis>services [index]</emphasis> - services
1028
+          </para>
1029
+        </listitem>
1030
+        <listitem>
1031
+          <para>
1032
+            <emphasis>regex [index]</emphasis> - regular expression
1033
+          </para>
1034
+        </listitem>
1035
+        <listitem>
1036
+          <para>
1037
+            <emphasis>replace [index]</emphasis> - replace
1038
+          </para>
1039
+        </listitem>
1040
+      </itemizedlist>
1041
+
1042
+      <example>
1043
+        <title>
1044
+          <function>naptr_query</function> usage
1045
+        </title>
1046
+        <programlisting format="linespecific">
1047
+...
1048
+if (naptr_query ("example.com", "res") > 0) {
1049
+  $var(cnt) = $naptrquery(res=>count);
1050
+  $var(i) = 0;
1051
+  while ($var(i) &lt; $var(cnt)) {
1052
+    xlog ("order[$var(i)] $naptrquery(udp=>order[$var(i)])\n");
1053
+    xlog ("pref[$var(i)] $naptrquery(udp=>pref[$var(i)])\n");
1054
+    xlog ("flags[$var(i)] $naptrquery(udp=>flags[$var(i)])\n");
1055
+    xlog ("services[$var(i)] $naptrquery(udp=>services[$var(i)])\n");
1056
+    xlog ("regex[$var(i)] $naptrquery(udp=>regex[$var(i)])\n");
1057
+    xlog ("replace[$var(i)] $naptrquery(udp=>replace[$var(i)])\n");
1058
+    $var(i) = $var(i) + 1;
1059
+  }
1060
+}
965 1061
 ...
966 1062
         </programlisting>
967 1063
       </example>
... ...
@@ -108,6 +108,7 @@ static int fixup_detailed_ip_type(void** param, int param_no);
108 108
 static int fixup_free_detailed_ip_type(void** param, int param_no);
109 109
 static int w_dns_query(struct sip_msg* msg, char* str1, char* str2);
110 110
 static int w_srv_query(struct sip_msg* msg, char* str1, char* str2);
111
+static int w_naptr_query(struct sip_msg* msg, char* str1, char* str2);
111 112
 static int mod_init(void);
112 113
 
113 114
 static pv_export_t mod_pvs[] = {
... ...
@@ -115,6 +116,8 @@ static pv_export_t mod_pvs[] = {
115 116
 		pv_parse_dns_name, 0, 0, 0 },
116 117
 	{ {"srvquery", sizeof("srvquery")-1}, PVT_OTHER, pv_get_srv, 0,
117 118
 		pv_parse_srv_name, 0, 0, 0 },
119
+	{ {"naptrquery", sizeof("naptrquery")-1}, PVT_OTHER, pv_get_naptr, 0,
120
+		pv_parse_naptr_name, 0, 0, 0 },
118 121
 	{ {"HN", sizeof("HN")-1}, PVT_OTHER, pv_get_hn, 0,
119 122
 		pv_parse_hn_name, 0, 0, 0 },
120 123
 	{ {0, 0}, 0, 0, 0, 0, 0, 0, 0 }
... ...
@@ -159,6 +162,8 @@ static cmd_export_t cmds[] =
159 162
 		ANY_ROUTE },
160 163
 	{ "srv_query", (cmd_function)w_srv_query, 2, fixup_spve_spve, 0,
161 164
 		ANY_ROUTE },
165
+	{ "naptr_query", (cmd_function)w_naptr_query, 2, fixup_spve_spve, 0,
166
+		ANY_ROUTE },
162 167
 	{ "bind_ipops", (cmd_function)bind_ipops, 0, 0, 0, 0},
163 168
 	{ 0, 0, 0, 0, 0, 0 }
164 169
 };
... ...
@@ -1088,3 +1093,32 @@ static int w_srv_query(struct sip_msg* msg, char* str1, char* str2)
1088 1093
 
1089 1094
 	return srv_update_pv(&srvcname, &name);
1090 1095
 }
1096
+
1097
+/**
1098
+ *
1099
+ */
1100
+static int w_naptr_query(struct sip_msg* msg, char* str1, char* str2)
1101
+{
1102
+	str naptrname;
1103
+	str name;
1104
+
1105
+	if(msg==NULL)
1106
+	{
1107
+		LM_ERR("received null msg\n");
1108
+		return -1;
1109
+	}
1110
+
1111
+	if(fixup_get_svalue(msg,(gparam_t*)str1, &naptrname)<0)
1112
+	{
1113
+		LM_ERR("cannot get the naptrcname\n");
1114
+		return -1;
1115
+	}
1116
+	if(fixup_get_svalue(msg,(gparam_t*)str2, &name)<0)
1117
+	{
1118
+		LM_ERR("cannot get the pvid name\n");
1119
+		return -1;
1120
+	}
1121
+
1122
+	return naptr_update_pv(&naptrname, &name);
1123
+}
1124
+
... ...
@@ -1133,3 +1133,509 @@ int pv_get_srv (sip_msg_t *pmsg, pv_param_t *param, pv_value_t *res)
1133 1133
 	}
1134 1134
 	return pv_get_null (pmsg, param, res);
1135 1135
 }
1136
+
1137
+/**********
1138
+ * naptrquery PV
1139
+ **********/
1140
+
1141
+static char *naptrqrylst[] =
1142
+{
1143
+	"count",
1144
+	"order",
1145
+	"pref",
1146
+	"flags",
1147
+	"services",
1148
+	"regex",
1149
+	"replace",
1150
+	NULL
1151
+};
1152
+
1153
+#define PV_NAPTR_MAXSTR 64
1154
+#define PV_NAPTR_MAXRECS 32
1155
+
1156
+typedef struct _sr_naptr_record {
1157
+	unsigned short count;
1158
+	unsigned short order;
1159
+	unsigned short pref;
1160
+	char flags[PV_NAPTR_MAXSTR + 1];
1161
+	char services[PV_NAPTR_MAXSTR + 1];
1162
+	char regex[PV_NAPTR_MAXSTR + 1];
1163
+	char replace[PV_NAPTR_MAXSTR + 1];
1164
+} sr_naptr_record_t;
1165
+
1166
+typedef struct _sr_naptr_item {
1167
+	str pvid;
1168
+	unsigned int hashid;
1169
+	int count;
1170
+	sr_naptr_record_t rr[PV_NAPTR_MAXRECS];
1171
+	struct _sr_naptr_item *next;
1172
+} sr_naptr_item_t;
1173
+
1174
+typedef struct _naptr_pv {
1175
+	sr_naptr_item_t *item;
1176
+	int type;
1177
+	int flags;
1178
+	pv_spec_t *pidx;
1179
+	int        nidx;
1180
+} naptr_pv_t;
1181
+
1182
+static sr_naptr_item_t *_sr_naptr_list = NULL;
1183
+
1184
+/**********
1185
+ * Add naptrquery Item
1186
+ *
1187
+ * INPUT:
1188
+ *   Arg (1) = pvid string pointer
1189
+ *   Arg (2) = find flag; <>0=search only
1190
+ * OUTPUT: naptr record pointer; NULL=not found
1191
+ **********/
1192
+
1193
+sr_naptr_item_t *sr_naptr_add_item(str *pvid, int findflg)
1194
+{
1195
+	sr_naptr_item_t *pitem;
1196
+	unsigned int hashid;
1197
+
1198
+	LM_DBG("%s:%d %s - called: pvid => [%.*s] findflg => [%d]\n",
1199
+			__FILE__,__LINE__,__PRETTY_FUNCTION__,
1200
+			STR_FMT(pvid), findflg);
1201
+
1202
+	/**********
1203
+	 * o get hash
1204
+	 * o already exists?
1205
+	 **********/
1206
+
1207
+	hashid = get_hash1_raw (pvid->s, pvid->len);
1208
+	for (pitem = _sr_naptr_list; pitem; pitem = pitem->next) {
1209
+		if (pitem->hashid == hashid
1210
+				&& pitem->pvid.len == pvid->len
1211
+				&& !strncmp(pitem->pvid.s, pvid->s, pvid->len))
1212
+			return pitem;
1213
+	}
1214
+	if (findflg)
1215
+		return NULL;
1216
+
1217
+	/**********
1218
+	 * o alloc/init item structure
1219
+	 * o link in new item
1220
+	 **********/
1221
+
1222
+	pitem = (sr_naptr_item_t *)pkg_malloc(sizeof (sr_naptr_item_t));
1223
+	if (!pitem) {
1224
+		LM_ERR ("No more pkg memory!\n");
1225
+		return NULL;
1226
+	}
1227
+	memset(pitem, 0, sizeof(sr_naptr_item_t));
1228
+
1229
+	pitem->pvid.s = (char *)pkg_malloc(pvid->len + 1);
1230
+	if (!pitem->pvid.s) {
1231
+		LM_ERR ("No more pkg memory!\n");
1232
+		pkg_free(pitem);
1233
+		return NULL;
1234
+	}
1235
+	memcpy(pitem->pvid.s, pvid->s, pvid->len);
1236
+	pitem->pvid.len = pvid->len;
1237
+	pitem->hashid   = hashid;
1238
+	pitem->next     = _sr_naptr_list;
1239
+
1240
+	_sr_naptr_list = pitem;
1241
+
1242
+	LM_DBG("New item [%.*s]", STR_FMT(pvid));
1243
+
1244
+	return pitem;
1245
+}
1246
+
1247
+/**********
1248
+ * Sort NAPTR Records by Order/Pref
1249
+ *
1250
+ * INPUT:
1251
+ *   Arg (1) = pointer to array of NAPTR records
1252
+ *   Arg (2) = record count
1253
+ * OUTPUT: position past skipped
1254
+ **********/
1255
+
1256
+void sort_naptr(struct naptr_rdata **plist, int rcount)
1257
+
1258
+{
1259
+	int idx1, idx2;
1260
+	struct naptr_rdata *pswap;
1261
+
1262
+	for (idx1 = 1; idx1 < rcount; idx1++) {
1263
+		pswap = plist[idx1];
1264
+		for (idx2 = idx1;
1265
+				idx2 &&
1266
+				(
1267
+						(plist[idx2 - 1]->order > pswap->order)
1268
+						||
1269
+						(plist[idx2 - 1]->order == pswap->order && plist[idx2 - 1]->pref > pswap->pref)
1270
+				);
1271
+				--idx2) {
1272
+			plist [idx2] = plist [idx2 - 1];
1273
+		}
1274
+		plist [idx2] = pswap;
1275
+	}
1276
+
1277
+	return;
1278
+}
1279
+
1280
+/**********
1281
+ * Parse naptrquery Name
1282
+ *
1283
+ * INPUT:
1284
+ *   Arg (1) = pv spec pointer
1285
+ *   Arg (2) = input string pointer
1286
+ * OUTPUT: 0=success
1287
+ **********/
1288
+int pv_parse_naptr_name(pv_spec_t *sp, str *in)
1289
+{
1290
+	LM_DBG("%s:%d %s - called: sp => [%p] in => [%.*s]\n",
1291
+			__FILE__,__LINE__,__PRETTY_FUNCTION__,
1292
+			sp, STR_FMT(in));
1293
+
1294
+	char *pstr;
1295
+	int i, pos, sign;
1296
+	naptr_pv_t *dpv;
1297
+	str pvn = {0}, pvk = {0}, pvi = {0};
1298
+
1299
+	/**********
1300
+	 * o alloc/init pvid structure
1301
+	 * o extract pvid name
1302
+	 * o check separator
1303
+	 **********/
1304
+
1305
+	if (!sp || !in || in->len<=0)
1306
+		return -1;
1307
+
1308
+	/* alloc/init pvid structure */
1309
+	dpv = (naptr_pv_t *)pkg_malloc(sizeof(naptr_pv_t));
1310
+	if (!dpv) {
1311
+		LM_ERR ("No more pkg memory!\n");
1312
+		return -1;
1313
+	}
1314
+	memset(dpv, 0, sizeof(naptr_pv_t));
1315
+
1316
+	/* skip blank chars and init pvn.s */
1317
+	pos = skip_over(in, 0, 1);
1318
+	if (pos == in->len)
1319
+		goto error;
1320
+	pvn.s = &in->s[pos];
1321
+	pvn.len = pos;
1322
+
1323
+	/* skip [a-zA-Z0-9] and find pvn.len */
1324
+	pos = skip_over(in, pos, 0);
1325
+	pvn.len = pos - pvn.len;
1326
+	if (!pvn.len)
1327
+		goto error;
1328
+
1329
+	/* skip blank chars */
1330
+	pos = skip_over(in, pos, 1);
1331
+	if ((pos + 2) > in->len)
1332
+		goto error;
1333
+
1334
+	if (strncmp(&in->s[pos], "=>", 2))
1335
+		goto error;
1336
+
1337
+	/**********
1338
+	 * o extract key name
1339
+	 * o check key name
1340
+	 * o count?
1341
+	 **********/
1342
+
1343
+	/* skip blank chars and init pvk.s */
1344
+	pos = skip_over(in, pos + 2, 1);
1345
+	pvk.s = &in->s[pos];
1346
+	pvk.len = pos;
1347
+
1348
+	/* skip [a-zA-Z0-9] and find pvk.len */
1349
+	pos = skip_over(in, pos, 0);
1350
+	pvk.len = pos - pvk.len;
1351
+	if (!pvk.len)
1352
+		goto error;
1353
+
1354
+
1355
+	for (i = 0; naptrqrylst[i]; i++) {
1356
+		if (strlen(naptrqrylst[i]) != pvk.len)
1357
+			continue;
1358
+		if (!strncmp(pvk.s, naptrqrylst[i], pvk.len)) {
1359
+			dpv->type = i;
1360
+			break;
1361
+		}
1362
+	}
1363
+
1364
+	if (!naptrqrylst[i])
1365
+		goto error;
1366
+
1367
+	/* "=>count" doesn't have any index */
1368
+	if (!i)
1369
+		goto noindex;
1370
+
1371
+	/**********
1372
+	 * o check for array
1373
+	 * o extract array index and check
1374
+	 **********/
1375
+
1376
+	/* skip blank between "=>order" and array index "["  */
1377
+	pos = skip_over (in, pos, 1);
1378
+	if ((pos + 3) > in->len)
1379
+		goto error;
1380
+
1381
+	if (in->s [pos] != '[')
1382
+		goto error;
1383
+
1384
+	/* skip blank between index sign "[" and a numeric value */
1385
+	pos = skip_over (in, pos + 1, 1);
1386
+	if ((pos + 2) > in->len)
1387
+		goto error;
1388
+
1389
+	pvi.s = &in->s[pos];
1390
+	pvi.len = pos;
1391
+	if (in->s[pos] == PV_MARKER) {
1392
+		/**********
1393
+		 * o search from the end back to array close
1394
+		 * o get PV value
1395
+		 **********/
1396
+
1397
+		for (i = in->len - 1; i != pos; --i) {
1398
+			if (in->s[i] == ']')
1399
+				break;
1400
+		}
1401
+		/* empty idx */
1402
+		if (i == pos)
1403
+			goto error;
1404
+
1405
+		pvi.len = i - pvi.len;
1406
+		pos = i + 1;
1407
+		dpv->pidx = pv_cache_get(&pvi);
1408
+		if (!dpv->pidx)
1409
+			goto error;
1410
+		dpv->flags |= SR_DNS_PVIDX;
1411
+	} else {
1412
+		/**********
1413
+		 * o get index value
1414
+		 * o check for reverse index
1415
+		 * o convert string to number
1416
+		 **********/
1417
+
1418
+		/* find the end of the index and its length */
1419
+		pos = skip_over(in, pos, 0);
1420
+		pvi.len = pos - pvi.len;
1421
+		sign = 1;
1422
+		i = 0;
1423
+		pstr = pvi.s;
1424
+		if (*pstr == '-') {
1425
+			sign = -1;
1426
+			i++;
1427
+			pstr++;
1428
+		}
1429
+		/* homemade atoi() */
1430
+		for (dpv->nidx = 0; i < pvi.len; i++) {
1431
+			if (*pstr >= '0' && *pstr <= '9')
1432
+				dpv->nidx = (dpv->nidx * 10) + *pstr++ - '0';
1433
+		}
1434
+		if (i != pvi.len)
1435
+			goto error;
1436
+		dpv->nidx *= sign;
1437
+
1438
+		/* skip blanks between index and the final "]" */
1439
+		pos = skip_over(in, pos, 1);
1440
+		if (pos == in->len)
1441
+			goto error;
1442
+
1443
+		/* check the final "]" */
1444
+		if (in->s [pos++] != ']')
1445
+			goto error;
1446
+	}
1447
+
1448
+	/**********
1449
+	 * o check for trailing whitespace
1450
+	 * o add data to PV
1451
+	 **********/
1452
+
1453
+noindex:
1454
+
1455
+	if (skip_over(in, pos, 1) != in->len)
1456
+		goto error;
1457
+
1458
+	LM_DBG ("naptrquery (%.*s => %.*s [%.*s])\n",
1459
+			pvn.len, ZSW(pvn.s), pvk.len, ZSW(pvk.s), pvi.len, ZSW(pvi.s));
1460
+
1461
+	dpv->item = sr_naptr_add_item(&pvn, 0);
1462
+	if (!dpv->item)
1463
+		goto error;
1464
+
1465
+	sp->pvp.pvn.u.dname = (void *)dpv;
1466
+	sp->pvp.pvn.type = PV_NAME_OTHER;
1467
+	return 0;
1468
+
1469
+error:
1470
+	LM_ERR ("error at PV naptrquery: %.*s@%d\n", in->len, in->s, pos);
1471
+	pkg_free (dpv);
1472
+	return -1;
1473
+}
1474
+
1475
+int naptr_update_pv(str *naptrname, str *pvid)
1476
+{
1477
+	LM_DBG("%s:%d %s - called: naptrname => [%.*s], pvid => [%.*s]\n", __FILE__,__LINE__,__PRETTY_FUNCTION__,
1478
+			STR_FMT(naptrname), STR_FMT(pvid));
1479
+
1480
+	int idx1, idx2, rcount;
1481
+	struct rdata *phead, *pnaptr;
1482
+	struct naptr_rdata *plist[PV_SRV_MAXRECS];
1483
+	sr_naptr_item_t *pitem;
1484
+	sr_naptr_record_t *prec;
1485
+
1486
+	/**********
1487
+	 * o service name missing?
1488
+	 * o find pvid
1489
+	 **********/
1490
+
1491
+	if (!naptrname->len) {
1492
+		LM_DBG ("naptr name missing: %.*s\n", naptrname->len, naptrname->s);
1493
+		return -2;
1494
+	}
1495
+	pitem = sr_naptr_add_item(pvid, 1);
1496
+	if (!pitem) {
1497
+		LM_DBG ("pvid not found: %.*s\n", pvid->len, pvid->s);
1498
+		return -3;
1499
+	}
1500
+
1501
+	/**********
1502
+	 * o get records
1503
+	 * o sort by order/pref
1504
+	 * o save to PV
1505
+	 **********/
1506
+
1507
+	LM_DBG ("attempting to query: %.*s\n", naptrname->len, naptrname->s);
1508
+	phead = get_record(naptrname->s, T_NAPTR, RES_ONLY_TYPE);
1509
+	rcount = 0;
1510
+	for (pnaptr = phead; pnaptr; pnaptr = pnaptr->next) {
1511
+		if (rcount < PV_NAPTR_MAXRECS) {
1512
+			plist[rcount++] = (struct naptr_rdata *)pnaptr->rdata;
1513
+		} else {
1514
+			LM_WARN ("truncating naptr_query list to %d records!", PV_NAPTR_MAXRECS);
1515
+			break;
1516
+		}
1517
+	}
1518
+	pitem->count = rcount;
1519
+	if (rcount)
1520
+		sort_naptr(plist, rcount);
1521
+	for (idx1 = 0; idx1 < rcount; idx1++) {
1522
+		prec = &pitem->rr[idx1];
1523
+
1524
+		prec->order = plist[idx1]->order;
1525
+		prec->pref  = plist[idx1]->pref;
1526
+
1527
+		idx2 = plist[idx1]->flags_len;
1528
+		if (idx2 > PV_NAPTR_MAXSTR)
1529
+		{
1530
+			LM_WARN ("truncating naptr_query flags (%.*s)!", idx2, plist[idx1]->flags);
1531
+			idx2 = PV_NAPTR_MAXSTR;
1532
+		}
1533
+		strncpy(prec->flags, plist[idx1]->flags, idx2);
1534
+		prec->flags[idx2] = '\0';
1535
+
1536
+		idx2 = plist[idx1]->services_len;
1537
+		if (idx2 > PV_NAPTR_MAXSTR)
1538
+		{
1539
+			LM_WARN ("truncating naptr query services (%.*s)!", idx2, plist[idx1]->services);
1540
+			idx2 = PV_NAPTR_MAXSTR;
1541
+		}
1542
+		strncpy(prec->services, plist[idx1]->services, idx2);
1543
+		prec->services[idx2] = '\0';
1544
+
1545
+		idx2 = plist[idx1]->regexp_len;
1546
+		if (idx2 > PV_NAPTR_MAXSTR)
1547
+		{
1548
+			LM_WARN ("truncating naptr query regexp (%.*s)!", idx2, plist[idx1]->regexp);
1549
+			idx2 = PV_NAPTR_MAXSTR;
1550
+		}
1551
+		strncpy(prec->regex, plist[idx1]->regexp, idx2);
1552
+		prec->regex[idx2] = '\0';
1553
+
1554
+		idx2 = plist[idx1]->repl_len;
1555
+		if (idx2 > PV_NAPTR_MAXSTR)
1556
+		{
1557
+			LM_WARN ("truncating naptr query replace (%.*s)!", idx2, plist[idx1]->repl);
1558
+			idx2 = PV_NAPTR_MAXSTR;
1559
+		}
1560
+		strncpy(prec->replace, plist[idx1]->repl, idx2);
1561
+		prec->replace[idx2] = '\0';
1562
+	}
1563
+	if (phead)
1564
+		free_rdata_list (phead);
1565
+	LM_DBG ("naptrquery PV updated for: %.*s (%d)\n",
1566
+			naptrname->len, naptrname->s, rcount);
1567
+
1568
+	return 1;
1569
+}
1570
+
1571
+/**********
1572
+ * Get naptrquery Values
1573
+ *
1574
+ * INPUT:
1575
+ *   Arg (1) = SIP message pointer
1576
+ *   Arg (2) = parameter pointer
1577
+ *   Arg (3) = PV value pointer
1578
+ * OUTPUT: 0=success
1579
+ **********/
1580
+
1581
+int pv_get_naptr(sip_msg_t *pmsg, pv_param_t *param, pv_value_t *res)
1582
+{
1583
+	pv_value_t val;
1584
+	naptr_pv_t *dpv;
1585
+
1586
+	LM_DBG("%s:%d %s - called: param => [%p], res => [%p]\n", __FILE__,__LINE__,__PRETTY_FUNCTION__,
1587
+			param, res);
1588
+
1589
+	/**********
1590
+	 * o sipmsg and param exist?
1591
+	 * o PV name exists?
1592
+	 * o count?
1593
+	 **********/
1594
+
1595
+	if (!pmsg || !param)
1596
+		return -1;
1597
+	dpv = (naptr_pv_t *)param->pvn.u.dname;
1598
+	if (!dpv || !dpv->item)
1599
+		return -1;
1600
+	if (!dpv->type)
1601
+		return pv_get_sintval(pmsg, param, res, dpv->item->count);
1602
+
1603
+	/**********
1604
+	 * o get index value
1605
+	 * o reverse index?
1606
+	 * o extract data
1607
+	 **********/
1608
+
1609
+	if (!dpv->pidx) {
1610
+		val.ri = dpv->nidx;
1611
+	} else {
1612
+		if (pv_get_spec_value(pmsg, dpv->pidx, &val) < 0
1613
+				|| !(val.flags & PV_VAL_INT)) {
1614
+			LM_ERR ("failed to evaluate index variable!\n");
1615
+			return pv_get_null (pmsg, param, res);
1616
+		}
1617
+	}
1618
+	if (val.ri < 0) {
1619
+		if ((dpv->item->count + val.ri) < 0)
1620
+			return pv_get_null(pmsg, param, res);
1621
+		val.ri = dpv->item->count + val.ri;
1622
+	}
1623
+	if (val.ri >= dpv->item->count)
1624
+		return pv_get_null(pmsg, param, res);
1625
+
1626
+	switch (dpv->type) {
1627
+		case 1: /* order */
1628
+			return pv_get_sintval(pmsg, param, res, dpv->item->rr[val.ri].order);
1629
+		case 2: /* pref */
1630
+			return pv_get_sintval(pmsg, param, res, dpv->item->rr[val.ri].pref);
1631
+		case 3: /* flags */
1632
+			return pv_get_strzval(pmsg, param, res, dpv->item->rr[val.ri].flags);
1633
+		case 4: /* services */
1634
+			return pv_get_strzval(pmsg, param, res, dpv->item->rr[val.ri].services);
1635
+		case 5: /* regex */
1636
+			return pv_get_strzval(pmsg, param, res, dpv->item->rr[val.ri].regex);
1637
+		case 6: /* replace */
1638
+			return pv_get_strzval(pmsg, param, res, dpv->item->rr[val.ri].replace);
1639
+	}
1640
+	return pv_get_null (pmsg, param, res);
1641
+}
... ...
@@ -43,5 +43,9 @@ int pv_parse_srv_name(pv_spec_t *, str *);
43 43
 int pv_get_srv(sip_msg_t *, pv_param_t *, pv_value_t *);
44 44
 int srv_update_pv(str *, str *);
45 45
 
46
+int pv_parse_naptr_name(pv_spec_t *, str *);
47
+int pv_get_naptr(sip_msg_t *, pv_param_t *, pv_value_t *);
48
+int naptr_update_pv(str *, str *);
49
+
46 50
 #endif
47 51