From aae45acbda1f6100cd9de816855166a32b991ce0 Mon Sep 17 00:00:00 2001 From: Mark Michelson Date: Wed, 15 Apr 2015 10:38:02 -0500 Subject: Detect potential forwarding loops based on count. A potential problem that can arise is the following: * Bob's phone is programmed to automatically forward to Carol. * Carol's phone is programmed to automatically forward to Bob. * Alice calls Bob. If left unchecked, this results in an endless loops of call forwards that would eventually result in some sort of fiery crash. Asterisk's method of solving this issue was to track which interfaces had been dialed. If a destination were dialed a second time, then the attempt to call that destination would fail since a loop was detected. The problem with this method is that call forwarding has evolved. Some SIP phones allow for a user to manually forward an incoming call to an ad-hoc destination. This can mean that: * There are legitimate use cases where a device may be dialed multiple times, or * There can be human error when forwarding calls. This change removes the old method of detecting forwarding loops in favor of keeping a count of the number of destinations a channel has dialed on a particular branch of a call. If the number exceeds the set number of max forwards, then the call fails. This approach has the following advantages over the old: * It is much simpler. * It can detect loops involving local channels. * It is user configurable. The only disadvantage it has is that in the case where there is a legitimate forwarding loop present, it takes longer to detect it. However, the forwarding loop is still properly detected and the call is cleaned up as it should be. Address review feedback on gerrit. * Correct "mfgium" to "Digium" * Decrement max forwards by one in the case where allocation of the max forwards datastore is required. * Remove irrelevant code change from pjsip_global_headers.c ASTERISK-24958 #close Change-Id: Ia7e4b7cd3bccfbd34d9a859838356931bba56c23 --- include/asterisk/global_datastores.h | 6 --- include/asterisk/max_forwards.h | 78 ++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 6 deletions(-) create mode 100644 include/asterisk/max_forwards.h (limited to 'include') diff --git a/include/asterisk/global_datastores.h b/include/asterisk/global_datastores.h index 16267a894..2946ede84 100644 --- a/include/asterisk/global_datastores.h +++ b/include/asterisk/global_datastores.h @@ -26,14 +26,8 @@ #include "asterisk/channel.h" -extern const struct ast_datastore_info dialed_interface_info; extern const struct ast_datastore_info secure_call_info; -struct ast_dialed_interface { - AST_LIST_ENTRY(ast_dialed_interface) list; - char interface[1]; -}; - struct ast_secure_call_store { unsigned int signaling:1; unsigned int media:1; diff --git a/include/asterisk/max_forwards.h b/include/asterisk/max_forwards.h new file mode 100644 index 000000000..3130b4b64 --- /dev/null +++ b/include/asterisk/max_forwards.h @@ -0,0 +1,78 @@ +/* + * Asterisk -- An open source telephony toolkit. + * + * Copyright (C) 2015, Digium, Inc. + * + * Mark Michelson + * + * See http://www.asterisk.org for more information about + * the Asterisk project. Please do not directly contact + * any of the maintainers of this project for assistance; + * the project provides a web site, mailing lists and IRC + * channels for your use. + * + * This program is free software, distributed under the terms of + * the GNU General Public License Version 2. See the LICENSE file + * at the top of the source tree. + */ + +#ifndef MAX_FORWARDS_H + +struct ast_channel; + +/*! + * \brief Set the starting max forwards for a particular channel. + * + * \pre chan is locked + * + * \param starting_count The value to set the max forwards to. + * \param chan The channel on which to set the max forwards. + * \retval 0 Success + * \retval 1 Failure + */ +int ast_max_forwards_set(struct ast_channel *chan, int starting_count); + +/*! + * \brief Get the current max forwards for a particular channel. + * + * If the channel has not had max forwards set on it, then the channel + * will have the default max forwards set on it and that value will + * be returned. + * + * \pre chan is locked + * + * \param chan The channel to get the max forwards for. + * \return The current max forwards count on the channel + */ +int ast_max_forwards_get(struct ast_channel *chan); + +/*! + * \brief Decrement the max forwards count for a particular channel. + * + * If the channel has not had max forwards set on it, then the channel + * will have the default max forwards set on it and that value will + * not be decremented. + * + * \pre chan is locked + * + * \chan The channel for which the max forwards value should be decremented + * \retval 0 Success + * \retval -1 Failure + */ +int ast_max_forwards_decrement(struct ast_channel *chan); + +/*! + * \brief Reset the max forwards on a channel to its starting value. + * + * If the channel has not had max forwards set on it, then the channel + * will have the default max forwards set on it. + * + * \pre chan is locked. + * + * \param chan The channel on which to reset the max forwards count. + * \retval 0 Success + * \retval -1 Failure + */ +int ast_max_forwards_reset(struct ast_channel *chan); + +#endif /* MAX_FORWARDS_H */ -- cgit v1.2.3