/* * ANOTHER ALIAS BY JAY-JAY! This time, it JUST collapses a timer * He is our miracle. YES, I have done this so many times this is * copy-paste */ void set_delete_flag (rip_route_t * route){ //int time_left = timerms_left (&route->time); //printf ("time_left: %d\n", time_left); timerms_reset (&route->time, TIMER_ZERO); }
rip_table_t * convert_message_table (rip_header_ptr pointer, int num_entries){ rip_table_t * table = rip_table_create (); /* * Name of the iface, just for printing @ the table * Recovered from eth.c by an extern directive */ char ifname[IFACE_NAME_LENGTH]; strcpy( ifname, eth_getname(iface_handler)); int index = 0; int i; for (i=0; i<num_entries; i++){ rip_route_t * route = rip_route_create ( pointer->entry [i].ip_addr, pointer->entry [i].ip_mask, ifname, pointer->entry [i].ip_next, pointer->entry [i].metric ); index = rip_route_table_add (table, route); timerms_reset (&table->routes[index]->time, TIMEOUT); } table->num_entries = num_entries; return table; }
void add_entries_table (rip_table_t * table, rip_header_ptr pointer, int num_entries){ char ifname[IFACE_NAME_LENGTH]; strcpy( ifname, eth_getname(iface_handler)); int index = 0; int i; for (i=0; i<num_entries; i++){ rip_route_t * route = rip_route_create ( pointer->entry [i].ip_addr, pointer->entry [i].ip_mask, ifname, pointer->entry [i].ip_next, pointer->entry [i].metric ); index = rip_route_table_add (table, route); timerms_reset (&table->routes[index]->time, TIMEOUT); } }
/* * In case we receive a better route than one * of our own, we shall destroy use the one better. * Otherwise we would be pretty dumb, don't we? * * @Params: &table, &route2remove, &route2write, * AND the index of route2remove */ int rip_replace_entry (rip_table_t * table, rip_route_t * route, rip_route_t * route_aux, int index){ int time_left = timerms_left (&route->time); route = rip_route_table_remove (table, index); rip_route_free (route); index = rip_route_table_add (table, route_aux); timerms_reset (&table->routes[index]->time, time_left); return index; }
/* int eth_recv * ( eth_iface_t * iface, * mac_addr_t src, uint16_t type, unsigned char buffer[], long int timeout ); * * DESCRIPCIÓN: * Esta función permite obtener el siguiente paquete recibido por la * interfaz Ethernet indicada. La operación puede esperar indefinidamente o * un tiempo limitando dependiento del parámetro 'timeout'. * * Esta función sólo permite recibir paquetes de una única interfaz. Si desea * escuchar varias interfaces Ethernet simultaneamente, utilice la función * 'eth_poll()'. * * PARÁMETROS: * 'iface': Manejador de la interfaz Ethernet por la que se desea recibir * un paquete. * La interfaz debe haber sido inicializada con 'eth_open()' * previamente. * 'src': Dirección MAC del equipo que envió la trama Ethernet recibida. * Este es un parámetro de salida. La dirección se copiará en la * memoria indicada, que debe estar reservada previamente. * 'type': Valor del campo 'Tipo' de la trama Ethernet que se desea * recibir. * Las tramas con un valor 'type' diferente serán descartadas. * 'buffer': Array donde se almacenarán los datos de la trama recibida. * Deben reservarse al menos 'ETH_MTU' bytes para recibir dichos * datos. * 'timeout': Tiempo en milisegundos que debe esperarse a recibir una trama * antes de retornar. Un número negativo indicará que debe * esperarse indefinidamente, mientras que con un '0' la función * retornará inmediatamente, se haya recibido o no una trama. * * VALOR DEVUELTO: * La longitud en bytes de los datos de la trama recibida, o '0' si no se ha * recibido ninguna trama porque ha expirado el temporizador. * * ERRORES: * La función devuelve '-1' si se ha producido algún error. */ int eth_recv(eth_iface_t * iface, mac_addr_t src, uint16_t type, unsigned char buffer[], long int timeout) { int payload_len; /* Comprobar parámetros */ if (iface == NULL) { fprintf(stderr, "eth_recv(): ERROR: iface == NULL\n"); return -1; } /* Inicializar temporizador para mantener timeout si se reciben tramas con tipo incorrecto. */ timerms_t timer; timerms_reset(&timer, timeout); int frame_len; unsigned char eth_buffer[ETH_FRAME_MAX_SIZE]; struct eth_frame * eth_frame_ptr = NULL; int is_target_type; int is_my_mac; int is_multicast; do { long int time_left = timerms_left(&timer); /* Recibir trama del interfaz Ethernet y procesar errores */ frame_len = rawnet_recv(iface->raw_iface, eth_buffer, ETH_FRAME_MAX_SIZE, time_left); if (frame_len == -1) { fprintf(stderr, "eth_recv(): ERROR en rawnet_recv(): %s\n", rawnet_strerror()); return -1; } else if (frame_len == 0) { /* DEBUG */ if (ETH_LOG >= NORMAL_LOG_LEVEL) { printf("eth_recv(): ¡ Timeout !\n"); } return 0; } /* Comprobar si es la trama que estamos buscando */ eth_frame_ptr = (struct eth_frame *) eth_buffer; is_my_mac = (memcmp(eth_frame_ptr->dest_addr, iface->mac_address, MAC_ADDR_SIZE) == 0); is_target_type = (ntohs(eth_frame_ptr->type) == type); /* Es el paquete multicast? (comprobamos el bit de la MAC) */ is_multicast = (eth_frame_ptr->dest_addr[0] && 0x1); } while (!((is_my_mac || is_multicast) && is_target_type)); /* Trama recibida con 'tipo' indicado. Copiar datos y dirección MAC origen */ memcpy(src, eth_frame_ptr->src_addr, MAC_ADDR_SIZE); payload_len = frame_len - ETH_HEADER_SIZE; memcpy(buffer, eth_frame_ptr->payload, payload_len); /* DEBUG */ if (ETH_LOG >= VERBOSE_LOG_LEVEL) { char mac_addr_str[MAC_ADDR_STR_LENGTH]; eth_mac_str(src, mac_addr_str); char* iface_name = eth_getname(iface); printf("eth_recv(type=0x%04x, payload[%d]) < %s/%s\n", type, payload_len, iface_name, mac_addr_str); if (ETH_LOG >= DEBUG_LOG_LEVEL) { print_pkt((unsigned char *) eth_frame_ptr, frame_len, ETH_HEADER_SIZE); } } return payload_len; }
void reset_entry_timer (rip_route_t * route){ timerms_reset(&route->time, TIMEOUT); route->garbage_flag = 0; }
int main(int argc, char * argv[]) { system("clear"); signal(SIGINT, interrupt); ipv4_addr_t multiaddress; ipv4_str_addr (RIP_MULTICAST_IPv4, multiaddress); if(argc == 2) { if( !strcmp(argv[1], "--verbose")) { is_verbose = 1; print_warning("(Debug mode ON) \n"); } } else printf("(Run with --verbose to print more info)\n"); bold ("Starting RIP Server... \t\t\t\t\t"); print_success("[ OK ]\n"); table = rip_table_create (); if (initialize_rip (table, RIP_PORT) == -1) { /* Already printed advert inside function */ return -1; } int K = rip_route_table_read ( RIP_TABLE_TXT, table ); /* set inf timer to routes read from file */ int k; for( k = 0; k < K; k++ ) { timerms_reset(&table->routes[k]->time, INFINITE_TIMER); } rip_table_t * table_aux; ipv4_addr_t src; long int r = random_number(-15, 15)*1000; //SEND UNSOLICITED RESPONSE MESSAGES EVERY 30 SECONDS +- 15s timerms_t update_timer = timer_start ( UPDATE_TIME + r ); //SEND REQUEST TO FILL ROUTE TABLE rip_route_table_print ( table ); for ( ;; ) { if (timer_ended (update_timer)) { /* Si se ha acabado el update timer */ send_rip_response (multiaddress, message_ptr, table, RIP_PORT); r = random_number(-15, 15)*1000; if ( is_verbose ) printf("(update_time set to %ld)\n", r +UPDATE_TIME); update_timer = timer_start (UPDATE_TIME + r); bold ("\nCurrent table:\n"); rip_route_table_print ( table ); } int src_port; int bytes_received = rip_recv (src, message_ptr, MIN_TIMER, &src_port); //WE RECEIVE A MESSAGE if (bytes_received>0) { //WE CONVERT THE MESSAGE TO A ROUTE TABLE FORMAT table_aux = convert_message_table (message_ptr, rip_number_entries(bytes_received)); if ( is_verbose ) { print_notice ("\nReceived packet\n"); print_packet (message_ptr, rip_number_entries(bytes_received)); } //IF THE MESSAGE IS A RESPONSE... if (message_ptr->command == 2) { //VALIDATE (HAY QUE IMPLEMENTARLO) //number of entries in the received message int num_entries = rip_number_entries (bytes_received); int trig_update_flag = 0; //by default, when receiving, do not send update //AND THIS IS WHERE THE MAGIC HAPPENS, WE PROCESS THE RESPONSE MESSAGE trig_update_flag = compare_tables (table, table_aux, num_entries, src); if (trig_update_flag) { send_rip_response (multiaddress, message_ptr, table, RIP_PORT); } bold ("\nCurrent table:\n"); rip_route_table_print ( table ); } if (message_ptr->command == 1 && metric_is_inf(ntohl(message_ptr->entry[0].metric))) { //IF REQUEST FOR WHOLE TABLE, RESPOND WITH WHOLE TABLE print_warning("Received a request for single entry, sending whole table\n"); send_rip_response (src, message_ptr, table, src_port); } else if (message_ptr->command == 1) { //IF REQUEST FOR SPECIFIC ENTRIES, RESPOND WITH SPECIFIC ENTRIES IF FOUND print_warning("Received a request for specific entries\n"); rip_table_t * table_send = table_to_send (table, table_aux); send_rip_response (src, message_ptr, table_send, src_port); } } int is_garbage_on = garbage_collector_start (table, garbage_collector_timers); int garbage_collected = garbage_collector (table, garbage_collector_timers); if (garbage_collected || is_garbage_on) { if(garbage_collected) print_notice("Garbage Collected \n"); else if(is_garbage_on) print_notice("Garbage countdown ON\n"); if( is_verbose ) rip_route_table_print(table); } } return 0; }