00001
00054 #include <sys/socket.h>
00055 #include <netinet/in.h>
00056 #include <unistd.h>
00057
00058 #include "peerstatemachine.h"
00059 #include "diameter_api.h"
00060
00061 #include "receiver.h"
00062 #include "peermanager.h"
00063 #include "config.h"
00064 #include "worker.h"
00065
00066 extern dp_config *config;
00069 char *dp_states[]={"Closed","Wait_Conn_Ack","Wait_I_CEA","Wait_Conn_Ack_Elect","Wait_Returns","R_Open","I_Open","Closing"};
00071 char *dp_events[]={"Start","Stop","Timeout","Win_Election","R_Conn_CER","I_Rcv_Conn_Ack","I_Rcv_Conn_NAck",
00072 "I_Rcv_CER","I_Rcv_CEA","R_Rcv_CER","R_Rcv_CEA","I_Rcv_Non_CEA",
00073 "I_Rcv_DPR","I_Rcv_DPA","R_Rcv_DPR","R_Rcv_DPA",
00074 "I_Rcv_DWR","I_Rcv_DWA","R_Rcv_DWR","R_Rcv_DWA",
00075 "Send_Message","I_Rcv_Message","R_Rcv_Message","I_Peer_Disc","R_Peer_Disc"};
00076
00088 int sm_process(peer *p,peer_event_t event,AAAMessage *msg,int peer_locked,int sock)
00089 {
00090 int result_code;
00091 peer_event_t next_event;
00092 int msg_received=0;
00093
00094 if (!peer_locked) lock_get(p->lock);
00095 LOG(L_INFO,"DBG:sm_process(): Peer %.*s \tState %s \tEvent %s\n",
00096 p->fqdn.len,p->fqdn.s,dp_states[p->state],dp_events[event-101]);
00097
00098 switch (p->state){
00099 case Closed:
00100 switch (event){
00101 case Start:
00102 p->state = Wait_Conn_Ack;
00103 next_event = I_Snd_Conn_Req(p);
00104 sm_process(p,next_event,0,1,p->I_sock);
00105 break;
00106 case R_Conn_CER:
00107 R_Accept(p,sock);
00108 result_code = Process_CER(p,msg);
00109 Snd_CEA(p,msg,result_code,p->R_sock);
00110 if (result_code>=2000 && result_code<3000)
00111 p->state = R_Open;
00112 else {
00113 R_Disc(p);
00114 p->state = Closed;
00115 }
00116 log_peer_list(L_INFO);
00117 break;
00118 case Stop:
00119
00120 p->state = Closed;
00121 break;
00122 default:
00123 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00124 dp_states[p->state],dp_events[event-101]);
00125 goto error;
00126 }
00127 break;
00128 case Wait_Conn_Ack:
00129 switch(event){
00130 case I_Rcv_Conn_Ack:
00131 I_Snd_CER(p);
00132 p->state = Wait_I_CEA;
00133 break;
00134 case I_Rcv_Conn_NAck:
00135 Cleanup(p,p->I_sock);
00136 p->state = Closed;
00137 break;
00138
00139 case R_Conn_CER:
00140 R_Accept(p,sock);
00141 result_code = Process_CER(p,msg);
00142 if (result_code>=2000 && result_code<3000)
00143 p->state = Wait_Conn_Ack_Elect;
00144 else {
00145 p->state = Wait_Conn_Ack;
00146 close(sock);
00147 }
00148 break;
00149 case Timeout:
00150 Error(p,p->I_sock);
00151 p->state = Closed;
00152 default:
00153 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00154 dp_states[p->state],dp_events[event-101]);
00155 goto error;
00156 }
00157 break;
00158
00159 case Wait_I_CEA:
00160 switch(event){
00161 case I_Rcv_CEA:
00162 result_code = Process_CEA(p,msg);
00163 if (result_code>=2000 && result_code<3000)
00164 p->state = I_Open;
00165 else {
00166 Cleanup(p,p->I_sock);
00167 p->state = Closed;
00168 }
00169 log_peer_list(L_INFO);
00170 break;
00171 case R_Conn_CER:
00172 R_Accept(p,sock);
00173 result_code = Process_CER(p,msg);
00174 p->state = Wait_Returns;
00175 if (Elect(p,msg))
00176 sm_process(p,Win_Election,msg,1,sock);
00177 break;
00178 case I_Peer_Disc:
00179 I_Disc(p);
00180 p->state = Closed;
00181 break;
00182 case I_Rcv_Non_CEA:
00183 Error(p,p->I_sock);
00184 p->state = Closed;
00185 break;
00186 case Timeout:
00187 Error(p,p->I_sock);
00188 p->state = Closed;
00189 break;
00190 default:
00191 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00192 dp_states[p->state],dp_events[event-101]);
00193 goto error;
00194 }
00195 break;
00196
00197 case Wait_Conn_Ack_Elect:
00198 switch(event){
00199 default:
00200 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00201 dp_states[p->state],dp_events[event-101]);
00202 goto error;
00203 }
00204 break;
00205 case Wait_Returns:
00206 switch(event){
00207 case Win_Election:
00208 I_Disc(p);
00209 result_code = Process_CER(p,msg);
00210 Snd_CEA(p,msg,result_code,p->R_sock);
00211 if (result_code>=2000 && result_code<3000){
00212 p->state = R_Open;
00213 }else{
00214 R_Disc(p);
00215 p->state = Closed;
00216 }
00217 break;
00218 case I_Peer_Disc:
00219 I_Disc(p);
00220 result_code = Process_CER(p,msg);
00221 Snd_CEA(p,msg,result_code,p->R_sock);
00222 if (result_code>=2000 && result_code<3000){
00223 p->state = R_Open;
00224 }else{
00225 R_Disc(p);
00226 p->state = Closed;
00227 }
00228 break;
00229 case I_Rcv_CEA:
00230 R_Disc(p);
00231 result_code = Process_CEA(p,msg);
00232 if (result_code>=2000 && result_code<3000)
00233 p->state = I_Open;
00234 else {
00235 Cleanup(p,p->I_sock);
00236 p->state = Closed;
00237 }
00238 break;
00239 case R_Peer_Disc:
00240 R_Disc(p);
00241 p->state = Wait_I_CEA;
00242 break;
00243 case R_Conn_CER:
00244 R_Reject(p,p->R_sock);
00245 p->state = Wait_Returns;
00246 break;
00247 case Timeout:
00248 if (p->I_sock>=0) Error(p,p->I_sock);
00249 if (p->R_sock>=0) Error(p,p->R_sock);
00250 p->state = Closed;
00251 default:
00252 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00253 dp_states[p->state],dp_events[event-101]);
00254 goto error;
00255 }
00256 break;
00257 case R_Open:
00258 switch (event){
00259 case Send_Message:
00260 Snd_Message(p,msg);
00261 p->state = R_Open;
00262 break;
00263 case R_Rcv_Message:
00264
00265
00266 msg_received = 1;
00267 p->state = R_Open;
00268 break;
00269 case R_Rcv_DWR:
00270 result_code = Process_DWR(p,msg);
00271 Snd_DWA(p,msg,result_code,p->R_sock);
00272 p->state = R_Open;
00273 break;
00274 case R_Rcv_DWA:
00275 Process_DWA(p,msg);
00276 p->state = R_Open;
00277 break;
00278 case R_Conn_CER:
00279 R_Reject(p,sock);
00280 p->state = R_Open;
00281 break;
00282 case Stop:
00283 Snd_DPR(p);
00284 p->state = Closing;
00285 break;
00286 case R_Rcv_DPR:
00287 Snd_DPA(p,msg,AAA_SUCCESS,p->R_sock);
00288 R_Disc(p);
00289 p->state = Closed;
00290 log_peer_list(L_INFO);
00291 break;
00292 case R_Peer_Disc:
00293 R_Disc(p);
00294 p->state = Closed;
00295 log_peer_list(L_INFO);
00296 break;
00297 case R_Rcv_CER:
00298 result_code = Process_CER(p,msg);
00299 Snd_CEA(p,msg,result_code,p->R_sock);
00300 if (result_code>=2000 && result_code<3000)
00301 p->state = R_Open;
00302 else {
00303
00304 p->state = R_Open;
00305 }
00306 break;
00307 case R_Rcv_CEA:
00308 result_code = Process_CEA(p,msg);
00309 if (result_code>=2000 && result_code<3000)
00310 p->state = R_Open;
00311 else {
00312
00313 p->state = R_Open;
00314 }
00315 log_peer_list(L_INFO);
00316 break;
00317 default:
00318 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00319 dp_states[p->state],dp_events[event-101]);
00320 goto error;
00321 }
00322 break;
00323 case I_Open:
00324 switch (event){
00325 case Send_Message:
00326 Snd_Message(p,msg);
00327 p->state = I_Open;
00328 break;
00329 case I_Rcv_Message:
00330
00331
00332 msg_received = 1;
00333 p->state = I_Open;
00334 break;
00335 case I_Rcv_DWR:
00336 result_code = Process_DWR(p,msg);
00337 Snd_DWA(p,msg,result_code,p->I_sock);
00338 p->state =I_Open;
00339 break;
00340 case I_Rcv_DWA:
00341 Process_DWA(p,msg);
00342 p->state =I_Open;
00343 break;
00344 case R_Conn_CER:
00345 R_Reject(p,sock);
00346 p->state = I_Open;
00347 break;
00348 case Stop:
00349 Snd_DPR(p);
00350 p->state = Closing;
00351 break;
00352 case I_Rcv_DPR:
00353 Snd_DPA(p,msg,2001,p->I_sock);
00354 R_Disc(p);
00355 p->state = Closed;
00356 log_peer_list(L_INFO);
00357 break;
00358 case I_Peer_Disc:
00359 I_Disc(p);
00360 p->state = Closed;
00361 log_peer_list(L_INFO);
00362 break;
00363 case I_Rcv_CER:
00364 result_code = Process_CER(p,msg);
00365 Snd_CEA(p,msg,result_code,p->I_sock);
00366 if (result_code>=2000 && result_code<3000)
00367 p->state = I_Open;
00368 else {
00369
00370 p->state = I_Open;
00371 }
00372 break;
00373 case I_Rcv_CEA:
00374 result_code = Process_CEA(p,msg);
00375 if (result_code>=2000 && result_code<3000)
00376 p->state = I_Open;
00377 else {
00378
00379 p->state = I_Open;
00380 }
00381 break;
00382 default:
00383 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00384 dp_states[p->state],dp_events[event-101]);
00385 goto error;
00386 }
00387 break;
00388 case Closing:
00389 switch(event){
00390 case I_Rcv_DPA:
00391 I_Disc(p);
00392 p->state = Closed;
00393 break;
00394 case R_Rcv_DPA:
00395 R_Disc(p);
00396 p->state = Closed;
00397 break;
00398 case Timeout:
00399 if (p->I_sock>=0) Error(p,p->I_sock);
00400 if (p->R_sock>=0) Error(p,p->R_sock);
00401 p->state = Closed;
00402 break;
00403 case I_Peer_Disc:
00404 I_Disc(p);
00405 p->state = Closed;
00406 break;
00407 case R_Peer_Disc:
00408 R_Disc(p);
00409 p->state = Closed;
00410 break;
00411 default:
00412 LOG(L_DBG,"DBG:sm_process(): In state %s invalid event %s\n",
00413 dp_states[p->state],dp_events[event-101]);
00414 goto error;
00415 }
00416 break;
00417 }
00418 if (!peer_locked) lock_release(p->lock);
00419
00420 if (msg_received)
00421 Rcv_Process(p,msg);
00422
00423 return 1;
00424 error:
00425 if (!peer_locked) lock_release(p->lock);
00426 return 0;
00427 }
00428
00437 peer_state_t I_Snd_Conn_Req(peer *p)
00438 {
00439 LOG(L_INFO,"DBG:I_Snd_Conn_Req(): Peer %.*s \n",
00440 p->fqdn.len,p->fqdn.s);
00441
00442 if (p->I_sock>0) close(p->I_sock);
00443 p->I_sock = -1;
00444 p->I_sock = peer_connect(p);
00445 if (p->I_sock<0){
00446 return I_Rcv_Conn_NAck;
00447 }
00448
00449 return I_Rcv_Conn_Ack;
00450 }
00451
00458 void Cleanup(peer *p,int sock)
00459 {
00460 if (sock<0) return;
00461 close(sock);
00462 if (p->I_sock == sock) p->I_sock = -1;
00463 if (p->R_sock == sock) p->R_sock = -1;
00464 }
00465
00472 void Error(peer *p, int sock)
00473 {
00474 Cleanup(p,sock);
00475 }
00476
00483 static inline void Snd_CE_add_applications(AAAMessage *msg,peer *p)
00484 {
00485 int i;
00486 app_config *app;
00487 char x[4];
00488 AAA_AVP *avp1,*avp2;
00489 AAA_AVP_LIST list;
00490 str group;
00491 list.head=0;list.tail=0;
00492
00493 for(i=0;i<config->applications_cnt;i++){
00494 app = config->applications+i;
00495 if (app->vendor==0){
00496 set_4bytes(x,app->id);
00497 AAACreateAndAddAVPToMessage(msg,
00498 (app->type==DP_AUTHORIZATION?AVP_Auth_Application_Id:AVP_Acct_Application_Id),
00499 AAA_AVP_FLAG_MANDATORY,0,x,4);
00500 }else{
00501 set_4bytes(x,app->vendor);
00502 avp1 = AAACreateAVP(AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4, AVP_DUPLICATE_DATA);
00503 AAAAddAVPToAVPList(&list,avp1);
00504
00505 set_4bytes(x,app->id);
00506 avp2 = AAACreateAVP((app->type==DP_AUTHORIZATION?AVP_Auth_Application_Id:AVP_Acct_Application_Id),
00507 AAA_AVP_FLAG_MANDATORY,0,x,4,AVP_DUPLICATE_DATA);
00508 AAAAddAVPToAVPList(&list,avp2);
00509
00510 group = AAAGroupAVPS(list);
00511 AAAFreeAVPList(&list);
00512
00513 AAACreateAndAddAVPToMessage(msg,
00514 AVP_Vendor_Specific_Application_Id,
00515 AAA_AVP_FLAG_MANDATORY,0,group.s,group.len);
00516 shm_free(group.s);
00517 }
00518 }
00519 }
00520
00526 void I_Snd_CER(peer *p)
00527 {
00528 AAAMessage *cer=0;
00529
00530 unsigned long ip;
00531 struct sockaddr_in6 addr;
00532 socklen_t addrlen;
00533 char x[18];
00534
00535 cer = AAANewMessage(Code_CE,0,0,0);
00536 if (!cer) return;
00537 cer->hopbyhopId = next_hopbyhop();
00538 cer->endtoendId = next_endtoend();
00539 addrlen = sizeof(struct sockaddr_in6);
00540 if (getsockname(p->I_sock,(struct sockaddr*) &addr, &addrlen) == -1) {
00541 LOG(L_ERR,"ERROR:I_Snd_CER(): Error on finding local host address > %s\n",strerror(errno));
00542 }else{
00543 switch(addr.sin6_family){
00544 case AF_INET:
00545 set_2bytes(x,1);
00546 ip = htonl(((struct sockaddr_in*)&addr)->sin_addr.s_addr);
00547 set_4bytes(x+2,ip);
00548 AAACreateAndAddAVPToMessage(cer,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,6);
00549 break;
00550 case AF_INET6:
00551 set_2bytes(x,2);
00552 memcpy(x+2,addr.sin6_addr.s6_addr,16);
00553 AAACreateAndAddAVPToMessage(cer,AVP_Host_IP_Address,AAA_AVP_FLAG_MANDATORY,0,x,18);
00554 break;
00555 default:
00556 LOG(L_ERR,"ERROR:I_Snd_CER(): unknown address type with family %d\n",addr.sin6_family);
00557 }
00558 }
00559
00560 set_4bytes(x,config->vendor_id);
00561 AAACreateAndAddAVPToMessage(cer,AVP_Vendor_Id,AAA_AVP_FLAG_MANDATORY,0,x,4);
00562
00563 AAACreateAndAddAVPToMessage(cer,AVP_Product_Name,AAA_AVP_FLAG_MANDATORY,0,config->product_name.s,config->product_name.len);
00564
00565 Snd_CE_add_applications(cer,p);
00566
00567 peer_send_msg(p,cer);
00568 }
00569
00570
00571 void add_peer_application(peer *p, int id, int vendor, app_type type)
00572 {
00573 int i;
00574 if (!p->applications) return;
00575 for(i=0;i<p->applications_cnt;i++)
00576 if (p->applications[i].id == id &&
00577 p->applications[i].vendor == vendor &&
00578 p->applications[i].type == type) return;
00579
00580 p->applications[p->applications_cnt].id = id;
00581 p->applications[p->applications_cnt].vendor = vendor;
00582 p->applications[p->applications_cnt].type = type;
00583 p->applications_cnt++;
00584 }
00585
00586 void save_peer_applications(peer *p,AAAMessage *msg)
00587 {
00588 int total_cnt=0;
00589 AAA_AVP *avp,*avp_vendor,*avp2;
00590 AAA_AVP_LIST group;
00591 int id,vendor;
00592
00593 if (p->applications) {
00594 shm_free(p->applications);
00595 p->applications = 0;
00596 p->applications_cnt = 0;
00597 }
00598 for(avp=msg->avpList.head;avp;avp = avp->next)
00599 switch (avp->code){
00600 case AVP_Auth_Application_Id:
00601 case AVP_Acct_Application_Id:
00602 case AVP_Vendor_Specific_Application_Id:
00603 total_cnt+=2;
00604 break;
00605 }
00606 p->applications_cnt = 0;
00607 p->applications = shm_malloc(sizeof(app_config)*total_cnt);
00608 if (!p->applications){
00609 LOG(L_ERR,"ERROR:save_peer_applications(): Error allocating %d bytes! No applications saved...\n",
00610 sizeof(app_config)*total_cnt);
00611 return;
00612 }
00613 for(avp=msg->avpList.head;avp;avp = avp->next)
00614 {
00615 switch (avp->code){
00616 case AVP_Auth_Application_Id:
00617 id = get_4bytes(avp->data.s);
00618 add_peer_application(p,id,0,DP_AUTHORIZATION);
00619 break;
00620 case AVP_Acct_Application_Id:
00621 id = get_4bytes(avp->data.s);
00622 add_peer_application(p,id,0,DP_ACCOUNTING);
00623 break;
00624 case AVP_Vendor_Specific_Application_Id:
00625 group = AAAUngroupAVPS(avp->data);
00626 avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);
00627 avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);
00628 if (avp_vendor&&avp2){
00629 vendor = get_4bytes(avp_vendor->data.s);
00630 id = get_4bytes(avp2->data.s);
00631 add_peer_application(p,id,vendor,DP_AUTHORIZATION);
00632 }
00633 avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);
00634 if (avp_vendor&&avp2){
00635 vendor = get_4bytes(avp_vendor->data.s);
00636 id = get_4bytes(avp2->data.s);
00637 add_peer_application(p,id,vendor,DP_ACCOUNTING);
00638 }
00639 AAAFreeAVPList(&group);
00640 break;
00641
00642 }
00643 }
00644 }
00645
00653 int Process_CEA(peer *p,AAAMessage *cea)
00654 {
00655 AAA_AVP *avp;
00656 avp = AAAFindMatchingAVP(cea,cea->avpList.head,AVP_Result_Code,0,0);
00657 save_peer_applications(p,cea);
00658 AAAFreeMessage(&cea);
00659 if (!avp) return AAA_UNABLE_TO_COMPLY;
00660 else return get_4bytes(avp->data.s);
00661 }
00662
00668 void I_Disc(peer *p)
00669 {
00670 if (p->I_sock>=0){
00671 close(p->I_sock);
00672 p->I_sock = -1;
00673 }
00674 }
00675
00681 void R_Disc(peer *p)
00682 {
00683 if (p->R_sock>=0){
00684 close(p->R_sock);
00685 p->R_sock = -1;
00686 }
00687 }
00688
00697 int Process_DWR(peer *p,AAAMessage *dwr)
00698 {
00699 return AAA_SUCCESS;
00700 }
00701
00709 void Process_DWA(peer *p,AAAMessage *dwa)
00710 {
00711 p->waitingDWA = 0;
00712 AAAFreeMessage(&dwa);
00713 }
00714
00721 void Snd_DWR(peer *p)
00722 {
00723 AAAMessage *dwr=0;
00724
00725 dwr = AAANewMessage(Code_DW,0,0,0);
00726 if (!dwr) return;
00727 dwr->hopbyhopId = next_hopbyhop();
00728 dwr->endtoendId = next_endtoend();
00729 if (p->state==I_Open)
00730 peer_send_msg(p,dwr);
00731 else
00732 peer_send_msg(p,dwr);
00733 }
00734
00743 void Snd_DWA(peer *p,AAAMessage *dwr,int result_code,int sock)
00744 {
00745 AAAMessage *dwa;
00746 char x[4];
00747
00748 dwa = AAANewMessage(Code_DW,0,0,dwr);
00749 if (!dwa) goto done;
00750
00751 set_4bytes(x,result_code);
00752 AAACreateAndAddAVPToMessage(dwa,AVP_Result_Code,AAA_AVP_FLAG_MANDATORY,0,x,4);
00753
00754 peer_send_msg(p,dwa);
00755 done:
00756 AAAFreeMessage(&dwr);
00757 }
00758
00764 void Snd_DPR(peer *p)
00765 {
00766 AAAMessage *dpr=0;
00767 char x[4];
00768
00769 dpr = AAANewMessage(Code_DP,0,0,0);
00770 if (!dpr) return;
00771 dpr->hopbyhopId = next_hopbyhop();
00772 dpr->endtoendId = next_endtoend();
00773
00774 set_4bytes(x,0);
00775 AAACreateAndAddAVPToMessage(dpr,AVP_Disconnect_Cause,AAA_AVP_FLAG_MANDATORY,0,x,4);
00776
00777 if (p->state==I_Open)
00778 peer_send_msg(p,dpr);
00779 else
00780 peer_send_msg(p,dpr);
00781 }
00782
00791 void Snd_DPA(peer *p,AAAMessage *dpr,int result_code,int sock)
00792 {
00793 AAAMessage *dpa;
00794
00795 dpa = AAANewMessage(Code_DP,0,0,dpr);
00796 if (dpa) peer_send_msg(p,dpa);
00797 AAAFreeMessage(&dpr);
00798 }
00799
00806 void R_Accept(peer *p,int sock)
00807 {
00808 p->R_sock = sock;
00809 touch_peer(p);
00810 }
00811
00818 void R_Reject(peer *p,int sock)
00819 {
00820 close(sock);
00821 }
00822
00831 int Process_CER(peer *p,AAAMessage *cer)
00832 {
00833 int common_app=0;
00834 AAA_AVP *avp,*avp_vendor,*avp2;
00835 AAA_AVP_LIST group;
00836 int i,id,vendor;
00837 for(avp=cer->avpList.head;avp;avp = avp->next)
00838 {
00839 switch (avp->code){
00840 case AVP_Auth_Application_Id:
00841 id = get_4bytes(avp->data.s);
00842 for(i=0;i<config->applications_cnt;i++)
00843 if (id == config->applications[i].id &&
00844 config->applications[i].vendor==0 &&
00845 config->applications[i].type==DP_AUTHORIZATION) common_app++;
00846 break;
00847 case AVP_Acct_Application_Id:
00848 id = get_4bytes(avp->data.s);
00849 for(i=0;i<config->applications_cnt;i++)
00850 if (id == config->applications[i].id &&
00851 config->applications[i].vendor==0 &&
00852 config->applications[i].type==DP_ACCOUNTING) common_app++;
00853 break;
00854 case AVP_Vendor_Specific_Application_Id:
00855 group = AAAUngroupAVPS(avp->data);
00856 avp_vendor = AAAFindMatchingAVPList(group,group.head,AVP_Vendor_Id,0,0);
00857 avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Auth_Application_Id,0,0);
00858 if (avp_vendor&&avp2){
00859 vendor = get_4bytes(avp_vendor->data.s);
00860 id = get_4bytes(avp2->data.s);
00861 for(i=0;i<config->applications_cnt;i++)
00862 if (id == config->applications[i].id &&
00863 config->applications[i].vendor==vendor &&
00864 config->applications[i].type==DP_AUTHORIZATION) common_app++;
00865
00866 }
00867 avp2 = AAAFindMatchingAVPList(group,group.head,AVP_Acct_Application_Id,0,0);
00868 if (avp_vendor&&avp2){
00869 vendor = get_4bytes(avp_vendor->data.s);
00870 id = get_4bytes(avp2->data.s);
00871 for(i=0;i<config->applications_cnt;i++)
00872 if (id == config->applications[i].id &&
00873 config->applications[i].vendor==vendor &&
00874 config->applications[i].type==