On 08/26/2015 01:36 PM, Irrwahn wrote:
> [...]
> Or, even better, you could easily pass the IF name as an additional
> parameter to the backend (and possily even use it as additional component
> to construct the interface file names).
An easy way to obtain a list of interface names on Linux is:
awk 'NR>2{gsub(/:/,"");print $1}' /proc/net/dev
For doing this in pure C, by the "rtnetlink" method, please see
attached file, which is based on .
Kind regards,
Tilman.
/* ifnames - On Linux, list available network interfaces, one by line.
gcc -g -o ifnames ifnames.c
./ifnames
Based on "nprocnetdev.c":
https://gist.github.com/javiermon/43a0b9e1c07abd4b13df
(javiermon. "nprocnetdev.c: print proc/net/dev via netlink sockets")
Originally based on:
http://www.iijlab.net/~jean/iflist.c
Reference:
http://iijean.blogspot.com/2010/03/howto-get-list-of-network-interfaces-in.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <signal.h>
#include <errno.h>
#define IFLIST_REPLY_BUFFER 8192 // FIXME: is this defined somewhere?
typedef struct nl_req_s nl_req_t;
struct nl_req_s {
struct nlmsghdr hdr;
struct rtgenmsg gen;
};
void rtnl_print_link(struct nlmsghdr *h) {
struct ifinfomsg *iface;
struct rtattr *attribute;
int len;
iface = NLMSG_DATA(h);
len = h->nlmsg_len - NLMSG_LENGTH(sizeof(*iface));
for(
attribute = IFLA_RTA(iface);
RTA_OK(attribute, len);
attribute = RTA_NEXT(attribute, len)
) {
switch(attribute->rta_type) {
case IFLA_IFNAME:
printf("%s\n", (char *) RTA_DATA(attribute));
break;
default:
break;
}
}
}
int main(void) {
int fd;
struct sockaddr_nl local;
struct sockaddr_nl kernel;
struct msghdr rtnl_msg;
struct iovec io;
nl_req_t req;
char reply[IFLIST_REPLY_BUFFER];
pid_t pid = getpid();
unsigned int sleep_sec = 0;
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
if(-1 == fd) {
fprintf(stderr, "ERROR: socket(): %s\n", strerror(errno));
return -1;
}
memset(&local, 0, sizeof(local));
local.nl_family = AF_NETLINK;
local.nl_pid = pid;
local.nl_groups = 0;
if(0 > bind(fd, (struct sockaddr *) &local, sizeof(local))) {
fprintf(stderr, "ERROR: bind(): %s\n", strerror(errno));
return -1;
}
int msg_done = 0;
memset(&rtnl_msg, 0, sizeof(rtnl_msg));
memset(&kernel, 0, sizeof(kernel));
memset(&req, 0, sizeof(req));
kernel.nl_family = AF_NETLINK;
req.hdr.nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
req.hdr.nlmsg_type = RTM_GETLINK;
req.hdr.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
req.hdr.nlmsg_seq = 1;
req.hdr.nlmsg_pid = pid;
req.gen.rtgen_family = AF_PACKET;
io.iov_base = &req;
io.iov_len = req.hdr.nlmsg_len;
rtnl_msg.msg_iov = &io;
rtnl_msg.msg_iovlen = 1;
rtnl_msg.msg_name = &kernel;
rtnl_msg.msg_namelen = sizeof(kernel);
if(sendmsg(fd, (struct msghdr *) &rtnl_msg, 0) < 0)
fprintf(stderr, "ERROR: sendmsg(): %s", strerror(errno));
while (!msg_done) {
int len;
struct nlmsghdr *msg_ptr;
struct msghdr rtnl_reply;
struct iovec io_reply;
memset(&io_reply, 0, sizeof(io_reply));
memset(&rtnl_reply, 0, sizeof(rtnl_reply));
io.iov_base = reply;
io.iov_len = IFLIST_REPLY_BUFFER;
rtnl_reply.msg_iov = &io;
rtnl_reply.msg_iovlen = 1;
rtnl_reply.msg_name = &kernel;
rtnl_reply.msg_namelen = sizeof(kernel);
if ((len = recvmsg(fd, &rtnl_reply, 0)) != 0) {
for (
msg_ptr = (struct nlmsghdr *) reply;
NLMSG_OK(msg_ptr, len);
msg_ptr = NLMSG_NEXT(msg_ptr, len)
) {
switch(msg_ptr->nlmsg_type) {
case NLMSG_DONE:
msg_done = 1;
break;
case RTM_NEWLINK:
rtnl_print_link(msg_ptr);
break;
default:
break;
}
}
}
}
close(fd);
return 0;
}