modules/ims_qos: new mod_param to add RTCP flow description for media flow
authorRichard Good <richard.good@smilecoms.com>
Fri, 25 Nov 2016 14:48:27 +0000 (16:48 +0200)
committerRichard Good <richard.good@smilecoms.com>
Fri, 25 Nov 2016 14:48:27 +0000 (16:48 +0200)
New parameter include_rtcp_fd that if set adds additional flow description to AAR for RTCP

modules/ims_qos/doc/ims_qos_admin.xml
modules/ims_qos/mod.c
modules/ims_qos/rx_avp.c

index 3c4b73f..640ae66 100644 (file)
@@ -360,6 +360,26 @@ if the Rx session fails</para>
         <programlisting format="linespecific">
 ...
 modparam("ims_qos", "delete_contact_on_rx_failure", 0)
+...
+        </programlisting>
+      </example>
+    </section>
+    
+    <section>
+      <title><varname>include_rtcp_fd</varname> integer</title>
+
+      <para>If set then a flow description is added for media flows - next available odd port 
+          is used as the default for RTCP traffic</para>
+
+      <para><emphasis> Default value is 0, RTCP flow description not added</emphasis></para>
+
+      <example>
+        <title><varname>include_rtcp_fd</varname> parameter
+        usage</title>
+
+        <programlisting format="linespecific">
+...
+modparam("ims_qos", "include_rtcp_fd", 1)
 ...
         </programlisting>
       </example>
index f088d1a..58891ae 100644 (file)
@@ -104,6 +104,9 @@ int video_default_bandwidth = 128;
 //Very useful for UEs that change ports mid way through call therefore breaking flow description filters
 str regex_sdp_ip_prefix_to_maintain_in_fd = {0, 0};
 
+//If set this will include an additional filter for all existing filters using the next odd port up - as this is the RTCP port
+int include_rtcp_fd = 0;
+
 int cdp_event_list_size_threshold = 0; /**Threshold for size of cdp event list after which a warning is logged */
 
 stat_var *aars;
@@ -204,6 +207,7 @@ static param_export_t params[] = {
                { "terminate_dialog_on_rx_failure", INT_PARAM, &terminate_dialog_on_rx_failure},
                { "delete_contact_on_rx_failure", INT_PARAM, &delete_contact_on_rx_failure},
                { "regex_sdp_ip_prefix_to_maintain_in_fd", PARAM_STR, &regex_sdp_ip_prefix_to_maintain_in_fd},
+               { "include_rtcp_fd", INT_PARAM, &include_rtcp_fd},
                { 0, 0, 0}
 };
 
index 58f7e2e..a7b9020 100644 (file)
@@ -66,6 +66,8 @@ extern cdp_avp_bind_t *cdp_avp;
 
 extern str regex_sdp_ip_prefix_to_maintain_in_fd;
 
