以编程方式启用/禁用 UNIX 网络接口

发布于 2024-10-18 21:29:10 字数 182 浏览 2 评论 0原文

有很多非常相似的问题发布,但它们都是针对 Windows - 我想知道如何(如果可能的话)我可以让我的 C 程序(在 Linux 上以 root 身份运行)禁用网络接口,以便它不再接收任何数据包。

如果有人可以告诉我需要哪些功能来执行此操作,那就太好了,但如果您可以将我链接到示例脚本或教程(例如)关闭并再次打开网络接口,那就更好了。

There are a lot of very similar questions posted, but they are all for windows - I want to know how (if it is possible) I can have my C program (run as root, on linux) disable the network interface so that it is no longer receiving any packets.

If someone can tell me what functions I need to do this, that would be great, but even better if you can link me to an example script or tutorial somewhere that (exempli gratia) turns the network interface off and on again.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

等你爱我 2024-10-25 21:29:10

没有完整的示例,但以下关键字应该可以帮助您入门(至少在 Linux 上,不确定其他版本的 Unix):

ioctl、SIOCSIFFLAGS、IFF_UP

以下内容可能有助于显示相关 API:http://www.google.com/codesearch/p?hl=en#2--Ws53NXRc/src/ifdown.c

Don't have a complete example, but the following key words should get you started (on Linux at least, not sure about other flavours of Unix):

ioctl, SIOCSIFFLAGS, IFF_UP

The following might be of use as far as showing the relevant APIs: http://www.google.com/codesearch/p?hl=en#2--Ws53NXRc/src/ifdown.c

-残月青衣踏尘吟 2024-10-25 21:29:10

对于 Linux,所有这些都可以通过 MNL 和 RTNL 协议的知识轻松完成:

http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=blob; f=examples/rtnl/rtnl-link-set.c;hb=HEAD

在 Unices 或其他操作系统上,只有特定于操作系统的调用和/或古老的 ioctl 调用可用,后者无法表达Linux 每个接口都有多个地址,因此严肃的程序不会在该平台上使用它。

For Linux, all easily doable with MNL and knowledge of the RTNL protocol:

http://git.netfilter.org/cgi-bin/gitweb.cgi?p=libmnl.git;a=blob;f=examples/rtnl/rtnl-link-set.c;hb=HEAD

On Unices or other operating systems, only a OS-specific call and/or the archaic ioctl call is available, the latter of which cannot express Linux multiple addresses per interface properly, so serious programs do not make use of it on that platform.

哀由 2024-10-25 21:29:10

在 Linux 上,您可以使用 ifdown。我不知道它对于其他 UNIX 的移植性如何。

On Linux, you can use ifdown. I don't know how portable that is to other unixes.

拥抱我好吗 2024-10-25 21:29:10

在我使用过的 Linux 和大多数基于 Unix 的系统上,ifconfigup/down 用于打开或关闭接口。不确定是否有 C 例程可用于在不执行 ifconfig 的情况下执行此操作。

On both Linux and most Unix based systems I've used, ifconfig <interface> up/down is used to bring an interface up or down. Not sure if there is a C routine available for this without execing ifconfig.

瑾夏年华 2024-10-25 21:29:10

在 Linux 上,命令 ip link set down dev ethX 的作用与您想要的差不多。如果您在该平台上,我建议您调用该程序来完成您的工作。

如果你想自己做的话,C api 并不是一件简单的事情。 您可以深入研究 iproute 源代码以了解它的作用。

检查 @user611775 的答案,了解如何在 C 中执行此操作的绝佳示例。

如果您使用其他语言对于 Unix,每种特定风格的答案可能会有所不同。

On Linux, the command ip link set down dev ethX does no more or less then what you want. I'd suggest calling this program to do your work if you're on that platform.

If you want to do it yourself, the C api for this is not a simple thing. You could dive into the iproute source to find out what it does.

Check @user611775's answer for an excellent example of how to do it in C.

If you're on another Unix, the answer is likely going to to be different for each specific flavour.

绅士风度i 2024-10-25 21:29:10

下面是一个示例 C 代码,展示了如何使用 ioctl(netdevice) 或 (rt)netlink 打开和关闭接口

