Main Page | Class Hierarchy | Alphabetical List | Class List | File List | Class Members

pana_session.cxx

00001 /* BEGIN_COPYRIGHT                                                        */
00002 /*                                                                        */
00003 /* Open Diameter: Open-source software for the Diameter and               */
00004 /*                Diameter related protocols                              */
00005 /*                                                                        */
00006 /* Copyright (C) 2002-2004 Open Diameter Project                          */
00007 /*                                                                        */
00008 /* This library is free software; you can redistribute it and/or modify   */
00009 /* it under the terms of the GNU Lesser General Public License as         */
00010 /* published by the Free Software Foundation; either version 2.1 of the   */
00011 /* License, or (at your option) any later version.                        */
00012 /*                                                                        */
00013 /* This library is distributed in the hope that it will be useful,        */
00014 /* but WITHOUT ANY WARRANTY; without even the implied warranty of         */
00015 /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU      */
00016 /* Lesser General Public License for more details.                        */
00017 /*                                                                        */
00018 /* You should have received a copy of the GNU Lesser General Public       */
00019 /* License along with this library; if not, write to the Free Software    */
00020 /* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307    */
00021 /* USA.                                                                   */
00022 /*                                                                        */
00023 /* In addition, when you copy and redistribute some or the entire part of */
00024 /* the source code of this software with or without modification, you     */
00025 /* MUST include this copyright notice in each copy.                       */
00026 /*                                                                        */
00027 /* If you make any changes that are appeared to be useful, please send    */
00028 /* sources that include the changed part to                               */
00029 /* diameter-developers@lists.sourceforge.net so that we can reflect your  */
00030 /* changes to one unified version of this software.                       */
00031 /*                                                                        */
00032 /* END_COPYRIGHT                                                          */
00033 
00034 #include "ace/OS.h"
00035 #include "pana_exceptions.h"
00036 #include "pana_session.h"
00037 #include "pana_memory_manager.h"
00038 
00039 PANA_SessionAttribute::PANA_SessionAttribute()
00040 {
00041     m_LastPayload = NULL;
00042     Reset();
00043 }
00044 
00045 PANA_SessionAttribute::~PANA_SessionAttribute()
00046 {
00047     Reset();
00048 }
00049 
00050 void PANA_SessionAttribute::Reset()
00051 {
00052    if (m_LastPayload) {
00053       m_LastPayload->Release();
00054    }
00055 
00056    while (! m_RxMessageQueue.empty()) {
00057       PANA_Message &msg = *(m_RxMessageQueue.front());
00058       m_RxMessageQueue.pop_front();
00059       delete &msg;
00060    }
00061 
00062    m_PeerDeviceId.clear();
00063    
00064    m_InitialPacTsec        = 0; // TBD: compute this
00065    m_InitialPaaTsec        = 0;
00066    m_LastTransmittedTsec   = 0;
00067    m_LastReceivedRsec      = 0;
00068    m_PeerPort              = 0;
00069    m_LastPayload           = NULL;
00070    m_SessionLifetime       = 0;
00071    m_SeparateAuth          = false;
00072    m_BindCount             = 0;
00073    m_BindResult[0]         = 0;
00074    m_BindResult[1]         = 0;
00075    m_TerminationCause      = PANA_TC_INVALID;
00076 }
00077 
00078 void PANA_Session::ValidateMessage(PANA_Message &msg)
00079 {
00080    /* Peer address adjustments */
00081    PANA_DeviceId *ipId = msg.srcDevices().search(PANA_DeviceId::IPV4_ADDRESS);
00082    PANA_DeviceId *ipIdS = m_PeerDeviceId.search(PANA_DeviceId::IPV4_ADDRESS);
00083    if ((ipId && ipIdS) && (! (*ipId == *ipIdS))) {
00084       m_PeerDeviceId.replace(*ipId);
00085    }
00086    
00087 
00088    /*
00089       When a message is received, it is considered as valid in terms of 
00090       sequence numbers if and only if (i) its tseq is greater than the  
00091       tseq of the last accepted message and (ii) its rseq falls in the 
00092       range between the tseq of the last acknowledged message + 1 and the 
00093       tseq of the last transmitted message. 
00094     */ 
00095 #if __MAJOR_TBD__
00096    if (! ((msg.tseq() > m_LastReceivedTsec_) && 
00097        ((msg.rseq() >= (m_LastReceivedRsec_ + 1)) && 
00098         (msg.rseq() <= m_LastTransmittedTsec_)))) {
00099         throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00100                              "PANA session received msg with invalid seq number"));
00101    }
00102 #endif // __MAJOR_TBD__
00103 
00104    /*
00105      When a MAC AVP is included, the AVP value matches the MAC value 
00106      computed against the received message. 
00107     */
00108    if (m_SA.MSK().size() > 0) {
00109       ACE_DEBUG((LM_INFO, "(%P|%t) SA Present, validating MAC\n"));    
00110       if (m_SA.ValidateMacValue(msg) == false) {
00111          throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00112                               "PANA session received msg with invalid MAC value"));
00113       }
00114    }
00115 
00116    // verify the session id
00117    if (m_SessionId.size() > 0) {
00118 
00119       AAAAvpContainer *c_sessionId = msg.avpList().search("Session-Id");
00120       if (c_sessionId == NULL) {
00121          throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00122                               "PANA session received msg with no session ID"));
00123       }
00124       diameter_utf8string_t &id = (*c_sessionId)[0]->dataRef(Type2Type<diameter_utf8string_t>());
00125 
00126       if (ACE_OS::memcmp(m_SessionId.data(), id.data(), id.size())) {
00127          throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00128                               "PANA session received invalid message, session id does not match"));
00129       }
00130    }
00131 
00132    // verify the peer deivce id
00133    if (m_PeerDeviceId.size() > 0) {
00134       AAAAvpContainer *c_deviceId = msg.avpList().search("Device-Id");
00135       if (c_deviceId) {
00136          PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00137          PANA_DeviceId *knownId = m_PeerDeviceId.search(PANA_DeviceId::TYPE(deviceId.type));
00138          if (knownId) {
00139              if (ACE_OS::memcmp(deviceId.value.data(), knownId->id().data(), knownId->id().size())) {
00140                 throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE,
00141                                      "Device ID AVP value does not match device id of known peer"));
00142              }
00143          }
00144       }
00145    }
00146 
00147    // Update sequence number
00148    m_LastReceivedTsec = msg.tseq();
00149    m_LastReceivedRsec = msg.rseq();
00150 }
00151 
00152 void PANA_Session::DestinationAddressFormatting(PANA_Message &msg,
00153                                                 AAAMessageBlock *eapPayload)
00154 {
00155    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: No Tx address formatting present\n"));
00156 }
00157 
00158 void PANA_Session::SendReAuthenticateRequest()
00159 {
00160    /*
00161        PaC      PAA     Message(tseq,rseq)[AVPs] 
00162        ------------------------------------------------------ 
00163           ----->        PANA-Reauth-Request(q,p)[MAC] 
00164           <-----        PANA-Reauth-Answer(p+1,q)[MAC] 
00165     
00166        Figure 5: Example Sequence for PaC-initiated Re-authentication 
00167     
00168        PaC      PAA     Message(tseq,rseq)[AVPs] 
00169        ------------------------------------------------------ 
00170           <-----        PANA-Reauth-Request(p,q)[MAC] 
00171           ----->        PANA-Reauth-Answer(q+1,p)[MAC] 
00172     
00173        Figure 6: Example Sequence for PAA-initiated Re-authentication 
00174 
00175        9.3.9 PANA-Reauth-Request (PRAR)
00176 
00177          PANA-Reauth-Request (PRAR) is either sent by the PaC or the PAA.
00178 
00179                PANA-Reauth-Request ::= < PANA-Header: 5, REQ >
00180                              < Session-Id >
00181                              < Device-Id >
00182                           *  [ AVP ]
00183                          0*1 < MAC >
00184     */
00185 
00186    ACE_DEBUG((LM_INFO, "(%P|%t) Sending re-auth request\n"));
00187 
00188    if (m_SA.MSK().size() == 0) {
00189       throw (PANA_Exception(PANA_Exception::FAILED, 
00190                             "No MSK setup for this session"));
00191    }
00192 
00193    AAAAvpContainerManager cm;
00194    AAAAvpContainerEntryManager em;
00195    PANA_Message *msg;
00196 
00197    ACE_NEW_NORETURN(msg, PANA_Message);
00198    if (msg == NULL) {
00199       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00200                             "Failed to allocate msg message"));
00201    }
00202 
00203    // Populate header
00204    PANA_MsgHeader::Flags flg = { 1, 0, 0, 0 };
00205    msg->flags(flg);
00206    msg->type(PANA_MTYPE_REAUTH);
00207    msg->tseq(++ m_LastTransmittedTsec);
00208    msg->rseq(m_LastReceivedTsec);
00209 
00210    // Populate AVP's
00211    AAAAvpContainerEntry *e;
00212    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00213    AAAAvpContainer *c_deviceId = cm.acquire("Device-Id");
00214 
00215    // Add the AVP's to containers
00216    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00217    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00218    c_sessionId->add(e);
00219 
00220    e = em.acquire(AAA_AVPDataType(AAA_AVP_DEVICEID_TYPE));
00221    PANA_TVData_t &deviceId = e->dataRef(Type2Type<PANA_TVData_t>());
00222    c_deviceId->add(e);
00223 
00224    // Add containers to listen
00225    msg->avpList().add(c_sessionId);
00226    msg->avpList().add(c_deviceId);
00227 
00228    // Populate data
00229    PANA_DeviceIdContainer srcDevices;
00230    m_TxChannel.GetLocalAddress(srcDevices);
00231    PANA_DeviceId *id = srcDevices.search(m_ReqDeviceId);
00232    if (id) {
00233       deviceId.type = id->type();
00234       deviceId.value.assign(id->id().data(), id->id().size());
00235    }
00236    else {
00237       throw (PANA_Exception(PANA_Exception::FAILED, 
00238                            "No MAC address given in the device list"));
00239    }
00240    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00241 
00242    // Send message
00243    DestinationAddressFormatting(*msg);
00244    m_TxChannel.Send(*this, *msg);
00245 
00246    PANA_RtQueueNullData data;
00247    if (m_RtQueue.Schedule(data)) {
00248        m_Timer.Schedule(PANA_TID_PRAR_RETRY, data.Timeout());       
00249    }
00250 
00251    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Re-Auth-Request, tseq=%d, rseq=%d\n",
00252               msg->tseq(), msg->rseq()));
00253 }
00254 
00255 void PANA_Session::RetryReAuthenticateRequest()
00256 {
00257    m_Timer.Cancel(PANA_TID_PRAR_RETRY);
00258    
00259    PANA_RtQueueData *data = NULL;
00260    if (m_RtQueue.ReSchedule(data)) {
00261        SendReAuthenticateRequest();
00262        m_Timer.Schedule(PANA_TID_PRAR_RETRY, data->Timeout());       
00263    }
00264    else {
00265        m_Timer.Schedule(PANA_TID_DISCONNECT, 0);
00266    }
00267 }
00268 
00269 void PANA_Session::ReceiveReAuthenticateRequest()
00270 {
00271    PANA_Message &msg = *(m_RxMessageQueue.front());
00272    m_RxMessageQueue.pop_front();
00273 
00274    // cancel discovery retry if any
00275    m_Timer.Cancel(PANA_TID_DISC_RETRY);
00276    m_RtQueue.ClearFront();
00277    
00278    // cancel start answer retry if any
00279    m_Timer.Cancel(PANA_TID_PSA_RETRY);
00280    m_RtQueue.ClearFront();
00281 
00282    AAAAvpContainer* c_deviceId = msg.avpList().search("Device-Id");
00283    if (c_deviceId) {
00284        PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00285        PANA_DeviceId id(PANA_DeviceId::TYPE(deviceId.type), deviceId.value);
00286        PANA_DeviceId *knownId = m_PeerDeviceId.search(PANA_DeviceId::TYPE(deviceId.type));
00287        if (knownId && !(*knownId == id)) {
00288            throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00289                          "Device id type in re-auth request does not match known peer id"));
00290        }
00291        else if (! knownId) {
00292            m_PeerDeviceId.clone(id);
00293            m_ReqDeviceId = PANA_DeviceId::TYPE(deviceId.type);
00294        }
00295    }
00296 
00297    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: ReAuthenticate-Req, tseq=%d, rseq=%d\n",
00298               msg.tseq(), msg.rseq()));
00299    
00300    SendReAuthenticateAnswer();
00301 
00302    ReAuthenticate(PANA_REAUTH_PANA);
00303 
00304    if (c_deviceId) {
00305        PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00306        PANA_DeviceId id(PANA_DeviceId::TYPE(deviceId.type), deviceId.value);
00307        m_Event.AuthorizePeer(id, true);
00308    }
00309 
00310    m_Timer.Schedule(PANA_TID_SESSION, m_SessionLifetime);  
00311    delete &msg;
00312 }
00313 
00314 void PANA_Session::SendReAuthenticateAnswer()
00315 {
00316    /*
00317        PaC      PAA     Message(tseq,rseq)[AVPs] 
00318        ------------------------------------------------------ 
00319           ----->        PANA-Reauth-Request(q,p)[MAC] 
00320           <-----        PANA-Reauth-Answer(p+1,q)[MAC] 
00321     
00322        Figure 5: Example Sequence for PaC-initiated Re-authentication 
00323     
00324        PaC      PAA     Message(tseq,rseq)[AVPs] 
00325        ------------------------------------------------------ 
00326           <-----        PANA-Reauth-Request(p,q)[MAC] 
00327           ----->        PANA-Reauth-Answer(q+1,p)[MAC] 
00328     
00329        Figure 6: Example Sequence for PAA-initiated Re-authentication 
00330 
00331        9.3.10 PANA-Reauth-Answer (PRAA)
00332 
00333          PANA-Reauth-Answer (PRAA) is sent in response to a
00334          PANA-Reauth-Request.
00335 
00336               PANA-Reauth-Answer ::= < PANA-Header: 5 >
00337                             < Session-Id >
00338                             < Device-Id >
00339                          *  [ AVP ]
00340                         0*1 < MAC >
00341     */
00342 
00343    ACE_DEBUG((LM_INFO, "(%P|%t) Sending re-auth answer\n"));
00344 
00345    if (m_SA.MSK().size() == 0) {
00346       throw (PANA_Exception(PANA_Exception::FAILED, 
00347                            "No MSK setup for this session"));
00348    }
00349 
00350    AAAAvpContainerManager cm;
00351    AAAAvpContainerEntryManager em;
00352    PANA_Message *msg;
00353 
00354    ACE_NEW_NORETURN(msg, PANA_Message);
00355    if (msg == NULL) {
00356       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00357                             "Failed to allocate msg message"));
00358    }
00359 
00360    // Populate header
00361    PANA_MsgHeader::Flags flg = { 0, 0, 0, 0 }; // TBD: answer
00362    msg->flags(flg);
00363    msg->type(PANA_MTYPE_REAUTH);
00364    msg->tseq(++ m_LastTransmittedTsec);
00365    msg->rseq(m_LastReceivedTsec);
00366 
00367    // Populate AVP's
00368    AAAAvpContainerEntry *e;
00369    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00370    AAAAvpContainer *c_deviceId = cm.acquire("Device-Id");
00371 
00372    // Add the AVP's to containers
00373    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00374    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00375    c_sessionId->add(e);
00376 
00377    e = em.acquire(AAA_AVPDataType(AAA_AVP_DEVICEID_TYPE));
00378    PANA_TVData_t &deviceId = e->dataRef(Type2Type<PANA_TVData_t>());
00379    c_deviceId->add(e);
00380 
00381    // Add containers to listen
00382    msg->avpList().add(c_sessionId);
00383    msg->avpList().add(c_deviceId);
00384 
00385    // Populate data
00386    PANA_DeviceIdContainer srcDevices;
00387    m_TxChannel.GetLocalAddress(srcDevices);
00388    PANA_DeviceId *id = srcDevices.search(m_ReqDeviceId);
00389    if (id) {
00390       deviceId.type = id->type();
00391       deviceId.value.assign(id->id().data(), id->id().size());
00392    }
00393    else {
00394       throw (PANA_Exception(PANA_Exception::FAILED, 
00395                            "No MAC address given in the device list"));
00396    }
00397    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00398 
00399    // Send message
00400    DestinationAddressFormatting(*msg);
00401    m_TxChannel.Send(*this, *msg);
00402 
00403    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Re-Auth-Answer, tseq=%d, rseq=%d\n",
00404               msg->tseq(), msg->rseq()));
00405 }
00406 
00407 void PANA_Session::ReceiveReAuthenticateAnswer()
00408 {
00409    PANA_Message &msg = *(m_RxMessageQueue.front());
00410    m_RxMessageQueue.pop_front();
00411 
00412    m_Timer.Cancel(PANA_TID_PRAR_RETRY);
00413    m_RtQueue.ClearFront();
00414    
00415    AAAAvpContainer* c_deviceId = msg.avpList().search("Device-Id");
00416    if (c_deviceId) {
00417        PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00418        if (m_ReqDeviceId != deviceId.type) {
00419            throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00420                            "Device id type in bind answer does not match request"));
00421        }
00422        PANA_DeviceId id(PANA_DeviceId::TYPE(deviceId.type), deviceId.value);
00423        PANA_DeviceId *knownId = m_PeerDeviceId.search(PANA_DeviceId::TYPE(deviceId.type));
00424        if (knownId && !(*knownId == id)) {
00425            throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00426                          "Device id type in re-auth answer does not match known peer id"));
00427        }
00428        else if (! knownId) {
00429            m_PeerDeviceId.clone(id);
00430        }
00431    }
00432 
00433    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: ReAuthenticate-Answer, tseq=%d, rseq=%d\n",
00434               msg.tseq(), msg.rseq()));
00435 
00436    ReAuthenticate(PANA_REAUTH_PANA);
00437 
00438    if (c_deviceId) {
00439        PANA_TVData_t &deviceId = (*c_deviceId)[0]->dataRef(Type2Type<PANA_TVData_t>());
00440        PANA_DeviceId id(PANA_DeviceId::TYPE(deviceId.type), deviceId.value);
00441        m_Event.AuthorizePeer(id, true);
00442    }
00443 
00444    m_Timer.Schedule(PANA_TID_SESSION, m_SessionLifetime);   
00445    delete &msg;
00446 }
00447 
00448 void PANA_Session::SendTerminationRequest()
00449 {
00450    /*
00451        PaC      PAA     Message(tseq,rseq)[AVPs] 
00452        ------------------------------------------------------ 
00453           ----->        PANA-Termination-Request(q,p)[MAC] 
00454           <-----        PANA-Termination-Answer(p+1,q)[MAC] 
00455     
00456        Figure 7: Example Sequence for Session Termination 
00457 
00458        9.3.11 PANA-Termination-Request (PTR)
00459 
00460          PANA-Termination-Request (PTR) is sent either by the PaC or the PAA.
00461 
00462               PANA-Termination-Request ::= < PANA-Header: 6, REQ >
00463                             < Session-Id >
00464                             < Termination-Cause >
00465                          *  [ AVP ]
00466                         0*1 < MAC >
00467    */
00468 
00469    ACE_DEBUG((LM_INFO, "(%P|%t) Sending termination request\n"));
00470 
00471    AAAAvpContainerManager cm;
00472    AAAAvpContainerEntryManager em;
00473    PANA_Message *msg;
00474 
00475    ACE_NEW_NORETURN(msg, PANA_Message);
00476    if (msg == NULL) {
00477       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00478                            "Failed to allocate msg message"));
00479    }
00480 
00481    // Populate header
00482    PANA_MsgHeader::Flags flg = { 1, 0, 0, 0 }; 
00483    msg->flags(flg);
00484    msg->type(PANA_MTYPE_TERM);
00485    msg->tseq(++ m_LastTransmittedTsec);
00486    msg->rseq(m_LastReceivedTsec);
00487 
00488    // Populate AVP's
00489    AAAAvpContainerEntry *e;
00490    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00491    AAAAvpContainer *c_termCause = cm.acquire("Termination-Cause");
00492 
00493    // Add the AVP's to containers
00494    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00495    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00496    c_sessionId->add(e);
00497 
00498    e = em.acquire(AAA_AVP_UINTEGER32_TYPE);
00499    diameter_unsigned32_t &termCause = e->dataRef(Type2Type<diameter_unsigned32_t>());
00500    c_termCause->add(e);
00501 
00502    // Add containers to listen
00503    msg->avpList().add(c_sessionId);
00504    msg->avpList().add(c_termCause);
00505 
00506    // Populate data
00507    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00508    termCause = m_TerminationCause;
00509 
00510    // Send message
00511    DestinationAddressFormatting(*msg);
00512    m_TxChannel.Send(*this, *msg);
00513 
00514    PANA_RtQueueNullData data;
00515    if (m_RtQueue.Schedule(data)) {
00516        m_Timer.Schedule(PANA_TID_PTR_RETRY, data.Timeout());       
00517    }
00518 
00519    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Termination-Request, tseq=%d, rseq=%d\n",
00520               msg->tseq(), msg->rseq()));
00521 }
00522 
00523 void PANA_Session::RetryTerminationRequest()
00524 {
00525    m_Timer.Cancel(PANA_TID_PTR_RETRY);
00526    
00527    PANA_RtQueueData *data = NULL;
00528    if (m_RtQueue.ReSchedule(data)) {
00529        SendTerminationRequest();
00530        m_Timer.Schedule(PANA_TID_PTR_RETRY, data->Timeout());       
00531    }
00532    else {
00533        m_Timer.Schedule(PANA_TID_DISCONNECT, 0);
00534    }
00535 }
00536 
00537 void PANA_Session::ReceiveTerminationRequest()
00538 {
00539    PANA_Message &msg = *(m_RxMessageQueue.front());
00540    m_RxMessageQueue.pop_front();
00541 
00542    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: Termination-Req, tseq=%d, rseq=%d\n",
00543               msg.tseq(), msg.rseq()));
00544 
00545    AAAAvpContainer* c_cause = msg.avpList().search("Termination-Cause");
00546    if (c_cause == NULL) {
00547        throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00548                             "PANA client received term msg with no term cause"));
00549    }
00550    diameter_unsigned32_t &cause = (*c_cause)[0]->dataRef(Type2Type<diameter_unsigned32_t>());
00551    SendTerminationAnswer();
00552    Disconnect(cause);
00553    delete &msg;
00554 }
00555 
00556 void PANA_Session::SendTerminationAnswer()
00557 {
00558    /*
00559        PaC      PAA     Message(tseq,rseq)[AVPs] 
00560        ------------------------------------------------------ 
00561           ----->        PANA-Termination-Request(q,p)[MAC] 
00562           <-----        PANA-Termination-Answer(p+1,q)[MAC] 
00563     
00564        Figure 7: Example Sequence for Session Termination 
00565 
00566        9.3.12 PANA-Termination-Answer (PTA)
00567 
00568          PANA-Termination-Answer (PTA) is sent either by the PaC or the PAA in
00569          response to PANA-Termination-Request.
00570 
00571               PANA-Termination-Answer ::= < PANA-Header: 6 >
00572                              < Session-Id >
00573                           *  [ AVP ]
00574                          0*1 < MAC >
00575     */
00576    AAAAvpContainerManager cm;
00577    AAAAvpContainerEntryManager em;
00578    PANA_Message *msg;
00579 
00580    ACE_NEW_NORETURN(msg, PANA_Message);
00581    if (msg == NULL) {
00582       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00583                            "Failed to allocate msg message"));
00584    }
00585 
00586    // Populate header
00587    PANA_MsgHeader::Flags flg = { 0, 0, 0, 0 }; 
00588    msg->flags(flg);
00589    msg->type(PANA_MTYPE_TERM);
00590    msg->tseq(++ m_LastTransmittedTsec);
00591    msg->rseq(m_LastReceivedTsec);
00592 
00593    // Populate AVP's
00594    AAAAvpContainerEntry *e;
00595    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00596 
00597    // Add the AVP's to containers
00598    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00599    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00600    c_sessionId->add(e);
00601 
00602    // Add containers to listen
00603    msg->avpList().add(c_sessionId);
00604 
00605    // Populate data
00606    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00607 
00608    // send message
00609    DestinationAddressFormatting(*msg);
00610    m_TxChannel.Send(*this, *msg);
00611 
00612    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Termination-Answer, tseq=%d, rseq=%d\n",
00613               msg->tseq(), msg->rseq()));
00614 }
00615 
00616 void PANA_Session::ReceiveTerminationAnswer()
00617 {
00618    PANA_Message &msg = *(m_RxMessageQueue.front());
00619    m_RxMessageQueue.pop_front();
00620 
00621    m_Timer.Cancel(PANA_TID_PTR_RETRY);
00622    m_RtQueue.ClearFront();
00623    
00624    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: Termination-Answer, tseq=%d, rseq=%d\n",
00625               msg.tseq(), msg.rseq()));
00626 
00627    Disconnect(m_TerminationCause);
00628    delete &msg;
00629 }
00630 
00631 void PANA_Session::ReAuthenticate(PANA_REAUTH cause)
00632 {
00633    ACE_DEBUG((LM_INFO, "(%P|%t) EVENT: Re-Authentication, cause=%d\n", cause));
00634    m_Timer.Cancel(PANA_TID_SESSION);
00635    m_Event.ReAuthentication(cause);
00636 }
00637 
00638 void PANA_Session::Disconnect(ACE_UINT32 cause) 
00639 { 
00640    ACE_DEBUG((LM_INFO, "(%P|%t) EVENT: Disconnect, cause=%d\n", cause));
00641 
00642    // cancel reauth request retry if any
00643    m_Timer.Cancel(PANA_TID_PRAR_RETRY);
00644    m_RtQueue.ClearFront();
00645 
00646    // cancel termination request retry if any
00647    m_Timer.Cancel(PANA_TID_PTR_RETRY);
00648    m_RtQueue.ClearFront();
00649 
00650    // cancel bind answer retry if any
00651    m_Timer.Cancel(PANA_TID_PBR_RETRY);
00652    m_RtQueue.ClearFront();
00653 
00654    // cancel all other session global timers
00655    m_Timer.Cancel(PANA_TID_DISCONNECT);
00656    m_Timer.Cancel(PANA_TID_SESSION);
00657 
00658    // tell the user
00659    m_Event.Disconnect(cause); 
00660 }
00661 
00662 PANA_BIND_RESULT PANA_Session::BindResult(int rcode)
00663 {
00664    if (m_SeparateAuth) {
00665        if (m_BindCount < PANA_BIND_COUNT_MAX) {
00666            m_BindCount ++;
00667            m_BindResult[m_BindCount - 1] = rcode;
00668        }
00669    }
00670    else {
00671        m_BindResult[0] = rcode;
00672    }
00673    return BindResult();
00674 }
00675 
00676 PANA_BIND_RESULT PANA_Session::BindResult()
00677 {
00678    PANA_BIND_RESULT br = PANA_BIND_FAILED;
00679    if (m_SeparateAuth) {
00680       if (m_BindCount < PANA_BIND_COUNT_MAX) {
00681          return (PANA_BIND_INTERIM);
00682       }
00683       else {
00684          for (unsigned int i = 0; i < m_BindCount; i ++) {
00685              if (PANA_RCODE_SUCCESS(m_BindResult[i])) {
00686                 br = (i == 0) ? PANA_BIND_SUCCESS_INITIAL :
00687                                 PANA_BIND_SUCCESS_FINAL;
00688                 break;
00689              }
00690          }
00691       }
00692    }
00693    else {
00694       br = PANA_RCODE_SUCCESS(m_BindResult[0]) ?
00695                 PANA_BIND_SUCCESS_FINAL :
00696                 PANA_BIND_FAILED;
00697    }
00698    return (br);
00699 }
00700 
00701 void PANA_Session::BindResultReset()
00702 {
00703    m_BindCount = 0;
00704    for (int i = 0; i < PANA_BIND_COUNT_MAX; i++) {
00705        m_BindResult[i] = PANA_BIND_INVALID;
00706    }
00707 }
00708 
00709 void PANA_Session::SendErrorMessage(ACE_UINT32 rcode, AAAAvpContainer *failedAvp)
00710 {
00711    /*
00712        PANA-Error message MAY be sent by either PaC or PAA when a badly
00713        formed PANA message is received or in case of other errors.  If the
00714        cause of this error message was a request message (e.g.,
00715        PANA-PAA-Discover or *-Request), then the request MAY be
00716        retransmitted immediately without waiting for its retransmission
00717        timer to go off. If the cause of the error was a response message,
00718        the receiver of the PANA-Error message SHOULD NOT resend the same
00719        response until it receives the next request.
00720 
00721        9.3.13 PANA-Error (PER)
00722 
00723           PANA-Error is sent either by the PaC or the PAA.
00724   
00725                 PANA-Error ::= < PANA-Header: 7 >
00726                                < Session-Id >
00727                                < Result-Code >
00728                                { Failed-AVP }
00729                             *  [ AVP ]
00730                            0*1 < MAC >
00731    */
00732    AAAAvpContainerManager cm;
00733    AAAAvpContainerEntryManager em;
00734    PANA_Message *msg;
00735 
00736    ACE_NEW_NORETURN(msg, PANA_Message);
00737    if (msg == NULL) {
00738       throw (PANA_Exception(PANA_Exception::NO_MEMORY, 
00739                            "Failed to allocate msg message"));
00740    }
00741 
00742    // Populate header
00743    PANA_MsgHeader::Flags flg = { 0, 0, 0, 0 };
00744    msg->flags(flg);
00745    msg->type(PANA_MTYPE_ERROR);
00746    msg->tseq(++ m_LastTransmittedTsec);
00747    msg->rseq(m_LastReceivedTsec);
00748 
00749    // Populate AVP's
00750    AAAAvpContainerEntry *e;
00751    AAAAvpContainer *c_sessionId = cm.acquire("Session-Id");
00752    AAAAvpContainer *c_resultCode = cm.acquire("Result-Code");
00753    AAAAvpContainer *c_failedAvp = cm.acquire("Failed-AVP");        
00754 
00755    // Add the AVP's to containers
00756    e = em.acquire(AAA_AVP_UTF8_STRING_TYPE);
00757    diameter_utf8string_t &sessionId = e->dataRef(Type2Type<diameter_utf8string_t>());
00758    c_sessionId->add(e);
00759 
00760    e = em.acquire(AAA_AVP_UINTEGER32_TYPE);
00761    diameter_unsigned32_t &resultCode = e->dataRef(Type2Type<diameter_unsigned32_t>());
00762    c_resultCode->add(e);
00763 
00764    e = em.acquire(AAA_AVP_GROUPED_TYPE);
00765    diameter_grouped_t &grpfailedAvp = e->dataRef(Type2Type<diameter_grouped_t>());
00766    c_failedAvp->add(e);
00767 
00768    // Add containers to listen
00769    msg->avpList().add(c_sessionId);
00770    msg->avpList().add(c_resultCode);
00771    msg->avpList().add(c_failedAvp);
00772 
00773    // Populate data
00774    sessionId.assign(m_SessionId.data(), m_SessionId.size());
00775    resultCode = rcode;
00776    grpfailedAvp.add(failedAvp);
00777 
00778    // Send message
00779    DestinationAddressFormatting(*msg);
00780    m_TxChannel.Send(*this, *msg);
00781 
00782    ACE_DEBUG((LM_INFO, "(%P|%t) SEND: Error-Message, tseq=%d, rseq=%d\n",
00783               msg->tseq(), msg->rseq()));
00784 }
00785 
00786 void PANA_Session::ReceiveErrorMessage(PANA_Message &msg)
00787 {
00788    ACE_DEBUG((LM_INFO, "(%P|%t) RECV: Error-Message, tseq=%d, rseq=%d\n",
00789               msg.tseq(), msg.rseq()));
00790 
00791    AAAAvpContainer* c_rcode = msg.avpList().search("Result-Code");
00792    if (c_rcode == NULL) {
00793        throw (PANA_Exception(PANA_Exception::INVALID_MESSAGE, 
00794                             "PANA client received error msg with no result code"));
00795    }
00796    diameter_unsigned32_t &rcode = (*c_rcode)[0]->dataRef(Type2Type<diameter_unsigned32_t>());
00797    m_Event.Error(rcode);
00798 }
00799 
00800 void PANA_Session::Reset()
00801 {
00802    PANA_SessionAttribute::Reset();
00803    m_InStatefulDiscovery = false;
00804    m_RtQueue.Clear();
00805 }
00806 

Generated on Fri Jun 25 19:18:30 2004 for PANA by doxygen 1.3.5