作者:Alex.Duan 日期:2019-09-03
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include <stdint.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/if.h>
#include <linux/sockios.h>
#include <linux/ethtool.h>
//---------------------------------------------------------------
/*
* 功能描述: 通过MII接口,访问PHY寄存器来确认网络连接状态
* 参数说明: if_name - 网络接口名("eth0")
* 返 回 值: 1 - 连接正常
* 0 - 断开连接
* -1 - 错误
*/
int mii_link_status(char *ifname)
{
int skfd;
struct ifreq ifr;
uint16_t *pdata;
uint16_t mii_val;
uint16_t phy_id;
if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0)
{
return -1;
}
/* Get the vitals from the interface. */
strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
if (ioctl(skfd, SIOCGMIIPHY, &ifr) < 0)
{
fprintf(stderr, "SIOCGMIIPHY on %s failed: %s\n", ifname, strerror(errno));
close(skfd);
return -2;
}
pdata = (uint16_t *)(&ifr.ifr_data);
phy_id = pdata[0];
pdata[1] = 1;
if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0)
{
fprintf(stderr, "SIOCGMIIREG on %s failed: %s\n", ifr.ifr_name, strerror(errno));
return -3;
}
close(skfd);
mii_val = pdata[3];
return (((mii_val & 0x0016) == 0x0004) ? 0 : 1);
}
//---------------------------------------------------------------
/*
* 功能描述: 通过SIOCETHTOOL命令获取网络连接状态
* 参数说明: if_name - 网络接口名("eth0")
* 返 回 值: 1 - 连接正常
* 0 - 断开连接
* -1 - 错误
*/
int get_netlink_status(const char *if_name)
{
int skfd;
struct ifreq ifr;
struct ethtool_value edata;
edata.cmd = ETHTOOL_GLINK;
edata.data = 0;
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name) - 1);
ifr.ifr_data = (char *)&edata;
if ((skfd = socket(AF_INET, SOCK_DGRAM, 0)) == 0)
{
return -1;
}
if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1)
{
close(skfd);
return -1;
}
close(skfd);
return edata.data;
}
//---------------------------------------------------------------
int main(int argc, char* argv[])
{
int ret;
if (argc != 2)
{
fprintf(stderr, "usage: %s eth0 \r\n", argv[0]);
return -1;
}
// 只有超级用户才有权限操作
if (getuid() != 0)
{
fprintf(stderr, "only root can do it.\n");
return 1;
}
while(1)
{
// 方法一:SIOCETHTOOL
ret = get_netlink_status(argv[1]);
if(ret == 1)
{
printf("[SIOCETHTOOL] net link up.\r\n");
}
else
{
printf("[SIOCETHTOOL] net link down.\r\n");
}
// 方法二:读取PHY寄存器方式
ret = mii_link_status(argv[1]);
if(ret == 0)
{
printf("[SIOCGMIIREG] net link up.\r\n");
}
else
{
printf("[SIOCGMIIREG] net link down.\r\n");
}
sleep(2);
}
return 0;
}
//---------------------------------------------------------------