ver saber publica para kali como comando cambiar c++ linux

c++ - saber - ¿Cómo detectar el cambio de dirección IP programáticamente en Linux?



ipconfig en linux (8)

¿Hay alguna manera de detectar cambios de direcciones IP en la máquina local en Linux mediante programación mediante C ++?


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). Puede usar, por ejemplo, /sbin/ifconfig para obtener las direcciones IP de las interfaces, pero ni siquiera puede estar seguro de si lo encontrará en este lugar, o en absoluto, etc.

Además, dado que tienes ese ejecutable, debes 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 se me ocurre es que, si tiene la oportunidad de utilizar 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 bus estándar DBUS cuando cambia un dispositivo. Tienes que implementar un oyente para esas señales. Información aquí (no funciona ahora, así que aquí hay un caché ). 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.


Una forma sería escribir un trabajo cron que contenga una llamada a uno de la familia gethost de 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 tu programa, engendra un pthread que hace lo mismo, luego duerme durante un período de tiempo arbitrario.


En C, para obtener la IP actual que uso:

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));

Reemplaza "eth0" con la interfaz que estás viendo. Todo lo que debes hacer ahora es sondear para un cambio.


Si iproute2 está instalado y estás en un kernel 2.6,

/sbin/ip monitor

La producción cambiará en el estado de la interfaz local y las direcciones a stdout. Tu programa puede leer esto.

También podría usar el mismo mecanismo de bajo nivel que la herramienta iproute2 (creo que es un socket de netlink).


Desde la página man de rtnetlink:

DESCRIPCIÓN

Rtnetlink permite leer y modificar las tablas de enrutamiento del kernel. 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.


La sugerencia de ste de usar ioctl SIOCGIFADDR solía ser técnicamente correcta, desafortunadamente no es confiable para los sistemas Linux modernos, donde una sola interfaz puede tener múltiples direcciones sin usar subinterfaces (ej. eth0: 1) como se hizo con el ifconfig ahora obsoleto.

Su mejor opción es usar getifaddrs (3), que está presente en glibc 2.3: http://www.kernel.org/doc/man-pages/online/pages/man3/getifaddrs.3.html

Desafortunadamente es un poco ineficiente (se obtiene una lista vinculada de todas las direcciones en todas las interfaces y tendrá que repetir para encontrar las que le interesan), pero en la mayoría de los casos probablemente no lo esté verificando más de una vez por minuto. más o menos, haciendo que la sobrecarga sea tolerable.


aquí tienes ... esto lo hace sin votación.

solo escucha RTM_NEWADDR pero debería ser fácil cambiar para admitir 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; }