Browse code

registrar: option to send 423 when expires less than min_expires

- control behaviour via min_expires_mode parameter
- default is 0, same behaviour like so far (update expires to
min_expires)

Daniel-Constantin Mierla authored on 04/02/2020 14:17:24
Showing 6 changed files
... ...
@@ -137,6 +137,7 @@ int reg_expire_event_rt = -1; /* default disabled */
137 137
 str reg_event_callback = STR_NULL;
138 138
 
139 139
 int reg_lookup_filter_mode = 0;
140
+int reg_min_expires_mode = 0;
140 141
 
141 142
 sr_kemi_eng_t *keng = NULL;
142 143
 
... ...
@@ -246,6 +247,7 @@ static param_export_t params[] = {
246 247
 	{"contact_max_size",   INT_PARAM, &contact_max_size					},
247 248
 	{"event_callback",     PARAM_STR, &reg_event_callback				},
248 249
 	{"lookup_filter_mode", INT_PARAM, &reg_lookup_filter_mode			},
250
+	{"min_expires_mode",   PARAM_INT, &reg_min_expires_mode				},
249 251
 	{0, 0, 0}
250 252
 };
251 253
 
... ...
@@ -108,6 +108,7 @@ extern usrloc_api_t ul;/*!< Structure containing pointers to usrloc functions*/
108 108
 extern sl_api_t slb;
109 109
 
110 110
 extern int reg_expire_event_rt;
111
+extern int reg_min_expires_mode;
111 112
 
112 113
 extern stat_var *accepted_registrations;
113 114
 extern stat_var *rejected_registrations;
... ...
@@ -340,6 +340,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
340 340
 #define MSG_400 "Bad Request"
341 341
 #define MSG_420 "Bad Extension"
342 342
 #define MSG_421 "Extension Required"
343
+#define MSG_423 "Interval Too Brief"
343 344
 #define MSG_439 "First Hop Lacks Outbound Support"
344 345
 #define MSG_500 "Server Internal Error"
345 346
 #define MSG_503 "Service Unavailable"
... ...
@@ -378,6 +379,7 @@ int build_contact(sip_msg_t *msg, ucontact_t* c, str *host)
378 379
 #define EI_R_OB_REQD     "No support for Outbound on server"        /* R_OB_REQD */
379 380
 #define EI_R_OB_UNSUP_EDGE "No support for Outbound on edge proxy"  /* R_OB_UNSUP_EDGE */
380 381
 #define	EI_R_INV_REGID   "Invalid Reg-Id number"                    /* R_INV_REGID */
382
+#define	EI_R_LOW_EXP     "Interval too brief"                       /* R_LOW_EXP */
381 383
 
382 384
 
383 385
 str error_info[] = {
... ...
@@ -415,6 +417,7 @@ str error_info[] = {
415 417
 	{EI_R_OB_REQD,    sizeof(EI_R_OB_REQD) - 1},
416 418
 	{EI_R_OB_UNSUP_EDGE, sizeof(EI_R_OB_UNSUP_EDGE) - 1},
417 419
 	{EI_R_INV_REGID,  sizeof(EI_R_INV_REGID) - 1},
420
+	{EI_R_LOW_EXP,    sizeof(EI_R_LOW_EXP) - 1},
418 421
 };
419 422
 
420 423
 int codes[] = {
... ...
@@ -452,6 +455,7 @@ int codes[] = {
452 455
 	420, /* R_OB_REQD */
453 456
 	439, /* R_OB_UNSUP_EDGE */
454 457
 	400, /* R_INV_REGID */
458
+	423, /* R_LOW_EXP */
455 459
 };
456 460
 
457 461
 
... ...
@@ -537,6 +541,28 @@ static int add_require(struct sip_msg* _m, str* _p)
537 541
 	return 0;
538 542
 }
539 543
 
544
+#define REG_MINEXP "Min-Expires: "
545
+#define REG_MINEXP_LEN (sizeof(REG_MINEXP) - 1)
546
+
547
+static int add_min_expires(struct sip_msg* _m)
548
+{
549
+	char* buf, *me_s;
550
+	int me_len;
551
+
552
+	me_s = int2str(cfg_get(registrar, registrar_cfg, min_expires), &me_len);
553
+	buf = (char*)pkg_malloc(REG_MINEXP_LEN + me_len + CRLF_LEN);
554
+	if (!buf) {
555
+		LM_ERR("no pkg memory left\n");
556
+		return -1;
557
+	}
558
+	memcpy(buf, REG_MINEXP, REG_MINEXP_LEN);
559
+	memcpy(buf + REG_MINEXP_LEN, me_s, me_len);
560
+	memcpy(buf + REG_MINEXP_LEN + me_len, CRLF, CRLF_LEN);
561
+	add_lump_rpl(_m, buf, REG_MINEXP_LEN + me_len + CRLF_LEN,
562
+			LUMP_RPL_HDR | LUMP_RPL_NODUP);
563
+	return 0;
564
+}
565
+
540 566
 #define SUPPORTED "Supported: "
541 567
 #define SUPPORTED_LEN (sizeof(SUPPORTED) - 1)
542 568
 
... ...
@@ -664,6 +690,10 @@ int reg_send_reply(struct sip_msg* _m)
664 690
 		if (add_unsupported(_m, &outbound_str) < 0)
665 691
 			return -1;
666 692
 		break;
693
+	case R_LOW_EXP:
694
+		if (add_min_expires(_m) < 0)
695
+			return -1;
696
+		break;
667 697
 	default:
668 698
 		break;
669 699
 	}
