Find the interface used by a connected socket - linux

I need to find the specific interface which is used by a socket, so that I can keep stats for it, using the sysfs files (/sys/class/net/<IF>/statistics/etc).
I've tried two different approaches in the test code below, but both fail. The first one connects to a remote server, and uses ioctl with SIOCGIFNAME, but this fails with 'no such device'. The second one instead uses getsockopt with SO_BINDTODEVICE, but this again fails (it sets the name length to 0).
Any ideas on why these are failing, or how to get the I/F name? after compiling, run the test code as test "a.b.c.d", where a.b.c.d is any IPV4 address which is listening on port 80. Note that I've compiled this on Centos 7, which doesn't appear to have IFNAMSZ in <net/if.h>, so you may have to comment out the #define IFNAMSZ line to get this to compile on other systems.
Thanks.
EDIT
I've since found that this is essentially a dupe of How can I get the interface name/index associated with a TCP socket?, so I should probably remove this. (Only) one of the answers there is correct (https://stackoverflow.com/a/37987807/785194) - get your local IP address with getsockname, and then look up this address in the list returned by getifaddrs.
On the general issue that sockets are essentially dynamic (mentioned below, and several times in the other question): not really relevant. I've checked the kernel source, and sockets have an interface index and interface name, and the API includes at least three ways to get the current name, and other routines to look up the name from the index, and vice-versa. However, the index is somtimes zero, which is not valid, which is why the getsockopt version below fails. No idea why ioctl fails.
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/ioctl.h>
#include <net/if.h>
int main(int argc, char **argv) {
int sock;
struct sockaddr_in dst_sin;
struct in_addr haddr;
if(argc != 2)
return 1;
if(inet_aton(argv[1], &haddr) == 0) {
printf("'%s' is not a valid IP address\n", argv[1]);
return 1;
}
dst_sin.sin_family = AF_INET;
dst_sin.sin_port = htons(80);
dst_sin.sin_addr = haddr;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
perror("socket");
return 1;
}
if(connect(sock, (struct sockaddr*)&dst_sin, sizeof(dst_sin)) < 0) {
perror("connect");
return 1;
}
printf(
"connected to %s:%d\n",
inet_ntoa(dst_sin.sin_addr), ntohs(dst_sin.sin_port));
#if 0 // ioctl fails with 'no such device'
struct ifreq ifr;
memset(&ifr, 0, sizeof(ifr));
// get the socket's interface index into ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
perror("SIOCGIFINDEX");
return 1;
}
// get the I/F name for ifreq.ifr_ifindex
if(ioctl(sock, SIOCGIFNAME, &ifr) < 0) {
perror("SIOCGIFNAME");
return 1;
}
printf("I/F is on '%s'\n", ifr.ifr_name);
#else // only works on Linux 3.8+
#define IFNAMSZ IFNAMSIZ // Centos7 bug in if.h??
char optval[IFNAMSZ] = {0};
socklen_t optlen = IFNAMSZ;
if(getsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, &optval, &optlen) < 0) {
perror("getsockopt");
return 1;
}
if(!optlen) {
printf("invalid optlen\n");
return 1;
}
printf("I/F is on '%s'\n", optval);
#endif
close(sock);
return 0;
}

TCP (and UDP) sockets are not bound to interfaces, so there is really no facility for answering this query. Now it's true that in general, a given socket will end up passing packets to a specific interface based on the address of the peer endpoint, but that is nowhere encoded in the socket. That's a routing decision that is made dynamically.
For example, let's say that you are communicating with a remote peer that is not directly on your local LAN. And let's say you have a default gateway configured to be 192.168.2.1 via eth0. There is nothing to prevent your configuring a second gateway, say, 192.168.3.1 via eth1, then taking eth0 down. As long as the new gateway can also reach the remote IP, eth1 can now be used to reach the destination and your session should continue uninterrupted.
So, if you need this info, you'll need to infer it from routing entries (but realize that it is not guaranteed to be static, even though in practice it will likely be so). You can obtain the address of your peer from getpeername(2). You can then examine the available routes to determine which one will get you there.
To do this, you could parse and interpret /proc/net/route for yourself, or you can just ask the ip command. For example, my route to an (arbitrary) ibm.com address goes through my eth0 interface, and connecting a socket to there, my local address will be 192.168.0.102 (which should match what getsockname(2) on the connected socket returns):
$ ip route get 129.42.38.1
129.42.38.1 via 192.168.0.1 dev eth0 src 192.168.0.102
cache

