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_config * | config |
| 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. | |
| 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.
| 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 |
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.
| p | - peer to send to |
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.
| 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.
| 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.
| 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.
| 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 }
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