Archivo

Entradas Etiquetadas ‘ip’

Hallar la IP de un dispositivo en C

Lunes, 30 de Abril de 2012 Gaspar Fernández 2 comentarios

Puede que se nos haya presentado alguna vez la necesidad de saber la dirección de un dispositivo desde nuestro programa, y no es plan de ponernos a ejecutar ifconfig o algún programa parecido para hallar la dirección.

Podemos hablar con ioctl() una función destinada a definir y obtener información de dispositivos. Hay cientos de llamadas, aquí comentaremos la llamada SIOCGIFADDR cuya función es la que comentábamos, obtener la dirección de un interfaz de red.

Podemos probar el siguiente programa con el que hallaremos la IP del dispositivo eth0:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <string.h>

int main()
{
  int sock;
  struct ifreq ifr;

  sock=socket(AF_INET, SOCK_DGRAM, 0);
  if (sock<0)
    return -1;          /* No puedo crear el socket */

  ifr.ifr_addr.sa_family = AF_INET;
  strcpy(ifr.ifr_name, "eth0");

  if (ioctl(sock, SIOCGIFADDR, &ifr) < 0)
    return -1;          /* No encuentro el dispositivo */
 
  printf("IP de eth0: %s\n", inet_ntoa( (*(struct in_addr *) &ifr.ifr_addr.sa_data[2])));

  close(sock);

  return 0;
}

Primero creamos un socket, luego definimos la familia y el dispositivo que queremos consultar con:

1
2
ifr.ifr_addr.sa_family = AF_INET;
  strcpy(ifr.ifr_name, "eth0");

Para comprender cómo obtenemos la dirección debemos echar un ojo a las estructuras:
(struct ifreq)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
struct ifreq
{
    char            ifr_name[IFNAMSIZ];   /* Nombre de la interfaz */
    union {
                    struct sockaddr       ifr_addr;
                    struct sockaddr       ifr_dstaddr;
                    struct sockaddr       ifr_broadaddr;
                    struct sockaddr       ifr_netmask;
                    struct sockaddr       ifr_hwaddr;
                    short                 ifr_flags;
                    int                   ifr_ifindex;
                    int                   ifr_metric;
                    int                   ifr_mtu;
                    struct ifmap          ifr_map;
                    char                  ifr_slave[IFNAMSIZ];
                    char                  ifr_newname[IFNAMSIZ];
                    char *                ifr_data;
    };
}

(struct sockaddr)

1
2
3
4
5
struct sockaddr
{
   unsigned short sa_family;  /* familia de la dirección */
   char sa_data[14];          /* 14 bytes de la dirección del protocolo */  
};

(struct sockaddr_in)

1
2
3
4
5
6
7
struct sockaddr_in
{
   short int sin_family;        /* Familia de la Dirección              */
   unsigned short int sin_port; /* Puerto                               */
   struct in_addr sin_addr;     /* Dirección de Internet                */
   unsigned char sin_zero[8];   /* Del mismo tamaño que struct sockaddr */
};

(struct in_addr)

1
2
3
4
struct in_addr
{
   unsigned   long s_addr;
};

Bien, en el programa anterior, la línea más conflictiva es:

1
printf("IP de eth0: %s\n", inet_ntoa( (*(struct in_addr *) &ifr.ifr_addr.sa_data[2])));

