瀏覽代碼

modules/tm: add faked_reply_prio parameter to be able to punish faked replies

Thi should fix FS#54.
Alex Hermann 14 年之前
父節點
當前提交
6b2d6a3f8b
共有 5 個文件被更改,包括 142 次插入52 次删除
  1. 68 44
      modules/tm/README
  2. 40 0
      modules/tm/doc/params.xml
  3. 29 8
      modules/tm/t_reply.c
  4. 4 0
      modules/tm/t_reply.h
  5. 1 0
      modules/tm/tm.c

+ 68 - 44
modules/tm/README

@@ -55,8 +55,9 @@ Juha Heinanen
         1.4.35. disable_6xx_block (integer)
         1.4.35. disable_6xx_block (integer)
         1.4.36. local_ack_mode (integer)
         1.4.36. local_ack_mode (integer)
         1.4.37. failure_reply_mode (integer)
         1.4.37. failure_reply_mode (integer)
-        1.4.38. local_cancel_reason (boolean)
-        1.4.39. e2e_cancel_reason (boolean)
+        1.4.38. faked_reply_prio (integer)
+        1.4.39. local_cancel_reason (boolean)
+        1.4.40. e2e_cancel_reason (boolean)
 
 
    1.5. Functions
    1.5. Functions
 
 
@@ -1129,7 +1130,30 @@ modparam("tm", "local_ack_mode", 1)
 modparam("tm", "failure_reply_mode", 3)
 modparam("tm", "failure_reply_mode", 3)
 ...
 ...
 
 
-1.4.38. local_cancel_reason (boolean)
+1.4.38. faked_reply_prio (integer)
+
+   It controls how branch selection is done. It allows to give a penalty
+   to faked replies such as the infamous 408 on branch timeout.
+
+   Internally, every reply is assigned a priority between 0 (high prio)
+   and 32000 (low prio). With this parameter the priority of fake replies
+   can be adjusted.
+     * 0 - disabled (default)
+     * < 0 - priority is increased by given amount.
+     * > 0 - priority is decreased by given amount. Do not make it higer
+       than 10000 or faked replies will even loose from 1xx clsss replies.
+
+   The default value is 0.
+
+   To let received replies win from a locally generated 408, set this
+   value to 2000.
+
+   Example 38. Set faked_reply_prio parameter
+...
+modparam("tm", "faked_reply_prio", 2000)
+...
+
+1.4.39. local_cancel_reason (boolean)
 
 
    Enables/disables adding reason headers (RFC 3326) for CANCELs generated
    Enables/disables adding reason headers (RFC 3326) for CANCELs generated
    due to receiving a final reply. The reason header added will look like:
    due to receiving a final reply. The reason header added will look like:
@@ -1142,12 +1166,12 @@ modparam("tm", "failure_reply_mode", 3)
 
 
    See also: e2e_cancel_reason.
    See also: e2e_cancel_reason.
 
 
-   Example 38. Set local_cancel_reason parameter
+   Example 39. Set local_cancel_reason parameter
 ...
 ...
 modparam("tm", "local_cancel_reason", 0)
 modparam("tm", "local_cancel_reason", 0)
 ...
 ...
 
 
-1.4.39. e2e_cancel_reason (boolean)
+1.4.40. e2e_cancel_reason (boolean)
 
 
    Enables/disables adding reason headers (RFC 3326) for CANCELs generated
    Enables/disables adding reason headers (RFC 3326) for CANCELs generated
    due to a received CANCEL. If enabled the reason headers from received
    due to a received CANCEL. If enabled the reason headers from received
@@ -1160,7 +1184,7 @@ modparam("tm", "local_cancel_reason", 0)
 
 
    See also: t_set_no_e2e_cancel_reason() and local_cancel_reason.
    See also: t_set_no_e2e_cancel_reason() and local_cancel_reason.
 
 
-   Example 39. Set e2e_cancel_reason parameter
+   Example 40. Set e2e_cancel_reason parameter
 ...
 ...
 modparam("tm", "e2e_cancel_reason", 0)
 modparam("tm", "e2e_cancel_reason", 0)
 ...
 ...
@@ -1187,7 +1211,7 @@ t_relay_to_sctp(ip, port) t_relay_to_sctp()
    derived from the message uri (using sip sepcific DNS lookups), but with
    derived from the message uri (using sip sepcific DNS lookups), but with
    the protocol corresponding to the function name.
    the protocol corresponding to the function name.
 
 