+extern int include_rtcp_fd;
+
 static const int prefix_length_ipv6 = 128;
 
 /**
@@ -675,8 +677,12 @@ AAA_AVP *rx_create_media_subcomponent_avp(int number, str* proto,
                str *ipB, str *portB, int flow_usage_type)
 {
                str data;
-               int len, len2, len3;
+               
+               int len, len2;
+               int int_port_rctp_a,int_port_rctp_b;
+               str port_rtcp_a, port_rtcp_b;
                AAA_AVP *flow_description1 = 0, *flow_description2 = 0, *flow_description3 = 0, *flow_description4 = 0, *flow_number = 0;
+               AAA_AVP *flow_description5 = 0, *flow_description6 = 0, *flow_description7 = 0, *flow_description8 = 0;
                AAA_AVP *flow_usage = 0;
 
                AAA_AVP_LIST list;
@@ -704,7 +710,145 @@ AAA_AVP *rx_create_media_subcomponent_avp(int number, str* proto,
 
                int intportA = atoi(portA->s);
                int intportB = atoi(portB->s);
+               
+               set_4bytes(x, number);
+               flow_number = cdpb.AAACreateAVP(AVP_IMS_Flow_Number,
+                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                               IMS_vendor_id_3GPP, x, 4,
+                               AVP_DUPLICATE_DATA);
+               cdpb.AAAAddAVPToList(&list, flow_number);
+                               
+               /*IMS Flow descriptions*/
+               /*first flow is the receive flow*/
+               
+               len = (permit_out.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
+                                               proto_len + portA->len + portB->len + 1/*nul terminator*/) * sizeof(char);
+               
+               if (!flowdata_buf.s || flowdata_buflen < len) {
+                               if (flowdata_buf.s)
+                                               pkg_free(flowdata_buf.s);
+                               flowdata_buf.s = (char*) pkg_malloc(len);
+                               if (!flowdata_buf.s) {
+                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                        when allocating %i bytes in pkg\n", len);
+                                               return NULL;
+                               }
+                               flowdata_buflen = len;
+               }
+               
+               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_ports, proto_nr,
+                                               ipA->len, ipA->s, intportA,
+                                               ipB->len, ipB->s, intportB);
+               
+               flowdata_buf.len = strlen(flowdata_buf.s);
+               flow_description1 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                               AVP_DUPLICATE_DATA);
+               cdpb.AAAAddAVPToList(&list, flow_description1);
+               
+               /*second flow*/
+               len2 = (permit_in.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
+                                               proto_len + portA->len + portB->len + 1/*nul terminator*/) * sizeof(char);              
+               if (!flowdata_buf.s || len < len2) {
+                               len = len2;
+                               if (flowdata_buf.s)
+                                               pkg_free(flowdata_buf.s);
+                               flowdata_buf.s = (char*) pkg_malloc(len);
+                               if (!flowdata_buf.s) {
+                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                when allocating %i bytes in pkg\n", len);
+                                               return NULL;
+                               }
+                               flowdata_buflen = len;
+               }
+               
+               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_ports, proto_nr,
+                                               ipB->len, ipB->s, intportB,
+                                               ipA->len, ipA->s, intportA);
+               
+               flowdata_buf.len = strlen(flowdata_buf.s);
+               flow_description2 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                               AVP_DUPLICATE_DATA);
+               cdpb.AAAAddAVPToList(&list, flow_description2);
+               
+               if (include_rtcp_fd) {
+                               LM_DBG("Need to add RTCP FD description - RTCP ports are by default next odd port number up from RTP ports\n");
+                               int_port_rctp_a = intportA + 1;
+                               if (int_port_rctp_a % 2 == 0) {
+                                               int_port_rctp_a ++;
+                               }
+                               int_port_rctp_b = intportB + 1;
+                               if (int_port_rctp_b % 2 == 0) {
+                                               int_port_rctp_b ++;
+                               }
+                               char c_port_rtcp_a[5];
+                               port_rtcp_a.len = sprintf(c_port_rtcp_a, "%d", int_port_rctp_a);
+                               port_rtcp_a.s = c_port_rtcp_a;
+                               char c_port_rtcp_b[5];
+                               port_rtcp_b.len = sprintf(c_port_rtcp_b, "%d", int_port_rctp_b);
+                               port_rtcp_b.s = c_port_rtcp_b;
+                               LM_DBG("RTCP A Port [%.*s] RCTP B Port [%.*s]\n", port_rtcp_a.len, port_rtcp_a.s, port_rtcp_b.len, port_rtcp_b.s);
+                               
+                               /*3rd (optional RTCP) flow*/
+                               len2 = (permit_out.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
+                                               proto_len + port_rtcp_a.len + port_rtcp_b.len + 1/*nul terminator*/) * sizeof(char);
+               
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
+                                               if (flowdata_buf.s)
+                                                               pkg_free(flowdata_buf.s);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                               if (!flowdata_buf.s) {
+                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                               return NULL;
+                                               }
+                                               flowdata_buflen = len;
+                               }
+
+                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_ports, proto_nr,
+                                                               ipA->len, ipA->s, int_port_rctp_a,
+                                                               ipB->len, ipB->s, int_port_rctp_b);
+
+                               flowdata_buf.len = strlen(flowdata_buf.s);
+                               flow_description3 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                               AVP_DUPLICATE_DATA);
+                               cdpb.AAAAddAVPToList(&list, flow_description3);
+                               
+                               /*4th (optional RTCP) flow*/
+                               len2 = (permit_in.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
+                                               proto_len + port_rtcp_a.len + port_rtcp_b.len + 1/*nul terminator*/) * sizeof(char);            
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
+                                               if (flowdata_buf.s)
+                                                               pkg_free(flowdata_buf.s);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                               if (!flowdata_buf.s) {
+                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                               return NULL;
+                                               }
+                                               flowdata_buflen = len;
+                               }
 
+                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_ports, proto_nr,
+                                                               ipB->len, ipB->s, int_port_rctp_b,
+                                                               ipA->len, ipA->s, int_port_rctp_a);
+
+                               flowdata_buf.len = strlen(flowdata_buf.s);
+                               flow_description4 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                               AVP_DUPLICATE_DATA);
+                               cdpb.AAAAddAVPToList(&list, flow_description4);
+                               
+               }
+               
                int useAnyForIpA = 0;
                int useAnyForIpB = 0;
 
