Browse code

ims_charging: add missing change for ccr.c (related to previous commit f5e44252c39c7695cb)

Henning Westerholt authored on 02/07/2020 09:09:27
Showing 1 changed files
... ...
@@ -234,7 +234,11 @@ AAAMessage * Ro_write_CCR_avps(AAAMessage * ccr, Ro_CCR_t* x) {
234 234
     if (x->origin_realm.s && x->origin_realm.len > 0) {
235 235
         if (!cdp_avp->base.add_Origin_Realm(&(ccr->avpList), x->origin_realm, 0)) goto error;
236 236
     }
237
-    
237
+
238
+    if (x->destination_host.s && x->destination_host.len > 0) {
239
+        if (!cdp_avp->base.add_Destination_Host(&(ccr->avpList), x->destination_host, 0)) goto error;
240
+    }
241
+
238 242
     if (x->destination_realm.s && x->destination_realm.len > 0) {
239 243
         if (!ro_add_destination_realm_avp(ccr, x->destination_realm)) goto error;
240 244
     }
Browse code

ims_charging: add support for Application-Provided-Called-Party-Address AVP

Henning Westerholt authored on 16/06/2020 19:49:17
Showing 1 changed files
... ...
@@ -176,6 +176,15 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
176 176
         if (!cdp_avp->epcapp.add_Cause_Code(&aList2, *(x->cause_code)))
177 177
             goto error;
178 178
 
179
+    if (x->app_provided_party) {
180
+        if (!cdp_avp->epcapp.add_Application_Provided_Called_Party_Address(&aList, *(x->app_provided_party),0))
181
+            goto error;
182
+        if (!cdp_avp->epcapp.add_Application_Server_Information(&aList2, &aList, 0))
183
+            goto error;
184
+        cdp_avp->cdp->AAAFreeAVPList(&aList);
185
+        aList.head = aList.tail = 0;
186
+    }
187
+
179 188
     if (!cdp_avp->epcapp.add_IMS_Information(avp_list, &aList2, AVP_FREE_DATA))//TODO check why not DONT FREE DATA
180 189
         goto error;
181 190
 
Browse code

ims_charging: add structured debug logging for key functions

Henning Westerholt authored on 10/06/2020 19:25:20
Showing 1 changed files
... ...
@@ -11,6 +11,7 @@ extern struct cdp_binds cdpb;
11 11
 int Ro_write_event_type_avps(AAA_AVP_LIST * avp_list, event_type_t * x) {
12 12
     AAA_AVP_LIST aList = {0, 0};
13 13
 
14
+    LM_DBG("write event type AVPs\n");
14 15
     if (x->sip_method) {
15 16
         if (!cdp_avp->epcapp.add_SIP_Method(&aList, *(x->sip_method), AVP_DUPLICATE_DATA))
16 17
             goto error;
... ...
@@ -37,6 +38,7 @@ error:
37 38
 int Ro_write_time_stamps_avps(AAA_AVP_LIST * avp_list, time_stamps_t* x) {
38 39
     AAA_AVP_LIST aList = {0, 0};
39 40
 
41
+    LM_DBG("write timestamp AVPs\n");
40 42
     if (x->sip_request_timestamp)
41 43
         if (!cdp_avp->epcapp.add_SIP_Request_Timestamp(&aList, *(x->sip_request_timestamp)))
42 44
             goto error;
... ...
@@ -74,6 +76,8 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
74 76
     service_specific_info_list_element_t * info = 0;
75 77
     ioi_list_element_t * ioi_elem = 0;
76 78
 
79
+    LM_DBG("write IMS information AVPs\n");
80
+
77 81
     if (x->event_type)
78 82
         if (!Ro_write_event_type_avps(&aList2, x->event_type))
79 83
             goto error;
... ...
@@ -90,11 +94,15 @@ int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x)
90 94
     for (sl = x->calling_party_address.head; sl; sl = sl->next) {
91 95
         if (!cdp_avp->epcapp.add_Calling_Party_Address(&aList2, sl->data, 0))
92 96
             goto error;
97
+        LM_DBG("added calling party address %.*s\n", sl->data.len, sl->data.s);
93 98
     }
94 99
 
95
-    if (x->called_party_address)
100
+    if (x->called_party_address) {
96 101
         if (!cdp_avp->epcapp.add_Called_Party_Address(&aList2, *(x->called_party_address), 0))
97 102
             goto error;
103
+        LM_DBG("added called party address %.*s\n",
104
+                x->called_party_address->len, x->called_party_address->s);
105
+    }
98 106
     
99 107
     if (x->incoming_trunk_id && (x->incoming_trunk_id->len > 0) && x->outgoing_trunk_id && (x->outgoing_trunk_id->len > 0)) {
100 108
 	if (!cdp_avp->epcapp.add_Outgoing_Trunk_Group_Id(&aList, *(x->outgoing_trunk_id), 0))
... ...
@@ -176,7 +184,7 @@ error:
176 184
     /*free aList*/
177 185
     cdp_avp->cdp->AAAFreeAVPList(&aList);
178 186
     cdp_avp->cdp->AAAFreeAVPList(&aList2);
179
-    LM_ERR("could not add ims information avps\n");
187
+    LM_ERR("could not add ims information AVPs\n");
180 188
     return 0;
181 189
 }
182 190
 
... ...
@@ -184,6 +192,7 @@ int Ro_write_service_information_avps(AAA_AVP_LIST * avp_list, service_informati
184 192
     subscription_id_list_element_t * elem = 0;
185 193
     AAA_AVP_LIST aList = {0, 0};
186 194
 
195
+    LM_DBG("write service information\n");
187 196
     for (elem = x->subscription_id.head; elem; elem = elem->next) {
188 197
 
189 198
         if (!cdp_avp->ccapp.add_Subscription_Id_Group(&aList, elem->s.type, elem->s.id, 0))
... ...
@@ -207,6 +216,7 @@ error:
207 216
 AAAMessage * Ro_write_CCR_avps(AAAMessage * ccr, Ro_CCR_t* x) {
208 217
 
209 218
     if (!ccr) return 0;
219
+    LM_DBG("write all CCR AVPs\n");
210 220
 
211 221
     if (x->origin_host.s && x->origin_host.len > 0) {
212 222
         if (!cdp_avp->base.add_Origin_Host(&(ccr->avpList), x->origin_host, 0)) goto error;
... ...
@@ -250,6 +260,7 @@ error:
250 260
 AAAMessage *Ro_new_ccr(AAASession * session, Ro_CCR_t * ro_ccr_data) {
251 261
 
252 262
     AAAMessage * ccr = 0;
263
+    LM_DBG("create a new CCR\n");
253 264
     ccr = cdp_avp->cdp->AAACreateRequest(IMS_Ro, Diameter_CCR, Flag_Proxyable, session);
254 265
     if (!ccr) {
255 266
         LM_ERR("could not create CCR\n");
... ...
@@ -265,6 +276,7 @@ Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
265 276
     if (!cca)
266 277
         return 0;
267 278
 
279
+    LM_DBG("parse CCA AVPs\n");
268 280
     Ro_CCA_t *ro_cca_data = 0;
269 281
     mem_new(ro_cca_data, sizeof (Ro_CCR_t), pkg);
270 282
     multiple_services_credit_control_t *mscc = 0;
Browse code

ims_charging: fix missing line-breaks for log messages

Henning Westerholt authored on 10/06/2020 11:50:51
Showing 1 changed files
... ...
@@ -300,7 +300,7 @@ Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
300 300
                 mscc_avp_list_ptr = &mscc_avp_list;
301 301
                 AAA_AVP *mscc_avp = mscc_avp_list_ptr->head;
302 302
                 while (mscc_avp != NULL) {
303
-                    LM_DBG("MSCC AVP code is [%i] and data length is [%i]", mscc_avp->code, mscc_avp->data.len);
303
+                    LM_DBG("MSCC AVP code is [%i] and data length is [%i]\n", mscc_avp->code, mscc_avp->data.len);
304 304
                     switch (mscc_avp->code) {
305 305
                             AAA_AVP_LIST y;
306 306
                             AAA_AVP *z;
Browse code

ims_charging: Rename module interface file #82

Victor Seva authored on 13/02/2017 14:27:40
Showing 1 changed files
... ...
@@ -3,7 +3,7 @@
3 3
 #include "ccr.h"
4 4
 #include "Ro_data.h"
5 5
 #include "ro_avp.h"
6
-#include "mod.h"
6
+#include "ims_charging_mod.h"
7 7
 
8 8
 extern cdp_avp_bind_t *cdp_avp;
9 9
 extern struct cdp_binds cdpb;
Browse code

cdp_avp: Rename module interface file #82

Victor Seva authored on 05/01/2017 12:03:55
Showing 1 changed files
... ...
@@ -1,4 +1,4 @@
1
-#include "../cdp_avp/mod_export.h"
1
+#include "../cdp_avp/cdp_avp_mod.h"
2 2
 
3 3
 #include "ccr.h"
4 4
 #include "Ro_data.h"
Browse code

core, lib, modules: restructured source code tree

- new folder src/ to hold the source code for main project applications
- main.c is in src/
- all core files are subfolder are in src/core/
- modules are in src/modules/
- libs are in src/lib/
- application Makefiles are in src/
- application binary is built in src/ (src/kamailio)

Daniel-Constantin Mierla authored on 07/12/2016 11:03:51
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,388 @@
1
+#include "../cdp_avp/mod_export.h"
2
+
3
+#include "ccr.h"
4
+#include "Ro_data.h"
5
+#include "ro_avp.h"
6
+#include "mod.h"
7
+
8
+extern cdp_avp_bind_t *cdp_avp;
9
+extern struct cdp_binds cdpb;
10
+
11
+int Ro_write_event_type_avps(AAA_AVP_LIST * avp_list, event_type_t * x) {
12
+    AAA_AVP_LIST aList = {0, 0};
13
+
14
+    if (x->sip_method) {
15
+        if (!cdp_avp->epcapp.add_SIP_Method(&aList, *(x->sip_method), AVP_DUPLICATE_DATA))
16
+            goto error;
17
+    }
18
+
19
+    if (x->event)
20
+        if (!cdp_avp->epcapp.add_Event(&aList, *(x->event), 0))
21
+            goto error;
22
+
23
+    if (x->expires)
24
+        if (!cdp_avp->epcapp.add_Expires(&aList, *(x->expires)))
25
+            goto error;
26
+
27
+    if (!cdp_avp->epcapp.add_Event_Type(avp_list, &aList, AVP_FREE_DATA))	//TODO: used to be DONT FREE
28
+        goto error;
29
+
30
+    return 1;
31
+error:
32
+    cdp_avp->cdp->AAAFreeAVPList(&aList);
33
+    LM_ERR("error while adding event type avps\n");
34
+    return 0;
35
+}
36
+
37
+int Ro_write_time_stamps_avps(AAA_AVP_LIST * avp_list, time_stamps_t* x) {
38
+    AAA_AVP_LIST aList = {0, 0};
39
+
40
+    if (x->sip_request_timestamp)
41
+        if (!cdp_avp->epcapp.add_SIP_Request_Timestamp(&aList, *(x->sip_request_timestamp)))
42
+            goto error;
43
+
44
+    if (x->sip_request_timestamp_fraction)
45
+        if (!cdp_avp->epcapp.add_SIP_Request_Timestamp_Fraction(&aList,
46
+                *(x->sip_request_timestamp_fraction)))
47
+            goto error;
48
+
49
+    if (x->sip_response_timestamp)
50
+        if (!cdp_avp->epcapp.add_SIP_Response_Timestamp(&aList, *(x->sip_response_timestamp)))
51
+            goto error;
52
+
53
+    if (x->sip_response_timestamp_fraction)
54
+        if (!cdp_avp->epcapp.add_SIP_Response_Timestamp_Fraction(&aList,
55
+                *(x->sip_response_timestamp_fraction)))
56
+            goto error;
57
+
58
+    if (!cdp_avp->epcapp.add_Time_Stamps(avp_list, &aList, AVP_FREE_DATA))	//used to be DONT FREE
59
+        goto error;
60
+
61
+
62
+    return 1;
63
+error:
64
+    cdp_avp->cdp->AAAFreeAVPList(&aList);
65
+    LM_ERR("error while adding time stamps avps\n");
66
+
67
+    return 0;
68
+}
69
+
70
+int Ro_write_ims_information_avps(AAA_AVP_LIST * avp_list, ims_information_t* x) {
71
+    str_list_slot_t * sl = 0;
72
+    AAA_AVP_LIST aList = {0, 0};
73
+    AAA_AVP_LIST aList2 = {0, 0};
74
+    service_specific_info_list_element_t * info = 0;
75
+    ioi_list_element_t * ioi_elem = 0;
76
+
77
+    if (x->event_type)
78
+        if (!Ro_write_event_type_avps(&aList2, x->event_type))
79
+            goto error;
80
+    if (x->role_of_node)
81
+        if (!cdp_avp->epcapp.add_Role_Of_Node(&aList2, *(x->role_of_node))) goto error;
82
+
83
+    if (!cdp_avp->epcapp.add_Node_Functionality(&aList2, x->node_functionality))
84
+        goto error;
85
+
86
+    if (x->user_session_id)
87
+        if (!cdp_avp->epcapp.add_User_Session_Id(&aList2, *(x->user_session_id), 0))
88
+            goto error;
89
+
90
+    for (sl = x->calling_party_address.head; sl; sl = sl->next) {
91
+        if (!cdp_avp->epcapp.add_Calling_Party_Address(&aList2, sl->data, 0))
92
+            goto error;
93
+    }
94
+
95
+    if (x->called_party_address)
96
+        if (!cdp_avp->epcapp.add_Called_Party_Address(&aList2, *(x->called_party_address), 0))
97
+            goto error;
98
+    
99
+    if (x->incoming_trunk_id && (x->incoming_trunk_id->len > 0) && x->outgoing_trunk_id && (x->outgoing_trunk_id->len > 0)) {
100
+	if (!cdp_avp->epcapp.add_Outgoing_Trunk_Group_Id(&aList, *(x->outgoing_trunk_id), 0))
101
+	    goto error;
102
+	    
103
+	if (!cdp_avp->epcapp.add_Incoming_Trunk_Group_Id(&aList, *(x->incoming_trunk_id), 0))
104
+	    goto error;
105
+	    
106
+	if (!cdp_avp->epcapp.add_Trunk_Group_Id(&aList2, &aList, 0))
107
+            goto error;
108
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
109
+        aList.head = aList.tail = 0;
110
+    }
111
+    
112
+    if (x->access_network_info) {
113
+		cdp_avp->imsapp.add_Access_Network_Information(&aList2, *(x->access_network_info), 0);
114
+    }
115
+
116
+    for (sl = x->called_asserted_identity.head; sl; sl = sl->next) {
117
+        if (!cdp_avp->epcapp.add_Called_Asserted_Identity(&aList2, sl->data, 0))
118
+            goto error;
119
+    }
120
+
121
+    if (x->requested_party_address)
122
+        if (!cdp_avp->epcapp.add_Requested_Party_Address(&aList2, *(x->requested_party_address), 0))
123
+            goto error;
124
+    if (x->time_stamps)
125
+        if (!Ro_write_time_stamps_avps(&aList2, x->time_stamps))
126
+            goto error;
127
+
128
+    for (ioi_elem = x->ioi.head; ioi_elem; ioi_elem = ioi_elem->next) {
129
+
130
+        if (ioi_elem->info.originating_ioi)
131
+            if (!cdp_avp->epcapp.add_Originating_IOI(&aList, *(ioi_elem->info.originating_ioi), 0))
132
+                goto error;
133
+
134
+        if (ioi_elem->info.terminating_ioi)
135
+            if (!cdp_avp->epcapp.add_Terminating_IOI(&aList, *(ioi_elem->info.terminating_ioi), 0))
136
+                goto error;
137
+
138
+        if (!cdp_avp->epcapp.add_Inter_Operator_Identifier(&aList2, &aList, 0))
139
+            goto error;
140
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
141
+        aList.head = aList.tail = 0;
142
+    }
143
+
144
+    if (x->icid)
145
+        if (!cdp_avp->epcapp.add_IMS_Charging_Identifier(&aList2, *(x->icid), 0))
146
+            goto error;
147
+
148
+    if (x->service_id)
149
+        if (!cdp_avp->epcapp.add_Service_ID(&aList2, *(x->service_id), 0))
150
+            goto error;
151
+
152
+    for (info = x->service_specific_info.head; info; info = info->next) {
153
+
154
+        if (info->info.data)
155
+            if (!cdp_avp->epcapp.add_Service_Specific_Data(&aList, *(info->info.data), 0))
156
+                goto error;
157
+        if (info->info.type)
158
+            if (!cdp_avp->epcapp.add_Service_Specific_Type(&aList, *(info->info.type)))
159
+                goto error;
160
+
161
+        if (!cdp_avp->epcapp.add_Service_Specific_Info(&aList2, &aList, 0))
162
+            goto error;
163
+	cdp_avp->cdp->AAAFreeAVPList(&aList);
164
+        aList.head = aList.tail = 0;
165
+    }
166
+
167
+    if (x->cause_code)
168
+        if (!cdp_avp->epcapp.add_Cause_Code(&aList2, *(x->cause_code)))
169
+            goto error;
170
+
171
+    if (!cdp_avp->epcapp.add_IMS_Information(avp_list, &aList2, AVP_FREE_DATA))//TODO check why not DONT FREE DATA
172
+        goto error;
173
+
174
+    return 1;
175
+error:
176
+    /*free aList*/
177
+    cdp_avp->cdp->AAAFreeAVPList(&aList);
178
+    cdp_avp->cdp->AAAFreeAVPList(&aList2);
179
+    LM_ERR("could not add ims information avps\n");
180
+    return 0;
181
+}
182
+
183
+int Ro_write_service_information_avps(AAA_AVP_LIST * avp_list, service_information_t* x) {
184
+    subscription_id_list_element_t * elem = 0;
185
+    AAA_AVP_LIST aList = {0, 0};
186
+
187
+    for (elem = x->subscription_id.head; elem; elem = elem->next) {
188
+
189
+        if (!cdp_avp->ccapp.add_Subscription_Id_Group(&aList, elem->s.type, elem->s.id, 0))
190
+            goto error;
191
+
192
+    }
193
+
194
+    if (x->ims_information)
195
+        if (!Ro_write_ims_information_avps(&aList, x->ims_information))
196
+            goto error;
197
+
198
+    if (!cdp_avp->epcapp.add_Service_Information(avp_list, &aList, AVP_FREE_DATA)) //TODO: use to be dont free
199
+        goto error;
200
+
201
+    return 1;
202
+error:
203
+    cdp_avp->cdp->AAAFreeAVPList(&aList);
204
+    return 0;
205
+}
206
+
207
+AAAMessage * Ro_write_CCR_avps(AAAMessage * ccr, Ro_CCR_t* x) {
208
+
209
+    if (!ccr) return 0;
210
+
211
+    if (x->origin_host.s && x->origin_host.len > 0) {
212
+        if (!cdp_avp->base.add_Origin_Host(&(ccr->avpList), x->origin_host, 0)) goto error;
213
+    }
214
+    
215
+    if (x->origin_realm.s && x->origin_realm.len > 0) {
216
+        if (!cdp_avp->base.add_Origin_Realm(&(ccr->avpList), x->origin_realm, 0)) goto error;
217
+    }
218
+    
219
+    if (x->destination_realm.s && x->destination_realm.len > 0) {
220
+        if (!ro_add_destination_realm_avp(ccr, x->destination_realm)) goto error;
221
+    }
222
+    
223
+    if (!cdp_avp->base.add_Accounting_Record_Type(&(ccr->avpList), x->acct_record_type)) goto error;
224
+    if (!cdp_avp->base.add_Accounting_Record_Number(&(ccr->avpList), x->acct_record_number)) goto error;
225
+
226
+    if (x->user_name)
227
+        if (!cdp_avp->base.add_User_Name(&(ccr->avpList), *(x->user_name), AVP_DUPLICATE_DATA)) goto error;
228
+
229
+    if (x->acct_interim_interval)
230
+        if (!cdp_avp->base.add_Acct_Interim_Interval(&(ccr->avpList), *(x->acct_interim_interval))) goto error;
231
+
232
+    if (x->origin_state_id)
233
+        if (!cdp_avp->base.add_Origin_State_Id(&(ccr->avpList), *(x->origin_state_id))) goto error;
234
+
235
+    if (x->event_timestamp)
236
+        if (!cdp_avp->base.add_Event_Timestamp(&(ccr->avpList), *(x->event_timestamp))) goto error;
237
+
238
+    if (x->service_context_id)
239
+        if (!cdp_avp->ccapp.add_Service_Context_Id(&(ccr->avpList), *(x->service_context_id), 0)) goto error;
240
+
241
+    if (x->service_information)
242
+        if (!Ro_write_service_information_avps(&(ccr->avpList), x->service_information))
243
+            goto error;
244
+    return ccr;
245
+error:
246
+    cdp_avp->cdp->AAAFreeMessage(&ccr);
247
+    return 0;
248
+}
249
+
250
+AAAMessage *Ro_new_ccr(AAASession * session, Ro_CCR_t * ro_ccr_data) {
251
+
252
+    AAAMessage * ccr = 0;
253
+    ccr = cdp_avp->cdp->AAACreateRequest(IMS_Ro, Diameter_CCR, Flag_Proxyable, session);
254
+    if (!ccr) {
255
+        LM_ERR("could not create CCR\n");
256
+        return 0;
257
+    }
258
+  
259
+    ccr = Ro_write_CCR_avps(ccr, ro_ccr_data);
260
+
261
+    return ccr;
262
+}
263
+
264
+Ro_CCA_t *Ro_parse_CCA_avps(AAAMessage *cca) {
265
+    if (!cca)
266
+        return 0;
267
+
268
+    Ro_CCA_t *ro_cca_data = 0;
269
+    mem_new(ro_cca_data, sizeof (Ro_CCR_t), pkg);
270
+    multiple_services_credit_control_t *mscc = 0;
271
+    mem_new(mscc, sizeof (multiple_services_credit_control_t), pkg);
272
+    granted_services_unit_t *gsu = 0;
273
+    mem_new(gsu, sizeof (granted_services_unit_t), pkg);
274
+    final_unit_indication_t *fui = 0;
275
+    mem_new(fui, sizeof (final_unit_indication_t), pkg);
276
+    mscc->granted_service_unit = gsu;
277
+    mscc->final_unit_action = fui;
278
+
279
+    mscc->final_unit_action->action = -1;
280
+	mscc->final_unit_action->redirect_server = 0;
281
+
282
+    AAA_AVP_LIST* avp_list = &cca->avpList;
283
+    AAA_AVP_LIST mscc_avp_list;
284
+    AAA_AVP_LIST* mscc_avp_list_ptr;
285
+
286
+    AAA_AVP *avp = avp_list->head;
287
+    unsigned int x;
288
+    while (avp != NULL) {
289
+        switch (avp->code) {
290
+            case AVP_CC_Request_Type:
291
+                x = get_4bytes(avp->data.s);
292
+                ro_cca_data->cc_request_type = x;
293
+                break;
294
+            case AVP_CC_Request_Number:
295
+                x = get_4bytes(avp->data.s);
296
+                ro_cca_data->cc_request_number = x;
297
+                break;
298
+            case AVP_Multiple_Services_Credit_Control:
299
+                mscc_avp_list = cdp_avp->cdp->AAAUngroupAVPS(avp->data);
300
+                mscc_avp_list_ptr = &mscc_avp_list;
301
+                AAA_AVP *mscc_avp = mscc_avp_list_ptr->head;
302
+                while (mscc_avp != NULL) {
303
+                    LM_DBG("MSCC AVP code is [%i] and data length is [%i]", mscc_avp->code, mscc_avp->data.len);
304
+                    switch (mscc_avp->code) {
305
+                            AAA_AVP_LIST y;
306
+                            AAA_AVP *z;
307
+                        case AVP_Granted_Service_Unit:
308
+                            y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data);
309
+                            z = y.head;
310
+                            while (z) {
311
+                                switch (z->code) {
312
+                                    case AVP_CC_Time:
313
+                                        mscc->granted_service_unit->cc_time = get_4bytes(z->data.s);
314
+                                        break;
315
+                                    default:
316
+                                        LM_ERR("Unsupported Granted Service Unit with code:[%d]\n", z->code);
317
+                                }
318
+                                z = z->next;
319
+                            }
320
+                            cdp_avp->cdp->AAAFreeAVPList(&y);
321
+                            break;
322
+                        case AVP_Validity_Time:
323
+                            mscc->validity_time = get_4bytes(mscc_avp->data.s);
324
+                            break;
325
+						case AVP_Result_Code:
326
+							mscc->resultcode = get_4bytes(mscc_avp->data.s);
327
+							break;
328
+                        case AVP_Final_Unit_Indication:
329
+                            y = cdp_avp->cdp->AAAUngroupAVPS(mscc_avp->data);
330
+                            z = y.head;
331
+                            while (z) {
332
+                                switch (z->code) {
333
+                                    case AVP_Final_Unit_Action:
334
+                                        mscc->final_unit_action->action = get_4bytes(z->data.s);
335
+                                        break;
336
+									case AVP_Redirect_Server:
337
+										LM_DBG("Received redirect server\n");
338
+										redirect_server_t* redirect_server_info = 0;
339
+										mem_new(redirect_server_info, sizeof (redirect_server_t), pkg);
340
+										mscc->final_unit_action->redirect_server = redirect_server_info;
341
+										
342
+										AAA_AVP_LIST yy;
343
+										AAA_AVP *zz;
344
+										yy = cdp_avp->cdp->AAAUngroupAVPS(z->data);
345
+										zz = yy.head;
346
+										while (zz) {
347
+											switch (zz->code) {
348
+												case AVP_Redirect_Address_Type:
349
+													LM_DBG("Received redirect address type\n");
350
+													mscc->final_unit_action->redirect_server->address_type = get_4bytes(zz->data.s);
351
+													break;
352
+												case AVP_Redirect_Server_Address:
353
+													LM_DBG("Received redirect server address of [%.*s]\n", zz->data.len, zz->data.s);
354
+													str_dup_ptr(redirect_server_info->server_address, zz->data, pkg);
355
+													break;	
356
+												default:
357
+													LM_ERR("Unsupported Redirect Server AVP with code:[%d]\n", zz->code);
358
+											}
359
+											zz = zz->next;
360
+											cdp_avp->cdp->AAAFreeAVPList(&yy);
361
+										}
362
+										break;		
363
+                                    default:
364
+                                        LM_ERR("Unsupported Final Unit Indication AVP.\n");
365
+                                }
366
+                                z = z->next;
367
+                            }
368
+                            cdp_avp->cdp->AAAFreeAVPList(&y);
369
+                    }
370
+                    mscc_avp = mscc_avp->next;
371
+                }
372
+                cdp_avp->cdp->AAAFreeAVPList(mscc_avp_list_ptr);
373
+                break;
374
+            case AVP_Result_Code:
375
+                x = get_4bytes(avp->data.s);
376
+                ro_cca_data->resultcode = x;
377
+                break;
378
+        }
379
+        avp = avp->next;
380
+    }
381
+    ro_cca_data->mscc = mscc;
382
+    return ro_cca_data;
383
+
384
+out_of_memory:
385
+    LM_ERR("out of pkg memory\n");
386
+    Ro_free_CCA(ro_cca_data);
387
+    return 0;
388
+}