Ejemplo n.º 1
0
static int rtr_handle_cache_response_pdu(struct rtr_socket *rtr_socket, char *pdu)
{

    RTR_DBG1("Cache Response PDU received");
    struct pdu_cache_response *cr_pdu = (struct pdu_cache_response *) pdu;
    //set connection session_id
    if (rtr_socket->request_session_id) {
        if (rtr_socket->last_update != 0) {
            //if this isnt the first sync, but we already received records, delete old records in the pfx_table
            pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
            spki_table_src_remove(rtr_socket->spki_table, rtr_socket);

            rtr_socket->last_update = 0;
        }
        rtr_socket->session_id = cr_pdu->session_id;
    } else {
        if (rtr_socket->session_id != cr_pdu->session_id) {
            const char txt[] = "Wrong session_id in Cache Response PDU"; //TODO: Appendrtr_socket->session_id to string
            rtr_send_error_pdu(rtr_socket, NULL, 0, CORRUPT_DATA, txt, sizeof(txt));
            rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
            return RTR_ERROR;
        }
    }
    return RTR_SUCCESS;
}
Ejemplo n.º 2
0
Archivo: rtr.c Proyecto: CZ-NIC/rtrlib
void rtr_purge_outdated_records(struct rtr_socket *rtr_socket)
{
    if(rtr_socket->last_update == 0)
        return;
    time_t cur_time;
    int rtval = lrtr_get_monotonic_time(&cur_time);
    if(rtval == -1 || (rtr_socket->last_update + rtr_socket->expire_interval) < cur_time) {
        if(rtval == -1)
            RTR_DBG1("get_monotic_time(..) failed");
        pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
        RTR_DBG1("Removed outdated records from pfx_table");
        spki_table_src_remove(rtr_socket->spki_table, rtr_socket);
        RTR_DBG1("Removed outdated router keys from spki_table");
        rtr_socket->request_session_id = true;
        rtr_socket->serial_number = 0;
        rtr_socket->last_update = 0;
    }
}
Ejemplo n.º 3
0
Archivo: rtr.c Proyecto: ColinBS/rtrlib
void rtr_stop(struct rtr_socket *rtr_socket)
{
    RTR_DBG1("rtr_stop()");
    rtr_change_socket_state(rtr_socket, RTR_SHUTDOWN);
    if(rtr_socket->thread_id != 0) {
        RTR_DBG1("pthread_cancel()");
        pthread_cancel(rtr_socket->thread_id);
        RTR_DBG1("pthread_join()");
        pthread_join(rtr_socket->thread_id, NULL);

        tr_close(rtr_socket->tr_socket);
        rtr_socket->request_session_id = true;
        rtr_socket->serial_number = 0;
        rtr_socket->last_update = 0;
        pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
        spki_table_src_remove(rtr_socket->spki_table, rtr_socket);
        rtr_socket->thread_id = 0;
    }
    RTR_DBG1("Socket shut down");
}
Ejemplo n.º 4
0
int rtr_sync_receive_and_store_pdus(struct rtr_socket *rtr_socket){
    char pdu[RTR_MAX_PDU_LEN];
    enum pdu_type type;
    int retval = RTR_SUCCESS;

    struct pdu_ipv6 *ipv6_pdus = NULL;
    unsigned int ipv6_pdus_nindex = 0; //next free index in ipv6_pdus
    unsigned int ipv6_pdus_size = 0;

    struct pdu_ipv4 *ipv4_pdus = NULL;
    unsigned int ipv4_pdus_size = 0; //next free index in ipv4_pdus
    unsigned int ipv4_pdus_nindex = 0;

    struct pdu_router_key *router_key_pdus = NULL;
    unsigned int router_key_pdus_size = 0;
    unsigned int router_key_pdus_nindex = 0;

    //receive LRTR_IPV4/IPV6 PDUs till EOD
    do {
        retval = rtr_receive_pdu(rtr_socket, pdu, RTR_MAX_PDU_LEN, RTR_RECV_TIMEOUT);
        if (retval == TR_WOULDBLOCK) {
            rtr_change_socket_state(rtr_socket, RTR_ERROR_TRANSPORT);
            retval = RTR_ERROR;
            goto cleanup;
        } else if (retval < 0) {
            retval = RTR_ERROR;
            goto cleanup;
        }

        type = rtr_get_pdu_type(pdu);
        if (type == IPV4_PREFIX) {
            if (rtr_store_prefix_pdu(rtr_socket, pdu, sizeof(*ipv4_pdus), (void **) &ipv4_pdus, &ipv4_pdus_nindex, &ipv4_pdus_size) == RTR_ERROR){
                rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                retval = RTR_ERROR;
                goto cleanup;
            }
        } else if (type == IPV6_PREFIX) {
            if (rtr_store_prefix_pdu(rtr_socket, pdu, sizeof(*ipv6_pdus), (void **) &ipv6_pdus, &ipv6_pdus_nindex, &ipv6_pdus_size) == RTR_ERROR){
                rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                retval = RTR_ERROR;
                goto cleanup;
            }
        } else if (type == ROUTER_KEY) {
            if (rtr_store_router_key_pdu(rtr_socket, pdu, sizeof(*router_key_pdus), &router_key_pdus, &router_key_pdus_nindex, &router_key_pdus_size) == RTR_ERROR){
                rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                retval = RTR_ERROR;
                goto cleanup;
            }
        } else if (type == EOD) {
            RTR_DBG1("EOD PDU received.");
            struct pdu_end_of_data_v0 *eod_pdu = (struct pdu_end_of_data_v0 *) pdu;

            if (eod_pdu->session_id != rtr_socket->session_id) {
                char txt[67];
                snprintf(txt, sizeof(txt),"Expected session_id: %u, received session_id. %u in EOD PDU",rtr_socket->session_id, eod_pdu->session_id);
                rtr_send_error_pdu(rtr_socket, pdu, RTR_MAX_PDU_LEN, CORRUPT_DATA, txt, strlen(txt) + 1);
                rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                retval = RTR_ERROR;
                goto cleanup;
            }

            if (eod_pdu->ver == RTR_PROTOCOL_VERSION_1) {
                rtr_socket->expire_interval = ((struct pdu_end_of_data_v1 *) pdu)->expire_interval;
                rtr_socket->refresh_interval = ((struct pdu_end_of_data_v1 *) pdu)->refresh_interval;
                rtr_socket->retry_interval = ((struct pdu_end_of_data_v1 *) pdu)->retry_interval;
                RTR_DBG("New interval values: expire_interval:%u, refresh_interval:%u, retry_interval:%u",
                        rtr_socket->expire_interval, rtr_socket->refresh_interval, rtr_socket->retry_interval);
            }

            int retval = PFX_SUCCESS;
            //add all IPv4 prefix pdu to the pfx_table
            for (unsigned int i = 0; i < ipv4_pdus_nindex; i++) {
                if (rtr_update_pfx_table(rtr_socket, &(ipv4_pdus[i])) == PFX_ERROR) {
                    //undo all record updates, except the last which produced the error
                    RTR_DBG("Error during data synchronisation, recovering Serial Nr. %u state",rtr_socket->serial_number);
                    for (unsigned int j = 0; j < i && retval == PFX_SUCCESS; j++)
                        retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv4_pdus[j]));
                    if (retval == RTR_ERROR) {
                        RTR_DBG1("Couldn't undo all update operations from failed data synchronisation: Purging all records");
                        pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
                        rtr_socket->request_session_id = true;
                    }
                    rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                    retval = RTR_ERROR;
                    goto cleanup;
                }
            }
            //add all IPv6 prefix pdu to the pfx_table
            for (unsigned int i = 0; i < ipv6_pdus_nindex; i++) {
                if (rtr_update_pfx_table(rtr_socket, &(ipv6_pdus[i])) == PFX_ERROR) {
                    //undo all record updates if error occured
                    RTR_DBG("Error during data synchronisation, recovering Serial Nr. %u state",rtr_socket->serial_number);
                    for (unsigned int j = 0; j < ipv4_pdus_nindex && retval == PFX_SUCCESS; j++)
                        retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv4_pdus[j]));
                    for (unsigned int j = 0; j < i && retval == PFX_SUCCESS; j++)
                        retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv6_pdus[j]));
                    if (retval == PFX_ERROR) {
                        RTR_DBG1("Couldn't undo all update operations from failed data synchronisation: Purging all records");
                        pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
                        rtr_socket->request_session_id = true;
                    }
                    rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                    retval = RTR_ERROR;
                    goto cleanup;
                }
            }

            //add all router key pdu to the spki_table
            for (unsigned int i = 0; i < router_key_pdus_nindex; i++) {
                if (rtr_update_spki_table(rtr_socket, &(router_key_pdus[i])) == SPKI_ERROR) {
                    RTR_DBG("Error during router key data synchronisation, recovering Serial Nr. %u state",rtr_socket->serial_number);
                    for (unsigned int j = 0; j < ipv4_pdus_nindex && retval == PFX_SUCCESS; j++)
                        retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv4_pdus[j]));
                    for (unsigned int j = 0; j < ipv6_pdus_nindex && retval == PFX_SUCCESS; j++)
                        retval = rtr_undo_update_pfx_table(rtr_socket, &(ipv6_pdus[j]));
		     // cppcheck-suppress duplicateExpression
                    for (unsigned int j = 0; j < i && (retval == PFX_SUCCESS || retval == SPKI_SUCCESS); j++)
                        retval = rtr_undo_update_spki_table(rtr_socket, &(router_key_pdus[j]));
		     // cppcheck-suppress duplicateExpression
                    if (retval == RTR_ERROR || retval == SPKI_ERROR) {
                        RTR_DBG1("Couldn't undo all update operations from failed data synchronisation: Purging all key entries");
                        spki_table_src_remove(rtr_socket->spki_table, rtr_socket);
                        rtr_socket->request_session_id = true;
                    }
                    rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
                    retval = RTR_ERROR;
                    goto cleanup;
                }
            }
            rtr_socket->serial_number = eod_pdu->sn;
            RTR_DBG("Sync successfull, received %u Prefix PDUs, %u Router Key PDUs, session_id: %u, SN: %u", (ipv4_pdus_nindex + ipv6_pdus_nindex), router_key_pdus_nindex,rtr_socket->session_id,rtr_socket->serial_number);
            goto cleanup;
        } else if (type == ERROR) {
            rtr_handle_error_pdu(rtr_socket, pdu);
            retval = RTR_ERROR;
            goto cleanup;
        } else if (type == SERIAL_NOTIFY) {
            RTR_DBG1("Ignoring Serial Notify");
        } else {
            RTR_DBG("Received unexpected PDU (Type: %u)", ((struct pdu_header *) pdu)->type);
            const char txt[] = "Unexpected PDU received during data synchronisation";
            rtr_send_error_pdu(rtr_socket, pdu, sizeof(struct pdu_header), CORRUPT_DATA, txt, sizeof(txt));
            retval = RTR_ERROR;
            goto cleanup;
        }
    } while (type != EOD);

    cleanup:
    free(router_key_pdus);
    free(ipv6_pdus);
    free(ipv4_pdus);
    return retval;
}
Ejemplo n.º 5
0
Archivo: rtr.c Proyecto: CZ-NIC/rtrlib
void rtr_fsm_start(struct rtr_socket *rtr_socket)
{
    rtr_socket->state = RTR_CONNECTING;
    install_sig_handler();
    while(1) {
        if(rtr_socket->state == RTR_CONNECTING) {
            RTR_DBG1("State: RTR_CONNECTING");
            rtr_socket->has_received_pdus = false;

            //old pfx_record could exists in the pfx_table, check if they are too old and must be removed
            //old key_entry could exists in the spki_table, check if they are too old and must be removed
            rtr_purge_outdated_records(rtr_socket);

            if(tr_open(rtr_socket->tr_socket) == TR_ERROR) {
                rtr_change_socket_state(rtr_socket, RTR_ERROR_TRANSPORT);
            } else if(rtr_socket->request_session_id) {
                //change to state RESET, if socket dont has a session_id
                rtr_change_socket_state(rtr_socket, RTR_RESET);
            } else {
                //if we already have a session_id, send a serial query and start to sync
                if(rtr_send_serial_query(rtr_socket) == RTR_SUCCESS)
                    rtr_change_socket_state(rtr_socket, RTR_SYNC);
                else
                    rtr_change_socket_state(rtr_socket, RTR_ERROR_FATAL);
            }

        }

        else if(rtr_socket->state == RTR_RESET) {
            RTR_DBG1("State: RTR_RESET");
            if (rtr_send_reset_query(rtr_socket) == RTR_SUCCESS) {
                RTR_DBG1("rtr_start: reset pdu sent");
                rtr_change_socket_state(rtr_socket, RTR_SYNC); //start to sync after connection is established
            }
        }

        else if(rtr_socket->state == RTR_SYNC) {
            RTR_DBG1("State: RTR_SYNC");
            if(rtr_sync(rtr_socket) == RTR_SUCCESS)
                rtr_change_socket_state(rtr_socket, RTR_ESTABLISHED); //wait for next sync after first successful sync
        }

        else if(rtr_socket->state == RTR_ESTABLISHED) {
            RTR_DBG1("State: RTR_ESTABLISHED");
            if(rtr_wait_for_sync(rtr_socket) == RTR_SUCCESS) { //blocks till expire_interval is expired or PDU was received
                //send serial query
                if(rtr_send_serial_query(rtr_socket) == RTR_SUCCESS)
                    rtr_change_socket_state(rtr_socket, RTR_SYNC);
            }
        }

        else if(rtr_socket->state == RTR_FAST_RECONNECT) {
            RTR_DBG1("State: RTR_FAST_RECONNECT");
            tr_close(rtr_socket->tr_socket);
            rtr_change_socket_state(rtr_socket, RTR_CONNECTING);
        }

        else if(rtr_socket->state == RTR_ERROR_NO_DATA_AVAIL) {
            RTR_DBG1("State: RTR_ERROR_NO_DATA_AVAIL");
            rtr_socket->request_session_id = true;
            rtr_socket->serial_number = 0;
            rtr_change_socket_state(rtr_socket, RTR_RESET);
            sleep(rtr_socket->retry_interval);
            rtr_purge_outdated_records(rtr_socket);
        }

        else if(rtr_socket->state == RTR_ERROR_NO_INCR_UPDATE_AVAIL) {
            RTR_DBG1("State: RTR_ERROR_NO_INCR_UPDATE_AVAIL");
            rtr_socket->request_session_id = true;
            rtr_socket->serial_number = 0;
            rtr_change_socket_state(rtr_socket, RTR_RESET);
            rtr_purge_outdated_records(rtr_socket);
        }

        else if(rtr_socket->state == RTR_ERROR_TRANSPORT) {
            RTR_DBG1("State: RTR_ERROR_TRANSPORT");
            tr_close(rtr_socket->tr_socket);
            rtr_change_socket_state(rtr_socket, RTR_CONNECTING);
            RTR_DBG("Waiting %u", rtr_socket->retry_interval);
            sleep(rtr_socket->retry_interval);
        }

        else if(rtr_socket->state == RTR_ERROR_FATAL) {
            RTR_DBG1("State: RTR_ERROR_FATAL");
            tr_close(rtr_socket->tr_socket);
            rtr_change_socket_state(rtr_socket, RTR_CONNECTING);
            RTR_DBG("Waiting %u", rtr_socket->retry_interval);
            sleep(rtr_socket->retry_interval);
        }

        else if(rtr_socket->state == RTR_SHUTDOWN) {
            RTR_DBG1("State: RTR_SHUTDOWN");
            tr_close(rtr_socket->tr_socket);
            rtr_socket->request_session_id = true;
            rtr_socket->serial_number = 0;
            rtr_socket->last_update = 0;
            pfx_table_src_remove(rtr_socket->pfx_table, rtr_socket);
            spki_table_src_remove(rtr_socket->spki_table, rtr_socket);
            pthread_exit(NULL);
        }
    }
}