@@ -728,153 +872,210 @@ AAA_AVP *rx_create_media_subcomponent_avp(int number, str* proto,
                                }
 
                }
-
-               if (!useAnyForIpA && !useAnyForIpB) {
-                               len = (permit_out.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
-                                               proto_len + portA->len + portB->len + 1/*nul terminator*/) * sizeof(char);
-               } else if (useAnyForIpA) {
-                               len = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipB->len + 4 +
+               
+               if (useAnyForIpA) {
+                               /*5th (optional replace IP A with ANY) flow*/
+                               len2 = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipB->len + 4 +
                                                proto_len + portB->len + 1/*nul terminator*/) * sizeof(char);
-                               len3 = (permit_out.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
-                                               proto_len + portA->len + portB->len + 1/*nul terminator*/) * sizeof(char);
-               } else if (useAnyForIpB) {
-                               len = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipA->len + 4 +
-                                               proto_len + portA->len + 1/*nul terminator*/) * sizeof(char);
-                               len3 = (permit_out.len + from_s.len + to_s.len + ipB->len + ipA->len + 4 +
-                                               proto_len + portA->len + portB->len + 1/*nul terminator*/) * sizeof(char);
-               }
-
-               if (!flowdata_buf.s || flowdata_buflen < len) {
-                               if (flowdata_buf.s)
-                                               pkg_free(flowdata_buf.s);
-                               flowdata_buf.s = (char*) pkg_malloc(len);
-                               if (!flowdata_buf.s) {
-                                               LM_ERR("PCC_create_media_component: out of memory \
-                                                        when allocating %i bytes in pkg\n", len);
-                                               return NULL;
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
+                                               if (flowdata_buf.s)
+                                                               pkg_free(flowdata_buf.s);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                               if (!flowdata_buf.s) {
+                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                               return NULL;
+                                               }
+                                               flowdata_buflen = len;
                                }
-                               flowdata_buflen = len;
-               }
-
-               set_4bytes(x, number);
-
-               flow_number = cdpb.AAACreateAVP(AVP_IMS_Flow_Number,
-                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
-                               IMS_vendor_id_3GPP, x, 4,
-                               AVP_DUPLICATE_DATA);
-               cdpb.AAAAddAVPToList(&list, flow_number);
-
-               /*IMS Flow descriptions*/
-               /*first flow is the receive flow*/
-               if (!useAnyForIpA && !useAnyForIpB) {
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_ports, proto_nr,
-                                               ipA->len, ipA->s, intportA,
-                                               ipB->len, ipB->s, intportB);
-               } else if (useAnyForIpA) {
                                flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_any_as_dst, proto_nr,
                                                ipB->len, ipB->s, intportB);
-               } else if (useAnyForIpB) {
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_any_as_dst, proto_nr,
-                                               ipA->len, ipA->s, intportA);
-               }
-
-
-               flowdata_buf.len = strlen(flowdata_buf.s);
-               flow_description1 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
-                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
-                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
-                               AVP_DUPLICATE_DATA);
-               cdpb.AAAAddAVPToList(&list, flow_description1);
-
-               //Extra flow for some devices - if you have any any filter also include the specific one
-               if (regex_sdp_ip_prefix_to_maintain_in_fd.len > 0 && regex_sdp_ip_prefix_to_maintain_in_fd.s && (useAnyForIpA || useAnyForIpB)) {
+                               flowdata_buf.len = strlen(flowdata_buf.s);
+                               flow_description5 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                               AVP_DUPLICATE_DATA);
+                               cdpb.AAAAddAVPToList(&list, flow_description5);
+                               
+                               if (include_rtcp_fd) {
+                                               /*7th (optional RTCP replace IP A with ANY) flow*/
+                                               len2 = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipB->len + 4 +
+                                                               proto_len + port_rtcp_b.len + 1/*nul terminator*/) * sizeof(char);
+                                               if (!flowdata_buf.s || len < len2) {
+                                                               len = len2;
+                                                               if (flowdata_buf.s)
+                                                                               pkg_free(flowdata_buf.s);
+                                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                                               if (!flowdata_buf.s) {
+                                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                                               return NULL;
+                                                               }
+                                                               flowdata_buflen = len;
+                                               }
+                                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_any_as_dst, proto_nr,
+                                                               ipB->len, ipB->s, int_port_rctp_b);
+                                               flowdata_buf.len = strlen(flowdata_buf.s);
+                                               flow_description7 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                                               AVP_DUPLICATE_DATA);
+                                               cdpb.AAAAddAVPToList(&list, flow_description7);
+                               }
                                
-                               LM_DBG("This is to fix some devices that want specific and any any filters");
                                