-   Example 40. t_relay_to_udp usage
+   Example 41. t_relay_to_udp usage
 ...
 ...
 if (src_ip==10.0.0.0/8)
 if (src_ip==10.0.0.0/8)
         t_relay_to_udp("1.2.3.4", "5060"); # sent to 1.2.3.4:5060 over udp
         t_relay_to_udp("1.2.3.4", "5060"); # sent to 1.2.3.4:5060 over udp
@@ -1214,7 +1238,7 @@ else
    Returns a negative value on failure--you may still want to send a
    Returns a negative value on failure--you may still want to send a
    negative reply upstream statelessly not to leave upstream UAC in lurch.
    negative reply upstream statelessly not to leave upstream UAC in lurch.
 
 
-   Example 41. t_relay usage
+   Example 42. t_relay usage
 ...
 ...
 if (!t_relay())
 if (!t_relay())
 {
 {
@@ -1243,7 +1267,7 @@ if (!t_relay())
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
      * failure_route - Failure route block to be called.
      * failure_route - Failure route block to be called.
 
 
-   Example 42. t_on_failure usage
+   Example 43. t_on_failure usage
 ...
 ...
 route {
 route {
     t_on_failure("1");
     t_on_failure("1");
@@ -1269,7 +1293,7 @@ failure_route[1] {
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
      * onreply_route - Onreply route block to be called.
      * onreply_route - Onreply route block to be called.
 
 
-   Example 43. t_on_reply usage
+   Example 44. t_on_reply usage
 ...
 ...
 loadmodule "/usr/local/lib/ser/modules/nathelper.so"
 loadmodule "/usr/local/lib/ser/modules/nathelper.so"
 ...
 ...
@@ -1301,7 +1325,7 @@ es');
    Meaning of the parameters is as follows:
    Meaning of the parameters is as follows:
      * branch_route - branch route block to be called.
      * branch_route - branch route block to be called.
 
 
-   Example 44. t_on_branch usage
+   Example 45. t_on_branch usage
 ...
 ...
 route {
 route {
         t_on_branch("1");
         t_on_branch("1");
@@ -1319,7 +1343,7 @@ branch_route[1] {
    Similarly to t_fork_to, it extends destination set by a new entry. The
    Similarly to t_fork_to, it extends destination set by a new entry. The
    difference is that current URI is taken as new entry.
    difference is that current URI is taken as new entry.
 
 
-   Example 45. append_branch usage
+   Example 46. append_branch usage
 ...
 ...
 set_user("john");
 set_user("john");
 t_fork();
 t_fork();
@@ -1334,7 +1358,7 @@ t_relay();
    the only way a script can add a new transaction in an atomic way.
    the only way a script can add a new transaction in an atomic way.
    Typically, it is used to deploy a UAS.
    Typically, it is used to deploy a UAS.
 
 
-   Example 46. t_newtran usage
+   Example 47. t_newtran usage
 ...
 ...
 if (t_newtran()) {
 if (t_newtran()) {
     log("UAS logic");
     log("UAS logic");
@@ -1353,7 +1377,7 @@ if (t_newtran()) {
      * code - Reply code number.
      * code - Reply code number.
      * reason_phrase - Reason string.
      * reason_phrase - Reason string.
 
 
-   Example 47. t_reply usage
+   Example 48. t_reply usage
 ...
 ...
 t_reply("404", "Not found");
 t_reply("404", "Not found");
 ...
 ...
@@ -1366,7 +1390,7 @@ t_reply("404", "Not found");
    none was found. However this is safely (atomically) done using
    none was found. However this is safely (atomically) done using
    t_newtran.
    t_newtran.
 
 
-   Example 48. t_lookup_request usage
+   Example 49. t_lookup_request usage
 ...
 ...
 if (t_lookup_request()) {
 if (t_lookup_request()) {
     ...
     ...
@@ -1377,7 +1401,7 @@ if (t_lookup_request()) {
 
 
    Retransmits a reply sent previously by UAS transaction.
    Retransmits a reply sent previously by UAS transaction.
 
 
-   Example 49. t_retransmit_reply usage
+   Example 50. t_retransmit_reply usage
 ...
 ...
 t_retransmit_reply();
 t_retransmit_reply();
 ...
 ...
@@ -1387,7 +1411,7 @@ t_retransmit_reply();
    Remove transaction from memory (it will be first put on a wait timer to
    Remove transaction from memory (it will be first put on a wait timer to
    absorb delayed messages).
    absorb delayed messages).
 
 
-   Example 50. t_release usage
+   Example 51. t_release usage
 ...
 ...
 t_release();
 t_release();
 ...
 ...
@@ -1402,7 +1426,7 @@ t_forward_nonack_tls(ip, port) t_forward_nonack_sctp(ip, port)
      * ip - IP address where the message should be sent.
      * ip - IP address where the message should be sent.
      * port - Port number.
      * port - Port number.
 
 
-   Example 51. t_forward_nonack usage
+   Example 52. t_forward_nonack usage
 ...
 ...
 t_forward_nonack("1.2.3.4", "5060");
 t_forward_nonack("1.2.3.4", "5060");
 ...
 ...
@@ -1425,7 +1449,7 @@ t_forward_nonack("1.2.3.4", "5060");
 
 
    See also: fr_timer, fr_inv_timer, t_reset_fr().
    See also: fr_timer, fr_inv_timer, t_reset_fr().
 
 
-   Example 52. t_set_fr usage
+   Example 53. t_set_fr usage
 ...
 ...
 route {
 route {
         t_set_fr(10000); # set only fr invite timeout to 10s
         t_set_fr(10000); # set only fr invite timeout to 10s
@@ -1452,7 +1476,7 @@ branch_route[1] {
 
 
    See also: fr_timer, fr_inv_timer, t_set_fr.
    See also: fr_timer, fr_inv_timer, t_set_fr.
 
 
-   Example 53. t_reset_fr usage
+   Example 54. t_reset_fr usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -1478,7 +1502,7 @@ route {
 
 
    See also: max_inv_lifetime, max_noninv_lifetime, t_reset_max_lifetime.
    See also: max_inv_lifetime, max_noninv_lifetime, t_reset_max_lifetime.
 
 
-   Example 54. t_set_max_lifetime usage
+   Example 55. t_set_max_lifetime usage
 ...
 ...
 route {
 route {
     if (src_ip=1.2.3.4)
     if (src_ip=1.2.3.4)
@@ -1500,7 +1524,7 @@ route {
 
 
    See also: max_inv_lifetime, max_noninv_lifetime, t_set_max_lifetime.
    See also: max_inv_lifetime, max_noninv_lifetime, t_set_max_lifetime.
 
 
-   Example 55. t_reset_max_lifetime usage
+   Example 56. t_reset_max_lifetime usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -1538,7 +1562,7 @@ route {
 
 
    See also: retr_timer1, retr_timer2, t_reset_retr().
    See also: retr_timer1, retr_timer2, t_reset_retr().
 
 
-   Example 56. t_set_retr usage
+   Example 57. t_set_retr usage
 ...
 ...
 route {
 route {
         t_set_retr(250, 0); # set only T1 to 250 ms
         t_set_retr(250, 0); # set only T1 to 250 ms
@@ -1565,7 +1589,7 @@ branch_route[1] {
 
 
    See also: retr_timer1, retr_timer2, t_set_retr.
    See also: retr_timer1, retr_timer2, t_set_retr.
 
 
-   Example 57. t_reset_retr usage
+   Example 58. t_reset_retr usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -1581,7 +1605,7 @@ route {
 
 
    See also: auto_inv_100.
    See also: auto_inv_100.
 
 
-   Example 58. t_set_auto_inv_100 usage
+   Example 59. t_set_auto_inv_100 usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -1595,7 +1619,7 @@ route {
    Returns true if the failure route is executed for a branch that did
    Returns true if the failure route is executed for a branch that did
    timeout. It can be used only from the failure_route.
    timeout. It can be used only from the failure_route.
 
 
-   Example 59. t_branch_timeout usage
+   Example 60. t_branch_timeout usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (t_branch_timeout()){
         if (t_branch_timeout()){
@@ -1610,7 +1634,7 @@ failure_route[0]{
    receive at least one reply in the past (the "current" reply is not
    receive at least one reply in the past (the "current" reply is not
    taken into account). It can be used only from the failure_route.
    taken into account). It can be used only from the failure_route.
 
 
-   Example 60. t_branch_replied usage
+   Example 61. t_branch_replied usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (t_branch_timeout()){
         if (t_branch_timeout()){
@@ -1627,7 +1651,7 @@ failure_route[0]{
    Returns true if at least one of the current transactions branches did
    Returns true if at least one of the current transactions branches did
    timeout.
    timeout.
 
 
-   Example 61. t_any_timeout usage
+   Example 62. t_any_timeout usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (!t_branch_timeout()){
         if (!t_branch_timeout()){
@@ -1644,7 +1668,7 @@ failure_route[0]{
    receive some reply in the past. If called from a failure or onreply
    receive some reply in the past. If called from a failure or onreply
    route, the "current" reply is not taken into account.
    route, the "current" reply is not taken into account.
 
 
-   Example 62. t_any_replied usage
+   Example 63. t_any_replied usage
 ...
 ...
 onreply_route[0]{
 onreply_route[0]{
         if (!t_any_replied()){
         if (!t_any_replied()){
@@ -1658,7 +1682,7 @@ onreply_route[0]{
    Returns true if "code" is the final reply received (or locally
    Returns true if "code" is the final reply received (or locally
    generated) in at least one of the current transactions branches.
    generated) in at least one of the current transactions branches.
 
 
-   Example 63. t_grep_status usage
+   Example 64. t_grep_status usage
 ...
 ...
 onreply_route[0]{
 onreply_route[0]{
         if (t_grep_status("486")){
         if (t_grep_status("486")){
@@ -1671,7 +1695,7 @@ onreply_route[0]{
 
 
    Returns true if the current transaction was canceled.
    Returns true if the current transaction was canceled.
 
 
-   Example 64. t_is_canceled usage
+   Example 65. t_is_canceled usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (t_is_canceled()){
         if (t_is_canceled()){
@@ -1685,7 +1709,7 @@ failure_route[0]{
    Returns true if the current transaction has already been expired, i.e.
    Returns true if the current transaction has already been expired, i.e.
    the max_inv_lifetime/max_noninv_lifetime interval has already elapsed.
    the max_inv_lifetime/max_noninv_lifetime interval has already elapsed.
 
 
-   Example 65. t_is_expired usage
+   Example 66. t_is_expired usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (t_is_expired()){
         if (t_is_expired()){
@@ -1706,7 +1730,7 @@ failure_route[0]{
    CANCELs were successfully sent to the pending branches, true if the
    CANCELs were successfully sent to the pending branches, true if the
    INVITE was not found, and false in case of any error.
    INVITE was not found, and false in case of any error.
 
 
-   Example 66. t_relay_cancel usage
+   Example 67. t_relay_cancel usage
 if (method == CANCEL) {
 if (method == CANCEL) {
         if (!t_relay_cancel()) {  # implicit drop if relaying was successful,
         if (!t_relay_cancel()) {  # implicit drop if relaying was successful,
                                   # nothing to do
                                   # nothing to do
@@ -1733,7 +1757,7 @@ if (method == CANCEL) {
    overwritten with the flags of the INVITE. isflagset() can be used to
    overwritten with the flags of the INVITE. isflagset() can be used to
    check the flags of the previously forwarded INVITE in this case.
    check the flags of the previously forwarded INVITE in this case.
 
 
-   Example 67. t_lookup_cancel usage
+   Example 68. t_lookup_cancel usage
 if (method == CANCEL) {
 if (method == CANCEL) {
         if (t_lookup_cancel()) {
         if (t_lookup_cancel()) {
                 log("INVITE transaction exists");
                 log("INVITE transaction exists");
@@ -1763,7 +1787,7 @@ if (method == CANCEL) {
    Dropping replies works only if a new branch is added to the
    Dropping replies works only if a new branch is added to the
    transaction, or it is explicitly replied in the script!
    transaction, or it is explicitly replied in the script!
 
 
-   Example 68. t_drop_replies() usage
+   Example 69. t_drop_replies() usage
 ...
 ...
 failure_route[0]{
 failure_route[0]{
         if (t_check_status("5[0-9][0-9]")){
         if (t_check_status("5[0-9][0-9]")){
@@ -1794,7 +1818,7 @@ failure_route[0]{
    The transaction must be created by t_newtran() before calling
    The transaction must be created by t_newtran() before calling
    t_save_lumps().
    t_save_lumps().
 
 
-   Example 69. t_save_lumps() usage
+   Example 70. t_save_lumps() usage
 route {
 route {
         ...
         ...
         t_newtran();
         t_newtran();
@@ -1864,7 +1888,7 @@ failure_route[1] {
 
 
    This function can be used from REQUEST_ROUTE.
    This function can be used from REQUEST_ROUTE.
 
 
-   Example 70. t_load_contacts usage
+   Example 71. t_load_contacts usage
 ...
 ...
 if (!t_load_contacts()) {
 if (!t_load_contacts()) {
         sl_send_reply("500", "Server Internal Error - Cannot load contacts");
         sl_send_reply("500", "Server Internal Error - Cannot load contacts");
@@ -1905,7 +1929,7 @@ if (!t_load_contacts()) {
    anymore set. Based on that test, you can then use t_set_fr() function
    anymore set. Based on that test, you can then use t_set_fr() function
    to set timers according to your needs.
    to set timers according to your needs.
 
 
-   Example 71. t_next_contacts usage
+   Example 72. t_next_contacts usage
 ...
 ...
 # First call after t_load_contacts() when transaction does not exist yet
 # First call after t_load_contacts() when transaction does not exist yet
 # and contacts should be available
 # and contacts should be available
@@ -1969,7 +1993,7 @@ Note
 
 
    See also: t_lookup_request(), t_lookup_cancel().
    See also: t_lookup_request(), t_lookup_cancel().
 
 
-   Example 72. t_check_trans usage
+   Example 73. t_check_trans usage
 if ( method == "CANCEL" && !t_check_trans())
 if ( method == "CANCEL" && !t_check_trans())
         sl_reply("403", "cancel out of the blue forbidden");
         sl_reply("403", "cancel out of the blue forbidden");
 # note: in this example t_check_trans() can be replaced by t_lookup_cancel()
 # note: in this example t_check_trans() can be replaced by t_lookup_cancel()
@@ -1984,7 +2008,7 @@ if ( method == "CANCEL" && !t_check_trans())
 
 
    See also: disable_6xx_block.
    See also: disable_6xx_block.
 
 
-   Example 73. t_set_disable_6xx usage
+   Example 74. t_set_disable_6xx usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -1999,7 +2023,7 @@ route {
 
 
    See also: use_dns_failover.
    See also: use_dns_failover.
 
 
-   Example 74. t_set_disable_failover usage
+   Example 75. t_set_disable_failover usage
 ...
 ...
 route {
 route {
 ...
 ...
@@ -2030,7 +2054,7 @@ route {
      * hostport - address in "host:port" format. It can be given via an
      * hostport - address in "host:port" format. It can be given via an
        AVP.
        AVP.
 
 
-   Example 75. t_replicate usage
+   Example 76. t_replicate usage
 ...
 ...
 # sent to 1.2.3.4:5060 over tcp
 # sent to 1.2.3.4:5060 over tcp
 t_replicate("sip:1.2.3.4:5060;transport=tcp");
 t_replicate("sip:1.2.3.4:5060;transport=tcp");
@@ -2065,7 +2089,7 @@ t_replicate_to_udp("1.2.3.4", "5060");
             effect anymore).
             effect anymore).
           + 0x04 - disable dns failover.
           + 0x04 - disable dns failover.
 
 
-   Example 76. t_replicate usage
+   Example 77. t_replicate usage
 ...
 ...
 # sent to 1.2.3.4:5060 over tcp
 # sent to 1.2.3.4:5060 over tcp
 t_relay_to("tcp:1.2.3.4:5060");
 t_relay_to("tcp:1.2.3.4:5060");
@@ -2088,7 +2112,7 @@ t_relay_to("0x01");
 
 
    See also: e2e_cancel_reason.
    See also: e2e_cancel_reason.
 
 
-   Example 77. t_set_no_e2e_cancel_reason usage
+   Example 78. t_set_no_e2e_cancel_reason usage
 ...
 ...
 route {
 route {
 ...
 ...

+ 40 - 0
modules/tm/doc/params.xml

@@ -1168,6 +1168,46 @@ modparam("tm", "failure_reply_mode", 3)
 	</example>
 	</example>
 	</section>
 	</section>
 
 
+	<section id="faked_reply_prio">
+	<title><varname>faked_reply_prio</varname> (integer)</title>
+	<para>
+		It controls how branch selection is done. It allows to give a penalty
+		to faked replies such as the infamous 408 on branch timeout.
+	</para>
+	<para>
+		Internally, every reply is assigned a priority between 0 (high prio) 
+		and 32000 (low prio). With this parameter the priority of fake replies
+		can be adjusted.
+	</para>
+	<itemizedlist>
+		<listitem><para>
+		<emphasis>0</emphasis> - disabled (default)
+		</para></listitem>
+		<listitem><para>
+		<emphasis>&lt; 0</emphasis> - priority is increased by given amount.
+		</para></listitem>
+		<listitem><para>
+		<emphasis>&gt; 0</emphasis> - priority is decreased by given amount.
+		Do not make it higer than 10000 or faked replies will even loose
+		from 1xx clsss replies.
+		</para></listitem>
+	</itemizedlist>
+	<para>
+		The default value is 0.
+	</para>
+	<para>
+		To let received replies win from a locally generated 408, set this
+		value to 2000.
+	</para>
+	<example>
+		<title>Set <varname>faked_reply_prio</varname> parameter</title>
+		<programlisting>
+...
+modparam("tm", "faked_reply_prio", 2000)
+...
+	    </programlisting>
+	</example>
+	</section>
 
 
 	<section id="local_cancel_reason">
 	<section id="local_cancel_reason">
 		<title><varname>local_cancel_reason</varname> (boolean)</title>
 		<title><varname>local_cancel_reason</varname> (boolean)</title>

+ 29 - 8
modules/tm/t_reply.c

@@ -201,6 +201,14 @@ static unsigned short resp_class_prio[]={
 			1000   /* 6xx, highest priority */
 			1000   /* 6xx, highest priority */
 };
 };
 
 
+/* How to prioritize faked replies 
+ * The value will be added to the default prio
+ * - 0 disabled
+ * - < 0 increase prio
+ * - > 0 decrease prio
+ */
+int faked_reply_prio = 0;
+
 
 
 int t_get_reply_totag(struct sip_msg *msg, str *totag)
 int t_get_reply_totag(struct sip_msg *msg, str *totag)
 {
 {
@@ -1007,18 +1015,26 @@ inline static short int get_4xx_prio(unsigned char xx)
  *  6xx                          1000+xx              (high)
  *  6xx                          1000+xx              (high)
  *  2xx                          0000+xx              (highest) 
  *  2xx                          0000+xx              (highest) 
  */
  */
-inline static short int get_prio(unsigned int resp)
+inline static short int get_prio(unsigned int resp, struct sip_msg *rpl)
 {
 {
 	int class;
 	int class;
 	int xx;
 	int xx;
+	int prio;
 	
 	
 	class=resp/100;
 	class=resp/100;
 
 
 	if (class<7){
 	if (class<7){
 		xx=resp%100;
 		xx=resp%100;
-		return resp_class_prio[class]+((class==4)?get_4xx_prio(xx):xx);
+		prio = resp_class_prio[class]+((class==4)?get_4xx_prio(xx):xx);
+	} else {
+		prio = 10000+resp; /* unknown response class => return very low prio */
+	}
+	if (rpl == FAKED_REPLY) {
+		/* Add faked_reply penalty */
+		return prio + faked_reply_prio;
+	} else {
+		return prio;
 	}
 	}
-	return 10000+resp; /* unknown response class => return very low prio */
 }
 }
 
 
 
 
@@ -1031,12 +1047,15 @@ inline static short int get_prio(unsigned int resp)
 int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
 int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
 {
 {
 	int best_b, best_s, b;
 	int best_b, best_s, b;
+	sip_msg_t *rpl;
 
 
 	best_b=-1; best_s=0;
 	best_b=-1; best_s=0;
 	for ( b=0; b<t->nr_of_outgoings ; b++ ) {
 	for ( b=0; b<t->nr_of_outgoings ; b++ ) {
+		rpl = t->uac[b].reply;
+
 		/* "fake" for the currently processed branch */
 		/* "fake" for the currently processed branch */
 		if (b==inc_branch) {
 		if (b==inc_branch) {
-			if (get_prio(inc_code)<get_prio(best_s)) {
+			if (get_prio(inc_code, rpl)<get_prio(best_s, rpl)) {
 				best_b=b;
 				best_b=b;
 				best_s=inc_code;
 				best_s=inc_code;
 			}
 			}
@@ -1051,8 +1070,8 @@ int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
 		if ( t->uac[b].last_received<200 )
 		if ( t->uac[b].last_received<200 )
 			return -2;
 			return -2;
 		/* if reply is null => t_send_branch "faked" reply, skip over it */
 		/* if reply is null => t_send_branch "faked" reply, skip over it */
-		if ( t->uac[b].reply && 
-				get_prio(t->uac[b].last_received)<get_prio(best_s) ) {
+		if ( rpl && 
+				get_prio(t->uac[b].last_received, rpl)<get_prio(best_s, rpl) ) {
 			best_b =b;
 			best_b =b;
 			best_s = t->uac[b].last_received;
 			best_s = t->uac[b].last_received;
 		}
 		}
@@ -1075,6 +1094,7 @@ int t_pick_branch(int inc_branch, int inc_code, struct cell *t, int *res_code)
 int t_pick_branch_blind(struct cell *t, int *res_code)
 int t_pick_branch_blind(struct cell *t, int *res_code)
 {
 {
 	int best_b, best_s, b;
 	int best_b, best_s, b;
+	sip_msg_t *rpl;
 
 
 	best_b=-1; best_s=0;
 	best_b=-1; best_s=0;
 	for ( b=0; b<t->nr_of_outgoings ; b++ ) {
 	for ( b=0; b<t->nr_of_outgoings ; b++ ) {
@@ -1082,8 +1102,9 @@ int t_pick_branch_blind(struct cell *t, int *res_code)
 		if ( t->uac[b].last_received<200 )
 		if ( t->uac[b].last_received<200 )
 			return -2;
 			return -2;
 		/* if reply is null => t_send_branch "faked" reply, skip over it */
 		/* if reply is null => t_send_branch "faked" reply, skip over it */
-		if ( t->uac[b].reply && 
-				get_prio(t->uac[b].last_received)<get_prio(best_s) ) {
+		rpl = t->uac[b].reply;
+		if ( rpl && 
+				get_prio(t->uac[b].last_received, rpl)<get_prio(best_s, rpl) ) {
 			best_b = b;
 			best_b = b;
 			best_s = t->uac[b].last_received;
 			best_s = t->uac[b].last_received;
 		}
 		}

+ 4 - 0
modules/tm/t_reply.h

@@ -65,6 +65,10 @@ extern int goto_on_sl_reply;
 
 
 extern int failure_reply_mode;
 extern int failure_reply_mode;
 
 
+extern int faked_reply_prio;
+
+extern int tm_rich_redirect;
+ 
 /* has this to-tag been never seen in previous 200/INVs? */
 /* has this to-tag been never seen in previous 200/INVs? */
 int unmatched_totag(struct cell *t, struct sip_msg *ack);
 int unmatched_totag(struct cell *t, struct sip_msg *ack);
 
 

+ 1 - 0
modules/tm/tm.c

@@ -517,6 +517,7 @@ static param_export_t params[]={
 	{"disable_6xx_block",   PARAM_INT, &default_tm_cfg.disable_6xx           },
 	{"disable_6xx_block",   PARAM_INT, &default_tm_cfg.disable_6xx           },
 	{"local_ack_mode",      PARAM_INT, &default_tm_cfg.local_ack_mode        },
 	{"local_ack_mode",      PARAM_INT, &default_tm_cfg.local_ack_mode        },
 	{"failure_reply_mode",  PARAM_INT, &failure_reply_mode                   },
 	{"failure_reply_mode",  PARAM_INT, &failure_reply_mode                   },
+	{"faked_reply_prio",    PARAM_INT, &faked_reply_prio                     },
 #ifdef CANCEL_REASON_SUPPORT
 #ifdef CANCEL_REASON_SUPPORT
 	{"local_cancel_reason", PARAM_INT, &default_tm_cfg.local_cancel_reason   },
 	{"local_cancel_reason", PARAM_INT, &default_tm_cfg.local_cancel_reason   },
 	{"e2e_cancel_reason",   PARAM_INT, &default_tm_cfg.e2e_cancel_reason     },
 	{"e2e_cancel_reason",   PARAM_INT, &default_tm_cfg.e2e_cancel_reason     },