... ...
@@ -674,6 +704,7 @@ int reg_send_reply(struct sip_msg* _m)
674 704
 	case 400: msg.s = MSG_400; msg.len = sizeof(MSG_400)-1;break;
675 705
 	case 420: msg.s = MSG_420; msg.len = sizeof(MSG_420)-1;break;
676 706
 	case 421: msg.s = MSG_421; msg.len = sizeof(MSG_421)-1;break;
707
+	case 423: msg.s = MSG_423; msg.len = sizeof(MSG_423)-1;break;
677 708
 	case 439: msg.s = MSG_439; msg.len = sizeof(MSG_439)-1;break;
678 709
 	case 500: msg.s = MSG_500; msg.len = sizeof(MSG_500)-1;break;
679 710
 	case 503: msg.s = MSG_503; msg.len = sizeof(MSG_503)-1;break;
... ...
@@ -66,6 +66,7 @@ typedef enum rerr {
66 66
 	R_OB_REQD,    /*!< Outbound required by UAC but not supported on server */
67 67
 	R_OB_UNSUP_EDGE, /*!< Outbound needed for this registration but not supported on edge proxy */
68 68
 	R_INV_REGID,  /*!< Invalid Reg-Id value */
69
+	R_LOW_EXP,    /*!< Expires lower than min value */
69 70
 
70 71
 } rerr_t;
71 72
 
... ...
@@ -483,6 +483,10 @@ static inline int insert_contacts(struct sip_msg* _m, udomain_t* _d, str* _a, in
483 483
 	for( num=0,r=0,ci=0 ; _c ; _c = get_next_contact(_c) ) {
484 484
 		/* calculate expires */
485 485
 		calc_contact_expires(_m, _c->expires, &expires, novariation);
486
+		if(rerrno == R_LOW_EXP) {
487
+			LM_DBG("expires lower than minimum value\n");
488
+			goto error;
489
+		}
486 490
 		/* Skip contacts with zero expires */
487 491
 		if (expires == 0)
488 492
 			continue;
... ...
@@ -680,6 +684,10 @@ static inline int update_contacts(struct sip_msg* _m, urecord_t* _r, int _mode,
680 684
 	for( ; _c ; _c = get_next_contact(_c) ) {
681 685
 		/* calculate expires */
682 686
 		calc_contact_expires(_m, _c->expires, &expires, novariation);
687
+		if(rerrno == R_LOW_EXP) {
688
+			LM_DBG("expires lower than minimum value\n");
689
+			goto error;
690
+		}
683 691
 
684 692
 		/* pack the contact info */
685 693
 		if ( (ci=pack_ci( 0, _c, expires, 0, _use_regid))==0 ) {
... ...
@@ -282,7 +282,12 @@ void calc_contact_expires(struct sip_msg* _m, param_t* _ep, int* _e, int novaria
282 282
 		}
283 283
 
284 284
 		if (*_e < cfg_get(registrar, registrar_cfg, min_expires)) {
285
-			*_e = cfg_get(registrar, registrar_cfg, min_expires);
285
+			if(reg_min_expires_mode) {
286
+				rerrno = R_LOW_EXP;
287
+				return;
288
+			} else {
289
+				*_e = cfg_get(registrar, registrar_cfg, min_expires);
290
+			}
286 291
 		}
287 292
 
288 293
 		if (cfg_get(registrar, registrar_cfg, max_expires) && (*_e > cfg_get(registrar, registrar_cfg, max_expires))) {