void Connector::Transmit (Path* path) {
    if (path == nil) {
        Path newPath;
        Retransmit(&newPath);

    } else {
        Retransmit(path);
    }
}
void Connector::Retransmit (Path* path) {
    if (path->Visited(this)) {
        return;
    }
    boolean forking = _cnxns->First() != _cnxns->Last(); // fork if > 1 cnxn
    path->Visit(this);
    
    for (UList* u = _cnxns->First(); u != _cnxns->End(); u = u->Next()) {
        Connector* peer = Conn(u);

        if (!path->Visited(peer)) {
            if (forking) {
                Path fork(path);
                Retransmit(peer, &fork);
            } else {
                Retransmit(peer, path);
            }
        }
    }
}
Exemple #3
0
static bytebuff_t *
paa_process(pana_session_t * pacs, bytebuff_t * datain) {
    paa_ctx_t * ctx =  pacs->ctx;
    
    bytebuff_t * respData;
    pana_packet_t * pkt_in = NULL;
    pana_avp_node_t * tmpavplist = NULL;
    pana_avp_t * tmp_avp;
    
    if (datain != NULL) {
        dbg_hexdump(PKT_RECVD, "Packet-contents:", bytebuff_data(datain), datain->used);
        pkt_in = parse_pana_packet(datain);
        if (pkt_in == NULL) {
            dbg_printf(MSG_ERROR,"Packet is invalid");
            clear_events();
            return NULL;
        }
    }
#define RTX_COUNTER (ctx->rtx_timer.count)
#define RTX_MAX_NUM (cfg->rtx_max_count)
    
//   ----------
//   State: ANY
//   ----------
//   - - - - - - - - - - - - - (Re-transmissions)- - - - - - - - - -
//   RTX_TIMEOUT &&           Retransmit();              (no change)
//   RTX_COUNTER<
//   RTX_MAX_NUM
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if (RTX_TIMEOUT && RTX_COUNTER < RTX_MAX_NUM) {
        clear_events();
        Retransmit(pacs);
    }
//   - - - - - - - (Reach maximum number of transmissions)- - - - - -
//   (RTX_TIMEOUT &&          Disconnect();              CLOSED
//    RTX_COUNTER>=
//    RTX_MAX_NUM) ||
//   SESS_TIMEOUT
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if ((RTX_TIMEOUT && RTX_COUNTER >= RTX_MAX_NUM) || 
        SESS_TIMEOUT) {
        clear_events();
        Disconnect(pacs);
        pacs->cstate = PAA_STATE_CLOSED;
    }
    
    
    if (PKT_RECVD) {
//   -------------------------
//   State: ANY except INITIAL
//   -------------------------
//   - - - - - - - - - - (liveness test initiated by peer)- - - - - -
//   Rx:PNR[P]                Tx:PNA[P]();               (no change)
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       if (pacs->cstate != PAA_STATE_INITIAL) {
           if (RX_PNR_P(pkt_in)) {
               /* reset the event status */
               clear_events();
               TX_PNA_P(respData, NULL);
           }
       }

//   -------------------------
//   State: ANY except WAIT_PNA_PING
//   -------------------------
//   - - - - - - - - - - - - (liveness test response) - - - - - - - -
//   Rx:PNA[P]                None();                    (no change)
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
       if (pacs->cstate != PAA_STATE_WAIT_PNA_PING){
           if (RX_PNA_P(pkt_in)) {
               clear_events();
               /* just discard the packet because it's not meant occur in this phase */
           }
       }
   }    

//   -------------------------
//   State: CLOSED
//   -------------------------
//   - - - - - - - -(Catch all event on closed state) - - - - - - - -
//   ANY                      None();                    CLOSED
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    if (pacs->cstate == PAA_STATE_CLOSED){
        clear_events();
        /* just discard the packet because it's not meant occur in this phase */
    }

    
    
    while(ctx->event_occured) {
        switch (pacs->cstate) {
//   ------------------------------
//   State: INITIAL (Initial State)
//   ------------------------------
        case  PAA_STATE_INITIAL:
//   ------------------------+--------------------------+------------
//    - - - - - - - - (PCI and PAA initiated PANA) - - - - - - - - -
//   (Rx:PCI[] ||             if (OPTIMIZED_INIT ==      INITIAL
//    PAC_FOUND)                  Set) {
//                              EAP_Restart();
//                              SessionTimerReStart
//                               (FAILED_SESS_TIMEOUT);
//                            }
//                            else {
//                              if (generate_pana_sa())
//                                   Tx:PAR[S]("PRF-Algorithm",
//                                      "Integrity-Algorithm");
//                              else
//                                   Tx:PAR[S]();
//                            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PCI(pkt_in)) {
                clear_events();
                if (OPTIMIZED_INIT) {
                    EAP_Restart(pacs);
                    SessionTimerReStart(pacs, FAILED_SESS_TIMEOUT);
                }
                else {
                    if (generate_pana_sa()) {
                        tmpavplist = AVPLIST(PAVP_PRF_ALG,"Integrity-Algorithm");
                        TX_PAR_S(respData, tmpavplist);
                    }
                    else {
                        TX_PAR_S(respData, NULL);
                    }
                }
                
                pacs->cstate = PAA_STATE_INITIAL;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//   EAP_REQUEST              if (generate_pana_sa())    INITIAL
//                                Tx:PAR[S]("EAP-Payload",
//                                   "PRF-Algorithm",
//                                   "Integrity-Algorithm");
//                            else
//                                Tx:PAR[S]("EAP-Payload");
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_REQUEST) {
                clear_events();

                if (generate_pana_sa()) {
                    tmpavplist = AVPLIST(PAVP_EAP_PAYLOAD,PAVP_PRF_ALG,"Integrity-Algorithm");
                    TX_PAR_S(respData, tmpavplist);
                }
                else{
                    tmpavplist = AVPLIST(PAVP_EAP_PAYLOAD);
                    TX_PAR_S(respData, tmpavplist);
                }
                RtxTimerStart(pacs, respData);

                pacs->cstate = PAA_STATE_INITIAL;
            }
//   - - - - - - - - - - - - - - (PAN Handling)  - - - - - - - - - -
//   Rx:PAN[S] &&             if (PAN.exist_avp          WAIT_EAP_MSG
//   ((OPTIMIZED_INIT ==         ("EAP-Payload"))
//     Unset) ||                TxEAP();
//   PAN.exist_avp            else {
//     ("EAP-Payload"))         EAP_Restart();
//                              SessionTimerReStart
//                               (FAILED_SESS_TIMEOUT);
//                            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PAN_S(pkt_in) && 
                    ((!OPTIMIZED_INIT) || exists_avp(pkt_in, PAVP_EAP_PAYLOAD))) {
                clear_events();
                
                pacs->seq_rx = pkt_in->pp_seq_number;
                 
                tmp_avp = get_vend_avp_by_code(pkt_in->pp_avp_list, PAVP_PEER_MACADDR,
                        PANA_VENDOR_UPB, AVP_GET_FIRST);
                if (tmp_avp) {
                    memcpy(ctx->peer_macaddr, tmp_avp->avp_value, MACADDR_LEN);
                }
                
                if (exists_avp(pkt_in, PAVP_EAP_PAYLOAD)) {
                    TxEAP(pacs, pkt_in);
                }
                else {
                    EAP_Restart(pacs);
                    SessionTimerReStart(pacs, FAILED_SESS_TIMEOUT);

                }
                
                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//   Rx:PAN[S] &&             None();                    WAIT_PAN_OR_PAR
//   (OPTIMIZED_INIT ==
//     Set) &&
//   ! PAN.exist_avp
//    ("EAP-Payload")
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PAN_S(pkt_in) &&(OPTIMIZED_INIT) && 
                    !exists_avp(pkt_in, PAVP_EAP_PAYLOAD)) {
                clear_events();

                pacs->seq_rx = pkt_in->pp_seq_number;
                // None();

                pacs->cstate = PAA_STATE_WAIT_PAN_OR_PAR;
            } break;
//   -------------------
//   State: WAIT_EAP_MSG
//   -------------------
        case PAA_STATE_WAIT_EAP_MSG:
//   - - - - - - - - - - - -(Receiving EAP-Request)- - - - - - - - -
//   EAP_REQUEST              if (NONCE_SENT==Unset) {   WAIT_PAN_OR_PAR
//                              Tx:PAR[]("Nonce",
//                                       "EAP-Payload");
//                              NONCE_SENT=Set;
//                            }
//                            else
//                              Tx:PAR[]("EAP-Payload");
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (EAP_REQUEST) {
                clear_events();

                if (!NONCE_SENT) {
                    tmpavplist = AVPLIST(PAVP_NONCE, PAVP_EAP_PAYLOAD);
                    TX_PAR(respData, tmpavplist);
                    NONCE_SENT_Set();
                }
                else {
                              tmpavplist = AVPLIST(PAVP_EAP_PAYLOAD);
			TX_PAR(respData, tmpavplist);
             }
                            RtxTimerStart(pacs, respData);
                
                pacs->cstate = PAA_STATE_WAIT_PAN_OR_PAR;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//   - - - - - - - - - - -(Receiving EAP-Success/Failure) - - - - -
//   EAP_FAILURE              PAR.RESULT_CODE =          WAIT_FAIL_PAN
//                              PANA_AUTHENTICATION_
//                                  REJECTED;
//                            Tx:PAR[C]("EAP-Payload");
//                            RtxTimerStart();
//                            SessionTimerStop();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_FAILURE) {
                clear_events();


                tmpavplist = AVPLIST(PAVP_RESULT_AUTHENTICATION_REJECTED,
                        PAVP_EAP_PAYLOAD);
                TX_PAR_C(respData, tmpavplist);
                RtxTimerStart(pacs, respData);
                SessionTimerStop(pacs);
                
                pacs->cstate = PAA_STATE_WAIT_FAIL_PAN;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//   EAP_SUCCESS &&           PAR.RESULT_CODE =          WAIT_SUCC_PAN
//   Authorize()                PANA_SUCCESS;
//                            if (new_key_available())
//                              Tx:PAR[C]("EAP-Payload",
//                                   "Key-Id");
//                            else
//                              Tx:PAR[C]("EAP-Payload");
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_SUCCESS  && Authorize(pacs)) {
                clear_events();
                

                if (new_key_available()) {
                    tmpavplist = AVPLIST(PAVP_RESULT_SUCCESS,
                            PAVP_EAP_PAYLOAD,"Key-Id");
                    TX_PAR_C(respData, tmpavplist);
                } else{
                    tmpavplist = AVPLIST(PAVP_RESULT_SUCCESS, PAVP_EAP_PAYLOAD);
                    TX_PAR_C(respData, tmpavplist);}
                RtxTimerStart(pacs, respData);

                pacs->cstate = PAA_STATE_WAIT_SUCC_PAN;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//   EAP_SUCCESS &&           PAR.RESULT_CODE =          WAIT_FAIL_PAN
//   !Authorize()               PANA_AUTHORIZATION_
//                                REJECTED;
//                            if (new_key_available())
//                              Tx:PAR[C]("EAP-Payload",
//                                   "Key-Id");
//                            else
//                              Tx:PAR[C]("EAP-Payload");
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_SUCCESS && !Authorize(pacs)) {
                clear_events();

                if (new_key_available()) {
                    tmpavplist = AVPLIST(PAVP_RESULT_AUTHORIZATION_REJECTED ,PAVP_EAP_PAYLOAD,"Key-Id");
                    TX_PAR_C(respData, tmpavplist);
                }else{
                    tmpavplist = AVPLIST(PAVP_RESULT_AUTHORIZATION_REJECTED, PAVP_EAP_PAYLOAD);
                    TX_PAR_C(respData, tmpavplist);
                }
                RtxTimerStart(pacs, respData);
                
                pacs->cstate = PAA_STATE_WAIT_FAIL_PAN;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
//    - - - - - (Receiving EAP-Timeout or invalid message) - - - - -
//   EAP_TIMEOUT ||           SessionTimerStop();        CLOSED
//   EAP_DISCARD              Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_TIMEOUT || EAP_DISCARD) {
                clear_events();

                SessionTimerStop(pacs);
                Disconnect(pacs);
                
                pacs->cstate = PAA_STATE_CLOSED;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   --------------------
//   State: WAIT_SUCC_PAN
//   --------------------
        case PAA_STATE_WAIT_SUCC_PAN:
//   - - - - - - - - - - - - - (PAN Processing)- - - - - - - - - - -
//   Rx:PAN[C]                RtxTimerStop();            OPEN
//                            SessionTimerReStart
//                              (LIFETIME_SESS_TIMEOUT);
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PAN_C(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                SessionTimerReStart(pacs, LIFETIME_SESS_TIMEOUT);

                pacs->cstate = PAA_STATE_OPEN;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   --------------------
//   State: WAIT_FAIL_PAN
//   --------------------
        case PAA_STATE_WAIT_FAIL_PAN:
//   - - - - - - - - - - - - - - (PAN Processing)- - - - - - - - - -
//   Rx:PAN[C]                RtxTimerStop();            CLOSED
//                            Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PAN_C(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                Disconnect(pacs);
                
                pacs->cstate = PAA_STATE_CLOSED;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   -----------
//   State: OPEN
//   -----------
        case PAA_STATE_OPEN:
//   - - - - - - - - (re-authentication initiated by PaC) - - - - - -
//   Rx:PNR[A]                NONCE_SENT=Unset;          WAIT_EAP_MSG
//                            EAP_Restart();
//                            Tx:PNA[A]();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PNR_A(pkt_in)) {
                clear_events();

                NONCE_SENT_Unset();
                EAP_Restart(pacs);
                TX_PNA_A(respData, NULL);

                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - - - - - - - (re-authentication initiated by PAA)- - - - - -
//   REAUTH ||                NONCE_SENT=Unset;          WAIT_EAP_MSG
//   REAUTH_TIMEOUT           EAP_Restart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            /* will require the PaC to reauth */
            else if (REAUTH ) {
                clear_events();

                NONCE_SENT_Unset();
                EAP_Restart(pacs);
                
                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - (liveness test based on PNR-PNA exchange initiated by PAA)-
//   PANA_PING                Tx:PNR[P]();               WAIT_PNA_PING
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (PANA_PING) {
                clear_events();

                TX_PNR_P(respData, NULL);
                RtxTimerStart(pacs, respData);
                
                pacs->cstate = PAA_STATE_WAIT_PNA_PING;
            }
//   - - - - - - - - (Session termination initated from PAA) - - - -
//   TERMINATE                Tx:PTR[]();                SESS_TERM
//                            SessionTimerStop();
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (TERMINATE) {
                clear_events();

                TX_PTR(respData, NULL);
                SessionTimerStop(pacs);
                RtxTimerStart(pacs, respData);
                
                pacs->cstate = PAA_STATE_SESS_TERM;
            }
//   - - - - - - - - (Session termination initated from PaC) - - - -
//   Rx:PTR[]                 Tx:PTA[]();                CLOSED
//                            SessionTimerStop();
//                            Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PTR(pkt_in)) {
                clear_events();

                TX_PTA(respData, NULL); 
                SessionTimerStop(pacs);
                Disconnect(pacs);
       
                pacs->cstate = PAA_STATE_CLOSED;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   --------------------
//   State: WAIT_PNA_PING
//   --------------------
        case PAA_STATE_WAIT_PNA_PING:
//   - - - - - - - - - - - - - -(PNA processing) - - - - - - - - - -
//   Rx:PNA[P]                RtxTimerStop();            OPEN
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PNA_P(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                
                pacs->cstate = PAA_STATE_OPEN;
            }
//   - - - - - - - - (re-authentication initiated by PaC) - - - - - -
//   Rx:PNR[A]                RtxTimerStop();            WAIT_EAP_MSG
//                            NONCE_SENT=Unset;
//                            EAP_Restart();
//                            Tx:PNA[A]();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PNR_A(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                NONCE_SENT_Unset();
                EAP_Restart(pacs);
                TX_PNA_A(respData, NULL);
                
                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - - - - - - - (Session termination initated from PaC) - - - -
//   Rx:PTR[]                 RtxTimerStop();            CLOSED
//                            Tx:PTA[]();
//                            SessionTimerStop();
//                            Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if ( RX_PTR(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                TX_PTA(respData, NULL);
                SessionTimerStop(pacs);
                Disconnect(pacs);
                
                pacs->cstate = PAA_STATE_CLOSED;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   ----------------------
//   State: WAIT_PAN_OR_PAR
//   ----------------------
        case PAA_STATE_WAIT_PAN_OR_PAR:
//   - - - - - - - - - - - - - (PAR Processing)- - - - - - - - - - -
//   Rx:PAR[]                 TxEAP();                   WAIT_EAP_MSG
//                            RtxTimerStop();
//                            Tx:PAN[]();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PAR(pkt_in)) {
                clear_events();

                TxEAP(pacs, pkt_in); 
                RtxTimerStop(pacs);
                TX_PAN(respData, NULL);
                
                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - - - - - (Pass EAP Response to the EAP authenticator)- - - -
//   Rx:PAN[] &&              TxEAP();                   WAIT_EAP_MSG
//   PAN.exist_avp            RtxTimerStop();
//   ("EAP-Payload")
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PAN(pkt_in) && exists_avp(pkt_in, PAVP_EAP_PAYLOAD)) {
                clear_events();

                TxEAP(pacs, pkt_in);
                RtxTimerStop(pacs);      

                pacs->cstate = PAA_STATE_WAIT_EAP_MSG;
            }
//   - - - - - - - - - - (PAN without an EAP response) - - - - - - -
//   Rx:PAN[] &&              RtxTimerStop();            WAIT_PAN_OR_PAR
//   !PAN.exist_avp
//   ("EAP-Payload")
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (RX_PAN(pkt_in) && !exists_avp(pkt_in, PAVP_EAP_PAYLOAD)) {
                clear_events();

                RtxTimerStop(pacs);
                
                pacs->cstate = PAA_STATE_WAIT_PAN_OR_PAR;
            }
//   - - - - - - - - - - - -(EAP retransmission) - - - - - - - - - -
//   EAP_REQUEST              RtxTimerStop();            WAIT_PAN_OR_PAR
//                            Tx:PAR[]("EAP-Payload");
//                            RtxTimerStart();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_REQUEST) {
                clear_events();

                RtxTimerStop(pacs);
                tmpavplist = AVPLIST(PAVP_EAP_PAYLOAD);
                TX_PAR(respData, tmpavplist);  
                RtxTimerStart(pacs, respData);
 
                pacs->cstate = PAA_STATE_WAIT_PAN_OR_PAR;
            }
//   - - - - - - - (EAP authentication timeout or failure)- - - - -
//   EAP_FAILURE ||           RtxTimerStop();            CLOSED
//   EAP_TIMEOUT ||           SessionTimerStop();
//   EAP_DISCARD              Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            else if (EAP_FAILURE || EAP_TIMEOUT ||EAP_DISCARD ) {
                clear_events();

                RtxTimerStop(pacs); 
                SessionTimerStop(pacs);
                Disconnect(pacs);
  
                pacs->cstate = PAA_STATE_CLOSED;
            } break;
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

//   ----------------
//   State: SESS_TERM
//   ----------------
        case PAA_STATE_SESS_TERM:
//   - - - - - - - - - - - - - -(PTA processing) - - - - - - - - - -
//   Rx:PTA[]                 RtxTimerStop();            CLOSED
//                            Disconnect();
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
            if (RX_PTA(pkt_in)) {
                clear_events();

                RtxTimerStop(pacs);
                Disconnect(pacs);
                
                pacs->cstate = PAA_STATE_CLOSED;
            }
//   - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        
        
            /* End switch */
        }
    
    }

    
    if (respData == NULL) {
        return NULL;
    }
    
    dbgi_asciihexdump(respData,"replycontents:",bytebuff_data(respData), respData->used);
    return respData;
    
}