peerstatemachine.c File Reference


Detailed Description

CDiameterPeer Diameter base protocol state-machine definition.

Author:
Dragos Vingarzan vingarzan -at- fokus dot fraunhofer dot de

Definition in file peerstatemachine.c.

#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include "peerstatemachine.h"
#include "diameter_api.h"
#include "receiver.h"
#include "peermanager.h"
#include "config.h"
#include "worker.h"

Go to the source code of this file.

Functions

int sm_process (peer *p, peer_event_t event, AAAMessage *msg, int peer_locked, int sock)
 Diameter base protocol state-machine processing.
peer_state_t I_Snd_Conn_Req (peer *p)
 Initiator - Send Connection Request.
void Cleanup (peer *p, int sock)
 Cleans a socket by closing it and removing the reference.
void Error (peer *p, int sock)
 Error action for a peer, triggers a Cleanup action.
static void Snd_CE_add_applications (AAAMessage *msg, peer *p)
 Adds the Applications to a Capability Exchange message.
void I_Snd_CER (peer *p)
 Send a Capability Exchange Request.
void add_peer_application (peer *p, int id, int vendor, app_type type)
void save_peer_applications (peer *p, AAAMessage *msg)
int Process_CEA (peer *p, AAAMessage *cea)
 Process a Capability Exchange Answer.
void I_Disc (peer *p)
 Initiator - disconnect peer.
void R_Disc (peer *p)
 Receiver - disconnect peer.
int Process_DWR (peer *p, AAAMessage *dwr)
 Process a Diameter Watch-dog Request.
void Process_DWA (peer *p, AAAMessage *dwa)
 Process a Diameter Watch-dog Answer.
void Snd_DWR (peer *p)
 Sends a Diameter Watch-dog Request.
void Snd_DWA (peer *p, AAAMessage *dwr, int result_code, int sock)
 Sends a Diameter Watch-dog Answer.
void Snd_DPR (peer *p)
 Sends a Disconnect Peer Request.
void Snd_DPA (peer *p, AAAMessage *dpr, int result_code, int sock)
 Sends a Disconnect Peer Answer.
void R_Accept (peer *p, int sock)
 Receiver - Accept a connection.
void R_Reject (peer *p, int sock)
 Receiver - Reject a connection.
int Process_CER (peer *p, AAAMessage *cer)
 Process a Capabilities Exchange Request.
void Snd_CEA (peer *p, AAAMessage *cer, int result_code, int sock)
 Send a Capabilities Exchange Answer.
int Elect (peer *p, AAAMessage *cer)
 Perform the Election mechanism.
void Snd_Message (peer *p, AAAMessage *msg)
 Sends a message to the peer.
void Rcv_Process (peer *p, AAAMessage *msg)
 Processes an incoming message.

Variables

dp_configconfig
 Configuration for this diameter peer.
char * dp_states [] = {"Closed","Wait_Conn_Ack","Wait_I_CEA","Wait_Conn_Ack_Elect","Wait_Returns","R_Open","I_Open","Closing"}
 Strings for the peer states.
char * dp_events []
 Strings for the peer events.


Function Documentation

int sm_process ( peer p,
peer_event_t  event,
AAAMessage msg,
int  peer_locked,
int  sock 
)

Diameter base protocol state-machine processing.

This function get's called for every event. It updates the states and can trigger other events.

Parameters:
p - the peer for which the event happened
event - the event that happened
msg - if a Diameter message was received this is it, or NULL if not
peer_locked - if the peer lock is already aquired
sock - socket that this event happened on, or NULL if unrelated
Returns:
1 on success, 0 on error. Also the peer states are updated

Definition at line 88 of file peerstatemachine.c.

References AAA_SUCCESS, Cleanup(), Closed, Closing, dp_events, dp_states, Elect(), Error(), _peer_t::fqdn, I_Disc(), I_Open, I_Peer_Disc, I_Rcv_CEA, I_Rcv_CER, I_Rcv_Conn_Ack, I_Rcv_Conn_NAck, I_Rcv_DPA, I_Rcv_DPR, I_Rcv_DWA, I_Rcv_DWR, I_Rcv_Message, I_Rcv_Non_CEA, I_Snd_CER(), I_Snd_Conn_Req(), _peer_t::I_sock, _peer_t::lock, log_peer_list(), Process_CEA(), Process_CER(), Process_DWA(), Process_DWR(), R_Accept(), R_Conn_CER, R_Disc(), R_Open, R_Peer_Disc, R_Rcv_CEA, R_Rcv_CER, R_Rcv_DPA, R_Rcv_DPR, R_Rcv_DWA, R_Rcv_DWR, R_Rcv_Message, R_Reject(), _peer_t::R_sock, Rcv_Process(), Send_Message, sm_process(), Snd_CEA(), Snd_DPA(), Snd_DPR(), Snd_DWA(), Snd_Message(), Start, _peer_t::state, Stop, Timeout, Wait_Conn_Ack, Wait_Conn_Ack_Elect, Wait_I_CEA, Wait_Returns, and Win_Election.

