/* int eth_poll 
 * ( eth_iface_t * ifaces[], int ifnum, long int timeout );
 *
 * DESCRIPCIÓN:
 *   Esta función permite esperar paquetes en múltiples interfaces Ethernet
 *   simultaneamente. Cuando alguna de las interfaces indicadas reciba una
 *   trama, la función devolverá la primera interfaz que tiene una trama
 *   listo para ser recibida mediante la funcion 'eth_recv()'.
 *
 *   Esta operación puede escuchar de los interfaces Ethernet indefinidamente
 *   o un tiempo limitado dependiento del parámetro 'timeout'.
 *
 * PARÁMETROS:
 *  'ifaces': Array con los manejadores de interfaces Ethernet por los que se
 *            quiere recibir.
 *            Todos los interfaces deben haber sido inicializados con
 *            'eth_open()' previamente.
 *   'ifnum': Número de interfaces que aparecen en el array 'ifaces'.
 * 'timeout': Tiempo en milisegundos que debe esperarse a recibir una trama
 *            antes de retornar. Un número negativo indicará que debe
 *            esperarse indefinidamente.
 *
 * VALOR DEVUELTO:
 *   El índice del primer interfaz [0, ifnum-1] que tiene una trama lista para
 *   ser recibida o '-2' si ha expirado el temporizador.
 * 
 * ERRORES:
 *   La función devuelve '-1' si se ha producido algún error.
 */
int eth_poll(eth_iface_t * ifaces[], int ifnum, long int timeout) {
	int iface_index;

	/* Crear lista de interfaces hardware */
	rawiface_t * raw_ifaces[ifnum];
	int i;
	for (i = 0; i < ifnum; i++) {
		raw_ifaces[i] = ifaces[i]->raw_iface;
	}

	/* Llamar a rawnet_poll() y procesar errores */
	iface_index = rawnet_poll(raw_ifaces, ifnum, timeout);
	if (iface_index == -1) {
		fprintf(stderr, "eth_poll(): ERROR en rawnet_poll(): %s\n", rawnet_strerror());
		return -1;
	} else if (iface_index == -2) {

		/* DEBUG */
		if (ETH_LOG >= NORMAL_LOG_LEVEL) {
			printf("eth_poll(): ¡ Timeout !\n");
		}

		return -2;
	}

	/* DEBUG */
	if (ETH_LOG >= DEBUG_LOG_LEVEL) {
		char * iface_name = eth_getname(ifaces[iface_index]);
		printf("eth_poll()=\"%s\"\n", iface_name);
	}

	return iface_index;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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);
  }
      
}
/* int eth_close ( eth_iface_t * iface );
 * 
 * DESCRIPCIÓN:
 *   Esta función cierra la interfaz Ethernet especificada y libera la memoria
 *   de su manejador.
 *
 * PARÁMETROS:
 *   'iface': Manejador de la interfaz Ethernet que se desea cerrar.
 *
 * VALOR DEVUELTO:
 *   Devuelve 0 si la interfaz Ethernet se ha cerrado correctamente.
 * 
 * ERRORES:
 *   La función devuelve '-1' si se ha producido algún error. 
 */
int eth_close(eth_iface_t * iface) {
	int err = -1;

	if (iface != NULL) {

		/* DEBUG */
		if (ETH_LOG >= DEBUG_LOG_LEVEL) {
			char* iface_name = eth_getname(iface);
			printf("eth_close(%s)\n", iface_name);
		}

		err = rawiface_close(iface->raw_iface);
		free(iface);
	}

	return err;
}
/* int eth_send 
 * ( eth_iface_t * iface, 
 *   mac_addr_t dst, uint16_t type, unsigned char * data, int data_len );
 *
 * DESCRIPCIÓN:
 *   Esta función permite enviar una trama Ethernet a través de la interfaz
 *   indicada.
 *
 * PARÁMETROS:
 *    'iface': Manejador de la interfaz Ethernet por la que se quiere enviar
 *             el paquete.
 *             La interfaz debe haber sido inicializada con 'eth_open()'
 *             previamente.
 *      'dst': Dirección MAC del equipo destino.
 *     'type': Valor del campo 'Tipo' de la trama Ethernet a enviar.
 *     'data': Puntero a los datos que se quieren enviar en la trama
 *             Ethernet.
 * 'data_len': Longitud en bytes de los datos a enviar.
 *
 * VALOR DEVUELTO:
 *   El número de bytes que han podido ser enviados.
 * 
 * ERRORES:
 *   La función devuelve '-1' si se ha producido algún error. 
 */
int eth_send(eth_iface_t * iface, mac_addr_t dst, uint16_t type, unsigned char * payload, int payload_len) {
	int bytes_sent;

	/* Comprobar parámetros */
	if (iface == NULL) {
		fprintf(stderr, "eth_send(): ERROR: iface == NULL\n");
		return -1;
	}

	/* Crear la Trama Ethernet y rellenar todos los campos */
	struct eth_frame eth_frame;
	memcpy(eth_frame.dest_addr, dst, MAC_ADDR_SIZE);
	memcpy(eth_frame.src_addr, iface->mac_address, MAC_ADDR_SIZE);
	eth_frame.type = htons(type);
	memcpy(eth_frame.payload, payload, payload_len);
	int eth_frame_len = ETH_HEADER_SIZE + payload_len;

	/* DEBUG */
	if (ETH_LOG >= VERBOSE_LOG_LEVEL) {
		char* iface_name = eth_getname(iface);
		char mac_addr_str[MAC_ADDR_STR_LENGTH];
		eth_mac_str(dst, mac_addr_str);
		printf("eth_send(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, eth_frame_len, ETH_HEADER_SIZE);
		}
	}

	/* Enviar la trama Ethernet creada con rawnet_send() y comprobar errores */
	bytes_sent = rawnet_send(iface->raw_iface, (unsigned char *) &eth_frame, eth_frame_len);
	if (bytes_sent == -1) {
		fprintf(stderr, "eth_send(): ERROR en rawnet_send(): %s\n", rawnet_strerror());
		return -1;
	}

	/* Devolver el número de bytes de datos recibidos */
	return (bytes_sent - ETH_HEADER_SIZE);
}
/* 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;
}