[asterisk-commits] trunk r19546 - /trunk/channels/chan_sip.c

asterisk-commits at lists.digium.com asterisk-commits at lists.digium.com
Wed Apr 12 13:57:09 MST 2006


Author: oej
Date: Wed Apr 12 15:57:07 2006
New Revision: 19546

URL: http://svn.digium.com/view/asterisk?rev=19546&view=rev
Log:
Implement a setting for denying/allowing transfer requests. At this stage,
we only have open/closed. Well, at least you can deny transfers from unknown
callers or at least incoming calls.
(Part of the SIPtransfer branch)

Modified:
    trunk/channels/chan_sip.c

Modified: trunk/channels/chan_sip.c
URL: http://svn.digium.com/view/asterisk/trunk/channels/chan_sip.c?rev=19546&r1=19545&r2=19546&view=diff
==============================================================================
--- trunk/channels/chan_sip.c (original)
+++ trunk/channels/chan_sip.c Wed Apr 12 15:57:07 2006
@@ -203,6 +203,15 @@
 #define RTP 	1
 #define NO_RTP	0
 
+/*! \brief Authorization scheme for call transfers 
+\note Not a bitfield flag, since there are plans for other modes,
+	like "only allow transfers for authenticated devices" */
+enum transfermodes {
+	TRANSFER_OPENFORALL, 		/*!< Allow all SIP transfers */
+	TRANSFER_CLOSED,		/*!< Allow no SIP transfers */
+};
+
+
 /* Do _NOT_ make any changes to this enum, or the array following it;
    if you think you are doing the right thing, you are probably
    not doing the right thing. If you think there are changes
@@ -450,6 +459,7 @@
 static int allow_external_domains;	/*!< Accept calls to external SIP domains? */
 static int global_callevents;		/*!< Whether we send manager events or not */
 static int global_t1min;		/*!< T1 roundtrip time minimum */
+enum transfermodes global_allowtransfer;	/*! SIP Refer restriction scheme */
 
 /*! \brief Codecs that we support by default: */
 static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263;
@@ -756,6 +766,7 @@
 	int rtptimeout;				/*!< RTP timeout time */
 	int rtpholdtimeout;			/*!< RTP timeout when on hold */
 	int rtpkeepalive;			/*!< Send RTP packets for keepalive */
+	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	enum subscriptiontype subscribed;	/*!< Is this dialog a subscription?  */
 	int stateid;
 	int laststate;				/*!< Last known extension state */
@@ -817,6 +828,7 @@
 	int capability;			/*!< Codec capability */
 	int inUse;			/*!< Number of calls in use */
 	int call_limit;			/*!< Limit of concurrent calls */
+	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	struct ast_ha *ha;		/*!< ACL setting */
 	struct ast_variable *chanvars;	/*!< Variables to set for channel created by user */
 	int maxcallbitrate;		/*!< Maximum Bitrate for a video call */
@@ -845,6 +857,7 @@
 	int callingpres;		/*!< Calling id presentation */
 	int inUse;			/*!< Number of calls in use */
 	int call_limit;			/*!< Limit of concurrent calls */
+	enum transfermodes allowtransfer;	/*! SIP Refer restriction scheme */
 	char vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
 	char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
 	char language[MAX_LANGUAGE];	/*!<  Default language for prompts */
@@ -2001,6 +2014,7 @@
 	r->maxtime = peer->maxms;
 	r->callgroup = peer->callgroup;
 	r->pickupgroup = peer->pickupgroup;
+	r->allowtransfer = peer->allowtransfer;
 	/* Set timer T1 to RTT for this peer (if known by qualify=) */
 	/* Minimum is settable or default to 100 ms */
 	if (peer->maxms && peer->lastms)
@@ -3293,6 +3307,7 @@
 	/* Assign default music on hold class */
 	ast_string_field_set(p, musicclass, default_musicclass);
 	p->capability = global_capability;
+	p->allowtransfer = global_allowtransfer;
 	if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
 	    (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
 		p->noncodeccapability |= AST_RTP_DTMF;
@@ -7210,6 +7225,7 @@
 			ast_string_field_set(p, accountcode, user->accountcode);
 			ast_string_field_set(p, language, user->language);
 			ast_string_field_set(p, musicclass, user->musicclass);
+			p->allowtransfer = user->allowtransfer;
 			p->amaflags = user->amaflags;
 			p->callgroup = user->callgroup;
 			p->pickupgroup = user->pickupgroup;
@@ -7495,6 +7511,16 @@
 #undef FORMAT2
 }
 