Related

Linux application for reading packets from raw socket stops receiving packets after sometime

I have written a Linux application program that receives UDP packets transmitted from a Desktop with fixed & known IP-address on the network. I am using a raw socket to receive packets on my system and filter the received packets based on the source address.
The problem I am facing is, the program runs fine for some time and I get all the required packets, but after a couple of hours, the application stops getting any packets. If I run the command,
tcpdump -i eth0 src 192.168.20.48 on my system, then I see that the system continues to receive the expected packets. But I am not sure what is causing my program to stop receiving packets.
Below is the code snippet used to open a raw socket, receive packets, and filter out the UDP packets transmitted from the known IP address.
int main()
{
int sockfd;
int one = 1;
struct timeval tv;
socklen_t len;
int bytes;
unsigned char tsptr[2048];
struct sockaddr_in cliaddr;
struct iphdr *iph;
int result=0;
char source_add[50];
char expected_source_add[50];
len = sizeof(struct sockaddr_in);
// Creating socket file descriptor
if ((sockfd = socket(AF_INET , SOCK_RAW , IPPROTO_UDP)) < 0 ) {
BRH_PERROR("socket creation failed");
return 1;
}
tv.tv_sec = 30;
tv.tv_usec = 0;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR|SO_REUSEPORT, &one, sizeof(one));
setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO,(char*)&tv,sizeof(tv));
strcpy(expected_source_add, "192.168.20.48");
while (1) {
/*Read fixed data count from socket*/
bytes =recvfrom(sockfd, tsptr, 1500, MSG_WAITALL, (struct sockaddr *)&cliaddr, &len);
iph=(struct iphdr*)tsptr;
//get only UDP packet
if (iph->protocol != 17) continue;
strcpy(source_add,inet_ntoa(cliaddr.sin_addr));
result = strcmp(expected_source_add,source_add);
/*receive data from expected IP address only*/
if( result == 0) {
//Consume the packet
}
}
return 0;
}
Any clue on why the packet receive stops on my application, even though tcpdump shows that packets are being received on the interface, will be helpful.
The code you write here can not see any problem that you describe, I think you should do something like below.
1. using wireshark or tcpdump to see if the nic receive packets successfully
2. beyond the program, do you use any buffer or message queue and are they working good?
3. using tools to see if there exists any memeory leak
4. writing log in every step, especially around recvefrom and strcmp

How to bind to all addresses of only one network interface (Linux)?

