mirror of
https://github.com/asterisk/asterisk.git
synced 2026-07-22 14:34:09 -07:00
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) git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@19546 65c4cc65-6c06-0410-ace0-fbb531ad65f3
This commit is contained in:
+67
-2
@@ -203,6 +203,15 @@ static int usecnt = 0;
|
||||
#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 char global_useragent[AST_MAX_EXTENSION]; /*!< Useragent for the SIP chan
|
||||
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 @@ static struct sip_pvt {
|
||||
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 @@ struct sip_user {
|
||||
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 @@ struct sip_peer {
|
||||
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 @@ static int create_addr_from_peer(struct sip_pvt *r, struct sip_peer *peer)
|
||||
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 @@ static struct sip_pvt *sip_alloc(ast_string_field callid, struct sockaddr_in *si
|
||||
/* 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 @@ static int check_user_full(struct sip_pvt *p, struct sip_request *req, int sipme
|
||||
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 @@ static int sip_show_inuse(int fd, int argc, char *argv[]) {
|
||||
#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 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
|
||||
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 @@ static int _sip_show_peer(int type, int fd, struct mansession *s, struct message
|
||||
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 @@ static int sip_show_user(int fd, int argc, char *argv[])
|
||||
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 @@ static int sip_show_settings(int fd, int argc, char *argv[])
|
||||
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 @@ static int sip_show_channel(int fd, int argc, char *argv[])
|
||||
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 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
|
||||
|
||||
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 @@ static int handle_request_refer(struct sip_pvt *p, struct sip_request *req, int
|
||||
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 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
|
||||
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 @@ static struct sip_user *build_user(const char *name, struct ast_variable *v, int
|
||||
} 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 @@ static void set_peer_defaults(struct sip_peer *peer)
|
||||
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 @@ static struct sip_peer *build_peer(const char *name, struct ast_variable *v, int
|
||||
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 @@ static int reload_config(enum channelreloadreason reason)
|
||||
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 @@ static int reload_config(enum channelreloadreason reason)
|
||||
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")) {
|
||||
|
||||
Reference in New Issue
Block a user