Question:
Is there a way of using ioctl
to change only a desired interface component without affecting the other parts of the network interface?
Reasoning
I'm writing a C++ program that allows a user to change the IP address, Broadcast address, Netmask, and Default Gateway independently of one another on a Linux machine. I modified this code for the IP, Bcast and NMask solution. However, changing the IP address with ioctl
is automatically modifying my Broadcast/Netmask, and clearing the Kernel IP Routing table.
Here's an example. Before running the code below, this is the result of ifconfig
and route -n
:
This is a functional version of the code that modifies the IP address:
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <string.h>
#include <iostream>
int main(int argc, const char *argv[]) {
struct ifreq ifr;
struct sockaddr_in* addr = (struct sockaddr_in*)&ifr.ifr_addr;
const char * name = "eth0";
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.10.2.59", &addr->sin_addr);
if(ioctl(fd, SIOCSIFADDR, &ifr) < 0)
{
std::cout << "Failed to set IP: " << strerror(errno) << std::endl;
return -1;
}
if(ioctl(fd, SIOCGIFFLAGS, &ifr) < 0)
{
std::cout << "Failed to get flags: " << strerror(errno) << std::endl;
return -2;
}
strncpy(ifr.ifr_name, name, IFNAMSIZ);
ifr.ifr_flags |= (IFF_UP | IFF_RUNNING);
if(ioctl(fd, SIOCSIFFLAGS, &ifr) < 0)
{
std::cout << "Failed to set flags: " << strerror(errno) << std::endl;
return -3;
}
return 0;
}
This is the resulting network card status after running the above program:
As you can see, the IP address was modified as desired, but the rest of the interface changed (which is not desirable).
I've been unable to find anything on the internet or the netdevice man page about preventing ioctl
from automatically modifying other parts of the network interface.
I know I could set the values of struct ifreq
so the Bcast and Mask components don't change, but I would prefer to be able to modify each component individually without worrying about the values of the other ones. I especially don't want to keep track of the default gateway and have to add it in every time I make a change to the IP address.
UPDATE
After doing more tests and research, I've found that this issue still occurs when running the system commands ifconfig
or ip
. For example, if instead of running the above code one ran ifconfig eth0 10.10.2.59
the result is the same.
Using the ip
command is somewhat different, as changing the ip address requires running ip addr del 10.10.2.58/16 dev eth0 && ip addr add 10.10.2.59/16 dev eth0
. Thus, you delete a known address/netmask combo and add another. Since the broadcast address was not specified, it is set to 0.0.0.0
. However, this command still removes the default gateway from the routing table.