What I am trying to achieve is binding an IPv6 socket to any address of just one particular device, not system-wide. My intuition is that I could setsockopt() with SO_BINDTODEVICE followed by a bind to ::. It mostly does what I expect it to do. The behaviour is the same in v4.
The sockets bound to an interface with SO_BINDTODEVICE will only accept connections made to addresses on that interface. That much is expected.
However, I run into errno "Address already in use", if I'm trying to bind to a source port on interface B when there is a socket using the same port but on interface A.
Ex:
nic A has IPv6 fd00:aaaa::a/64
nic B has IPv6 fd00:bbbb::b/64
they do not share networks.
Put shortly (pseudocode):
process 1 calls socket(...) and binds bind(fd00:aaaa::a/64, 9000).
process 2 calls socket(...) and setsockopt(SO_BINDTODEVICE, "B")
process 2 (continued) calls bind(::, 9000) and gets EADDRINUSE. Why?
How does SO_BINDTODEVICE really work? Does the determination for "addresses in use" ignore, conservatively, the interface sockets are bound to? Is it a networking stack layering issue?
Example traces:
I start a listening socket (server) on a specific address: nc -l fd00:aaaa::a 9000. Its trace is as follows:
socket(PF_INET6, SOCK_STREAM, IPPROTO_TCP) = 3
setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
bind(3, {
sa_family=AF_INET6,
sin6_port=htons(9000),
inet_pton(AF_INET6, "fd00:aaaa::a", &sin6_addr),
sin6_flowinfo=0, sin6_scope_id=0
}, 28) = 0
listen(3, 1) = 0
accept(3, ...
Connecting to it (client) fails if I bind to the port in use by the other interface, even though I've already bound to a different interface:
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
setsockopt(3, SOL_SOCKET, SO_BINDTODEVICE, "nicB\0", 5) = 0
bind(3, {sa_family=AF_INET6,
sin6_port=htons(9000),
inet_pton(AF_INET6, "::", &sin6_addr),
sin6_flowinfo=0,
sin6_scope_id=0
}, 28) = -1 //EADDRINUSE (Address already in use)
However, if I don't specify the port, then all is good when binding to :: (while the listener still runs):
socket(PF_INET6, SOCK_STREAM, IPPROTO_IP) = 3
setsockopt(3, SOL_SOCKET, SO_BINDTODEVICE, "nicB\0", 5) = 0
bind(3, {
sa_family=AF_INET6,
sin6_port=htons(0),
inet_pton(AF_INET6, "::", &sin6_addr),
sin6_flowinfo=0, sin6_scope_id=0
}, 28) = 0
connect(3, {
sa_family=AF_INET6,
sin6_port=htons(9000),
inet_pton(AF_INET6, "fd00:aaaa::a", &sin6_addr),
sin6_flowinfo=0, sin6_scope_id=0
}, 28) = ...
Note: This is on 3.19.0-68-generic x86_64 . Ubuntu 14.04. In case it makes a difference, for my tests, nicB is a macvlan in bridge mode whose parent is nicA.
I've found a satisfying explanation for this problem.
The observation is that even though only interface "A" has IP fd00:aaaa::a/64 when the program is started, the listening socket could accept connections coming in over different interfaces if they were to receive that IP in the future. IPs can be added and removed -- and server processes listening on :: or (0.0.0.0 in v4) need not be restarted when interfaces receive new IPs.
So, in a way, process 1's bind("fd00:aaaa::a/64", 9000) binds implicitly to ALL interfaces. Even though process 2 only needs to use interface B, process 1's already got first dibs, because it uses port 9000 on both interfaces, so process 2 gets denied.
If I change program 1 so that it too uses SO_BINDTODEVICE (to interface "A"), then both processes can bind(::, 9000) without issues.
experiment
I've tested this out with a little LD_PRELOAD goop, which precedes calls to bind() with setsockopt(...SO_BINDTODEVICE...). The two following TCP listeners can both bind to port 9000 simulateneously if they are each bound to a different interface.
# LD_PRELOAD=./bind_hook.so _BINDTODEVICE=eth0 nc -l 0.0.0.0 9000
# LD_PRELOAD=./bind_hook.so _BINDTODEVICE=eth1 nc -l 0.0.0.0 9000
If only one of the two uses SO_BINDTODEVICE, then the last process gets EADDRINUSE. Which is the situation put forward in the question.
I'm including the C code (GNU/Linux) for my tool in case someone needs something similar:
/**
* bind_hook.c
*
* Calls setsockopt() with #SO_BINDTODEVICE before _any_ bind().
* The name of the interface to bind to is obtained from
* environment variable `_BINDTODEVICE`.
*
* Needs root perms. errors are not signalled out.
*
* Compile with:
* gcc -Wall -Werror -shared -fPIC -o bind_hook.so -D_GNU_SOURCE bind_hook.c -ldl
* Example usage:
* LD_PRELOAD=./bind_hook.so _BINDTODEVICE=eth0 nc -l 0.0.0.0 9500
*
* #author: init-js
**/
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <net/if.h>
#include <dlfcn.h>
#include <errno.h>
static char iface[IF_NAMESIZE];
static int (*bind_original)(int, const struct sockaddr*, socklen_t addrlen);
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
__attribute__((constructor))
void ctor() {
bind_original = dlsym(RTLD_NEXT, "bind");
char *env_iface = getenv("_BINDTODEVICE");
if (env_iface) {
strncpy(iface, env_iface, IF_NAMESIZE - 1);
}
}
/* modified bind() -- call setsockopt first */
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
int _errno;
if (iface[0]) {
/* preserve errno */
_errno = errno;
setsockopt(sockfd, SOL_SOCKET, SO_BINDTODEVICE,
(void*)iface, IF_NAMESIZE);
errno = _errno;
}
return bind_original(sockfd, addr, addrlen);
}
If there is a socket already bound to a specific IP address and port, you can only bind to that port again if you provide another specific IP address. You cannot use INADDR_ANY in this circumstance.