Linux 手册页项目
netlink(7) netlink(3)
rtnetlink(7) rtnetlink(3)
netdevice(7)

so_q_5094495.c

#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h> // getuid()

// netlink
#include <linux/rtnetlink.h>

// ioctl
#include <net/if.h>
#include <netinet/in.h> // IPPROTO_UDP
#include <sys/ioctl.h>

int ioctlfd=-1;
int netlinkfd=-1;

typedef struct {
  struct nlmsghdr nh;
  struct ifinfomsg ifi;
} Req_link;

void ioctl_init(){
  ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  assert(ioctlfd==3);
}

void ioctl_end(){
  close(ioctlfd);
  ioctlfd=-1;
}

void ioctl_flags(const bool up,const char *const dev){
  assert(0==getuid());
  struct ifreq ifr={};
  strncpy(ifr.ifr_name,dev,IFNAMSIZ);
  assert(0==ioctl(ioctlfd,SIOCGIFFLAGS,&ifr));
  if(up) ifr.ifr_flags|=IFF_UP;
  else ifr.ifr_flags&=(~((short)IFF_UP));
  assert(0==ioctl(ioctlfd,SIOCSIFFLAGS,&ifr));
}

void netlink_init(){
  netlinkfd=socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
  assert(netlinkfd==3);
  assert(0==bind(netlinkfd,(struct sockaddr*)(&(struct sockaddr_nl){
    .nl_family=AF_NETLINK,
    .nl_pad=0,
    .nl_pid=getpid(),
    .nl_groups=0
  }),sizeof(struct sockaddr_nl)));
}

void netlink_end(){
  assert(0==close(netlinkfd));
  netlinkfd=-1;
}

void netlink_flags(const bool up,const char *const dev){

  assert(0==getuid());
  assert(dev&&strlen(dev));
  const unsigned index=if_nametoindex(dev);
  assert(index>0);

  assert(sizeof(Req_link)==send(netlinkfd,&(Req_link){
    .nh={
      .nlmsg_len=NLMSG_LENGTH(sizeof(struct ifinfomsg)),
      .nlmsg_type=RTM_NEWLINK,
      .nlmsg_flags=NLM_F_REQUEST,
      .nlmsg_seq=0,
      .nlmsg_pid=getpid()
    },
    .ifi={
      .ifi_family=AF_UNSPEC,
      .ifi_type=0,
      .ifi_index=index,
      .ifi_flags=up?IFF_UP:0,
      // https://www.spinics.net/lists/netdev/msg598191.html
      .ifi_change=IFF_UP
    }
  },sizeof(Req_link),0));

}

int main(const int argc,const char *argv[]){

  assert(argc==3+1);

  void (*flags)(const bool,const char *const)=NULL;
  void (*init)()=NULL;
  void (*end)()=NULL;
  assert(strlen(argv[1]));
  if(0==strcmp("ioctl",argv[1])){
    init=&ioctl_init;
    flags=&ioctl_flags;
    end=&ioctl_end;
  }else if(0==strcmp("netlink",argv[1])){
    init=&netlink_init;
    flags=&netlink_flags;
    end=&netlink_end;
  }else{
    assert(false);
  }

  bool up=false;
  if(0==strcmp("down",argv[2])) up=true;
  else if(0==strcmp("up",argv[2])) up=false;
  else assert(false);

  assert(strlen(argv[3])&&strlen(argv[3])<=IFNAMSIZ-1);

  (*init)();
  (*flags)(up,argv[3]);
  (*end)();

  return 0;

}

运行

$ gcc -Wall -std=gnu11 so_q_5094495.c
$ sudo ./a.out netlink up   enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<BROADCAST,MULTICAST>
$ sudo ./a.out netlink down enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<NO-CARRIER,BROADCAST,MULTICAST,UP>
$ sudo ./a.out ioctl   up   enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<BROADCAST,MULTICAST>
$ sudo ./a.out ioctl   down enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<NO-CARRIER,BROADCAST,MULTICAST,UP>

Here is an example C code showing how to turn interfaces up and down w/ ioctl(netdevice) or (rt)netlink