-                               len2 = len3;
-                               if (!flowdata_buf.s || flowdata_buflen <= len2) {
+                               /*6th (optional replace IP A with ANY) flow*/
+                               len2 = (permit_in.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipB->len + 4 +
+                                               proto_len + portB->len + 1/*nul terminator*/) * sizeof(char);
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
                                                if (flowdata_buf.s)
                                                                pkg_free(flowdata_buf.s);
-                                               flowdata_buf.s = (char*) pkg_malloc(len2);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
                                                if (!flowdata_buf.s) {
                                                                LM_ERR("PCC_create_media_component: out of memory \
-                                                                                                                                               when allocating %i bytes in pkg\n", len2);
+                                                                                                                               when allocating %i bytes in pkg\n", len);
                                                                return NULL;
                                                }
-                                               flowdata_buflen = len2;
+                                               flowdata_buflen = len;
                                }
-                               
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len3, permit_out_with_ports, proto_nr,
-                                               ipA->len, ipA->s, intportA,
+                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_any_as_src, proto_nr,
                                                ipB->len, ipB->s, intportB);
                                flowdata_buf.len = strlen(flowdata_buf.s);
-                               flow_description3 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                               flow_description6 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
                                                AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
                                                IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
                                                AVP_DUPLICATE_DATA);
-                               cdpb.AAAAddAVPToList(&list, flow_description3);
-
-               }
-               
-               /*second flow*/
-               len2 = len - (permit_out.len - permit_in.len) * sizeof(char);
-               if (!flowdata_buf.s || flowdata_buflen <= len2) {
-                               if (flowdata_buf.s)
-                                               pkg_free(flowdata_buf.s);
-                               flowdata_buf.s = (char*) pkg_malloc(len2);
-                               if (!flowdata_buf.s) {
-                                               LM_ERR("PCC_create_media_component: out of memory \
-                                                                when allocating %i bytes in pkg\n", len2);
-                                               return NULL;
+                               cdpb.AAAAddAVPToList(&list, flow_description6);
+                               
+                               if (include_rtcp_fd) {
+                                               /*8th (optional RTCP replace IP A with ANY) flow*/
+                                               len2 = (permit_in.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipB->len + 4 +
+                                                               proto_len + port_rtcp_b.len + 1/*nul terminator*/) * sizeof(char);
+                                               if (!flowdata_buf.s || len < len2) {
+                                                               len = len2;
+                                                               if (flowdata_buf.s)
+                                                                               pkg_free(flowdata_buf.s);
+                                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                                               if (!flowdata_buf.s) {
+                                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                                               return NULL;
+                                                               }
+                                                               flowdata_buflen = len;
+                                               }
+                                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_any_as_src, proto_nr,
+                                                               ipB->len, ipB->s, int_port_rctp_b);
+                                               flowdata_buf.len = strlen(flowdata_buf.s);
+                                               flow_description8 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                                               AVP_DUPLICATE_DATA);
+                                               cdpb.AAAAddAVPToList(&list, flow_description8);
                                }
-                               flowdata_buflen = len2;
-               }
-
-               if (!useAnyForIpA && !useAnyForIpB) {
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len2, permit_in_with_ports, proto_nr,
-                                               ipB->len, ipB->s, intportB,
-                                               ipA->len, ipA->s, intportA);
-               } else if (useAnyForIpA) {
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len2, permit_in_with_any_as_src, proto_nr,
-                                               ipB->len, ipB->s, intportB);
+                               
+                               
+                               
                } else if (useAnyForIpB) {
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len2, permit_in_with_any_as_src, proto_nr,
-                                               ipA->len, ipA->s, intportA);
-               }
-
-               flowdata_buf.len = strlen(flowdata_buf.s);
-               flow_description2 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
-                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
-                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
-                               AVP_DUPLICATE_DATA);
-               cdpb.AAAAddAVPToList(&list, flow_description2);
-               
-               //Extra flow for some devices - if you have any any filter also include the specific one
-               if (regex_sdp_ip_prefix_to_maintain_in_fd.len > 0 && regex_sdp_ip_prefix_to_maintain_in_fd.s && (useAnyForIpA || useAnyForIpB)) {
-                               len2 = len3 - (permit_out.len - permit_in.len) * sizeof(char);
-                               if (!flowdata_buf.s || flowdata_buflen <= len2) {
+                               /*5th (optional replace IP B with ANY) flow*/
+                               len2 = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipA->len + 4 +
+                                               proto_len + portA->len + 1/*nul terminator*/) * sizeof(char);
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
                                                if (flowdata_buf.s)
                                                                pkg_free(flowdata_buf.s);
-                                               flowdata_buf.s = (char*) pkg_malloc(len2);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
                                                if (!flowdata_buf.s) {
                                                                LM_ERR("PCC_create_media_component: out of memory \
-                                                                                                                                               when allocating %i bytes in pkg\n", len2);
+                                                                                                                               when allocating %i bytes in pkg\n", len);
                                                                return NULL;
                                                }
-                                               flowdata_buflen = len2;
+                                               flowdata_buflen = len;
                                }
