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
1.4
Olle Johansson 20 years ago
parent f841fe7d11
commit ea4235c56c

@ -203,6 +203,15 @@ static int usecnt = 0;
#define RTP 1 #define RTP 1
#define NO_RTP 0 #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; /* 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 if you think you are doing the right thing, you are probably
not doing the right thing. If you think there are changes 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 allow_external_domains; /*!< Accept calls to external SIP domains? */
static int global_callevents; /*!< Whether we send manager events or not */ static int global_callevents; /*!< Whether we send manager events or not */
static int global_t1min; /*!< T1 roundtrip time minimum */ static int global_t1min; /*!< T1 roundtrip time minimum */
enum transfermodes global_allowtransfer; /*! SIP Refer restriction scheme */
/*! \brief Codecs that we support by default: */ /*! \brief Codecs that we support by default: */
static int global_capability = AST_FORMAT_ULAW | AST_FORMAT_ALAW | AST_FORMAT_GSM | AST_FORMAT_H263; 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 rtptimeout; /*!< RTP timeout time */
int rtpholdtimeout; /*!< RTP timeout when on hold */ int rtpholdtimeout; /*!< RTP timeout when on hold */
int rtpkeepalive; /*!< Send RTP packets for keepalive */ int rtpkeepalive; /*!< Send RTP packets for keepalive */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
enum subscriptiontype subscribed; /*!< Is this dialog a subscription? */ enum subscriptiontype subscribed; /*!< Is this dialog a subscription? */
int stateid; int stateid;
int laststate; /*!< Last known extension state */ int laststate; /*!< Last known extension state */
@ -817,6 +828,7 @@ struct sip_user {
int capability; /*!< Codec capability */ int capability; /*!< Codec capability */
int inUse; /*!< Number of calls in use */ int inUse; /*!< Number of calls in use */
int call_limit; /*!< Limit of concurrent calls */ int call_limit; /*!< Limit of concurrent calls */
enum transfermodes allowtransfer; /*! SIP Refer restriction scheme */
struct ast_ha *ha; /*!< ACL setting */ struct ast_ha *ha; /*!< ACL setting */
struct ast_variable *chanvars; /*!< Variables to set for channel created by user */ struct ast_variable *chanvars; /*!< Variables to set for channel created by user */
int maxcallbitrate; /*!< Maximum Bitrate for a video call */ int maxcallbitrate; /*!< Maximum Bitrate for a video call */
@ -845,6 +857,7 @@ struct sip_peer {
int callingpres; /*!< Calling id presentation */ int callingpres; /*!< Calling id presentation */
int inUse; /*!< Number of calls in use */ int inUse; /*!< Number of calls in use */
int call_limit; /*!< Limit of concurrent calls */ 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 vmexten[AST_MAX_EXTENSION]; /*!< Dialplan extension for MWI notify message*/
char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */ char mailbox[AST_MAX_EXTENSION]; /*!< Mailbox setting for MWI checks */
char language[MAX_LANGUAGE]; /*!< Default language for prompts */ 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->maxtime = peer->maxms;
r->callgroup = peer->callgroup; r->callgroup = peer->callgroup;
r->pickupgroup = peer->pickupgroup; r->pickupgroup = peer->pickupgroup;
r->allowtransfer = peer->allowtransfer;
/* Set timer T1 to RTT for this peer (if known by qualify=) */ /* Set timer T1 to RTT for this peer (if known by qualify=) */
/* Minimum is settable or default to 100 ms */ /* Minimum is settable or default to 100 ms */
if (peer->maxms && peer->lastms) 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 */ /* Assign default music on hold class */
ast_string_field_set(p, musicclass, default_musicclass); ast_string_field_set(p, musicclass, default_musicclass);
p->capability = global_capability; p->capability = global_capability;
p->allowtransfer = global_allowtransfer;
if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) || if ((ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_RFC2833) ||
(ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO)) (ast_test_flag(&p->flags[0], SIP_DTMF) == SIP_DTMF_AUTO))
p->noncodeccapability |= AST_RTP_DTMF; 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, accountcode, user->accountcode);
ast_string_field_set(p, language, user->language); ast_string_field_set(p, language, user->language);
ast_string_field_set(p, musicclass, user->musicclass); ast_string_field_set(p, musicclass, user->musicclass);
p->allowtransfer = user->allowtransfer;
p->amaflags = user->amaflags; p->amaflags = user->amaflags;
p->callgroup = user->callgroup; p->callgroup = user->callgroup;
p->pickupgroup = user->pickupgroup; p->pickupgroup = user->pickupgroup;
@ -7495,6 +7511,16 @@ static int sip_show_inuse(int fd, int argc, char *argv[]) {
#undef FORMAT2 #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 */ /*! \brief Convert NAT setting to text string */
static char *nat2str(int nat) 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)) if (!ast_strlen_zero(peer->accountcode))
ast_cli(fd, " Accountcode : %s\n", 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, " 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)); ast_cli(fd, " CallingPres : %s\n", ast_describe_caller_presentation(peer->callingpres));
if (!ast_strlen_zero(peer->fromuser)) if (!ast_strlen_zero(peer->fromuser))
ast_cli(fd, " FromUser : %s\n", 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: "); astman_append(s, "Pickupgroup: ");
print_group(fd, peer->pickupgroup, 1); print_group(fd, peer->pickupgroup, 1);
astman_append(s, "VoiceMailbox: %s\r\n", peer->mailbox); 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, "LastMsgsSent: %d\r\n", peer->lastmsgssent);
astman_append(s, "Call limit: %d\r\n", peer->call_limit); astman_append(s, "Call limit: %d\r\n", peer->call_limit);
astman_append(s, "MaxCallBR: %dkbps\r\n", peer->maxcallbitrate); 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)) if (!ast_strlen_zero(user->accountcode))
ast_cli(fd, " Accountcode : %s\n", 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, " 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, " CallingPres : %s\n", ast_describe_caller_presentation(user->callingpres));
ast_cli(fd, " Call limit : %d\n", user->call_limit); ast_cli(fd, " Call limit : %d\n", user->call_limit);
ast_cli(fd, " Callgroup : "); 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. timeout: %d secs\n", global_reg_timeout);
ast_cli(fd, " Outbound reg. attempts: %d\n", global_regattempts_max); 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, " 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, " Max Call Bitrate: %dkbps\r\n", default_maxcallbitrate);
ast_cli(fd, "\nDefault Settings:\n"); ast_cli(fd, "\nDefault Settings:\n");
ast_cli(fd, "-----------------\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, " 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, " 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, " 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, " 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, " 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); 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) if (option_debug > 2)
ast_log(LOG_DEBUG, "SIP call transfer received for call %s (REFER)!\n", p->callid); 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)) if (ast_strlen_zero(p->context))
ast_string_field_set(p, context, default_context); ast_string_field_set(p, context, default_context);
res = get_refer_info(p, req); 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); transmit_response_with_allow(p, "404 Not Found", req, 1);
else { else {
int nobye = 0; int nobye = 0;
if (!ignore) { if (!ast_test_flag(req, SIP_PKT_IGNORE)) {
if (p->refer_call) { if (p->refer_call) {
ast_log(LOG_DEBUG,"202 Accepted (supervised)\n"); ast_log(LOG_DEBUG,"202 Accepted (supervised)\n");
attempt_transfer(p, p->refer_call); 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[0], &global_flags[0], SIP_FLAGS_TO_COPY);
ast_copy_flags(&user->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY); ast_copy_flags(&user->flags[1], &global_flags[1], SIP_PAGE2_FLAGS_TO_COPY);
user->capability = global_capability; user->capability = global_capability;
user->allowtransfer = global_allowtransfer;
user->prefs = default_prefs; user->prefs = default_prefs;
/* set default context */ /* set default context */
strcpy(user->context, 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") || } else if (!strcasecmp(v->name, "permit") ||
!strcasecmp(v->name, "deny")) { !strcasecmp(v->name, "deny")) {
user->ha = ast_append_ha(v->name, v->value, user->ha); 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")) { } else if (!strcasecmp(v->name, "secret")) {
ast_copy_string(user->secret, v->value, sizeof(user->secret)); ast_copy_string(user->secret, v->value, sizeof(user->secret));
} else if (!strcasecmp(v->name, "md5secret")) { } else if (!strcasecmp(v->name, "md5secret")) {
@ -12475,6 +12533,7 @@ static void set_peer_defaults(struct sip_peer *peer)
peer->rtptimeout = global_rtptimeout; peer->rtptimeout = global_rtptimeout;
peer->rtpholdtimeout = global_rtpholdtimeout; peer->rtpholdtimeout = global_rtpholdtimeout;
peer->rtpkeepalive = global_rtpkeepalive; peer->rtpkeepalive = global_rtpkeepalive;
peer->allowtransfer = global_allowtransfer;
strcpy(peer->vmexten, default_vmexten); strcpy(peer->vmexten, default_vmexten);
peer->secret[0] = '\0'; peer->secret[0] = '\0';
peer->md5secret[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)); ast_copy_string(peer->vmexten, v->value, sizeof(peer->vmexten));
} else if (!strcasecmp(v->name, "callgroup")) { } else if (!strcasecmp(v->name, "callgroup")) {
peer->callgroup = ast_get_group(v->value); 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")) { } else if (!strcasecmp(v->name, "pickupgroup")) {
peer->pickupgroup = ast_get_group(v->value); peer->pickupgroup = ast_get_group(v->value);
} else if (!strcasecmp(v->name, "allow")) { } else if (!strcasecmp(v->name, "allow")) {
@ -12821,6 +12882,7 @@ static int reload_config(enum channelreloadreason reason)
global_rtptimeout = 0; global_rtptimeout = 0;
global_rtpholdtimeout = 0; global_rtpholdtimeout = 0;
global_rtpkeepalive = 0; global_rtpkeepalive = 0;
global_allowtransfer = TRANSFER_OPENFORALL; /* Merrily accept all transfers by default */
global_rtautoclear = 120; 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_ALLOWSUBSCRIBE); /* Default for peers, users: TRUE */
ast_set_flag(&global_flags[1], SIP_PAGE2_ALLOWOVERLAP); /* 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)); ast_copy_string(global_realm, v->value, sizeof(global_realm));
} else if (!strcasecmp(v->name, "useragent")) { } else if (!strcasecmp(v->name, "useragent")) {
ast_copy_string(global_useragent, v->value, sizeof(global_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")) { } else if (!strcasecmp(v->name, "rtcachefriends")) {
ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS); ast_set2_flag(&global_flags[1], ast_true(v->value), SIP_PAGE2_RTCACHEFRIENDS);
} else if (!strcasecmp(v->name, "rtupdate")) { } else if (!strcasecmp(v->name, "rtupdate")) {

Loading…
Cancel
Save