how to implement tcpdump -i interface arp with libpcap

I want to implement command tcpdump -i eth0 arp to observe arp packets on interface eth0 on my ubuntu. I use libpcap, but the return value of function pcap_next_ex is always 0. With tcpdump -i eth0 arp in the same time , it can observe arp packets.
/*
* compile(root): gcc test.c -lpcap
* run : ./a.out
* output : time out
* time out
* time out
* ...
*/
#include <pcap.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#define ARP_REQUEST 1
#define ARP_REPLY 2
typedef struct arp_hdr_s arp_hdr_t;
struct arp_hdr_s {
u_int16_t htype;
u_int16_t ptype;
u_char hlen;
u_char plen;
u_int16_t oper;
u_char sha[6];
u_char spa[4];
u_char tha[6];
u_char tpa[4];
};
#define MAXBYTES2CAPTURE 2048
int
main(int argc, char **argv)
{
char err_buf[PCAP_ERRBUF_SIZE];
const unsigned char *packet;
int i;
int ret;
arp_hdr_t *arp_header;
bpf_u_int32 net_addr;
bpf_u_int32 mask;
pcap_t *desrc;
struct pcap_pkthdr *pkthdr;
struct bpf_program filter;
net_addr = 0;
mask = 0;
memset(err_buf, 0, PCAP_ERRBUF_SIZE);
desrc = pcap_open_live("eth0", MAXBYTES2CAPTURE, 0, 512, err_buf);
if (desrc == NULL) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_lookupnet("eth0", &net_addr, &mask, err_buf);
if (ret < 0) {
fprintf(stderr, "error: %s\n", err_buf);
exit(-1);
}
ret = pcap_compile(desrc, &filter, "arp", 1, mask);
if (ret < 0) {
fprintf(stderr, "error: %s\n", pcap_geterr(desrc));
exit(-1);
}
ret = pcap_setfilter(desrc, &filter);
if (ret < 0) {
fprintf(stderr, "errnor: %s\n", pcap_geterr(desrc));
exit(-1);
}
while (1) {
ret = pcap_next_ex(desrc, &pkthdr, &packet);
if (ret == -1) {
printf("%s\n", pcap_geterr(desrc));
exit(1);
} else if (ret == -2) {
printf("no more\n");
} else if (ret == 0) { // here
printf("time out\n");
continue;
}
arp_header = (arp_hdr_t *)(packet + 14);
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype == 0x0800)) {
printf("src IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->spa[i]);
}
printf("dst IP: ");
for (i = 0; i < 4; i++) {
printf("%d.", arp_header->tpa[i]);
}
printf("\n");
}
}
return 0;
}
Without getting too deep in your code, I can see a major problem:
In your use of pcap_open_live(), you do not set promiscuous mode: the third parameter should be non-zero. If the ARP request is not targeted to your interface IP, pcap will not see it without promiscuous mode. tcpdump does, unless specifically told not to do so by using the --no-promiscuous-mode, use promisc (and hence will require CAP_NET_ADMIN privilege, which you'll get by sudo, which your program will require too).
Side note:
1/ Leak: you may want to free your filter using pcap_freecode() after your pcap_setfilter().
2/ I assume you've read the official tuto here:
http://www.tcpdump.org/pcap.html
...if that's not the case you'd be well advised to do that first. I quote:
A note about promiscuous vs. non-promiscuous sniffing: The two
techniques are very different in style. In standard, non-promiscuous
sniffing, a host is sniffing only traffic that is directly related to
it. Only traffic to, from, or routed through the host will be picked
up by the sniffer. Promiscuous mode, on the other hand, sniffs all
traffic on the wire. In a non-switched environment, this could be all
network traffic. [... more stuff on promisc vs non-promisc]
EDIT:
Actually, looking deeper to you code compared to my code running for +1 year at production level (both in-house and at the customer) I can see many more things that could be wrong:
You never call pcap_create()
You never call pcap_set_promisc(), we've talked about this already
You never call pcap_activate(), this may be the core issue here
...pcap is very touchy about the sequence order of operations to first get a pcap_t handle, and then operate on it.
At the moment, the best advice I can give you - otherwise this is going to a live debugging session between you and me, are:
1/ read and play/tweak with the code from the official tutorial:
http://www.tcpdump.org/pcap.html
This is mandatory.
2/ FWIW, my - definitely working - sequence of operations is this:
pcap_lookupnet()
pcap_create()
pcap_set_promisc()
pcap_set_snaplen(), you may or may not need this
pcap_set_buffer_size(), you may or may not need this
pcap_activate() with a note: Very important: first activate, then set non-blocking from PCAP_SETNONBLOCK(3PCAP): When first activated with pcap_activate() or opened with pcap_open_live() , a capture handle is not in non-blocking mode''; a call to pcap_set-nonblock() is required in order to put it intonon-blocking'' mode.
...and then, because I do not use stinking blocking/blocking with timeout, busy looping:
pcap_setnonblock()
pcap_get_selectable_fd()
...then and only then:
- pcap_compile()
- followed by a pcap_setfilter()
- and then as I mentioned a pcap_freecode()
- and then a select() or family on the file'des' I get from pcap_get_selectable_fd(), to pcap_dispatch(), but this is another topic.
pcap is an old API starting back in the 80's, and its really very very touchy. But don't get discouraged! It's great - once you get it right.
It would probably work better if you did
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype) == 0x0800) {
rather than
if (ntohs(arp_header->htype) == 1 && ntohs(arp_header->ptype == 0x0800)) {
The latter evaluates arp_header->type == 0x0800, which, when running on a little-endian machine (such as a PC), will almost always evaluate to "false", because the value will look like 0x0008, not 0x0800, in an ARP packet - ARP types are big-endian, so they'll look byte-swapped on a little-endian machine). That means it'll evaluate to 0, and byte-swapping 0 gives you zero, so that if condition will evaluate to "false", and the printing code won't be called.
You'll still get lots of timeouts if you fix that, unless there's a flood of ARP packets, but at least you'll get the occasional ARP packet printed out. (I would advise printing nothing on a timeout; pcap-based programs doing live capturing should expect that timeouts should happen, and should not report them as unusual occurrences.)

redirect ethernet packets through sk_buff to localhost

I am writing a Linux kernel module which redirects a packet to the localhost webserver ,which was originally forwarded through this machine using bridge . It also redirects to reply to the client . The client is oblivious of the redirection . So there are 2 parts
1. all forwarded packets through bridge to some webserver outside are redirected to local webserver .
The output of the localhost webserver is channelled to the original client
I am able to do the second part through nf_hook NF_INET_LOCAL_OUT
unsigned int snoop_hook_reply( unsigned int hooknum, struct sk_buff *skb,
const struct net_device *in, const struct net_device *out,
int(*okfn)( struct sk_buff * ) )
{
int offset, len;
struct ethhdr *ethh;
struct iphdr *iph;
struct tcphdr *tcph;
bool flag = false;
struct net_device *eth1_dev , *lo_dev;
if (!skb) return NF_ACCEPT;
iph = ip_hdr(skb);
if (!iph) return NF_ACCEPT;
skb_set_transport_header(skb, iph->ihl * 4);
tcph = tcp_hdr(skb);
/* skip lo packets */
if (iph->saddr == iph->daddr) return NF_ACCEPT;
if (tcph->dest == htons(80))
flag=true;
if(flag != true)
return NF_ACCEPT;
// correct the IP checksum
iph->check = 0;
ip_send_check (iph);
//correct the TCP checksum
offset = skb_transport_offset(skb);
len = skb->len - offset;
tcph->check = 0;
if(skb->len > 60){
tcph->check = csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, csum_partial((unsigned char *)tcph,len,0));
}
else{
tcph->check = ~csum_tcpudp_magic((iph->saddr), (iph->daddr), len, IPPROTO_TCP, 0);
}
//send to dev
eth1_dev = dev_get_by_name(&init_net,"eth1");
lo_dev = dev_get_by_name(&init_net,"lo");
skb->dev = eth1_dev;
ethh = (struct ethhdr *) skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
skb->protocol = ethh->h_proto = htons(ETH_P_IP);
memcpy (ethh->h_source,eth1_dev->dev_addr , ETH_ALEN);
memcpy (ethh->h_dest, d_mac, ETH_ALEN); // d_mac is mac of the gateway
dev_queue_xmit(skb);
return NF_STOLEN;
}
the above code works perfectly for me . One issue is that later on I will mangle the packet so need to create a new sk_buff, probably .
I am not able to do the 1st part through NF_INET_PRE_ROUTING, I am not able to push the packet/sk_buff to the webserver process through the TCP/IP stack. I tried using dev_queue_xmit() function with skb->dev as both eth1 and lo . I am seeing the packets hitting on the lo or eth1 through tcpdump . But the packets are not reaching the localhost webserver. Can anyone help me regarding this or point to some similar answered question . I believe instead of dev_queue_xmit() I need to call some receiving function . Also when packets arrive in NF_INET_PREROUTING, I the ethernet headers are already there so I am not forming it .
I have already accomplished the above tasks in variety of ways , first using raw sockets , then using nf_queue , now I want to see the performance through this method.
Thanks
If you want to receive the packet locally, you cannot call dev_queue_xmit() on eth1 as it will be sent out. You probably need to call netif_rx() after pointing the skb->dev to eth1/lo.
One more point is if the dest-ip is not your local host ip, then you need to avoid routing again otherwise, there will be no use of your interception.
To achieve this, either you need to modify packet's dest ip to eth1/lo IP or
fool the IP layer by using skb_dst_set() to set "rth->dst.input= ip_local_deliver" for packet to be accepted as local packet.

Develop simple net_device in the linux kernel

I am trying to implement a netdevice (net_device) in linux kernel. This is simple net_device which pass the command/data from user space to kernel space and vice versa this is the goal of this simple net_device. I am using socket for passing command/data from user space to kernel space . After googling i successed in registering net_device and able to see my device in /sys/class/net/abc0 (device name)
when coming to file operation there is no clear idea of the flow
struct net_device_ops
{
.ndo_open =open,
.ndo_close = close,
.ndo_start_xmit = start_xmit
}
if i issue write in socket will it call start_xmit in data link layer.
If i want to call open method, how to call it using socket
How to call start_xmit using socket
How will i find , there is data packet in the receive buffer and pass it to user space.
There is no clear flow/information about simple net_device (except ethernet) can any suggest a link/pdf.
I tried writing simple socket program to test open,close,start_xmit. where socket read/write is not calling open,close,star_xmit .
Is there any way to test the developed net_device ?
Thank you
I found how to test the open,close function .
type : ifconfig abc0(Device name) up will call open method
type : ifconfig abc0(Device name) down will call close method
Can some one help me how to test these methods with sockets.
SIOCSIFFLAGS, -> IFF_UP you can actually set or unset it while doing an ioctl to the netdevice abc0.
first off you have to create a dgram socket,
then use ifreq structure defined in net/if.h
and fill interface and iff_flags
iff_flags can be set with IFF_UP or can be negated with the same IFF_UP to make interface down
and then close the socket.
#include <net/if.h>
....
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) {
goto fail;
}
struct ifreq ifreq;
strcpy(ifreq.ifr_name, "abcd0");
ifreq.iff_flags |= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface up");
}
ifreq.iff_flags ~= IFF_UP;
if (ioctl(sock, &ifreq, sizeof(ifreq) < 0) {
perror("ioctl setting interface down");
}
close(sock);
offtopic:
will you please share your code? we can understand too about your network device :)

Resources