En ella, sacaremos la dirección en forma de struct in_addr que es el que le gusta a inet_ntoa() (esta función sólo coge la dirección y la pone en forma de char* para que podamos entenderla.
Para llegar al struct in_addr, partimos de la estructura struct ifreq (variable ifr) que nos devuelve ioctl(), ésta tiene un campo llamado ifr_addr de tipo struct sockaddr. El tipo struct sockaddr y struct sockaddr_in podemos compararlos, es decir, podemos ponerlos uno encima de otro y pueden tener la misma información en el mismo byte, por tanto, podemos ver que el campo sa_data de un struct sockaddr coincide con sin_port, sin_addr y sin_zero de un struct sockaddr in; vemos que sin_port es de tipo unsigned short por tanto ocupará 2 bytes y como queremos la información encerrada en sa_data a partir del byte 2, de ahí viene dicho número. Si queremos ponerlo de otra forma, ésta podría ser:

1
2
struct sockaddr_in sain;
  printf("IP de eth0: %s\n", inet_ntoa( (*(struct in_addr *) &ifr.ifr_addr.sa_data[sizeof(sain.sin_port)])));

Skype + Webcam en Linux Mint / Ubuntu 64bit

Lunes, 11 de Abril de 2011 Gaspar Fernández 2 comentarios

skype-webcam_recorteLa semana pasada, el 6 de abril salió la nueva versión Beta de Skype 2.2 para Linux. Aunque esta versión esté a años luz de la versión para Windows (aunque por otra parte lo prefiero, no quiero que recarguen tanto el programa), había algunas cosas básicas que deberían haber hecho hace tiempo, sobre todo en el campo de la compatibilidad con la cámara web, por ejemplo.

El programa no es libre, ni piensa serlo, aunque el protocolo de voz de skype es de lo mejor que he visto, ya que permite la comunicación con mucha compresión, más nítida que con otros medios y un ancho de banda similar. Y aunque no se les vea muy comprometidos, hay que darles la enhorabuena por hacer su software para esta plataforma, y  al menos permitir comunicarnos con otros usuarios de skype.

Hasta el momento, para mí había varios problemas:

  • Con ALSA, a veces quería enviar más información de la cuenta o menos de la que se espera, y ALSA se quejaba, dejaba de escucharse un tiempo. Skype decía que era culpa de ALSA, ALSA, que era culpa de skype…
  • Con Pulseaudio a veces se perdía el sonido, era fallo de skype, pero bueno, se reinicia y no pasa nada.
  • Webcams:
    • Con una gráfica Intel, olvídate de que se vea tu webcam (es raro, pero ni ves ni envías)
    • Con otra gráfica, pero un SO de 64bit, olvídate también, no se podrá acceder a la webcam.

En esta nueva versión han hecho cambios en esos aspectos, dicen que han mejorado el audio con Pulseaudio, y al no poder provocar el error no lo he podido probar todavía, y han mejorado el soporte de webcams. Con un equipo con gráfica Intel no he probado, pero sí en 64bit.

Para funcionar con la webcam en 64bit (con ciertas cámaras, por ejemplo la OV511/519, yo tengo una Creative muy vieja, también se repite el problema con algunas Genius y algunas Logitech). Primero tendremos que instalar los módulos de compatibilidad de Video4Linux de 32 bit.

$ sudo apt-get install lib32v4l-0

Y a la hora de ejecutar skype:

$ LD_PRELOAD=/usr/lib32/libv4l/v4l1compat.so skype

Esto ya funcionaba en la Beta 2.1 con algunas cámaras, pero no con todas. Ahora funciona con algunas cámaras más.

Podremos configurar el acceso directo a skype para que ejecute también el LD_PRELOAD.

Ahora mismo, dejo las instrucciones para Linux Mint / Ubuntu, aunque en cualquier distribución podremos instalar las librerías Video4Linux de 32bit y precargarla antes de ejecutar skype.

Comprobación de IP invertida / Reverse IP Lookup

Martes, 16 de Febrero de 2010 Gaspar Fernández Sin comentarios

Desde hace mucho tiempo he utilizado CuWhois para hacer esta comprobación, ofrece muchos servicios interesantes para Webmasters y recomendaciones para posicionar mejor las webs, aunque desde hace tiempo, la comprobación de IP invertida no es tan completa como antes. Por ejemplo, hace unos años, probándola sobre este mismo dominio, daba unos 70 resultados de páginas que compartían esta misma IP (tengo un hosting compartido para esta web); ahora me dice que tengo 8 vecinos, y sólo me dice 6 de ellos.

Hoy gracias al página de Facebook de Hostarting he descubierto YouGetSignal, y aquí hay un listado más completo de las webs que encontramos en el servidor (dependiendo de con quién tengamos contratado el dominio nos convencerá mejor mirar en una u otra página, y siempre está bien que si encontramos información interesante la comprobemos a mano), y si tenemos un hosting compartido podemos ver cuánto se aprovecha nuestra empresa de hosting de nosotros y a veces, estimar más o menos cuánto están cobrando por un mismo servidor. :S Pero al menos nos da una idea aproximada de la carga que puede tener.

Geolocalización de una IP

Domingo, 26 de Julio de 2009 blakeyed Sin comentarios

A veces, nos es de bastante utilidad geolocalizar a un visitante, bien puede ser para mostrarle una publicidad relevante o porque prestamos un servicio que sólo existe en determinados países, para escoger automáticamente el idioma de nuestra web, o por motivos estadísticos, para saber de dónde provienen nuestras visitas, como medida en una red social para detectar automáticamente dónde estás… en fin, hay un sinfín de utilidades.

Lo más común para geolocalizar a los visitantes es verificar su dirección IP y consultar en una base de datos a qué país pertenece. Hay empresas que comercializan estas bases de datos, y las hay con mucha precisión (algunas pueden decirnos hasta la ciudad donde está conectada la persona con esa dirección IP). Aunque vengo a hablaros de un servicio gratuito: Ip to Country de Webhosting.info.

En las web citada viene mucha información de cómo utilizar la base de datos y código de ejemplo, por lo que no me extenderé mucho.

En resumen, tenemos que decargar el fichero CSV, que contiene la tabla que debemos incluir en nuestra base de datos (por ejemplo, PhpMyAdmin tiene la posibilidad de importar ficheros CSV). Seguidamente, hay que tener en cuenta que en esta tabla, la IP no está en el formato que estamos acostumbrados (4 números de 8bits separados por puntos), está en formato long, lo que es los 32bits (en PHP podemos hacer la conversión con ip2long()). Para hacer nuestro programa hemos de saber que la IP que queremos geolocalizar tiene que estar comprendida entre ip_from (primera ip que viene en la tabla) e ip_to (segunda ip).

Categories: PHP Tags: , , , , ,

Conseguir la IP del usuario

Viernes, 24 de Julio de 2009 blakeyed 2 comentarios

Os dejo el código:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function gf_obtiene_ip () {
  // Las variables _SERVER nos lo pueden decir
  $metodos = array("CLIENT_IP","HTTP_X_FORWARDED_FOR","HTTP_X_FORWARDED","HTTP_FORWARDED_FOR","HTTP_FORWARDED","REMOTE_ADDR");

  $i = 0;

  while ( ($i<count($metodos) ) || (!isset($ip) ) )  
    {
      $valor = $metodos[$i];
      if (isset($_SERVER[$valor]))
    $ip =$_SERVER[$valor];
      else if (isset($_ENV[$valor]))
    $ip =$_ENV[$valor];

      $i++;
  }
  return ( isset($ip) ) ? $ip: false;
}

Con este script intentamos evitar que se detecte como la IP del usuario la de un proxy intermedio recorriendo todas las variables que podemos encontrar en $metodos.

Categories: PHP Tags: , , ,

Visita otras webs de la red