peerstatemachine.c

Go to the documentation of this file.
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                     /* just ignore this state */
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 /* Commented as not reachable*/                     
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 /* commented as not reachable */
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                     // delayed processing until out of the critical zone
00265                     //Rcv_Process(p,msg);
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                         /*R_Disc(p);p.state = Closed;*/
00304                         p->state = R_Open; /* Or maybe I should disconnect it?*/
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                         /*R_Disc(p);p.state = Closed;*/
00313                         p->state = R_Open; /* Or maybe I should disconnect it?*/
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                     // delayed processing until out of the critical zone
00331                     //Rcv_Process(p,msg);
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                         /*I_Disc(p);p.state = Closed;*/
00370                         p->state = I_Open; /* Or maybe I should disconnect it?*/
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                         /*I_Disc(p);p.state = Closed;*/
00379                         p->state = I_Open; /* Or maybe I should disconnect it?*/
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 //  AAA_AVP *avp;
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 //  peer_send(p,p->I_sock,cer,1);
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;/* wasteful, but let's skip decoding */    
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/*busy*/);
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==