Linux无法使用ioctl删除持久性tun接口

问题描述


如果在未设置TUNSETPERSIST的情况下创建了tun接口,则该接口将一直存在,直到关闭文件描述符为止。

so_q_nonpersistent.c

#include <assert.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define D "tun0"

int main(){

  assert(0==getuid());

  struct ifreq ifc={.ifr_flags=IFF_TUN|IFF_NO_PI};
  strncpy(ifc.ifr_name,D,IFNAMSIZ);

  int tunfd=open("/dev/net/tun",O_RDWR);
  assert(tunfd>=3);
  assert(0==ioctl(tunfd,TUNSETIFF,&ifc));

  // Interface appears

  getchar();

  close(tunfd);
  tunfd=-1;

  // Interface disappears

  return 0;

}

如果设置了TUNSETPERSIST,它将在关闭文件描述符中保留。

如何重新打开文件描述符并正确删除它?

so_q_persistent.c

#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <linux/if.h>
#include <linux/if_tun.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define D "tun0"

void tun_create(){
  assert(0==getuid());
  struct ifreq ifc={.ifr_flags=IFF_TUN|IFF_NO_PI};
  strncpy(ifc.ifr_name,IFNAMSIZ);
  int tunfd=open("/dev/net/tun",&ifc));
  assert(0==ioctl(tunfd,TUNSETPERSIST,1));
  close(tunfd);
  tunfd=-1;
}

void tun_del(){
  assert(0==getuid());
  struct ifreq ifc={};
  strncpy(ifc.ifr_name,O_RDWR);
  assert(tunfd>=3);
  errno=0;
  const int r=ioctl(tunfd,0);
  const int e=errno;
  if(r!=0){
    printf("%d %d %s\n",r,e,strerror(e));
    assert(false);
  }
  close(tunfd);
  tunfd=-1;
}

int main(){
  tun_create();
  tun_del();
  return 0;
}

运行(无法删除

$ sudo ./persist.out
-1 77 File descriptor in bad state
persist.out: so_q_persist.c:37: tun_del: Assertion `false' Failed.
Aborted

An example without closing the file descriptor

if(delete) {
  /* remove persistent status */
  if(ioctl(tap_fd,0) < 0){
    perror("disabling TUNSETPERSIST");
    exit(1);
  }
  printf("Set '%s' nonpersistent\n",ifr.ifr_name);
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)