5

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.

6 Answers 6

4

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

Sign up to request clarification or add additional context in comments.

Comments

3

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.

4 Comments

That looks helpful, but can you give me a link to some details of MNL? I can't find it on google.
Did you click the link? It went to source code for exactly what you asked for. If you browse the git tree a bit, you'll find the README: git.netfilter.org/cgi-bin/…
This is exactly the reason why link only answers shouldn't be posted on StackOverflow.
rotted link. Can't vote this up.
1

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

2 Comments

That's a program - is there a C API for it?
Use apt-get source ifupdown (or your distro's equivalent) to get the source, and you can see how it does it. However, I think this is one of those rare exceptions where system() is the right thing to do.
1

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.

Comments

1

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.

Comments

1

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>

1 Comment

If this did not predate chatgpt I'd suspect it was written by an LLM. It actually does work, but there are zero comments, and some very weird code choices like function pointers and assertions instead of normal input parameter checking. And up and down have reversed functionality. It does work though! And actually answers the question with working c code that's not in a rotted link.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.