在linux系统中如何删除一个接口的ip地址?
由于软件需要,有时候需要对linux的网卡配置多个ip地址,如监控系统中的网卡处于网络分域或者是多个网段中,在程序配置网卡地址时需要增加或者删除ip地址:
一般使用ioctl系统调用来更改网络接口的属性:
一、删除应该使用SIOCDIFADDR,但是在ipv4中没有实现这个调用,在ipv6中实现了
所以在ipv4下调用会出现 Invalid argument的错误
二、这里有一种变通的方法来删除ip地址,即使用SIOCSIFADDR来给接口设置0.0.0.0的地址,效果是对应接口上ip地址被删除了,
具体的操作:
- 通过SIOCGIFCONF来枚举所有的带不同IP的接口
- 在这些接口中使用SIOCGIFADDR获取IP
- 如果发现要删除IP,使用SIOCSIFADDR "0.0.0.0"来删除IP
三、举例
int fd;
int interfaceNum = 0;
struct ifreq buf[32];
struct ifconf ifc;
struct ifreq ifrcopy;
int okNetA = 1;
int okNetB = 1;
if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket");
close(fd);
return false;
}
ifc.ifc_len = sizeof(buf);
ifc.ifc_buf = (caddr_t)buf;
if (!ioctl(fd, SIOCGIFCONF, (char *)&ifc))
{
interfaceNum = ifc.ifc_len / sizeof(struct ifreq);
while (interfaceNum-- > 0) //逐个提取
{
if ((okNetA && !strnicmp(buf[interfaceNum].ifr_name, ifname_a, strlen(ifname_a))) ||
(okNetB && !strnicmp(buf[interfaceNum].ifr_name, ifname_b, strlen(ifname_b))))
{
ifrcopy = buf[interfaceNum];
if (!ioctl(fd, SIOCGIFADDR, (char *)&ifrcopy))
{
char ip[32];
snprintf(ip, sizeof(ip), "%s",
(char *)inet_ntoa(((struct sockaddr_in *) &
(ifrcopy.ifr_addr))->sin_addr));
printf("device ip: %s\n", ip);
/*}
else
{
printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
close(fd);
return -1;*/
}
struct sockaddr_in sai;
memset(&sai, 0, sizeof(struct sockaddr));
sai.sin_family = AF_INET;
sai.sin_port = 0;
sai.sin_addr.s_addr = 0;
memcpy( (char *)&(ifrcopy.ifr_addr), (char *) &sai, sizeof(struct sockaddr));
if (ioctl(fd, SIOCSIFADDR, (caddr_t)&ifrcopy,sizeof(ifrcopy)))
{
printf("ioctl: %s [%s:%d]\n", strerror(errno), __FILE__, __LINE__);
//close(fd);
//return false;
}
}
}
四、参考资料:
http://mailman.icsi.berkeley.edu/pipermail/xorp-hackers/2003-October/000010.html
https://stackoverflow.com/questions/5308090/set-ip-address-using-siocsifaddr-ioctl