Cómo configurar la dirección IP desde C en Linux

Al usar strace y ifconfig, descubrí que puedo configurar la dirección IP de esta manera:

#include  #include  #include  #include  int main(int argc, const char *argv[]) { struct ifreq ifr; const char * name = "eth1"; int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_IP); strncpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_addr.sa_family = AF_INET; inet_pton(AF_INET, "10.12.0.1", ifr.ifr_addr.sa_data + 2); ioctl(fd, SIOCSIFADDR, &ifr); inet_pton(AF_INET, "255.255.0.0", ifr.ifr_addr.sa_data + 2); ioctl(fd, SIOCSIFNETMASK, &ifr); ioctl(fd, SIOCGIFFLAGS, &ifr); strncpy(ifr.ifr_name, name, IFNAMSIZ); ifr.ifr_flags |= (IFF_UP | IFF_RUNNING); ioctl(fd, SIOCSIFFLAGS, &ifr); return 0; } 

Pero no estoy muy contento con esta solución:

 inet_pton(AF_INET, "10.12.0.1", ifr.ifr_addr.sa_data + 2); 

¿Cuál es la forma “correcta” de hacer esto?

La forma “correcta” para IPv4 sin magic +2:

 struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr; inet_pton(AF_INET, "10.12.0.1", &addr->sin_addr); 

Para usar IPv6, sockaddr_in6 a sockaddr_in6

La forma “correcta” de hacerlo es generar una copia del progtwig “ip” de iproute2 (en / sbin / ip) con parámetros relevantes.

la interfaz ioctl generalmente es obsoleta y no le permite configurar todos los parámetros (por ejemplo, alias IP sin nombre).

Incluso daemons como dhcpcd que necesitan cambiar la dirección IP, normalmente lo hacen generando un progtwig externo … no es como si lo hicieras muy a menudo.

 #include  #include  #include  // close() #include  // strcpy, memset(), and memcpy() #include  // struct addrinfo #include  // needed for socket(), uint8_t, uint16_t #include  // needed for socket() #include  // IPPROTO_RAW, INET_ADDRSTRLEN #include  // IP_MAXPACKET (which is 65535) #include  // inet_pton() and inet_ntop() #include  // macro ioctl is defined #include  // defines values for argument "request" of ioctl. #include  // struct ifreq #include  // ETH_P_ARP = 0x0806 #include  // struct sockaddr_ll (see man 7 packet) #include  #include  // errno, perror() #include  #include  /** * Create socket function */ int create_socket() { int sockfd = 0; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if(sockfd == -1){ fprintf(stderr, "Could not get socket.\n"); return -1; } return sockfd; } /** * Generic ioctrlcall to reduce code size */ int generic_ioctrlcall(int sockfd, u_long *flags, struct ifreq *ifr) { if (ioctl(sockfd, (long unsigned int)flags, &ifr) < 0) { fprintf(stderr, "ioctl: %s\n", (char *)flags); return -1; } return 1; } /** * Set route with metric 100 */ int set_route(int sockfd, char *gateway_addr, struct sockaddr_in *addr) { struct rtentry route; int err = 0; memset(&route, 0, sizeof(route)); addr = (struct sockaddr_in*) &route.rt_gateway; addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr(gateway_addr); addr = (struct sockaddr_in*) &route.rt_dst; addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr("0.0.0.0"); addr = (struct sockaddr_in*) &route.rt_genmask; addr->sin_family = AF_INET; addr->sin_addr.s_addr = inet_addr("0.0.0.0"); route.rt_flags = RTF_UP | RTF_GATEWAY; route.rt_metric = 100; err = ioctl(sockfd, SIOCADDRT, &route); if ((err) < 0) { fprintf(stderr, "ioctl: %s\n", "mahdi MOAHMMADI Error"); return -1; } return 1; } /** * Set ip function */ int set_ip(char *iface_name, char *ip_addr, char *gateway_addr) { if(!iface_name) return -1; struct ifreq ifr; struct sockaddr_in sin; int sockfd = create_socket(); sin.sin_family = AF_INET; // Convert IP from numbers and dots to binary notation inet_aton(ip_addr,&sin.sin_addr.s_addr); /* get interface name */ strncpy(ifr.ifr_name, iface_name, IFNAMSIZ); /* Read interface flags */ generic_ioctrlcall(sockfd, (u_long *)"SIOCGIFFLAGS", &ifr); /* * Expected in  according to * "UNIX Network Programming". */ #ifdef ifr_flags # define IRFFLAGS ifr_flags #else /* Present on kFreeBSD */ # define IRFFLAGS ifr_flagshigh #endif // If interface is down, bring it up if (ifr.IRFFLAGS | ~(IFF_UP)) { ifr.IRFFLAGS |= IFF_UP; generic_ioctrlcall(sockfd, (u_long *)"SIOCSIFFLAGS", &ifr); } // Set route set_route(sockfd, gateway_addr , &sin); memcpy(&ifr.ifr_addr, &sin, sizeof(struct sockaddr)); // Set interface address if (ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { fprintf(stderr, "Cannot set IP address. "); perror(ifr.ifr_name); return -1; } #undef IRFFLAGS return 0; } 

uso:

 set_ip("eth0", "192.168.181.128", "192.168.181.1");