summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--channels/chan_iax2.c159
-rw-r--r--configs/iax.conf.sample20
-rw-r--r--include/asterisk/frame.h26
3 files changed, 184 insertions, 21 deletions
diff --git a/channels/chan_iax2.c b/channels/chan_iax2.c
index bb8c9eb5b..abeade87a 100644
--- a/channels/chan_iax2.c
+++ b/channels/chan_iax2.c
@@ -1332,6 +1332,103 @@ static void iax2_lock_owner(int callno)
}
}
+/*!
+ * \internal
+ * \brief Check if a control subtype is allowed on the wire.
+ *
+ * \param subtype Control frame subtype to check if allowed to/from the wire.
+ *
+ * \retval non-zero if allowed.
+ */
+static int iax2_is_control_frame_allowed(int subtype)
+{
+ enum ast_control_frame_type control = subtype;
+ int is_allowed;
+
+ /*
+ * Note: If we compare the enumeration type, which does not have any
+ * negative constants, the compiler may optimize this code away.
+ * Therefore, we must perform an integer comparison here.
+ */
+ if (subtype == -1) {
+ return -1;
+ }
+
+ /* Default to not allowing control frames to pass. */
+ is_allowed = 0;
+
+ /*
+ * The switch default is not present in order to take advantage
+ * of the compiler complaining of a missing enum case.
+ */
+ switch (control) {
+ /*
+ * These control frames make sense to send/receive across the link.
+ */
+ case AST_CONTROL_HANGUP:
+ case AST_CONTROL_RING:
+ case AST_CONTROL_RINGING:
+ case AST_CONTROL_ANSWER:
+ case AST_CONTROL_BUSY:
+ case AST_CONTROL_TAKEOFFHOOK:
+ case AST_CONTROL_OFFHOOK:
+ case AST_CONTROL_CONGESTION:
+ case AST_CONTROL_FLASH:
+ case AST_CONTROL_WINK:
+ case AST_CONTROL_OPTION:
+ case AST_CONTROL_RADIO_KEY:
+ case AST_CONTROL_RADIO_UNKEY:
+ case AST_CONTROL_PROGRESS:
+ case AST_CONTROL_PROCEEDING:
+ case AST_CONTROL_HOLD:
+ case AST_CONTROL_UNHOLD:
+ case AST_CONTROL_VIDUPDATE:
+ case AST_CONTROL_CONNECTED_LINE:
+ case AST_CONTROL_REDIRECTING:
+ case AST_CONTROL_T38_PARAMETERS:
+ case AST_CONTROL_AOC:
+ case AST_CONTROL_INCOMPLETE:
+ case AST_CONTROL_MCID:
+ is_allowed = -1;
+ break;
+
+ /*
+ * These control frames do not make sense to send/receive across the link.
+ */
+ case _XXX_AST_CONTROL_T38:
+ /* The control value is deprecated in favor of AST_CONTROL_T38_PARAMETERS. */
+ case AST_CONTROL_SRCUPDATE:
+ /* Across an IAX link the source is still the same. */
+ case AST_CONTROL_TRANSFER:
+ /* A success/fail status report from calling ast_transfer() on this machine. */
+ case AST_CONTROL_CC:
+ /* The payload contains pointers that are valid for the sending machine only. */
+ case AST_CONTROL_SRCCHANGE:
+ /* Across an IAX link the source is still the same. */
+ case AST_CONTROL_READ_ACTION:
+ /* The action can only be done by the sending machine. */
+ case AST_CONTROL_END_OF_Q:
+ /* This frame would cause the call to unexpectedly hangup. */
+ case AST_CONTROL_UPDATE_RTP_PEER:
+ /* Only meaningful across a bridge on this machine for direct-media exchange. */
+ case AST_CONTROL_PVT_CAUSE_CODE:
+ /* Intended only for the sending machine's local channel structure. */
+ case AST_CONTROL_STREAM_STOP:
+ case AST_CONTROL_STREAM_SUSPEND:
+ case AST_CONTROL_STREAM_RESTART:
+ case AST_CONTROL_STREAM_REVERSE:
+ case AST_CONTROL_STREAM_FORWARD:
+ /* None of these playback stream control frames should go across the link. */
+ case AST_CONTROL_RECORD_CANCEL:
+ case AST_CONTROL_RECORD_STOP:
+ case AST_CONTROL_RECORD_SUSPEND:
+ case AST_CONTROL_RECORD_MUTE:
+ /* None of these media recording control frames should go across the link. */
+ break;
+ }
+ return is_allowed;
+}
+
static void mwi_event_cb(void *userdata, struct stasis_subscription *sub, struct stasis_message *msg)
{
/* The MWI subscriptions exist just so the core knows we care about those
@@ -5615,8 +5712,13 @@ static int iax2_indicate(struct ast_channel *c, int condition, const void *data,
}
break;
case AST_CONTROL_CONNECTED_LINE:
- if (!ast_test_flag64(pvt, IAX_SENDCONNECTEDLINE))
+ case AST_CONTROL_REDIRECTING:
+ if (!ast_test_flag64(pvt, IAX_SENDCONNECTEDLINE)) {
+ /* We are not configured to allow sending these updates. */
+ ast_debug(2, "Callno %u: Config blocked sending control frame %d.\n",
+ callno, condition);
goto done;
+ }
break;
case AST_CONTROL_PVT_CAUSE_CODE:
res = -1;
@@ -7557,6 +7659,12 @@ static int __send_command(struct chan_iax2_pvt *i, char type, int command, unsig
static int send_command(struct chan_iax2_pvt *i, char type, int command, unsigned int ts, const unsigned char *data, int datalen, int seqno)
{
+ if (type == AST_FRAME_CONTROL && !iax2_is_control_frame_allowed(command)) {
+ /* Control frame should not go out on the wire. */
+ ast_debug(2, "Callno %u: Blocked sending control frame %d.\n",
+ i->callno, command);
+ return 0;
+ }
return __send_command(i, type, command, ts, data, datalen, seqno, 0, 0, 0);
}
@@ -10417,13 +10525,6 @@ static int socket_process_helper(struct iax2_thread *thread)
iaxs[fr->callno]->videoformat = ast_format_to_old_bitfield(&f.subclass.format);
}
}
- if (f.frametype == AST_FRAME_CONTROL && iaxs[fr->callno]->owner) {
- if (f.subclass.integer == AST_CONTROL_BUSY) {
- ast_channel_hangupcause_set(iaxs[fr->callno]->owner, AST_CAUSE_BUSY);
- } else if (f.subclass.integer == AST_CONTROL_CONGESTION) {
- ast_channel_hangupcause_set(iaxs[fr->callno]->owner, AST_CAUSE_CONGESTION);
- }
- }
if (f.frametype == AST_FRAME_IAX) {
AST_SCHED_DEL(sched, iaxs[fr->callno]->initid);
/* Handle the IAX pseudo frame itself */
@@ -11607,17 +11708,48 @@ immediatedial:
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
- /* Don't allow connected line updates unless we are configured to */
- if (f.frametype == AST_FRAME_CONTROL && f.subclass.integer == AST_CONTROL_CONNECTED_LINE) {
- struct ast_party_connected_line connected;
- if (!ast_test_flag64(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) {
+ if (f.frametype == AST_FRAME_CONTROL) {
+ if (!iax2_is_control_frame_allowed(f.subclass.integer)) {
+ /* Control frame not allowed to come from the wire. */
+ ast_debug(2, "Callno %u: Blocked receiving control frame %d.\n",
+ fr->callno, f.subclass.integer);
ast_variables_destroy(ies.vars);
ast_mutex_unlock(&iaxsl[fr->callno]);
return 1;
}
+ if (f.subclass.integer == AST_CONTROL_CONNECTED_LINE
+ || f.subclass.integer == AST_CONTROL_REDIRECTING) {
+ if (!ast_test_flag64(iaxs[fr->callno], IAX_RECVCONNECTEDLINE)) {
+ /* We are not configured to allow receiving these updates. */
+ ast_debug(2, "Callno %u: Config blocked receiving control frame %d.\n",
+ fr->callno, f.subclass.integer);
+ ast_variables_destroy(ies.vars);
+ ast_mutex_unlock(&iaxsl[fr->callno]);
+ return 1;
+ }
+ }
+
+ iax2_lock_owner(fr->callno);
+ if (iaxs[fr->callno] && iaxs[fr->callno]->owner) {
+ if (f.subclass.integer == AST_CONTROL_BUSY) {
+ ast_channel_hangupcause_set(iaxs[fr->callno]->owner, AST_CAUSE_BUSY);
+ } else if (f.subclass.integer == AST_CONTROL_CONGESTION) {
+ ast_channel_hangupcause_set(iaxs[fr->callno]->owner, AST_CAUSE_CONGESTION);
+ }
+ ast_channel_unlock(iaxs[fr->callno]->owner);
+ }
+ }
+
+ if (f.frametype == AST_FRAME_CONTROL
+ && f.subclass.integer == AST_CONTROL_CONNECTED_LINE) {
+ struct ast_party_connected_line connected;
- /* Initialize defaults */
+ /*
+ * Process a received connected line update.
+ *
+ * Initialize defaults.
+ */
ast_party_connected_line_init(&connected);
connected.id.number.presentation = iaxs[fr->callno]->calling_pres;
connected.id.name.presentation = iaxs[fr->callno]->calling_pres;
@@ -11640,6 +11772,7 @@ immediatedial:
}
ast_party_connected_line_free(&connected);
}
+
/* Common things */
f.src = "IAX2";
f.mallocd = 0;
diff --git a/configs/iax.conf.sample b/configs/iax.conf.sample
index a9841f0da..e17c7dfeb 100644
--- a/configs/iax.conf.sample
+++ b/configs/iax.conf.sample
@@ -610,14 +610,18 @@ description=Demo System At Digium ; Description of this peer, as listed by
; IPs can also optionally be given but are not required. Caller*ID can be
; suggested to the other side as well if it is for example a phone instead of
; another PBX.
-;connectedline=yes ; Set how connected line information is handled for this
-; ; peer. If set to "yes", both sending and receiving
-; ; connected line information will be enabled. If set to
-; ; "send", this peer will send connected line information
-; ; but will not process connected line updates. If set to
-; ; "receive", connected line updates will be processed
-; ; but not sent. If set to "no", connected line updates
-; ; will be disabled. Default is "no".
+;connectedline=yes ; Set if connected line and redirecting information updates
+; ; are passed between Asterisk servers for this peer.
+; ; yes - Sending and receiving updates are enabled.
+; ; send - Only send updates.
+; ; receive - Only process received updates.
+; ; no - Sending and receiving updates are disabled.
+; ; Default is "no".
+; ;
+; ; Note: Because of an incompatibility between Asterisk v1.4
+; ; and Asterisk v1.8 or later, this option must be set
+; ; to "no" toward the Asterisk v1.4 peer. A symptom of the
+; ; incompatibility is the call gets disconnected unexpectedly.
;[dynamichost]
diff --git a/include/asterisk/frame.h b/include/asterisk/frame.h
index 14491aed8..53383834f 100644
--- a/include/asterisk/frame.h
+++ b/include/asterisk/frame.h
@@ -235,6 +235,18 @@ extern struct ast_frame ast_null_frame;
/*! Reject link request */
#define AST_HTML_LINKREJECT 20
+/*!
+ * \brief Internal control frame subtype field values.
+ *
+ * \warning
+ * IAX2 sends these values out over the wire. To prevent future
+ * incompatibilities, pick the next value in the enum from whatever
+ * is on the current trunk. If you lose the merge race you need to
+ * fix the previous branches to match what is on trunk. In addition
+ * you need to change chan_iax2 to explicitly allow the control
+ * frame over the wire if it makes sense for the frame to be passed
+ * to another Asterisk instance.
+ */
enum ast_control_frame_type {
AST_CONTROL_HANGUP = 1, /*!< Other end has hungup */
AST_CONTROL_RING = 2, /*!< Local ring */
@@ -270,6 +282,20 @@ enum ast_control_frame_type {
AST_CONTROL_UPDATE_RTP_PEER = 32, /*!< Interrupt the bridge and have it update the peer */
AST_CONTROL_PVT_CAUSE_CODE = 33, /*!< Contains an update to the protocol-specific cause-code stored for branching dials */
+ /*
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ *
+ * IAX2 sends these values out over the wire. To prevent future
+ * incompatibilities, pick the next value in the enum from whatever
+ * is on the current trunk. If you lose the merge race you need to
+ * fix the previous branches to match what is on trunk. In addition
+ * you need to change chan_iax2 to explicitly allow the control
+ * frame over the wire if it makes sense for the frame to be passed
+ * to another Asterisk instance.
+ *
+ * WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING
+ */
+
/* Control frames used to manipulate a stream on a channel. The values for these
* must be greater than the allowed value for a 8-bit char, so that they avoid
* conflicts with DTMF values. */