mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 10:47:18 +00:00 
			
		
		
		
	chan_sip: Allow Asterisk to retry after 403 on register
This adds a global option in chan_sip to allow it to continue attempting registration if a 403 is received, clearing the cached nonce and treating it as a non-fatal response. Normally, this would cause registration attempts to that endpoint to stop. This also adds a similar per-outbound-registration option to chan_pjsip which allows the retry interval to be altered for 403 responses to REGISTER requests. (closes issue ASTERISK-17138) Review: https://reviewboard.asterisk.org/r/2874/ Reported by: Rudi ........ Merged revisions 400137 from http://svn.asterisk.org/svn/asterisk/branches/1.8 ........ Merged revisions 400140 from http://svn.asterisk.org/svn/asterisk/branches/11 ........ Merged revisions 400141 from http://svn.asterisk.org/svn/asterisk/branches/12 git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@400142 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
		
							
								
								
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								CHANGES
									
									
									
									
									
								
							| @@ -854,6 +854,10 @@ chan_sip | ||||
|  * Added 'ignore_requested_pref'. When enabled, this will use the preferred | ||||
|    codecs configured for a peer instead of the requested codec. | ||||
|  | ||||
|  * The option "register_retry_403" has been added to chan_sip to work around | ||||
|    servers that are known to erroneously send 403 in response to valid | ||||
|    REGISTER requests and allows Asterisk to continue attepmting to connect. | ||||
|  | ||||
| chan_skinny | ||||
| ------------------ | ||||
|  * Added the 'immeddialkey' parameter. If set, when the user presses the | ||||
|   | ||||
| @@ -819,6 +819,7 @@ static int global_rtpholdtimeout;   /*!< Time out call if no RTP during hold */ | ||||
| static int global_rtpkeepalive;     /*!< Send RTP keepalives */ | ||||
| static int global_reg_timeout;      /*!< Global time between attempts for outbound registrations */ | ||||
| static int global_regattempts_max;  /*!< Registration attempts before giving up */ | ||||
| static int global_reg_retry_403;    /*!< Treat 403 responses to registrations as 401 responses */ | ||||
| static int global_shrinkcallerid;   /*!< enable or disable shrinking of caller id  */ | ||||
| static int global_callcounter;      /*!< Enable call counters for all devices. This is currently enabled by setting the peer
 | ||||
|                                      *   call-limit to INT_MAX. When we remove the call-limit from the code, we can make it | ||||
| @@ -21143,6 +21144,7 @@ static char *sip_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_ | ||||
| 	ast_cli(a->fd, "  Sub. max duration:      %d secs\n", max_subexpiry); | ||||
| 	ast_cli(a->fd, "  Outbound reg. timeout:  %d secs\n", global_reg_timeout); | ||||
| 	ast_cli(a->fd, "  Outbound reg. attempts: %d\n", global_regattempts_max); | ||||
| 	ast_cli(a->fd, "  Outbound reg. retry 403:%d\n", global_reg_retry_403); | ||||
| 	ast_cli(a->fd, "  Notify ringing state:   %s\n", AST_CLI_YESNO(sip_cfg.notifyringing)); | ||||
| 	if (sip_cfg.notifyringing) { | ||||
| 		ast_cli(a->fd, "    Include CID:          %s%s\n", | ||||
| @@ -31373,6 +31375,7 @@ static int reload_config(enum channelreloadreason reason) | ||||
| 	sip_cfg.compactheaders = DEFAULT_COMPACTHEADERS; | ||||
| 	global_reg_timeout = DEFAULT_REGISTRATION_TIMEOUT; | ||||
| 	global_regattempts_max = 0; | ||||
| 	global_reg_retry_403 = 0; | ||||
| 	sip_cfg.pedanticsipchecking = DEFAULT_PEDANTIC; | ||||
| 	sip_cfg.autocreatepeer = DEFAULT_AUTOCREATEPEER; | ||||
| 	global_autoframing = 0; | ||||
| @@ -31761,6 +31764,8 @@ static int reload_config(enum channelreloadreason reason) | ||||
| 			} | ||||
| 		} else if (!strcasecmp(v->name, "registerattempts")) { | ||||
| 			global_regattempts_max = atoi(v->value); | ||||
| 		} else if (!strcasecmp(v->name, "register_retry_403")) { | ||||
| 			global_reg_retry_403 = ast_true(v->value); | ||||
| 		} else if (!strcasecmp(v->name, "bindaddr") || !strcasecmp(v->name, "udpbindaddr")) { | ||||
| 			if (ast_parse_arg(v->value, PARSE_ADDR, &bindaddr)) { | ||||
| 				ast_log(LOG_WARNING, "Invalid address: %s\n", v->value); | ||||
|   | ||||
| @@ -147,6 +147,7 @@ | ||||
| ;client_uri=sip:1234567890@sip.example.com | ||||
| ;contact_user=1234567890 | ||||
| ;retry_interval=60 | ||||
| ;forbidden_retry_interval=600 | ||||
| ;expiration=3600 | ||||
|  | ||||
| ;[mytrunk_auth] | ||||
|   | ||||
| @@ -787,6 +787,9 @@ srvlookup=yes                   ; Enable DNS SRV lookups on outbound calls | ||||
|                                 ; 0 = continue forever, hammering the other server | ||||
|                                 ; until it accepts the registration | ||||
|                                 ; Default is 0 tries, continue forever | ||||
| ;register_retry_403=yes         ; Treat 403 responses to registrations as if they were | ||||
|                                 ; 401 responses and continue retrying according to normal | ||||
|                                 ; retry rules. | ||||
|  | ||||
| ;----------------------------------------- OUTBOUND MWI SUBSCRIPTIONS ------------------------- | ||||
| ; Asterisk can subscribe to receive the MWI from another SIP server and store it locally for retrieval | ||||
|   | ||||
| @@ -85,6 +85,17 @@ | ||||
| 				<configOption name="retry_interval" default="60"> | ||||
| 					<synopsis>Interval in seconds between retries if outbound registration is unsuccessful</synopsis> | ||||
| 				</configOption> | ||||
| 				<configOption name="forbidden_retry_interval" default="0"> | ||||
| 					<synopsis>Interval used when receiving a 403 Forbidden response.</synopsis> | ||||
| 					<description><para> | ||||
| 						If a 403 Forbidden is received, chan_pjsip will wait | ||||
| 						<replaceable>forbidden_retry_interval</replaceable> seconds before | ||||
| 						attempting registration again. If 0 is specified, chan_pjsip will not | ||||
| 						retry after receiving a 403 Forbidden response. Setting this to a non-zero | ||||
| 						value goes against a "SHOULD NOT" in RFC3261, but can be used to work around | ||||
| 						buggy registrars. | ||||
| 					</para></description> | ||||
| 				</configOption> | ||||
| 				<configOption name="server_uri"> | ||||
| 					<synopsis>SIP URI of the server to register against</synopsis> | ||||
| 					<description><para> | ||||
| @@ -159,6 +170,8 @@ struct sip_outbound_registration_client_state { | ||||
| 	unsigned int max_retries; | ||||
| 	/*! \brief Interval at which retries should occur for temporal responses */ | ||||
| 	unsigned int retry_interval; | ||||
| 	/*! \brief Interval at which retries should occur for permanent responses */ | ||||
| 	unsigned int forbidden_retry_interval; | ||||
| 	/*! \brief Treat authentication challenges that we cannot handle as permanent failures */ | ||||
| 	unsigned int auth_rejection_permanent; | ||||
| 	/*! \brief Serializer for stuff and things */ | ||||
| @@ -198,6 +211,8 @@ struct sip_outbound_registration { | ||||
| 	unsigned int expiration; | ||||
| 	/*! \brief Interval at which retries should occur for temporal responses */ | ||||
| 	unsigned int retry_interval; | ||||
| 	/*! \brief Interval at which retries should occur for permanent responses */ | ||||
| 	unsigned int forbidden_retry_interval; | ||||
| 	/*! \brief Treat authentication challenges that we cannot handle as permanent failures */ | ||||
| 	unsigned int auth_rejection_permanent; | ||||
| 	/*! \brief Maximum number of retries permitted */ | ||||
| @@ -412,10 +427,21 @@ static int handle_registration_response(void *data) | ||||
| 				response->code, server_uri, client_uri, response->client_state->retry_interval); | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* Finally if there's no hope of registering give up */ | ||||
| 		response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT; | ||||
| 		ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n", | ||||
| 			response->code, server_uri, client_uri); | ||||
| 		if (response->code == 403 | ||||
| 			&& response->client_state->forbidden_retry_interval | ||||
| 			&& response->client_state->retries < response->client_state->max_retries) { | ||||
| 			/* A forbidden response retry interval is configured and there are retries remaining */ | ||||
| 			response->client_state->status = SIP_REGISTRATION_REJECTED_TEMPORARY; | ||||
| 			response->client_state->retries++; | ||||
| 			schedule_registration(response->client_state, response->client_state->forbidden_retry_interval); | ||||
| 			ast_log(LOG_WARNING, "403 Forbidden fatal response received from '%s' on registration attempt to '%s', retrying in '%d' seconds\n", | ||||
| 				server_uri, client_uri, response->client_state->forbidden_retry_interval); | ||||
| 		} else { | ||||
| 			/* Finally if there's no hope of registering give up */ | ||||
| 			response->client_state->status = SIP_REGISTRATION_REJECTED_PERMANENT; | ||||
| 			ast_log(LOG_WARNING, "Fatal response '%d' received from '%s' on registration attempt to '%s', stopping outbound registration\n", | ||||
| 				response->code, server_uri, client_uri); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	ast_system_publish_registry("PJSIP", client_uri, server_uri, sip_outbound_registration_status_str[response->client_state->status], NULL); | ||||
| @@ -716,6 +742,7 @@ static int sip_outbound_registration_perform(void *data) | ||||
| 	} | ||||
| 	registration->state->client_state->outbound_auths.num = registration->outbound_auths.num; | ||||
| 	registration->state->client_state->retry_interval = registration->retry_interval; | ||||
| 	registration->state->client_state->forbidden_retry_interval = registration->forbidden_retry_interval; | ||||
| 	registration->state->client_state->max_retries = registration->max_retries; | ||||
| 	registration->state->client_state->retries = 0; | ||||
|  | ||||
| @@ -911,6 +938,7 @@ static int load_module(void) | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "outbound_proxy", "", OPT_STRINGFIELD_T, 0, STRFLDSET(struct sip_outbound_registration, outbound_proxy)); | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "expiration", "3600", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, expiration)); | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "retry_interval", "60", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, retry_interval)); | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "forbidden_retry_interval", "0", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, forbidden_retry_interval)); | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "max_retries", "10", OPT_UINT_T, 0, FLDSET(struct sip_outbound_registration, max_retries)); | ||||
| 	ast_sorcery_object_field_register(ast_sip_get_sorcery(), "registration", "auth_rejection_permanent", "yes", OPT_BOOL_T, 1, FLDSET(struct sip_outbound_registration, auth_rejection_permanent)); | ||||
| 	ast_sorcery_object_field_register_custom(ast_sip_get_sorcery(), "registration", "outbound_auth", "", outbound_auth_handler, NULL, 0, 0); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user