Navigation


Changeset 78:a58f0757c06a in freeDiameter


Ignore:
Timestamp:
Dec 1, 2009, 4:24:06 PM (14 years ago)
Author:
Sebastien Decugis <sdecugis@nict.go.jp>
Branch:
default
Phase:
public
Message:

Added code for DPR/DPA

Files:
9 edited

Legend:

Unmodified
Added
Removed
  • freeDiameter/fD.h

    r70 r78  
    9191struct dict_object * fd_dict_cmd_CER; /* Capabilities-Exchange-Request */
    9292struct dict_object * fd_dict_cmd_DWR; /* Device-Watchdog-Request */
     93struct dict_object * fd_dict_avp_DC;  /* Disconnect-Cause */
    9394struct dict_object * fd_dict_cmd_DPR; /* Disconnect-Peer-Request */
    9495
     
    257258int  fd_psm_start();
    258259int  fd_psm_begin(struct fd_peer * peer );
    259 int  fd_psm_terminate(struct fd_peer * peer );
     260int  fd_psm_terminate(struct fd_peer * peer, char * reason );
    260261void fd_psm_abord(struct fd_peer * peer );
    261262void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay);
     
    287288int fd_p_dw_reopen(struct fd_peer * peer);
    288289int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer);
    289 int fd_p_dp_initiate(struct fd_peer * peer);
     290int fd_p_dp_initiate(struct fd_peer * peer, char * reason);
    290291
    291292/* Active peers -- routing process should only ever take the read lock, the write lock is managed by PSMs */
  • freeDiameter/messages.c

    r66 r78  
    4545struct dict_object * fd_dict_cmd_CER = NULL; /* Capabilities-Exchange-Request */
    4646struct dict_object * fd_dict_cmd_DWR = NULL; /* Device-Watchdog-Request */
     47struct dict_object * fd_dict_avp_DC  = NULL; /* Disconnect-Cause */
    4748struct dict_object * fd_dict_cmd_DPR = NULL; /* Disconnect-Peer-Request */
    4849
     
    6162        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Error-Reporting-Host", &dict_avp_ERH , ENOENT)  );
    6263        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Failed-AVP",         &dict_avp_FAVP, ENOENT)  );
     64       
     65        CHECK_FCT(  fd_dict_search( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_NAME, "Disconnect-Cause",   &fd_dict_avp_DC , ENOENT)  );
    6366       
    6467        CHECK_FCT( fd_dict_search ( fd_g_config->cnf_dict, DICT_COMMAND, CMD_BY_NAME, "Capabilities-Exchange-Request", &fd_dict_cmd_CER, ENOENT ) );
  • freeDiameter/p_ce.c

    r66 r78  
    763763                                {
    764764                                        TRACE_DEBUG(INFO, "Validation callback rejected the peer %s after handshake", peer->p_hdr.info.pi_diamid);
    765                                         CHECK_FCT( fd_psm_terminate( peer ) );
     765                                        CHECK_FCT( fd_psm_terminate( peer, "DO_NOT_WANT_TO_TALK_TO_YOU" ) );
    766766                                        return 0;
    767767                                }  );
  • freeDiameter/p_cnx.c

    r70 r78  
    8888                if (ret) {
    8989                        fd_log_debug("Unable to resolve address for peer '%s' (%s), aborting\n", peer->p_hdr.info.pi_diamid, gai_strerror(ret));
    90                         fd_psm_terminate( peer );
     90                        fd_psm_terminate( peer, NULL );
    9191                        return 0;
    9292                }
     
    110110        if (FD_IS_LIST_EMPTY(&peer->p_hdr.info.pi_endpoints)) {
    111111                fd_log_debug("No address %savailable to connect to peer '%s', aborting\n", peer->p_hdr.info.config.pic_flags.pro3 ? "in the configured family " : "", peer->p_hdr.info.pi_diamid);
    112                 fd_psm_terminate( peer );
     112                fd_psm_terminate( peer, NULL );
    113113                return 0;
    114114        }
  • freeDiameter/p_dp.c

    r40 r78  
    4141int fd_p_dp_handle(struct msg ** msg, int req, struct fd_peer * peer)
    4242{
    43         TODO("Handle depending on DPR or DPA and peer state");
     43        int delay = 0;
     44        TRACE_ENTRY("%p %d %p", msg, req, peer);
    4445       
    45         return ENOTSUP;
     46        if (req) {
     47                /* We received a DPR, save the Disconnect-Cause and terminate the connection */
     48                struct avp * dc;
     49               
     50                CHECK_FCT_DO( fd_msg_search_avp ( *msg, fd_dict_avp_DC, &dc ), return );
     51                if (dc) {
     52                        /* Check the value is consistent with the saved one */
     53                        struct avp_hdr * hdr;
     54                        CHECK_FCT_DO(  fd_msg_avp_hdr( dc, &hdr ), return  );
     55                        if (hdr->avp_value == NULL) {
     56                                /* This is a sanity check */
     57                                TRACE_DEBUG(NONE, "BUG: Unset value in Disconnect-Cause in DPR");
     58                                fd_msg_dump_one(NONE, dc);
     59                                ASSERT(0); /* To check if this really happens, and understand why... */
     60                        }
     61
     62                        peer->p_hdr.info.runtime.pir_lastDC = hdr->avp_value->u32;
     63                }
     64                if (TRACE_BOOL(INFO)) {
     65                        if (dc) {
     66                                struct dict_object * dictobj = NULL;
     67                                struct dict_enumval_request er;
     68                                memset(&er, 0, sizeof(er));
     69                                CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
     70                                er.search.enum_value.u32 = peer->p_hdr.info.runtime.pir_lastDC;
     71                                CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, 0 )  );
     72                                if (dictobj) {
     73                                        CHECK_FCT( fd_dict_getval( dictobj, &er.search ) );
     74                                        fd_log_debug("Peer '%s' sent a DPR with cause: %s\n", peer->p_hdr.info.pi_diamid, er.search.enum_name);
     75                                } else {
     76                                        fd_log_debug("Peer '%s' sent a DPR with unknown cause: %u\n", peer->p_hdr.info.pi_diamid, peer->p_hdr.info.runtime.pir_lastDC);
     77                                }
     78                        } else {
     79                                fd_log_debug("Peer '%s' sent a DPR without Disconnect-Cause AVP\n", peer->p_hdr.info.pi_diamid);
     80                        }
     81                }
     82               
     83                /* Now reply with a DPA */
     84                CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, 0 ) );
     85                CHECK_FCT( fd_msg_rescode_set( *msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
     86                CHECK_FCT( fd_msg_add_origin ( *msg, 0 ) );
     87               
     88                /* Move to CLOSING state to failover outgoing messages (and avoid failing the DPA...) */
     89                CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) );
     90               
     91                /* Now send the DPA */
     92                CHECK_FCT( fd_out_send( msg, NULL, peer) );
     93               
     94        } else {
     95                /* We received a DPA */
     96                if (peer->p_hdr.info.runtime.pir_state != STATE_CLOSING) {
     97                        TRACE_DEBUG(INFO, "Ignore DPA received in state %s", STATE_STR(peer->p_hdr.info.runtime.pir_state));
     98                }
     99                       
     100        }
     101       
     102        if (*msg) {
     103                /* In theory, we should control the Result-Code AVP. But since we will not go back to OPEN state here, let's skip it */
     104                CHECK_FCT_DO( fd_msg_free( *msg ), /* continue */ );
     105                *msg = NULL;
     106        }
     107       
     108        /* The calling function handles cleaning the PSM and terminating the peer */
     109        return 0;
    46110}
    47111
    48112/* Start disconnection of a peer: send DPR */
    49 int fd_p_dp_initiate(struct fd_peer * peer)
     113int fd_p_dp_initiate(struct fd_peer * peer, char * reason)
    50114{
    51         TODO("Create the DPR message");
    52         TODO("Send it");
    53         TODO("Mark the peer as CLOSING");
    54         TODO("Reset the timer");
     115        struct msg * msg = NULL;
     116        struct dict_object * dictobj = NULL;
     117        struct avp * avp = NULL;
     118        struct dict_enumval_request er;
     119        union avp_value val;
    55120       
    56         return ENOTSUP;
     121        TRACE_ENTRY("%p %p", peer, reason);
     122       
     123        /* Create a new DWR instance */
     124        CHECK_FCT( fd_msg_new ( fd_dict_cmd_DPR, MSGFL_ALLOC_ETEID, &msg ) );
     125       
     126        /* Add the Origin information */
     127        CHECK_FCT( fd_msg_add_origin ( msg, 0 ) );
     128       
     129        /* Add the Disconnect-Cause */
     130        CHECK_FCT( fd_msg_avp_new ( fd_dict_avp_DC, 0, &avp ) );
     131       
     132        /* Search the value in the dictionary */
     133        memset(&er, 0, sizeof(er));
     134        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_TYPE, TYPE_OF_AVP, fd_dict_avp_DC, &er.type_obj, ENOENT )  );
     135        er.search.enum_name = reason ?: "REBOOTING";
     136        CHECK_FCT( fd_dict_search( fd_g_config->cnf_dict, DICT_ENUMVAL, ENUMVAL_BY_STRUCT, &er, &dictobj, ENOENT )  );
     137        CHECK_FCT( fd_dict_getval( dictobj, &er.search ) );
     138       
     139        /* Set the value in the AVP */
     140        val.u32 = er.search.enum_value.u32;
     141        CHECK_FCT( fd_msg_avp_setvalue( avp, &val ) );
     142        CHECK_FCT( fd_msg_avp_add( msg, MSG_BRW_LAST_CHILD, avp ) );
     143       
     144        /* Save the value also in the peer */
     145        peer->p_hdr.info.runtime.pir_lastDC = val.u32;
     146       
     147        /* Now send this message */
     148        CHECK_FCT( fd_out_send(&msg, NULL, peer) );
     149       
     150        /* Update the peer state and timer */
     151        CHECK_FCT( fd_psm_change_state(peer, STATE_CLOSING) );
     152        fd_psm_next_timeout(peer, 0, DPR_TIMEOUT);
     153       
     154        return 0;
    57155}
  • freeDiameter/p_expiry.c

    r37 r78  
    132132                /* Now, the first peer in the list is expired; signal it */
    133133                fd_list_unlink( &first->p_expiry );
    134                 CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, 0, NULL), goto error );
     134                CHECK_FCT_DO( fd_event_send(first->p_events, FDEVP_TERMINATE, 0, "DO_NOT_WANT_TO_TALK_TO_YOU"), goto error );
    135135               
    136136        } while (1);
  • freeDiameter/p_psm.c

    r76 r78  
    9494                CHECK_FCT_DO( (*peer->p_cb2)(&peer->p_hdr.info),
    9595                        {
    96                                 TRACE_DEBUG(FULL, "Validation failed, moving to state CLOSING");
    97                                 peer->p_hdr.info.runtime.pir_state = STATE_CLOSING;
    98                                 fd_psm_terminate(peer);
     96                                TRACE_DEBUG(FULL, "Validation failed, terminating the connection");
     97                                fd_psm_terminate(peer, "DO_NOT_WANT_TO_TALK_TO_YOU" );
    9998                        } );
    10099                peer->p_cb2 = NULL;
     
    161160                        break;
    162161                       
     162                        case FDEVP_TERMINATE:
     163                                /* Do not free the string since it is a constant */
     164                        break;
     165                       
    163166                        case FDEVP_CNX_INCOMING: {
    164167                                struct cnx_incoming * evd = ev->data;
     
    216219void fd_psm_next_timeout(struct fd_peer * peer, int add_random, int delay)
    217220{
     221        TRACE_DEBUG(FULL, "Peer timeout reset to %d seconds%s", delay, add_random ? " (+/- 2)" : "" );
     222       
    218223        /* Initialize the timer */
    219224        CHECK_POSIX_DO(  clock_gettime( CLOCK_REALTIME,  &peer->p_psm_timer ), ASSERT(0) );
     
    235240       
    236241        peer->p_psm_timer.tv_sec += delay;
    237        
    238         TRACE_DEBUG(FULL, "Peer timeout reset to %d seconds%s", delay, add_random ? " (+/- 2)" : "" );
    239242       
    240243#ifdef SLOW_PSM
     
    348351                        case STATE_REOPEN:
    349352                                /* We cannot just close the conenction, we have to send a DPR first */
    350                                 CHECK_FCT_DO( fd_p_dp_initiate(peer), goto psm_end );
     353                                CHECK_FCT_DO( fd_p_dp_initiate(peer, ev_data), goto psm_end );
    351354                                goto psm_loop;
    352355                       
     
    471474                        case CC_DISCONNECT_PEER:
    472475                                CHECK_FCT_DO( fd_p_dp_handle(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_end );
     476                                if (peer->p_hdr.info.runtime.pir_state == STATE_CLOSING)
     477                                        goto psm_end;
    473478                                break;
    474479                       
     
    712717
    713718/* End the PSM (clean ending) */
    714 int fd_psm_terminate(struct fd_peer * peer )
     719int fd_psm_terminate(struct fd_peer * peer, char * reason )
    715720{
    716721        TRACE_ENTRY("%p", peer);
     
    718723       
    719724        if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) {
    720                 CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, NULL) );
     725                CHECK_FCT( fd_event_send(peer->p_events, FDEVP_TERMINATE, 0, reason) );
    721726        } else {
    722727                TRACE_DEBUG(FULL, "Peer '%s' was already terminated", peer->p_hdr.info.pi_diamid);
  • freeDiameter/peers.c

    r48 r78  
    255255               
    256256                if (peer->p_hdr.info.runtime.pir_state != STATE_ZOMBIE) {
    257                         CHECK_FCT_DO( fd_psm_terminate(peer), /* continue */ );
     257                        CHECK_FCT_DO( fd_psm_terminate(peer, "REBOOTING"), /* continue */ );
    258258                } else {
    259259                        li = li->prev; /* to avoid breaking the loop */
  • include/freeDiameter/freeDiameter.h

    r43 r78  
    338338                int             pir_isi;        /* Inband-Security-Id advertised (PI_SEC_* bits) */
    339339               
     340                uint32_t        pir_lastDC;     /* The last Disconnect-Cause value received */
     341               
    340342                int             pir_proto;      /* The L4 protocol currently used with the peer (IPPROTO_TCP or IPPROTO_SCTP) */
    341343                const gnutls_datum_t    *pir_cert_list;         /* The (valid) credentials that the peer has presented, or NULL if TLS is not used */
Note: See TracChangeset for help on using the changeset viewer.