+                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_any_as_dst, proto_nr,
+                                               ipA->len, ipA->s, intportA);
+                               flow_description5 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                               AVP_DUPLICATE_DATA);
+                               cdpb.AAAAddAVPToList(&list, flow_description5);
                                
-                               flowdata_buf.len = snprintf(flowdata_buf.s, len2, permit_in_with_ports, proto_nr,
-                                               ipB->len, ipB->s, intportB,
+                               if (include_rtcp_fd) {
+                                               /*7th (optional RTCP replace IP B with ANY) flow*/
+                                               len2 = (permit_out.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipA->len + 4 +
+                                                               proto_len + port_rtcp_a.len + 1/*nul terminator*/) * sizeof(char);
+                                               if (!flowdata_buf.s || len < len2) {
+                                                               len = len2;
+                                                               if (flowdata_buf.s)
+                                                                               pkg_free(flowdata_buf.s);
+                                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                                               if (!flowdata_buf.s) {
+                                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                                               return NULL;
+                                                               }
+                                                               flowdata_buflen = len;
+                                               }
+                                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_out_with_any_as_dst, proto_nr,
+                                                               ipA->len, ipA->s, int_port_rctp_a);
+                                               flow_description7 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                                               AVP_DUPLICATE_DATA);
+                                               cdpb.AAAAddAVPToList(&list, flow_description7);
+                               }
+                               
+                               /*6th (optional replace IP B with ANY) flow*/
+                               len2 = (permit_in.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipA->len + 4 +
+                                               proto_len + portA->len + 1/*nul terminator*/) * sizeof(char);
+                               if (!flowdata_buf.s || len < len2) {
+                                               len = len2;
+                                               if (flowdata_buf.s)
+                                                               pkg_free(flowdata_buf.s);
+                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                               if (!flowdata_buf.s) {
+                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                               return NULL;
+                                               }
+                                               flowdata_buflen = len;
+                               }
+                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_any_as_src, proto_nr,
                                                ipA->len, ipA->s, intportA);
-                               flowdata_buf.len = strlen(flowdata_buf.s);
-                               flow_description4 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                               flow_description6 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
                                                AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
                                                IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
                                                AVP_DUPLICATE_DATA);
-                               cdpb.AAAAddAVPToList(&list, flow_description4);
+                               cdpb.AAAAddAVPToList(&list, flow_description6);
+                               
+                               if (include_rtcp_fd) {
+                                               /*8th (optional RTCP replace IP B with ANY) flow*/
+                                               len2 = (permit_in.len + from_s.len + to_s.len + 3 /*for 'any'*/ + ipA->len + 4 +
+                                                               proto_len + port_rtcp_a.len + 1/*nul terminator*/) * sizeof(char);
+                                               if (!flowdata_buf.s || len < len2) {
+                                                               len = len2;
+                                                               if (flowdata_buf.s)
+                                                                               pkg_free(flowdata_buf.s);
+                                                               flowdata_buf.s = (char*) pkg_malloc(len);
+                                                               if (!flowdata_buf.s) {
+                                                                               LM_ERR("PCC_create_media_component: out of memory \
+                                                                                                                                               when allocating %i bytes in pkg\n", len);
+                                                                               return NULL;
+                                                               }
+                                                               flowdata_buflen = len;
+                                               }
+                                               flowdata_buf.len = snprintf(flowdata_buf.s, len, permit_in_with_any_as_src, proto_nr,
+                                                               ipA->len, ipA->s, int_port_rctp_a);
+                                               flow_description8 = cdpb.AAACreateAVP(AVP_IMS_Flow_Description,
+                                                               AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,
+                                                               IMS_vendor_id_3GPP, flowdata_buf.s, flowdata_buf.len,
+                                                               AVP_DUPLICATE_DATA);
+                                               cdpb.AAAAddAVPToList(&list, flow_description8);
+                               }
+                               
                }
-
+               
                set_4bytes(x, flow_usage_type);
                flow_usage = cdpb.AAACreateAVP(AVP_IMS_Flow_Usage,
                                AAA_AVP_FLAG_MANDATORY | AAA_AVP_FLAG_VENDOR_SPECIFIC,