The Linux man-pages project
netlink(7) netlink(3)
rtnetlink(7) rtnetlink(3)
netdevice(7)

so_q_5094495.c

#include <assert.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h> // getuid()

// netlink
#include <linux/rtnetlink.h>

// ioctl
#include <net/if.h>
#include <netinet/in.h> // IPPROTO_UDP
#include <sys/ioctl.h>

int ioctlfd=-1;
int netlinkfd=-1;

typedef struct {
  struct nlmsghdr nh;
  struct ifinfomsg ifi;
} Req_link;

void ioctl_init(){
  ioctlfd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  assert(ioctlfd==3);
}

void ioctl_end(){
  close(ioctlfd);
  ioctlfd=-1;
}

void ioctl_flags(const bool up,const char *const dev){
  assert(0==getuid());
  struct ifreq ifr={};
  strncpy(ifr.ifr_name,dev,IFNAMSIZ);
  assert(0==ioctl(ioctlfd,SIOCGIFFLAGS,&ifr));
  if(up) ifr.ifr_flags|=IFF_UP;
  else ifr.ifr_flags&=(~((short)IFF_UP));
  assert(0==ioctl(ioctlfd,SIOCSIFFLAGS,&ifr));
}

void netlink_init(){
  netlinkfd=socket(AF_NETLINK,SOCK_RAW,NETLINK_ROUTE);
  assert(netlinkfd==3);
  assert(0==bind(netlinkfd,(struct sockaddr*)(&(struct sockaddr_nl){
    .nl_family=AF_NETLINK,
    .nl_pad=0,
    .nl_pid=getpid(),
    .nl_groups=0
  }),sizeof(struct sockaddr_nl)));
}

void netlink_end(){
  assert(0==close(netlinkfd));
  netlinkfd=-1;
}

void netlink_flags(const bool up,const char *const dev){

  assert(0==getuid());
  assert(dev&&strlen(dev));
  const unsigned index=if_nametoindex(dev);
  assert(index>0);

  assert(sizeof(Req_link)==send(netlinkfd,&(Req_link){
    .nh={
      .nlmsg_len=NLMSG_LENGTH(sizeof(struct ifinfomsg)),
      .nlmsg_type=RTM_NEWLINK,
      .nlmsg_flags=NLM_F_REQUEST,
      .nlmsg_seq=0,
      .nlmsg_pid=getpid()
    },
    .ifi={
      .ifi_family=AF_UNSPEC,
      .ifi_type=0,
      .ifi_index=index,
      .ifi_flags=up?IFF_UP:0,
      // https://www.spinics.net/lists/netdev/msg598191.html
      .ifi_change=IFF_UP
    }
  },sizeof(Req_link),0));

}

int main(const int argc,const char *argv[]){

  assert(argc==3+1);

  void (*flags)(const bool,const char *const)=NULL;
  void (*init)()=NULL;
  void (*end)()=NULL;
  assert(strlen(argv[1]));
  if(0==strcmp("ioctl",argv[1])){
    init=&ioctl_init;
    flags=&ioctl_flags;
    end=&ioctl_end;
  }else if(0==strcmp("netlink",argv[1])){
    init=&netlink_init;
    flags=&netlink_flags;
    end=&netlink_end;
  }else{
    assert(false);
  }

  bool up=false;
  if(0==strcmp("down",argv[2])) up=true;
  else if(0==strcmp("up",argv[2])) up=false;
  else assert(false);

  assert(strlen(argv[3])&&strlen(argv[3])<=IFNAMSIZ-1);

  (*init)();
  (*flags)(up,argv[3]);
  (*end)();

  return 0;

}

Run

$ gcc -Wall -std=gnu11 so_q_5094495.c
$ sudo ./a.out netlink up   enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<BROADCAST,MULTICAST>
$ sudo ./a.out netlink down enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<NO-CARRIER,BROADCAST,MULTICAST,UP>
$ sudo ./a.out ioctl   up   enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<BROADCAST,MULTICAST>
$ sudo ./a.out ioctl   down enp0s31f6; ip link show enp0s31f6 | grep -o '<.*>'
<NO-CARRIER,BROADCAST,MULTICAST,UP>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文