原本是打算通过ioctl这个api获取网口是否插线状态,结果设备网口和驱动适配有问题
查出来的结果跟实际网口对不上 即使用ifconfig也是对不上 (ifconfig也是用的ioctl)
然后发现ethtool命令查的是准确的,打算使用ethtool源码进行裁剪
无奈发现源码比预期大,错综复杂,裁剪也困难。正在一边看着ethtool源码出神
一边想怎么搞 忽然想到 既然ethtool是使用netlink进行获取的
那我直接写个简单的netlink程序获取不就OK了吗
于是就有了以下这段代码
#include <linux/types.h>
#include <asm/types.h>
#include <inttypes.h>
#include <sys/file.h>
#include <sys/user.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/if.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <errno.h>
#include <arpa/inet.h>
typedef uint32_t u32;
typedef uint16_t u16;
struct nlsock {
int sock;
int seq;
struct sockaddr_nl snl;
char *name;
} nl_cmd = { -1, 0, {0}, "netlink-cmd" };
static int index_oif = 0;
struct nl_if_info {
u32 addr;
char *name;
};
static int nl_socket ( struct nlsock *nl, unsigned long groups )
{
int ret;
struct sockaddr_nl snl;
int sock;
int namelen;
/*创建netlink套接字*/
sock = socket ( AF_NETLINK, SOCK_RAW, NETLINK_ROUTE );
if ( sock < 0 ) {
fprintf ( stderr, "Can't open %s socket: %s", nl->name,
strerror ( errno ) );
return -1;
}
ret = fcntl ( sock, F_SETFL, O_NONBLOCK );
if ( ret < 0 ) {
fprintf ( stderr, "Can't set %s socket flags: %s", nl->name,
strerror ( errno ) );
close ( sock );
return -1;
}
/*设置地址信息*/
memset ( &snl, 0, sizeof snl );
snl.nl_family = AF_NETLINK;
snl.nl_groups = groups;
/* Bind the socket to the netlink structure for anything. */
ret = bind ( sock, ( struct sockaddr * ) &snl, sizeof snl );
if ( ret < 0 ) {
fprintf ( stderr, "Can't bind %s socket to group 0x%x: %s",
nl->name, snl.nl_groups, strerror ( errno ) );
close ( sock );
return -1;
}
/* multiple netlink sockets will have different nl_pid */
namelen = sizeof snl;
ret = getsockname ( sock, ( struct sockaddr * ) &snl, &namelen );
if ( ret < 0 || namelen != sizeof snl