¿Hay alguna manera de detectar cambios de direcciones IP en la máquina local en Linux mediante programación mediante C++?¿Cómo detectar el cambio de dirección IP programáticamente en Linux?
Respuesta
En C, para obtener el IP actual que utilizo:
int s;
struct ifreq ifr = {};
s = socket(PF_INET, SOCK_DGRAM, 0);
strncpy(ifr.ifr_name, "eth0", sizeof(ifr.ifr_name));
if (ioctl(s, SIOCGIFADDR, &ifr) >= 0)
printf("%s\n",
inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr));
reemplazar "eth0" con la interfaz que está viendo. Todo lo que debes hacer ahora es sondear para un cambio.
Esto es exactamente lo que hace "ifconfig" para obtener la dirección IP actual de una interfaz. Para averiguar qué nombres de interfaz existen, en realidad se abre y analiza "/ proc/net/dev". Sin embargo, debería haber una manera de obtener un evento del kernel cuando cambia la IP. Mi suposición es usar uevents. – nly
Lamentablemente, esto no es confiable para sistemas modernos, donde una única interfaz puede tener múltiples direcciones sin el uso de subinterfaces. –
hay un ejemplo de trabajo aquí: http://stackoverflow.com/a/701989/386557 –
Una forma sería escribir un trabajo cron que contenga una llamada a uno de la familia gethost de las funciones de la biblioteca. Si usa gethostbyname(), puede comparar los valores de retorno de h_addr_list. Ver hombre gethostbyname.
Si quieres hacer esto desde dentro de tu programa, engendra un pthread que hace lo mismo, luego duerme durante un período de tiempo arbitrario.
No es fácil de ninguna manera. Cada distribución de Linux utiliza diferentes lugares para almacenar direcciones IP, etc. (más variación si considera otras variantes de UNIX). Usted puede uso, por ejemplo, /sbin/ifconfig
para obtener las direcciones IP de las interfaces, pero ni siquiera se puede estar seguro de si lo encontrará en este lugar, o en absoluto, etc.
Además, dado que tiene ese ejecutable, tiene que configurar un hilo que lo llame para obtener los datos con un período determinado (digamos 5 segundos), e interpretar el resultado. Puede variar, por ejemplo, si tiene puentes, etc. etc. Es decir, no es fácil.
Una solución que me viene a la mente es que, si tiene la oportunidad de usar GNOME o alguna otra distribución generalizada como KDE, puede confiar en los mensajes/información que brindan. Por ejemplo, NetworkManager
emite una señal al DBUS standard bus cuando cambia un dispositivo. Tienes que implementar un oyente para esas señales. Información here (no funciona en este momento, así que aquí está un cache). Tenga en cuenta los diferentes mensajes cuando se agrega una nueva interfaz, o cuando uno de ellos cambia la dirección IP. Esta es la mejor manera en que puedo pensar en este momento.
Si sus usuarios usan NetworkManager, puede sondear NetworkManager.Connection.Active y NetworkManager.IP4Config a través de D-Bus para obtener una forma más de distribución cruzada para determinar esta información.
Si iproute2 está instalado y ya está en un kernel 2.6,
/sbin/ip monitor
cambios de salida será en el estado de la interfaz local y direcciones a la salida estándar. Tu programa puede leer esto.
También podría usar el mismo mecanismo de bajo nivel que la herramienta iproute2 (creo que es una conexión de red).
De página del manual de rtnetlink:
DESCRIPCIÓN
Rtnetlink permite tablas de enrutamiento del kernel para leer y alterar. Se usa dentro del kernel para comunicarse entre varios subsistemas, aunque este uso no está documentado aquí, y para la comunicación con programas de espacio de usuario. Las rutas de red, las direcciones IP, los parámetros de enlace, las configuraciones vecinas, las disciplinas de colas, las clases de tráfico y los clasificadores de paquetes pueden controlarse a través de los zócalos NETLINK_ROUTE. Se basa en mensajes netlink, ver netlink (7) para más información.
sugerencia de ste para usar ioctl SIOCGIFADDR solía ser técnicamente correcto, desafortunadamente no es confiable para los sistemas Linux modernos, donde una sola interfaz puede tener múltiples direcciones sin usar subinterfaces (por ej. Eth0: 1) como se hizo con el ahora -obsolete ifconfig.
Su mejor opción es utilizar getifaddrs (3), que está presente desde glibc 2.3: http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html
Por desgracia, es algo ineficaz (que obtener una lista enlazada de todas las direcciones de todas las interfaces y tendrá que recorrer para encontrar las que le interesan), pero en la mayoría de los casos probablemente no lo verifique más de una vez por minuto, lo que hace que la sobrecarga sea tolerable.
aquí tienes ... esto lo hace sin sondeo.
sólo escucha los RTM_NEWADDR pero debe ser fácil de cambiar para apoyar RTM_DELADDR si necesita
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <net/if.h>
int
main()
{
struct sockaddr_nl addr;
int sock, len;
char buffer[4096];
struct nlmsghdr *nlh;
if ((sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE)) == -1) {
perror("couldn't open NETLINK_ROUTE socket");
return 1;
}
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
addr.nl_groups = RTMGRP_IPV4_IFADDR;
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
perror("couldn't bind");
return 1;
}
nlh = (struct nlmsghdr *)buffer;
while ((len = recv(sock, nlh, 4096, 0)) > 0) {
while ((NLMSG_OK(nlh, len)) && (nlh->nlmsg_type != NLMSG_DONE)) {
if (nlh->nlmsg_type == RTM_NEWADDR) {
struct ifaddrmsg *ifa = (struct ifaddrmsg *) NLMSG_DATA(nlh);
struct rtattr *rth = IFA_RTA(ifa);
int rtl = IFA_PAYLOAD(nlh);
while (rtl && RTA_OK(rth, rtl)) {
if (rth->rta_type == IFA_LOCAL) {
uint32_t ipaddr = htonl(*((uint32_t *)RTA_DATA(rth)));
char name[IFNAMSIZ];
if_indextoname(ifa->ifa_index, name);
printf("%s is now %d.%d.%d.%d\n",
name,
(ipaddr >> 24) & 0xff,
(ipaddr >> 16) & 0xff,
(ipaddr >> 8) & 0xff,
ipaddr & 0xff);
}
rth = RTA_NEXT(rth, rtl);
}
}
nlh = NLMSG_NEXT(nlh, len);
}
}
return 0;
}
Gran código. ¿Hay alguna forma de mirar solo una interfaz específica para un cambio? – watain
@watain the 'struct ifaddrmsg' tiene un miembro' ifa_index', que es el índice de interfaz de la interfaz a la que está asociada la dirección. –
Debe tenerse en cuenta en la página de manual para estas API de netlink, se recomienda no utilizar esta interfaz de bajo nivel, sino más bien la [libnetlink lib] (http://man7.org/linux/man-pages/man3/libnetlink. 3.html) ... que a su vez enumera el uso de esta lib como un error y señala el uso de [libmnl] (http://www.netfilter.org/projects/libmnl/) en su lugar – Joakim
- 1. ¿Cómo establecer mi dirección de IP programáticamente?
- 2. Cómo detectar el cambio de dirección IP en OSX mediante programación en C o C++
- 3. ¿Cómo cambio la dirección IP en Oracle 10g
- 4. Obtenga la dirección IP de la máquina
- 5. Cómo obtener programáticamente la dirección del montón en Linux
- 6. Obtener la dirección IP de una interfaz en Linux
- 7. Dirección IP en Silverlight
- 8. Dirección IP de sk_buff
- 9. ¿Cómo obtener la dirección IP?
- 10. Cómo detectar el idioma de un usuario a través de su dirección IP
- 11. Mire para ver el cambio en el estado de la dirección IP
- 12. ¿Cómo compararías la dirección IP?
- 13. Dirección IP en un MaskedTextBox?
- 14. ¿Cómo detectar el cierre del sistema pendiente en Linux?
- 15. ¿Cómo cambio programáticamente los permisos de archivos?
- 16. Buscar dirección IP en iphone
- 17. Cómo registrar la dirección IP en JBoss
- 18. Cómo validar una dirección IP en C#
- 19. Cómo filtrar por dirección IP en Wireshark?
- 20. Cómo se detecta un cambio en la dirección IP de MS Windows sin sondeo
- 21. C# Dirección IP de cadena
- 22. recortar dirección IP octeto
- 23. Configurar Android IP, DNS, configuración GATEWAY programáticamente
- 24. Dirección IP inyección SQL
- 25. .Net Dirección IP IPv4
- 26. ¿Por qué recibo :: 1 como dirección IP en ASP.Net .. y cómo obtener la dirección IP correcta?
- 27. Dirección IP no obtenida en java
- 28. Generar dirección IP aleatoria
- 29. cómo redirigir el dominio según el país dirección de IP
- 30. Geocodificar una dirección IP?
+1: pregunta común, contento de ver que pidió aquí. –
Danny, en mi humilde opinión, si su solución no es una encuesta, ¿entonces qué es? esperas claramente recibir un mensaje particular del zócalo, también tranquilo complicado cuando uno simplemente puede sondear la salida de ifconfig o usar getifaddrs como otros sugirieron – user3529114