Navigation


Changeset 1103:d8591b1c56cd in freeDiameter


Ignore:
Timestamp:
May 10, 2013, 7:48:57 PM (11 years ago)
Author:
Sebastien Decugis <sdecugis@freediameter.net>
Branch:
default
Phase:
public
Message:

Implemented a few hooks

Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • extensions/CMakeLists.txt

    r1040 r1103  
    8686
    8787FD_EXTENSION_SUBDIR(dbg_monitor "Outputs periodical status information"              OFF)
     88FD_EXTENSION_SUBDIR(dbg_msg_timings "Show some timing information for messages"      OFF)
    8889FD_EXTENSION_SUBDIR(dbg_rt      "Routing extension for debugging the routing module" OFF)
    8990FD_EXTENSION_SUBDIR(test_app    "Testing application to send dummy message to another peer, like a Diameter 'ping'" OFF)
  • include/freeDiameter/libfdcore.h

    r1102 r1103  
    553553
    554554
    555 /* Parse a message against our dictionary, and in case of error log and eventually build the error reply (on return and EBADMSG, *msg == NULL or *msg is the error message ready to send) */
    556 int fd_msg_parse_or_error( struct msg ** msg );
     555/* Parse a message against our dictionary,
     556        return 0 in case of success.
     557        log parsing error & return error code in case of failure in parsing.
     558        In addition, if the error code is EBADMSG (the message does not follow our dictionary)
     559                if *msg was a request, *msg is NULL and *error contains the error message ready to send back on return
     560                if *msg was an answer, *msg is untouched and *error==*msg if *msg was an error message, *error is null otherwise */
     561int fd_msg_parse_or_error( struct msg ** msg, struct msg **error );
    557562
    558563
     
    926931                 - {peer} is set if the message is received from a peer's connection, and NULL if the message is from a new client
    927932                   connected and not yet identified
    928                  - {other} is NULL.
     933                 - {other} is NULL, or a char * identifying the connection when {peer} is null.
    929934                 - {permsgdata} points to either a new empty structure allocated for this message or the one passed to HOOK_DATA_RECEIVED if used.
    930935                 */
     
    959964                 */
    960965       
     966        HOOK_MESSAGE_PARSING_ERROR,
     967                /* Hook called when a message being processed cannot be parsed successfully.
     968                 - {msg} points to the message if buffer was parsed successfully, or NULL otherwise. You should not call fd_msg_parse_dict on this in any case.
     969                 - {peer} is NULL or the peer that received the message. If NULL and the message is not NULL, you can still retrieve the source from the message itself.
     970                 - {other} is a char * pointer to the error message (human-readable) if {msg} is not NULL, a pointer to struct fd_cnx_rcvdata containing the received buffer otherwise.
     971                 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered).
     972                 */
     973       
    961974        HOOK_MESSAGE_ROUTING_ERROR,
    962                 /* Hook called when a message being processed by the routing thread meets an error such as:
    963                      -- parsing error
    964                      -- no remaining available peer for sending, based on routing callbacks decisions (maybe after retries).
     975                /* Hook called when a message being processed by the routing thread meets an error such as no remaining available peer for sending, based on routing callbacks decisions (maybe after retries).
    965976                 - {msg} points to the message. Again, the objects may not have been dictionary resolved. If you
    966977                   try to call fd_msg_parse_dict, it might slow down the operation of a relay agent, although this hook is not on the normal execution path.
     
    9941005                   It is probably a good idea to log this for analysis / backup.
    9951006                 - {msg} points to the message, which will be freed as soon as the hook returns.
    996                  - {peer} is NULL.
     1007                 - {peer} may be NULL or a peer related to the event.
    9971008                 - {other} is a char * pointer to the error message (human-readable).
    9981009                 - {permsgdata} points to existing structure associated with this message (or new structure if no previous hook was registered).
     
    10001011       
    10011012        HOOK_PEER_CONNECT_FAILED,
    1002                 /* Hook called when a connection attempt to a remote peer has failed.
    1003                  - {msg} may be NULL (lower layer error, e.g. connection timeout) or points to the CEA message sent or received (with an error code).
     1013                /* Hook called when a connection attempt to/from a remote peer has failed. This hook is also called when the peer was in OPEN state and the connection is broken.
     1014                 - {msg} may be NULL (lower layer error, e.g. connection timeout) or points to a message showing the error (either invalid incoming message, or the CEA message sent or received with an error code).
    10041015                 - {peer} may be NULL for incoming requests from unknown peers being rejected, otherwise it points to the peer structure associated with the attempt.
    10051016                 - {other} is a char * pointer to the error message (human-readable).
     
    10081019       
    10091020        HOOK_PEER_CONNECT_SUCCESS,
    1010                 /* Hook called when a connection attempt to a remote peer has succeeded (the peer moves to OPEN state).
    1011                  - {msg} points to the CEA message sent or received (with an success code) -- in case it is sent, you can always get access to the matching CER.
     1021                /* Hook called when a connection attempt to/from a remote peer has succeeded (the peer moves to OPEN_HANDSHAKE or OPEN state).
     1022                    In case of deprecated TLS handshake after the CER/CEA exchange, this hook can still be followed by HOOK_PEER_CONNECT_FAILED if TLS handshake fails.
     1023                 - {msg} points to the CEA message sent or received (with a success code) -- in case it is sent, you can always get access to the matching CER.
    10121024                 - {peer} points to the peer structure.
    10131025                 - {other} is NULL.
     
    10691081 *
    10701082 * PARAMETERS:
    1071  *  type_mask     : A bitmask of fd_hook_type bits for which this cb is registered, e.g. ((1 << HOOK_MESSAGE_RECEIVED) || (1 << HOOK_MESSAGE_SENT))
     1083 *  type_mask     : A bitmask of fd_hook_type bits for which this cb is registered, e.g. ((1 << HOOK_MESSAGE_RECEIVED) | (1 << HOOK_MESSAGE_SENT))
    10721084 *  fd_hook_cb    : The callback function to register (see prototype above).
    10731085 *  regdata       : Pointer to pass to the callback when it is called. The data is opaque to the daemon.
     
    10931105/* Remove a hook registration */
    10941106int fd_hook_unregister( struct fd_hook_hdl * handler );
     1107
     1108
     1109/* Use the following function to retrieve any pmd structure associated with a request matching the current answer. Returns NULL in case of error / no such structure */
     1110struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer);
    10951111
    10961112
  • include/freeDiameter/libfdproto.h

    r1102 r1103  
    146146 */
    147147void fd_log ( int, const char *, ... ) _ATTRIBUTE_PRINTFLIKE_(2,3);
     148#ifndef SWIG
    148149void fd_log_va( int, const char *, va_list args );
     150#endif /* SWIG */
    149151
    150152/* these are internal objects of the debug facility,
     
    609611DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node, sSA * sa, int flags);
    610612DECLARE_FD_DUMP_PROTOTYPE(fd_sa_dump_node_serv, sSA * sa, int flags);
     613#define sSA_DUMP_STRLEN (INET6_ADDRSTRLEN + 1 + 32 + 2)
     614void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa);
    611615
    612616
  • libfdcore/cnxctx.c

    r1102 r1103  
    228228        CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL );
    229229       
    230         if (TRACE_BOOL(INFO)) {
    231                 char buf[1024];
    232                 sSA_DUMP_NODE( buf, sizeof(buf), &ss, NI_NUMERICHOST );
    233                 fd_log_debug("%s : accepted new client [%s].", fd_cnx_getid(serv), buf);
    234         }
    235        
    236230        CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } );
    237231        cli->cc_socket = cli_sock;
     
    264258                        snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc));
    265259        }
     260       
     261        LOG_D("Incoming connection: '%s' <- '%s'   {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id);
    266262
    267263#ifndef DISABLE_SCTP
     
    275271                        cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in;
    276272               
    277                 TRACE_DEBUG(FULL,"%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out);
     273                LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out);
    278274        }
    279275#endif /* DISABLE_SCTP */
     
    287283        int sock = 0;
    288284        struct cnxctx * cnx = NULL;
     285        char sa_buf[sSA_DUMP_STRLEN];
    289286       
    290287        TRACE_ENTRY("%p %d", sa, addrlen);
    291288        CHECK_PARAMS_DO( sa && addrlen, return NULL );
     289       
     290        fd_sa_sdump_numeric(sa_buf, sa);
    292291       
    293292        /* Create the socket and connect, which can take some time and/or fail */
     
    295294                int ret = fd_tcp_client( &sock, sa, addrlen );
    296295                if (ret != 0) {
    297                         int lvl;
    298                         switch (ret) {
    299                                 case ECONNREFUSED:
    300 
    301                                         /* "Normal" errors */
    302                                         lvl = FULL;
    303                                         break;
    304                                 default:
    305                                         lvl = INFO;
    306                         }
    307                         /* Some errors are expected, we log at different level */
    308                         TRACE_DEBUG( lvl, "fd_tcp_client returned an error: %s", strerror(ret));
     296                        LOG_A("TCP connection to %s failed: %s", sa_buf, strerror(ret));
    309297                        return NULL;
    310298                }
    311         }
    312        
    313         if (TRACE_BOOL(INFO)) {
    314                 char buf[1024];
    315                 sSA_DUMP_NODE_SERV( buf, sizeof(buf), sa, NI_NUMERICSERV);
    316                 fd_log_debug("Connection established to server '%s' (TCP:%d).", buf, sock);
    317299        }
    318300       
     
    329311        /* Generate the names for the object */
    330312        {
    331                 char addrbuf[INET6_ADDRSTRLEN];
    332                 char portbuf[10];
    333313                int  rc;
    334314               
    335                 /* Numeric values for debug... */
    336                 rc = getnameinfo(sa, addrlen, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
    337                 if (rc) {
    338                         snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
    339                         portbuf[0] = '\0';
    340                 }
    341                
    342                 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP to [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
     315                snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP,#%d->%s", cnx->cc_socket, sa_buf);
    343316               
    344317                /* ...Name for log messages */
     
    347320                        snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
    348321        }
     322       
     323        LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock);
    349324       
    350325        return cnx;
     
    362337        int sock = 0;
    363338        struct cnxctx * cnx = NULL;
     339        char sa_buf[sSA_DUMP_STRLEN];
    364340        sSS primary;
    365341       
    366342        TRACE_ENTRY("%p", list);
    367343        CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL );
     344       
     345        fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa);
    368346       
    369347        {
    370348                int ret = fd_sctp_client( &sock, no_ip6, port, list );
    371349                if (ret != 0) {
    372                         int lvl;
    373                         switch (ret) {
    374                                 case ECONNREFUSED:
    375 
    376                                         /* "Normal" errors */
    377                                         lvl = FULL;
    378                                         break;
    379                                 default:
    380                                         lvl = INFO;
    381                         }
    382                         /* Some errors are expected, we log at different level */
    383                         TRACE_DEBUG( lvl, "fd_sctp_client returned an error: %s", strerror(ret));
     350                        LOG_A("SCTP connection to [%s,...] failed: %s", sa_buf, strerror(ret));
    384351                        return NULL;
    385352                }
     
    403370                cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in;
    404371       
    405         if (TRACE_BOOL(INFO)) {
    406                 char buf[1024];
    407                 sSA_DUMP_NODE_SERV( buf, sizeof(buf), &primary, NI_NUMERICSERV);
    408                 fd_log_debug("Connection established to server '%s' (SCTP:%d, %d/%d streams).", buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
    409         }
     372        fd_sa_sdump_numeric(sa_buf, (sSA *)&primary);
    410373       
    411374        /* Generate the names for the object */
    412375        {
    413                 char addrbuf[INET6_ADDRSTRLEN];
    414                 char portbuf[10];
    415376                int  rc;
    416377               
    417                 /* Numeric values for debug... */
    418                 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV);
    419                 if (rc) {
    420                         snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc));
    421                         portbuf[0] = '\0';
    422                 }
    423                
    424                 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP to [%s]:%s (%d)", addrbuf, portbuf, cnx->cc_socket);
     378                snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP,#%d->%s", cnx->cc_socket, sa_buf);
    425379               
    426380                /* ...Name for log messages */
     
    429383                        snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc));
    430384        }
     385       
     386        LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out);
    431387       
    432388        return cnx;
     
    678634size_t fd_msg_pmdl_sizewithoverhead(size_t datalen)
    679635{
    680         return PMDL_PADDED(datalen);
     636        return PMDL_PADDED(datalen) + sizeof(struct fd_msg_pmdl);
    681637}
    682638
     
    698654        uint8_t * ret = NULL;
    699655       
    700         CHECK_MALLOC_DO(  ret = malloc( PMDL_PADDED(expected_len) ), return NULL );
     656        CHECK_MALLOC_DO(  ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
    701657        CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
    702658        return ret;
     
    707663        uint8_t * ret = NULL;
    708664       
    709         CHECK_MALLOC_DO(  ret = realloc( buffer, PMDL_PADDED(expected_len) ), return NULL );
     665        CHECK_MALLOC_DO(  ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL );
    710666        CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} );
    711667        return ret;
     
    762718                   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
    763719                        /* The message is suspect */
    764                         LOG_E( "Received suspect header [ver: %d, size: %zd], assuming disconnection", (int)header[0], rcv_data.length);
     720                        LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assuming disconnection", (int)header[0], rcv_data.length, conn->cc_remid);
    765721                        fd_cnx_markerror(conn);
    766722                        goto out; /* Stop the thread, the recipient of the event will cleanup */
     
    1004960                   || (rcv_data.length > DIAMETER_MSG_SIZE_MAX)) { /* to avoid too big mallocs */
    1005961                        /* The message is suspect */
    1006                         LOG_E( "Received suspect header [ver: %d, size: %zd], assume disconnection", (int)header[0], rcv_data.length);
     962                        LOG_E( "Received suspect header [ver: %d, size: %zd] from '%s', assume disconnection", (int)header[0], rcv_data.length, conn->cc_remid);
    1007963                        fd_cnx_markerror(conn);
    1008964                        goto out;
  • libfdcore/hooks.c

    r1098 r1103  
    186186        in_msg = fd_msg_pmdl_get(msg);
    187187        ASSERT(in_msg && (in_msg->sentinel.o == NULL)); /* error / already initialized ??? */
    188         fd_list_init(&in_msg->sentinel, pmdl_free);
    189         CHECK_POSIX_DO( pthread_mutex_init(&in_msg->lock, NULL), );
     188        in_msg->sentinel.o = pmdl_free;
    190189        /* Now move all items from the pmdl pointer into the initialized list */
    191190        CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
     
    201200        struct fd_hook_permsgdata * ret = NULL;
    202201        struct fd_list * li;
     202       
    203203        CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
     204       
     205        if (pmdl->sentinel.o == NULL) {
     206                pmdl->sentinel.o = pmdl_free;
     207        }
    204208       
    205209        /* Search in the list for an item with the same handle. The list is ordered by this handle */
     
    231235}
    232236
     237struct fd_hook_permsgdata * fd_hook_get_request_pmd(struct fd_hook_data_hdl *data_hdl, struct msg * answer)
     238{
     239        struct msg * qry;
     240        struct fd_msg_pmdl *pmdl;
     241        struct fd_hook_permsgdata * ret = NULL;
     242        struct fd_list * li;
     243       
     244        CHECK_FCT_DO( fd_msg_answ_getq(answer, &qry), return NULL );
     245        if (!qry)
     246                return NULL;
     247       
     248        pmdl = fd_msg_pmdl_get(qry);
     249        if (!pmdl)
     250                return NULL;
     251       
     252        CHECK_POSIX_DO( pthread_mutex_lock(&pmdl->lock), );
     253        /* Search in the list for an item with the same handle. The list is ordered by this handle */
     254        for (li=pmdl->sentinel.next; li != &pmdl->sentinel; li = li->next) {
     255                struct pmd_list_item * pli = (struct pmd_list_item *) li;
     256                if (pli->hdl == data_hdl)
     257                        ret = &pli->pmd;
     258                if (pli->hdl >= data_hdl)
     259                        break;
     260        }
     261        CHECK_POSIX_DO( pthread_mutex_unlock(&pmdl->lock), );
     262        return ret;
     263}
    233264
    234265/* The function that does the work of calling the extension's callbacks and also managing the permessagedata structures */
     
    237268        struct fd_list * li;
    238269        ASSERT(type <= HOOK_PEER_LAST);
     270        int call_default = 0;
    239271       
    240272        /* lock the list of hooks for this type */
    241273        CHECK_POSIX_DO( pthread_rwlock_rdlock(&HS_array[type].rwlock), );
    242274       
    243         /* for each registered hook */
    244         for (li = HS_array[type].sentinel.next; li != &HS_array[type].sentinel; li = li->next) {
    245                 struct fd_hook_hdl * h = (struct fd_hook_hdl *)li->o;
    246                 struct fd_hook_permsgdata * pmd = NULL;
    247                
    248                 /* do we need to handle pmd ? */
    249                 if (h->data_hdl && pmdl) {
    250                         pmd = get_or_create_pmd(pmdl, h);
    251                 }
    252                
    253                 /* Now, call this callback */
    254                 (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata);
     275        if (FD_IS_LIST_EMPTY(&HS_array[type].sentinel)) {
     276                call_default = 1;
     277        } else {
     278                /* for each registered hook */
     279                for (li = HS_array[type].sentinel.next; li != &HS_array[type].sentinel; li = li->next) {
     280                        struct fd_hook_hdl * h = (struct fd_hook_hdl *)li->o;
     281                        struct fd_hook_permsgdata * pmd = NULL;
     282
     283                        /* do we need to handle pmd ? */
     284                        if (h->data_hdl && pmdl) {
     285                                pmd = get_or_create_pmd(pmdl, h);
     286                        }
     287
     288                        /* Now, call this callback */
     289                        (*h->fd_hook_cb)(type, msg, &peer->p_hdr, other, pmd, h->regdata);
     290                }
    255291        }
    256292       
    257293        /* done */
    258294        CHECK_POSIX_DO( pthread_rwlock_unlock(&HS_array[type].rwlock), );
    259 }
     295       
     296        if (call_default) {
     297                char * buf = NULL;
     298                size_t len = 0;
     299       
     300                /* There was no registered handler, default behavior for this hook */
     301                switch (type) {
     302                        case HOOK_DATA_RECEIVED: {
     303                                struct fd_cnx_rcvdata *rcv_data = other;
     304                                LOG_A("RCV: %zd bytes", rcv_data->length);
     305                                break;
     306                        }
     307                       
     308                        case HOOK_MESSAGE_RECEIVED: {
     309                                CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break);
     310                                LOG_D("RCV from '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf);
     311                                break;
     312                        }
     313                       
     314                        case HOOK_MESSAGE_LOCAL: {
     315                                CHECK_MALLOC_DO(fd_msg_dump_full(&buf, &len, NULL, msg, NULL, 0, 1), break);
     316                                LOG_A("Handled to framework for sending: %s", buf);
     317                                break;
     318                        }
     319                       
     320                        case HOOK_MESSAGE_SENT: {
     321                                CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break);
     322                                LOG_D("SENT to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf);
     323                                break;
     324                        }
     325                       
     326                        case HOOK_MESSAGE_FAILOVER: {
     327                                CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break);
     328                                LOG_D("Failing over message sent to '%s': %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf);
     329                                break;
     330                        }
     331                       
     332                        case HOOK_MESSAGE_PARSING_ERROR: {
     333                                if (msg) {
     334                                        DiamId_t id = NULL;
     335                                        size_t idlen;
     336                                        if (!fd_msg_source_get( msg, &id, &idlen ))
     337                                                id = (DiamId_t)"<error getting source>";
     338                                       
     339                                        if (!id)
     340                                                id = (DiamId_t)"<local>";
     341                                       
     342                                        CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break);
     343                                       
     344                                        LOG_E("Parsing error: '%s' for the following message received from '%s':\n%s", (char *)other, (char *)id, buf);
     345                                } else {
     346                                        struct fd_cnx_rcvdata *rcv_data = other;
     347                                        CHECK_MALLOC_DO(fd_dump_extend_hexdump(&buf, &len, NULL, rcv_data->buffer, rcv_data->length, 0, 0), break);
     348                                        LOG_E("Parsing error: cannot parse %zdB buffer from '%s': %s",  rcv_data->length, peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf);
     349                                }
     350                                break;
     351                        }
     352                       
     353                        case HOOK_MESSAGE_ROUTING_ERROR: {
     354                                DiamId_t id = NULL;
     355                                size_t idlen;
     356                                if (!fd_msg_source_get( msg, &id, &idlen ))
     357                                        id = (DiamId_t)"<error getting source>";
     358
     359                                if (!id)
     360                                        id = (DiamId_t)"<local>";
     361
     362                                CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break);
     363
     364                                LOG_E("Routing error: '%s' for the following message:\n%s", (char *)other, buf);
     365                                break;
     366                        }
     367                       
     368                        case HOOK_MESSAGE_ROUTING_FORWARD: {
     369                                CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break);
     370                                LOG_D("FORWARDING: %s", buf);
     371                                break;
     372                        }
     373                       
     374                        case HOOK_MESSAGE_ROUTING_LOCAL: {
     375                                CHECK_MALLOC_DO(fd_msg_dump_summary(&buf, &len, NULL, msg, NULL, 0, 1), break);
     376                                LOG_D("DISPATCHING: %s", buf);
     377                                break;
     378                        }
     379                       
     380                        case HOOK_MESSAGE_DROPPED: {
     381                                CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break);
     382                                LOG_E("Message discarded ('%s'):\n%s", (char *)other, buf);
     383                                break;
     384                        }
     385                       
     386                        case HOOK_PEER_CONNECT_FAILED: {
     387                                if (msg) {
     388                                        size_t offset = 0;
     389                                        CHECK_MALLOC_DO(fd_dump_extend(&buf, &len, &offset, " CER/CEA dump:\n"), break);
     390                                        CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, &offset, msg, NULL, 0, 1), break);
     391                                        LOG_N("Connection to '%s' failed: %s%s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other, buf);
     392                                } else {
     393                                        LOG_D("Connection to '%s' failed: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", (char *)other);
     394                                }
     395                                break;
     396                        }
     397                       
     398                        case HOOK_PEER_CONNECT_SUCCESS: {
     399                                CHECK_MALLOC_DO(fd_msg_dump_treeview(&buf, &len, NULL, msg, NULL, 0, 1), break);
     400                                LOG_N("Connected to '%s', remote capabilities: %s", peer ? peer->p_hdr.info.pi_diamid : "<unknown>", buf);
     401                                break;
     402                        }
     403                       
     404                }
     405               
     406                free(buf);
     407        }
     408}
  • libfdcore/messages.c

    r1078 r1103  
    346346
    347347/* Parse a message against our dictionary, and in case of error log and eventually build the error reply -- returns the parsing status */
    348 int fd_msg_parse_or_error( struct msg ** msg )
     348int fd_msg_parse_or_error( struct msg ** msg, struct msg **error)
    349349{
    350350        int ret = 0;
     
    355355        TRACE_ENTRY("%p", msg);
    356356       
    357         CHECK_PARAMS(msg && *msg);
     357        CHECK_PARAMS(msg && *msg && error);
    358358        m = *msg;
     359        *error = NULL;
    359360       
    360361        /* Parse the message against our dictionary */
     
    364365                return ret; /* 0 or another error */
    365366       
    366         TRACE_DEBUG(INFO, "A message does not comply to the dictionary and/or rules (%s)", pei.pei_errcode);
    367         fd_msg_dump_walk(FULL, m);
     367        /* Log */
     368        fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, m, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(m));
    368369       
    369370        CHECK_FCT( fd_msg_hdr(m, &hdr) );
     
    373374               
    374375                /* Create the error message */
    375                 CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, msg, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) );
     376                CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, &m, pei.pei_protoerr ? MSGFL_ANSW_ERROR : 0 ) );
    376377               
    377378                /* Set the error code */
    378                 CHECK_FCT( fd_msg_rescode_set(*msg, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) );
     379                CHECK_FCT( fd_msg_rescode_set(m, pei.pei_errcode, pei.pei_message, pei.pei_avp, 1 ) );
     380               
     381                *msg = NULL;
     382                *error = m;
    379383               
    380384        } else {
     
    409413                                        default: /* Other errors */
    410414                                                /* We let the application decide what to do with the message, we rescue it */
    411                                                 return 0;
     415                                                *error = m;
    412416                                }
    413417                        }
    414418                } while (0);
    415                
    416                 /* Just discard */
    417                 //fd_msg_log( FD_MSG_LOG_DROPPED, m, "Answer not compliant to dictionary's ABNF (%s)", pei.pei_errcode  );
    418                 CHECK_FCT( fd_msg_free( m ) );
    419                 *msg = NULL;
    420419        }
    421420       
  • libfdcore/p_ce.c

    r1078 r1103  
    671671                        fd_cnx_destroy(initiator);
    672672
     673                        LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid);
     674                       
    673675                        /* Process with the receiver side */
    674676                        CHECK_FCT( fd_p_ce_process_receiver(peer) );
     
    678680                        memset(&pei, 0, sizeof(pei));
    679681                        pei.pei_errcode = "ELECTION_LOST";
     682                        pei.pei_message = "Please answer my CER instead, you won the election.";
     683                        LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid);
    680684
    681685                        /* Answer an ELECTION LOST to the receiver side */
     
    720724        if (req || ((st = fd_peer_getstate(peer)) != STATE_WAITCEA)) {
    721725                if (*msg) {
    722                         //fd_msg_log( FD_MSG_LOG_DROPPED, *msg, "Received CER/CEA while in '%s' state.", STATE_STR(st));
     726                        /* In such case, just discard the message */
     727                        char buf[128];
     728                        snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(st));
     729                        fd_hook_call(HOOK_MESSAGE_DROPPED, *msg, peer, buf, fd_msg_pmdl_get(*msg));
     730
    723731                        CHECK_FCT_DO( fd_msg_free(*msg), /* continue */);
    724732                        *msg = NULL;
     
    731739       
    732740        /* Save info from the CEA into the peer */
    733         CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &pei, &rc), goto cleanup );
    734        
    735         /* Dispose of the message, we don't need it anymore */
    736         CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
    737         *msg = NULL;
     741        CHECK_FCT_DO( save_remote_CE_info(*msg, peer, &pei, &rc),
     742                {
     743                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "An error occurred while processing incoming CEA.", NULL);
     744                        goto cleanup;
     745                } );
    738746       
    739747        /* Check the Result-Code */
    740748        switch (rc) {
    741749                case ER_DIAMETER_SUCCESS:
     750                        /* Log success */
     751                        fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, *msg, peer, NULL, NULL);
     752                       
     753                        /* Dispose of the message, we don't need it anymore */
     754                        CHECK_FCT_DO( fd_msg_free(*msg), /* continue */ );
     755                        *msg = NULL;
     756                       
    742757                        /* No problem, we can continue */
    743758                        break;
     
    745760                case ER_DIAMETER_TOO_BUSY:
    746761                        /* Retry later */
    747                         TRACE_DEBUG(INFO, "Peer %s replied a CEA with Result-Code AVP DIAMETER_TOO_BUSY, will retry later.", peer->p_hdr.info.pi_diamid);
     762                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "Remote peer is too busy", NULL);
    748763                        fd_psm_cleanup(peer, 0);
    749764                        fd_psm_next_timeout(peer, 0, 300);
     
    757772                default:
    758773                        /* In any other case, we abort all attempts to connect to this peer */
    759                         TRACE_DEBUG(INFO, "Peer %s replied a CEA with Result-Code %d, aborting connection attempts.", peer->p_hdr.info.pi_diamid, rc);
     774                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, *msg, peer, "CEA with unexpected error code", NULL);
    760775                        return EINVAL;
    761776        }
     777       
    762778       
    763779        /* Handshake if needed, start clear otherwise */
     
    778794                                {
    779795                                        /* Handshake failed ...  */
    780                                         fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid);
     796                                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL);
    781797                                        goto cleanup;
    782798                                } );
     
    818834        TRACE_ENTRY("%p", peer);
    819835       
    820         CHECK_FCT( set_peer_cnx(peer, &peer->p_receiver) );
     836        CHECK_FCT_DO( set_peer_cnx(peer, &peer->p_receiver),
     837                {
     838                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Error saving the incoming connection in the peer structure", NULL);
     839                        return __ret__;
     840                } );
    821841        msg = peer->p_cer;
    822842        peer->p_cer = NULL;
     
    928948        CHECK_FCT( fd_msg_rescode_set(msg, "DIAMETER_SUCCESS", NULL, NULL, 0 ) );
    929949        CHECK_FCT( add_CE_info(msg, peer->p_cnxctx, isi & PI_SEC_TLS_OLD, isi & PI_SEC_NONE) );
     950       
     951        /* The connection is complete, but we may still need TLS handshake */
     952        fd_hook_call(HOOK_PEER_CONNECT_SUCCESS, msg, peer, NULL, NULL);
     953       
    930954        CHECK_FCT( fd_out_send(&msg, peer->p_cnxctx, peer, FD_CNX_ORDERED ) );
    931955       
     
    936960                        {
    937961                                /* Handshake failed ...  */
    938                                 fd_log_debug("TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid);
     962                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS handshake failed after CER/CEA exchange", NULL);
    939963                                goto cleanup;
    940964                        } );
    941965               
    942966                /* Retrieve the credentials */
    943                 CHECK_FCT( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size) );
     967                CHECK_FCT_DO( fd_cnx_getcred(peer->p_cnxctx, &peer->p_hdr.info.runtime.pir_cert_list, &peer->p_hdr.info.runtime.pir_cert_list_size),
     968                        {
     969                                /* Error ...  */
     970                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Unable to retrieve remote credentials after TLS handshake", NULL);
     971                                goto cleanup;
     972                        } );
     973               
    944974               
    945975                /* Call second validation callback if needed */
     
    948978                        CHECK_FCT_DO( (*peer->p_cb2)( &peer->p_hdr.info ),
    949979                                {
    950                                         TRACE_DEBUG(INFO, "Validation callback rejected the peer %s after handshake", peer->p_hdr.info.pi_diamid);
     980                                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Validation callback rejected the peer after handshake", NULL);
    951981                                        CHECK_FCT( fd_psm_terminate( peer, "DO_NOT_WANT_TO_TALK_TO_YOU" ) );
    952982                                        return 0;
     
    9821012        if (pei.pei_errcode) {
    9831013                /* Send the error */
     1014                fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, pei.pei_message ?: pei.pei_errcode, NULL);
    9841015                receiver_reject(&peer->p_cnxctx, &msg, &pei);
     1016        } else {
     1017                char buf[1024];
     1018                snprintf(buf, sizeof(buf), "Unexpected error occurred while processing incoming connection from '%s'.", peer->p_hdr.info.pi_diamid);
     1019                fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, peer, buf, NULL);
    9851020        }
    9861021       
    9871022cleanup:
    9881023        if (msg) {
    989                 //fd_msg_log(FD_MSG_LOG_DROPPED, msg, "An error occurred while processing a CER.");
    9901024                fd_msg_free(msg);
    9911025        }
     
    10271061                               
    10281062                                /* Close initiator connection (was already set as principal) */
     1063                                LOG_D("%s: Election lost on outgoing connection, closing and answering CEA on incoming connection.", peer->p_hdr.info.pi_diamid);
    10291064                                fd_p_ce_clear_cnx(peer, NULL);
    10301065                               
     
    10411076                                pei.pei_errcode = "ELECTION_LOST";
    10421077                                pei.pei_message = "Please answer my CER instead, you won the election.";
     1078                                LOG_D("%s: Election lost on incoming connection, closing and waiting for CEA on outgoing connection.", peer->p_hdr.info.pi_diamid);
    10431079                                receiver_reject(cnx, msg, &pei);
    10441080                        }
     
    10481084                        pei.pei_errcode = "DIAMETER_UNABLE_TO_COMPLY"; /* INVALID COMMAND? in case of Capabilities-Updates? */
    10491085                        pei.pei_message = "Invalid state to receive a new connection attempt.";
     1086                        LOG_E("%s: Rejecting new connection attempt while our state machine is in state '%s'", peer->p_hdr.info.pi_diamid, STATE_STR(cur_state));
    10501087                        receiver_reject(cnx, msg, &pei);
    10511088        }
  • libfdcore/p_cnx.c

    r974 r1103  
    236236                        if (FD_IS_LIST_EMPTY(&peer->p_connparams)) {
    237237                                /* We encountered an error or we have looped over all the addresses of the peer. */
    238                                 TRACE_DEBUG(INFO, "Unable to connect to the peer %s, aborting attempts for now.", peer->p_hdr.info.pi_diamid);
     238                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "All connection attempts failed, will retry later", NULL);
     239                               
    239240                                CHECK_FCT_DO( fatal_error = fd_event_send(peer->p_events, FDEVP_CNX_FAILED, 0, NULL), goto out );
    240241                                return NULL;
     
    279280                        {
    280281                                /* Handshake failed ...  */
    281                                 TRACE_DEBUG(INFO, "TLS Handshake failed with peer '%s', resetting the connection", peer->p_hdr.info.pi_diamid);
     282                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "TLS Handshake failed", NULL);
    282283                                fd_cnx_destroy(cnx);
    283284                                empty_connection_list(peer);
     
    285286                                goto out_pop;
    286287                        } );
     288                LOG_A("%s: TLS handshake successful.", peer->p_hdr.info.pi_diamid);
    287289        } else {
    288290                /* Prepare to receive the next message */
  • libfdcore/p_out.c

    r1084 r1103  
    3737
    3838/* Alloc a new hbh for requests, bufferize the message and send on the connection, save in sentreq if provided */
    39 static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct sr_list * srl)
     39static int do_send(struct msg ** msg, uint32_t flags, struct cnxctx * cnx, uint32_t * hbh, struct fd_peer * peer)
    4040{
    4141        struct msg_hdr * hdr;
     
    4545        int ret;
    4646        uint32_t bkp_hbh = 0;
    47        
    48         TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, srl);
     47        struct msg *cpy_for_logs_only;
     48       
     49        TRACE_ENTRY("%p %x %p %p %p", msg, flags, cnx, hbh, peer);
    4950       
    5051        /* Retrieve the message header */
     
    5354        msg_is_a_req = (hdr->msg_flags & CMD_FLAG_REQUEST);
    5455        if (msg_is_a_req) {
    55                 CHECK_PARAMS(hbh && srl);
     56                CHECK_PARAMS(hbh && peer);
    5657                /* Alloc the hop-by-hop id and increment the value for next message */
    5758                bkp_hbh = hdr->msg_hbhid;
     
    6465        pthread_cleanup_push( free, buf );
    6566       
    66         // cpy_for_logs_only = *msg;
     67        cpy_for_logs_only = *msg;
    6768       
    6869        /* Save a request before sending so that there is no race condition with the answer */
    6970        if (msg_is_a_req) {
    70                 CHECK_FCT_DO( ret = fd_p_sr_store(srl, msg, &hdr->msg_hbhid, bkp_hbh), goto out );
     71                CHECK_FCT_DO( ret = fd_p_sr_store(&peer->p_sr, msg, &hdr->msg_hbhid, bkp_hbh), goto out );
    7172        }
    7273       
    7374        /* Log the message */
    74         // fd_msg_log( FD_MSG_LOG_SENT, cpy_for_logs_only, "Sent to '%s'", fd_cnx_getid(cnx));
     75        fd_hook_call(HOOK_MESSAGE_SENT, cpy_for_logs_only, peer, NULL, fd_msg_pmdl_get(cpy_for_logs_only));
    7576       
    7677        /* Send the message */
     
    127128               
    128129                /* Send the message, log any error */
    129                 CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, &peer->p_sr),
     130                CHECK_FCT_DO( ret = do_send(&msg, 0, peer->p_cnxctx, &peer->p_hbh, peer),
    130131                        {
    131132                                if (msg) {
     
    179180
    180181                /* Do send the message */
    181                 CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer ? &peer->p_sr : NULL),
     182                CHECK_FCT_DO( ret = do_send(msg, flags, cnx, hbh, peer),
    182183                        {
    183184                                if (msg) {
  • libfdcore/p_psm.c

    r1085 r1103  
    483483                struct msg * msg = NULL;
    484484                struct msg_hdr * hdr;
     485                struct fd_cnx_rcvdata rcv_data;
     486                struct fd_msg_pmdl * pmdl = NULL;
     487               
     488                rcv_data.buffer = ev_data;
     489                rcv_data.length = ev_sz;
     490                pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length);
    485491               
    486492                /* Parse the received buffer */
    487493                CHECK_FCT_DO( fd_msg_parse_buffer( (void *)&ev_data, ev_sz, &msg),
    488494                        {
    489                                 fd_log_debug("Received invalid data from peer '%s', closing the connection", peer->p_hdr.info.pi_diamid);
     495                                fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, peer, &rcv_data, pmdl );
    490496                                free(ev_data);
    491497                                CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset );
     
    493499                        } );
    494500                       
     501                fd_hook_associate(msg, pmdl);
     502       
    495503                /* If the current state does not allow receiving messages, just drop it */
    496504                if (cur_state == STATE_CLOSED) {
    497505                        /* In such case, just discard the message */
    498                         //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Purged from peer '%s''s queue (CLOSED state).", peer->p_hdr.info.pi_diamid );
     506                        fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Message purged from queue, peer in CLOSED state", fd_msg_pmdl_get(msg));
    499507                        fd_msg_free(msg);
    500508                        goto psm_loop;
    501509                }
    502510               
    503                 /* Log incoming message */
    504                 //fd_msg_log( FD_MSG_LOG_RECEIVED, msg, "Received %zdb from '%s' (%s)", ev_sz, peer->p_hdr.info.pi_diamid, STATE_STR(cur_state) );
    505        
    506511                /* Extract the header */
    507512                CHECK_FCT_DO( fd_msg_hdr(msg, &hdr), goto psm_end );
     
    513518                        CHECK_FCT_DO( fd_p_sr_fetch(&peer->p_sr, hdr->msg_hbhid, &req), goto psm_end );
    514519                        if (req == NULL) {
    515                                 //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Answer received with no corresponding sent request." );
     520                                fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, "Answer received with no corresponding sent request.", fd_msg_pmdl_get(msg));
    516521                                fd_msg_free(msg);
    517522                                goto psm_loop;
     
    521526                        CHECK_FCT_DO( fd_msg_answ_associate( msg, req ), goto psm_end );
    522527                       
    523                         /* Display the delay to receive the answer */
    524                         {
    525                                 //fd_msg_log( FD_MSG_LOG_TIMING, msg, "Answer received in %ld.%6.6ld sec.", (long)delay.tv_sec, delay.tv_nsec / 1000 );
    526                         }
    527528                } else {
    528529                        /* Mark the incoming request so that we know we have pending answers for this peer */
     
    531532                        CHECK_POSIX_DO( pthread_mutex_unlock(&peer->p_state_mtx), goto psm_end  );
    532533                }
     534               
     535                /* Log incoming message */
     536                fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, peer, NULL, fd_msg_pmdl_get(msg));
    533537               
    534538                if (cur_state == STATE_OPEN_NEW) {
     
    569573                                case STATE_WAITCEA:
    570574                                case STATE_CLOSED:
    571                                 default:
     575                                default: {
    572576                                        /* In such case, just discard the message */
    573                                         //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received from peer '%s' while connection was not in state %s.", peer->p_hdr.info.pi_diamid, STATE_STR(cur_state) );
     577                                        char buf[128];
     578                                        snprintf(buf, sizeof(buf), "Received while peer state machine was in state %s.", STATE_STR(cur_state));
     579                                        fd_hook_call(HOOK_MESSAGE_DROPPED, msg, peer, buf, fd_msg_pmdl_get(msg));
    574580                                        fd_msg_free(msg);
     581                                }
    575582                        }
    576583                        goto psm_loop;
     
    579586                /* Link-local message: They must be understood by our dictionary, otherwise we return an error */
    580587                {
    581                         int ret = fd_msg_parse_or_error( &msg );
     588                        struct msg * error = NULL;
     589                        int ret = fd_msg_parse_or_error( &msg, &error );
    582590                        if (ret != EBADMSG) {
    583                                 CHECK_FCT_DO( ret, goto psm_end );
     591                                CHECK_FCT_DO( ret,
     592                                        {
     593                                                LOG_E("%s: An unexpected error occurred while parsing a link-local message", peer->p_hdr.info.pi_diamid);
     594                                                fd_msg_free(msg);
     595                                                goto psm_end;
     596                                        } );
    584597                        } else {
    585                                 if (msg) {
     598                                if (msg == NULL) {
    586599                                        /* Send the error back to the peer */
    587                                         CHECK_FCT_DO( ret = fd_out_send(&msg, NULL, peer, FD_CNX_ORDERED),  );
    588                                         if (msg) {
     600                                        CHECK_FCT_DO( ret = fd_out_send(&error, NULL, peer, FD_CNX_ORDERED),  );
     601                                        if (error) {
    589602                                                /* Only if an error occurred & the message was not saved / dumped */
    590                                                 //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Internal error: Problem while sending (%s)", strerror(ret) );
    591                                                 CHECK_FCT_DO( fd_msg_free(msg), goto psm_end);
     603                                                LOG_E("%s: error sending a message", peer->p_hdr.info.pi_diamid);
     604                                                CHECK_FCT_DO( fd_msg_free(error), goto psm_end);
    592605                                        }
    593606                                } else {
    594607                                        /* We received an invalid answer, let's disconnect */
     608                                        LOG_E("%s: Received invalid answer to Base protocol message, disconnecting...", peer->p_hdr.info.pi_diamid);
     609                                        CHECK_FCT_DO( fd_msg_free(msg), goto psm_end);
    595610                                        CHECK_FCT_DO( fd_event_send(peer->p_events, FDEVP_CNX_ERROR, 0, NULL), goto psm_reset );
    596611                                }
     
    602617                switch (hdr->msg_code) {
    603618                        case CC_CAPABILITIES_EXCHANGE:
    604                                 CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer), goto psm_reset );
     619                                CHECK_FCT_DO( fd_p_ce_msgrcv(&msg, (hdr->msg_flags & CMD_FLAG_REQUEST), peer),
     620                                        {
     621                                                if (msg)
     622                                                        CHECK_FCT_DO( fd_msg_free(msg), );
     623                                                goto psm_reset;
     624                                        } );
    605625                                break;
    606626                       
     
    671691                                /* Mark the connection problem */
    672692                                peer->p_flags.pf_cnx_pb = 1;
     693                       
     694                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "The connection was broken", NULL);
    673695                               
    674696                                /* Destroy the connection, restart the timer to a new connection attempt */
     
    732754                }
    733755                if (params->cer) {
    734                         //fd_msg_log( FD_MSG_LOG_DROPPED, params->cer, "Internal error: this CER was not handled as expected." );
    735756                        CHECK_FCT_DO( fd_msg_free(params->cer), );
    736757                        params->cer = NULL;
     
    753774                        case STATE_WAITCNXACK_ELEC:
    754775                        case STATE_WAITCNXACK:
     776                                LOG_D("%s: Connection established", peer->p_hdr.info.pi_diamid);
    755777                                fd_p_ce_handle_newcnx(peer, cnx);
    756778                                break;
     
    781803                               
    782804                        case STATE_WAITCNXACK:
     805                                LOG_D("%s: Connection attempt failed", peer->p_hdr.info.pi_diamid);
    783806                                /* Go back to CLOSE */
    784807                                fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
     
    803826                               
    804827                        case STATE_CLOSED:
     828                                LOG_D("%s: Connecting...", peer->p_hdr.info.pi_diamid);
    805829                                CHECK_FCT_DO( fd_psm_change_state(peer, STATE_WAITCNXACK), goto psm_end );
    806830                                fd_psm_next_timeout(peer, 0, CNX_TIMEOUT);
     
    811835                                /* Mark the connection problem */
    812836                                peer->p_flags.pf_cnx_pb = 1;
    813                         case STATE_CLOSING:
    814837                        case STATE_WAITCNXACK:
    815838                        case STATE_WAITCEA:
     839                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, peer, "Timeout while waiting for remote peer", NULL);
     840                        case STATE_CLOSING:
    816841                                /* Destroy the connection, restart the timer to a new connection attempt */
    817842                                fd_psm_next_timeout(peer, 1, peer->p_hdr.info.config.pic_tctimer ?: fd_g_config->cnf_timer_tc);
     
    849874       
    850875psm_end:
     876        LOG_N("%s: Going to ZOMBIE state (no more activity)", peer->p_hdr.info.pi_diamid);
    851877        fd_psm_cleanup(peer, 1);
    852878        TRACE_DEBUG(INFO, "'%s'\t-> STATE_ZOMBIE (terminated)\t'%s'",
  • libfdcore/peers.c

    r1093 r1103  
    491491        if (!avp_oh_model) {
    492492                avp_code_t code = AC_ORIGIN_HOST;
    493                 int ret;
    494                 CHECK_FCT_DO( ret = fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT),
    495                         { CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) ); return ret; } );
     493                CHECK_FCT_DO( fd_dict_search ( fd_g_config->cnf_dict, DICT_AVP, AVP_BY_CODE, &code, &avp_oh_model, ENOENT),
     494                        { LOG_E("Cannot find Origin-Host AVP definition in the dictionary!"); (void) pthread_mutex_unlock(&cache_avp_lock); return __ret__; } );
    496495        }
    497496        CHECK_POSIX( pthread_mutex_unlock(&cache_avp_lock) );
     
    504503        /* First, check if the Origin-Host value is valid */
    505504        if (!fd_os_is_valid_DiameterIdentity(avp_hdr->avp_value->os.data, avp_hdr->avp_value->os.len)) {
    506                 TRACE_DEBUG(INFO, "Received new CER with invalid Origin-Host");
    507505                CHECK_FCT( fd_msg_new_answer_from_req ( fd_g_config->cnf_dict, cer, MSGFL_ANSW_ERROR ) );
    508506                CHECK_FCT( fd_msg_rescode_set(*cer, "DIAMETER_INVALID_AVP_VALUE",
    509507                                                        "Your Origin-Host contains invalid characters.", avp_oh, 1 ) );
     508               
     509                fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, "Received CER with invalid Origin-Host AVP", NULL);
     510               
    510511                CHECK_FCT( fd_out_send(cer, *cnx, NULL, FD_CNX_ORDERED) );
    511512                return EINVAL;
     
    545546                peer->p_flags.pf_responder = 1;
    546547                peer->p_flags.pf_delete = 1;
     548               
     549                LOG_D("Created new peer object for incoming CER: %s", peer->p_hdr.info.pi_diamid);
    547550               
    548551#ifndef DISABLE_PEER_EXPIRY
     
    591594                *cer = NULL;
    592595                *cnx = NULL;
     596        } else {
     597                char buf[1024];
     598                snprintf(buf, sizeof(buf), "An error occurred while processing new incoming CER: %s", strerror(ret));
     599                fd_hook_call(HOOK_PEER_CONNECT_FAILED, *cer, NULL, buf, NULL);
    593600        }
    594601       
  • libfdcore/routing_dispatch.c

    r1078 r1103  
    432432        char * ec = NULL;
    433433        char * em = NULL;
    434         struct msg *msgptr = msg;
     434        struct msg *msgptr = msg, *error = NULL;
    435435
    436436        /* Read the message header */
     
    442442
    443443        /* At this point, we need to understand the message content, so parse it */
    444         CHECK_FCT_DO( ret = fd_msg_parse_or_error( &msgptr ),
     444        CHECK_FCT_DO( fd_msg_parse_or_error( &msgptr, &error ),
    445445                {
    446                         /* in case of error */
    447                         if ((ret == EBADMSG) && (msgptr != NULL)) {
    448                                 /* msgptr now contains the answer message to send back */
    449                                 CHECK_FCT( fd_fifo_post(fd_g_outgoing, &msgptr) );
    450                         }
    451                         if (msgptr) {   /* another error happen'd */
    452                                 //fd_msg_log( FD_MSG_LOG_DROPPED, msgptr,  "An unexpected error occurred while parsing the message (%s)", strerror(ret));
    453                                 CHECK_FCT_DO( fd_msg_free(msgptr), /* continue */);
    454                         }
    455                         /* We're done with this one */
    456                         return 0;
     446                        int rescue = 0;
     447                        if (__ret__ != EBADMSG) {
     448                                fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Error while parsing received answer", fd_msg_pmdl_get(msgptr));
     449                                fd_msg_free(msgptr);
     450                        } else {
     451                                if (!msgptr) {
     452                                        /* error now contains the answer message to send back */
     453                                        CHECK_FCT( fd_fifo_post(fd_g_outgoing, &error) );
     454                                } else if (!error) {
     455                                        /* We have received an invalid answer to our query */
     456                                        fd_hook_call(HOOK_MESSAGE_DROPPED, msgptr, NULL, "Received answer failed the dictionary / rules parsing", fd_msg_pmdl_get(msgptr));
     457                                        fd_msg_free(msgptr);
     458                                } else {
     459                                        /* We will pass the invalid received error to the application */
     460                                        rescue = 1;
     461                                }
     462                        }
     463                        if (!rescue)
     464                                return 0; /* We are done with this message, go to the next */
    457465                } );
    458466
  • libfdcore/server.c

    r1093 r1103  
    134134        struct client * c = arg;
    135135        struct server * s = NULL;
    136         uint8_t       * buf = NULL;
    137         size_t          bufsz;
     136        struct fd_cnx_rcvdata rcv_data;
     137        struct fd_msg_pmdl * pmdl = NULL;
    138138        struct msg    * msg = NULL;
    139139        struct msg_hdr *hdr = NULL;
     140        struct fd_pei pei;
    140141       
    141142        TRACE_ENTRY("%p", c);
     
    152153                int ret = fd_cnx_handshake(c->conn, GNUTLS_SERVER, NULL, NULL);
    153154                if (ret != 0) {
    154                         if (TRACE_BOOL(INFO)) {
    155                                 fd_log_debug("TLS handshake failed for client '%s', connection aborted.", fd_cnx_getid(c->conn));
    156                         }
     155                        char buf[1024];
     156                        snprintf(buf, sizeof(buf), "TLS handshake failed for client '%s', connection aborted.", fd_cnx_getid(c->conn));
     157                       
     158                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
     159                       
    157160                        goto cleanup;
    158161                }
     
    166169       
    167170        /* Receive the first Diameter message on the connection -- cleanup in case of timeout */
    168         CHECK_FCT_DO( fd_cnx_receive(c->conn, &c->ts, &buf, &bufsz), goto cleanup );
    169        
    170         TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", bufsz, fd_cnx_getid(c->conn));
     171        CHECK_FCT_DO( fd_cnx_receive(c->conn, &c->ts, &rcv_data.buffer, &rcv_data.length),
     172                {
     173                        char buf[1024];
     174                       
     175                        switch (__ret__) {
     176                        case ETIMEDOUT:
     177                                snprintf(buf, sizeof(buf), "Client '%s' did not send CER within %ds, connection aborted.", fd_cnx_getid(c->conn), INCNX_TIMEOUT);
     178                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
     179                                break;
     180                       
     181                        case ENOTCONN:
     182                                snprintf(buf, sizeof(buf), "Connection from '%s' in error before CER was received.", fd_cnx_getid(c->conn));
     183                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
     184                                break;
     185                       
     186                        default:
     187                                snprintf(buf, sizeof(buf), "Connection from '%s': unspecified error, connection aborted.", fd_cnx_getid(c->conn));
     188                                fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
     189                        }
     190                        goto cleanup;
     191                } );
     192       
     193        TRACE_DEBUG(FULL, "Received %zdb from new client '%s'", rcv_data.length, fd_cnx_getid(c->conn));
     194       
     195        pmdl = fd_msg_pmdl_get_inbuf(rcv_data.buffer, rcv_data.length);
    171196       
    172197        /* Try parsing this message */
    173         CHECK_FCT_DO( fd_msg_parse_buffer( &buf, bufsz, &msg ), /* Parsing failed */ goto cleanup );
     198        CHECK_FCT_DO( fd_msg_parse_buffer( &rcv_data.buffer, rcv_data.length, &msg ),
     199                {       /* Parsing failed */
     200                        fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, NULL, NULL, &rcv_data, pmdl );
     201                        goto cleanup;
     202                } );
    174203       
    175204        /* Log incoming message */
    176         //fd_msg_log( FD_MSG_LOG_RECEIVED, msg, "Received %zdb from new client '%s'", bufsz, fd_cnx_getid(c->conn) );
     205        fd_hook_associate(msg, pmdl);
     206        fd_hook_call(HOOK_MESSAGE_RECEIVED, msg, NULL, fd_cnx_getid(c->conn), fd_msg_pmdl_get(msg));
    177207       
    178208        /* We expect a CER, it must parse with our dictionary and rules */
    179         CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, NULL ), /* Parsing failed -- trace details ? */ goto cleanup );
     209        CHECK_FCT_DO( fd_msg_parse_rules( msg, fd_g_config->cnf_dict, &pei ),
     210                { /* Parsing failed -- trace details */
     211                        char buf[1024];
     212                       
     213                        fd_hook_call(HOOK_MESSAGE_PARSING_ERROR, msg, NULL, pei.pei_message ?: pei.pei_errcode, fd_msg_pmdl_get(msg));
     214                       
     215                        snprintf(buf, sizeof(buf), "Error parsing CER from '%s', connection aborted.", fd_cnx_getid(c->conn));
     216                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, NULL, NULL, buf, NULL);
     217                       
     218                        goto cleanup;
     219                } );
    180220       
    181221        /* Now check we received a CER */
    182222        CHECK_FCT_DO( fd_msg_hdr ( msg, &hdr ), goto fatal_error );
    183223        CHECK_PARAMS_DO( (hdr->msg_appl == 0) && (hdr->msg_flags & CMD_FLAG_REQUEST) && (hdr->msg_code == CC_CAPABILITIES_EXCHANGE),
    184                 { fd_log_debug("Connection '%s', expecting CER, received something else, closing...", fd_cnx_getid(c->conn)); goto cleanup; } );
     224                { /* Parsing failed -- trace details */
     225                        char buf[1024];
     226                        snprintf(buf, sizeof(buf), "Expected CER from '%s', received a different message, connection aborted.", fd_cnx_getid(c->conn));
     227                        fd_hook_call(HOOK_PEER_CONNECT_FAILED, msg, NULL, buf, NULL);
     228                        goto cleanup;
     229                } );
    185230       
    186231        /* Finally, pass the information to the peers module which will handle it next */
     
    200245        /* Cleanup the parsed message if any */
    201246        if (msg) {
    202                 //fd_msg_log( FD_MSG_LOG_DROPPED, msg, "Received invalid/unexpected message from connecting client '%s'", fd_cnx_getid(c->conn) );
    203247                CHECK_FCT_DO( fd_msg_free(msg), /* continue */);
    204248        }
     
    209253       
    210254        /* Cleanup the received buffer if any */
    211         free(buf);
     255        free(rcv_data.buffer);
    212256       
    213257        /* Detach the thread, cleanup the client structure */
     
    239283                /* Wait for a new client or cancel */
    240284                CHECK_MALLOC_DO( conn = fd_cnx_serv_accept(s->conn), goto error );
    241                
    242                 TRACE_DEBUG(FULL, "New connection accepted");
    243285               
    244286                /* Create a client structure */
     
    261303        if (s)
    262304                set_status(s, TERMINATED);
    263         /* Send error signal to the daemon */
    264         TRACE_DEBUG(INFO, "An error occurred in server module! Thread is terminating...");
     305
     306        /* Send error signal to the core */
     307        LOG_F( "An error occurred in server module! Thread is terminating...");
    265308        CHECK_FCT_DO(fd_event_send(fd_g_config->cnf_main_ev, FDEV_TERMINATE, 0, NULL), );
    266309
  • libfdproto/fifo.c

    r1093 r1103  
    412412        CHECK_MALLOC_DO(  new = malloc (sizeof (struct fifo_item)) , {
    413413                        pthread_mutex_unlock( &queue->mtx );
     414                        return ENOMEM;
    414415                } );
    415416       
     
    470471        ASSERT( ! FD_IS_LIST_EMPTY(&queue->list) );
    471472       
    472         fi = (struct fifo_item *)queue->list.next;
     473        fi = (struct fifo_item *)(queue->list.next);
     474        ret = fi->item.o;
    473475        fd_list_unlink(&fi->item);
    474476        queue->count--;
    475477        queue->total_items++;
    476         ret = fi->item.o;
    477478       
    478479        /* Update the timings */
     
    598599                return EPIPE;
    599600        }
    600                
     601       
    601602        if (queue->count > 0) {
    602603                /* There are items in the queue, so pick the first one */
  • libfdproto/messages.c

    r1101 r1103  
    202202        init_chain( &msg->msg_chain, MSG_MSG);
    203203        msg->msg_eyec = MSG_MSG_EYEC;
     204       
     205        fd_list_init(&msg->msg_pmdl.sentinel, NULL);
     206        CHECK_POSIX_DO( pthread_mutex_init(&msg->msg_pmdl.lock, NULL), );
    204207}
    205208
     
    19521955        CHECK_PARAMS(  buffer &&  *buffer  &&  msg  &&  (buflen >= GETMSGHDRSZ())  );
    19531956        buf = *buffer;
    1954         *buffer = NULL;
    19551957       
    19561958        if ( buf[0] != DIAMETER_VERSION) {
    19571959                TRACE_DEBUG(INFO, "Invalid version in message: %d (supported: %d)", buf[0], DIAMETER_VERSION);
    1958                 free(buf);
    19591960                return EBADMSG;
    19601961        }
     
    19631964        if ( buflen < msglen ) { 
    19641965                TRACE_DEBUG(INFO, "Truncated message (%zd / %d)", buflen, msglen );
    1965                 free(buf);
    19661966                return EBADMSG;
    19671967        }
    19681968       
    19691969        /* Create a new object */
    1970         CHECK_MALLOC_DO( new = malloc (sizeof(struct msg)),  { free(buf); return ENOMEM; } );
     1970        CHECK_MALLOC( new = malloc (sizeof(struct msg)) );
    19711971       
    19721972        /* Initialize the fields */
     
    19841984        new->msg_public.msg_eteid = ntohl(*(uint32_t *)(buf+16));
    19851985       
    1986         new->msg_rawbuffer = buf;
    1987        
    19881986        /* Parse the AVP list */
    19891987        CHECK_FCT_DO( ret = parsebuf_list(buf + GETMSGHDRSZ(), buflen - GETMSGHDRSZ(), &new->msg_chain.children), { destroy_tree(_C(new)); return ret; }  );
    19901988       
     1989        /* Parsing successful */
     1990        new->msg_rawbuffer = buf;
     1991        *buffer = NULL;
    19911992        *msg = new;
    19921993        return 0;
  • libfdproto/utils.c

    r1093 r1103  
    6666                        CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", gai_strerror(rc)), return NULL);
    6767                } else {
    68                         CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s", &addrbuf[0]), return NULL);
     68                        CHECK_MALLOC_DO( fd_dump_extend( FD_DUMP_STD_PARAMS, "%s(s)", &addrbuf[0], &servbuf[0]), return NULL);
    6969                }
    7070        } else {
     
    7373        return *buf;
    7474}
     75
     76void fd_sa_sdump_numeric(char * buf /* must be at least sSA_DUMP_STRLEN */, sSA * sa)
     77{
     78        char addrbuf[INET6_ADDRSTRLEN];
     79        char servbuf[32];
     80       
     81        if (sa) {
     82                int rc = getnameinfo(sa, sSAlen( sa ), addrbuf, sizeof(addrbuf), servbuf, sizeof(servbuf), NI_NUMERICHOST | NI_NUMERICSERV);
     83                if (rc) {
     84                        snprintf(buf, sSA_DUMP_STRLEN, "%s", gai_strerror(rc));
     85                } else {
     86                        snprintf(buf, sSA_DUMP_STRLEN, "%s(%s)", addrbuf, servbuf);
     87                }
     88        } else {
     89                snprintf(buf, sSA_DUMP_STRLEN, "(NULL / ANY)");
     90        }
     91       
     92}
  • tests/testmesg.c

    r1088 r1103  
    757757                        {
    758758                                unsigned char * buftmp = NULL;
     759                                struct msg * error;
    759760                                /* Check the parse or error works as expected */
    760761                                CPYBUF();
     
    765766                                CHECK( 0, fd_msg_init() );
    766767                                CHECK( 0, fd_msg_parse_buffer( &buf_cpy, 344, &msg) );
    767                                 CHECK( EBADMSG, fd_msg_parse_or_error( &msg ) );
     768                                CHECK( EBADMSG, fd_msg_parse_or_error( &msg, &error ) );
     769                                CHECK( NULL, msg );
     770                                msg = error;
    768771                               
    769772                                CHECK( 0, fd_msg_bufferize( msg, &buftmp, NULL ) );                             
  • tests/tests.h

    r1090 r1103  
    206206        CHECK( 0, fd_libproto_init() );
    207207       
     208        CHECK( 0, fd_hooks_init() );   
     209       
    208210        fd_log_threadname(fname);
    209211       
Note: See TracChangeset for help on using the changeset viewer.