+/*! \brief Convert transfer mode to text string */
+static char *transfermode2str(enum transfermodes mode)
+{
+	if (mode == TRANSFER_OPENFORALL)
+		return "open";
+	else if (mode == TRANSFER_CLOSED)
+		return "closed";
+	return "strict";
+}
+
 /*! \brief  Convert NAT setting to text string */
 static char *nat2str(int nat)
 {
@@ -8100,6 +8126,7 @@
 		if (!ast_strlen_zero(peer->accountcode))
 			ast_cli(fd, "  Accountcode  : %s\n", peer->accountcode);
 		ast_cli(fd, "  AMA flags    : %s\n", ast_cdr_flags2str(peer->amaflags));
+		ast_cli(fd, "  Transfer mode: %s\n", transfermode2str(peer->allowtransfer));
 		ast_cli(fd, "  CallingPres  : %s\n", ast_describe_caller_presentation(peer->callingpres));
 		if (!ast_strlen_zero(peer->fromuser))
 			ast_cli(fd, "  FromUser     : %s\n", peer->fromuser);
@@ -8189,6 +8216,7 @@
 		astman_append(s, "Pickupgroup: ");
 		print_group(fd, peer->pickupgroup, 1);
 		astman_append(s, "VoiceMailbox: %s\r\n", peer->mailbox);
+		astman_append(s, "TransferMode: %s\r\n", transfermode2str(peer->allowtransfer));
 		astman_append(s, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
 		astman_append(s, "Call limit: %d\r\n", peer->call_limit);
 		astman_append(s, "MaxCallBR: %dkbps\r\n", peer->maxcallbitrate);
@@ -8275,6 +8303,7 @@
 		if (!ast_strlen_zero(user->accountcode))
 			ast_cli(fd, "  Accountcode  : %s\n", user->accountcode);
 		ast_cli(fd, "  AMA flags    : %s\n", ast_cdr_flags2str(user->amaflags));
+		ast_cli(fd, "  Transfer mode: %s\n", transfermode2str(user->allowtransfer));
 		ast_cli(fd, "  CallingPres  : %s\n", ast_describe_caller_presentation(user->callingpres));
 		ast_cli(fd, "  Call limit   : %d\n", user->call_limit);
 		ast_cli(fd, "  Callgroup    : ");
@@ -8395,6 +8424,7 @@
 	ast_cli(fd, "  Outbound reg. timeout:  %d secs\n", global_reg_timeout);
 	ast_cli(fd, "  Outbound reg. attempts: %d\n", global_regattempts_max);
 	ast_cli(fd, "  Notify ringing state:   %s\n", global_notifyringing ? "Yes" : "No");
+	ast_cli(fd, "  SIP Transfer mode:      %s\n", transfermode2str(global_allowtransfer));
 	ast_cli(fd, "  Max Call Bitrate:       %dkbps\r\n", default_maxcallbitrate);
 	ast_cli(fd, "\nDefault Settings:\n");
 	ast_cli(fd, "-----------------\n");
@@ -8672,6 +8702,7 @@
 			ast_cli(fd, "  Format                  %s\n", ast_getformatname(cur->owner ? cur->owner->nativeformats : 0) );
 			ast_cli(fd, "  Theoretical Address:    %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), cur->sa.sin_addr), ntohs(cur->sa.sin_port));
 			ast_cli(fd, "  Received Address:       %s:%d\n", ast_inet_ntoa(iabuf, sizeof(iabuf), cur->recv.sin_addr), ntohs(cur->recv.sin_port));
+			ast_cli(fd, "  SIP Transfer mode:      %s\n", transfermode2str(cur->allowtransfer));
 			ast_cli(fd, "  NAT Support:            %s\n", nat2str(ast_test_flag(&cur->flags[0], SIP_NAT)));
 			ast_cli(fd, "  Audio IP:               %s %s\n", ast_inet_ntoa(iabuf, sizeof(iabuf), cur->redirip.sin_addr.s_addr ? cur->redirip.sin_addr : cur->ourip), cur->redirip.sin_addr.s_addr ? "(Outside bridge)" : "(local)" );
 			ast_cli(fd, "  Our Tag:                %s\n", cur->tag);
@@ -10933,6 +10964,30 @@
 
 	if (option_debug > 2)
 		ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid);
+
+	/* Check if transfer is allowed from this device */
+	if (p->allowtransfer == TRANSFER_CLOSED ) {
+		/* Transfer not allowed, decline */
+		transmit_response(p, "603 Declined (policy)", req);
+		append_history(p, "Xfer", "Refer failed. Allowtransfer == closed.");
+		/* Do not destroy SIP session */
+		return 0;
+	}
+
+	if (!p->owner) {
+		/* This is a REFER outside of an existing SIP dialog */
+		/* We can't handle that, so decline it */
+		if (option_debug > 2)
+			ast_log(LOG_DEBUG, "Call %s: Declined REFER, outside of dialog...\n", p->callid);
+		transmit_response(p, "603 Declined (No dialog)", req);
+		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
+			append_history(p, "Xfer", "Refer failed. Outside of dialog.");
+			ast_set_flag(&p->flags[0], SIP_ALREADYGONE);	
+			ast_set_flag(&p->flags[0], SIP_NEEDDESTROY);	
+		}
+		return 0;
+	}	
+
 	if (ast_strlen_zero(p->context))
 		ast_string_field_set(p, context, default_context);
 	res = get_refer_info(p, req);
@@ -10945,7 +11000,7 @@
 		transmit_response_with_allow(p, "404 Not Found", req, 1);
 	else {
 		int nobye = 0;
-		if (!ignore) {
+		if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
 			if (p->refer_call) {
 				ast_log(LOG_DEBUG,"202 Accepted (supervised)\n");
 				attempt_transfer(p, p->refer_call);
@@ -12377,6 +12432,7 @@
 	ast_copy_flags(&user->flags[0], &global_flags[0], SIP_FLAGS_TO_COPY);
 	ast_copy_flags(&user->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
 	user->capability = global_capability;
+	user->allowtransfer = global_allowtransfer;
 	user->prefs = default_prefs;
 	/* set default context */
 	strcpy(user->context, default_context);
@@ -12402,6 +12458,8 @@
 		} else if (!strcasecmp(v->name, "permit") ||
 				   !strcasecmp(v->name, "deny")) {
 			user->ha = ast_append_ha(v->name, v->value, user->ha);
+		} else if (!strcasecmp(v->name, "allowtransfer")) {
+			user->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
 		} else if (!strcasecmp(v->name, "secret")) {
 			ast_copy_string(user->secret, v->value, sizeof(user->secret)); 
 		} else if (!strcasecmp(v->name, "md5secret")) {
@@ -12475,6 +12533,7 @@
 	peer->rtptimeout = global_rtptimeout;
 	peer->rtpholdtimeout = global_rtpholdtimeout;
 	peer->rtpkeepalive = global_rtpkeepalive;
+	peer->allowtransfer = global_allowtransfer;
 	strcpy(peer->vmexten, default_vmexten);
 	peer->secret[0] = '\0';
 	peer->md5secret[0] = '\0';
@@ -12677,6 +12736,8 @@
 			ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten));
 		} else if (!strcasecmp(v->name, "callgroup")) {
 			peer->callgroup = ast_get_group(v->value);
+		} else if (!strcasecmp(v->name, "allowtransfer")) {
+			peer->allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
 		} else if (!strcasecmp(v->name, "pickupgroup")) {
 			peer->pickupgroup = ast_get_group(v->value);
 		} else if (!strcasecmp(v->name, "allow")) {
@@ -12821,6 +12882,7 @@
 	global_rtptimeout = 0;
 	global_rtpholdtimeout = 0;
 	global_rtpkeepalive = 0;
+	global_allowtransfer = TRANSFER_OPENFORALL;	/* Merrily accept all transfers by default */
 	global_rtautoclear = 120;
 	ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWSUBSCRIBE);	/* Default for peers, users: TRUE */
 	ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP);		/* Default for peers, users: TRUE */
@@ -12862,7 +12924,10 @@
 			ast_copy_string(global_realm, v->value, sizeof(global_realm));
 		} else if (!strcasecmp(v->name, "useragent")) {
 			ast_copy_string(global_useragent, v->value, sizeof(global_useragent));
-			ast_log(LOG_DEBUG, "Setting SIP channel User-Agent Name to %s\n", global_useragent);
+			if (option_debug)
+				ast_log(LOG_DEBUG, "Setting SIP channel User-Agent Name to %s\n", global_useragent);
+		} else if (!strcasecmp(v->name, "allowtransfer")) {
+			global_allowtransfer = ast_true(v->value) ? TRANSFER_OPENFORALL : TRANSFER_CLOSED;
 		} else if (!strcasecmp(v->name, "rtcachefriends")) {
 			ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);	
 		} else if (!strcasecmp(v->name, "rtupdate")) {



More information about the asterisk-commits mailing list