Referenced by peer_send(), peer_timer(), receive_loop(), receive_message(), and sm_process().

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 }

peer_state_t I_Snd_Conn_Req ( peer p  ) 

Initiator - Send Connection Request.

Tries to connect to the remote peer's socket. If the connection is refused, the new state is I_Rcv_Conn_NAck, else I_Rcv_Conn_Ack.

Note:
Must be called with a lock on the peer.
Parameters:
p - peer to send to
Returns:
the new state for the peer

Definition at line 437 of file peerstatemachine.c.

References _peer_t::fqdn, I_Rcv_Conn_Ack, I_Rcv_Conn_NAck, _peer_t::I_sock, and peer_connect().

Referenced by sm_process().

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 }

void Cleanup ( peer p,
int  sock 
)

Cleans a socket by closing it and removing the reference.

Note:
Must be called with a lock on the peer.
Parameters:
p - the peer
sock - socket to close

Definition at line 458 of file peerstatemachine.c.

References _peer_t::I_sock, and _peer_t::R_sock.

Referenced by Error(), and sm_process().

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 }

void Error ( peer p,
int  sock 
)

Error action for a peer, triggers a Cleanup action.

Note:
Must be called with a lock on the peer.
Parameters:
p - the peer
sock - socket to close

Definition at line 472 of file peerstatemachine.c.

References Cleanup().

Referenced by sm_process().

00473 {
00474     Cleanup(p,sock);
00475 }

static void Snd_CE_add_applications ( AAAMessage msg,
peer p 
) [inline, static]

Adds the Applications to a Capability Exchange message.

Note:
Must be called with a lock on the peer.
Parameters:
msg - the message to add to (request/answer)
p - the peer to add applications from

Definition at line 483 of file peerstatemachine.c.

References AAA_AVP_FLAG_MANDATORY, AAAAddAVPToAVPList(), AAACreateAndAddAVPToMessage, AAACreateAVP(), AAAFreeAVPList(), AAAGroupAVPS(), dp_config::applications, dp_config::applications_cnt, AVP_Acct_Application_Id, AVP_Auth_Application_Id, AVP_DUPLICATE_DATA, AVP_Vendor_Id, AVP_Vendor_Specific_Application_Id, config, DP_AUTHORIZATION, _avp_list_t::head, app_config::id, if, set_4bytes, _avp_list_t::tail, app_config::type, and app_config::vendor.

Referenced by I_Snd_CER(), and Snd_CEA().

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 }

void I_Snd_CER ( peer p  ) 

Send a Capability Exchange Request.

Note:
Must be called with a lock on the peer.
Parameters:
p - the peer to send to

Definition at line 526 of file peerstatemachine.c.

References AAA_AVP_FLAG_MANDATORY, AAACreateAndAddAVPToMessage, AAANewMessage(), AVP_Host_IP_Address, AVP_Product_Name, AVP_Vendor_Id, Code_CE, config, _message_t::endtoendId, errno, _message_t::hopbyhopId, _peer_t::I_sock, next_endtoend(), next_hopbyhop(), peer_send_msg(), dp_config::product_name, set_2bytes, set_4bytes, Snd_CE_add_applications(), and dp_config::vendor_id.

Referenced by sm_process().

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.in6_u.u6_addr8,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 }

void add_peer_application ( peer p,
int  id,
int  vendor,
app_type  type 
)

Definition at line 571 of file peerstatemachine.c.

References _peer_t::applications, _peer_t::applications_cnt, app_config::id, app_config::type, and app_config::vendor.

Referenced by save_peer_applications().

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 }

void save_peer_applications ( peer p,
AAAMessage msg 
)

Definition at line 586 of file peerstatemachine.c.

References AAAFindMatchingAVPList(), AAAFreeAVPList(), AAAUngroupAVPS(), add_peer_application(), _peer_t::applications, _peer_t::applications_cnt, AVP_Acct_Application_Id, AVP_Auth_Application_Id, AVP_Vendor_Id, AVP_Vendor_Specific_Application_Id, _message_t::avpList, avp::code, avp::data, DP_ACCOUNTING, DP_AUTHORIZATION, get_4bytes, _avp_list_t::head, id, and avp::next.

Referenced by Process_CEA(), and Process_CER().

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