ifreq 可以用来获取网卡的一些信息。
这是获得网卡eth0的通讯消息。
#include <sys/socket.h>
#include <net/if.h>
#include <linux/if_ether.h>
#include <netinet/in.h>
#include <linux/sockios.h>
#include <sys/ioctl.h>
#include <linux/if_packet.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
codebegin:
int sockfd = -1;
sockfd = -1;
sockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
//ETH_P_ALL 0x3 接收发往本机mac的所有类型ip arp rarp的数据帧, 接收从本机发出的所有类型的数据帧.(混杂模式打开的情况下,会接收到非发往本地mac的数据帧(ARP,RARP))
////////////////////
char const *eth_name = "eth0"; //对网卡eth0进行混杂设置
struct ifreq ethreq; //网络接口结构
strncpy(ethreq.ifr_name, eth_name, strlen(eth_name) + 1); //指定网卡名称
printf("netcard = %s\n", ethreq.ifr_name);
if(-1 == ioctl(sockfd,
SIOCGIFFLAGS, ðreq)) //获取网络接口,SIOCGIFADDR获得IP地址。
{
/* Standard interface flags (netdevice->flags).
#define IFF_UP 0x1 /* interface is up */
#define IFF_BROADCAST 0x2 /* broadcast address valid */
#define IFF_DEBUG 0x4 /* turn on debugging */
#define IFF_LOOPBACK 0x8 /* is a loopback net */
#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
#define IFF_RUNNING 0x40 /* resources allocated */
#define IFF_NOARP 0x80 /* no ARP protocol */
#define IFF_PROMISC 0x100 /* receive all packets */
#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
#define IFF_MASTER 0x400 /* master of a load balancer */
#define IFF_SLAVE 0x800 /* slave of a load balancer */
#define IFF_MULTICAST 0x1000 /* Supports multicast */
#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_MASTER|IFF_SLAVE|IFF_RUNNING)
#define IFF_PORTSEL 0x2000 /* can set media type */
#define IFF_AUTOMEDIA 0x4000 /* auto media select active */
#define IFF_DYNAMIC 0x8000 /* dialup device with changing addresses*/
*/
perror("SIOCGIFFLAGS failed.\n");
close(sockfd);
exit(-1);
}
printf("ethreq.ifr_flags = %x\n", ethreq.ifr_flags);
ethreq.ifr_flags |= IFF_PROMISC;
printf("ethreq.ifr_flags = %x, IFF_PROMISC = %x\n", ethreq.ifr_flags, IFF_PROMISC);
if(-1 == ioctl(sockfd, SIOCSIFFLAGS, ðreq)) //将标志位设置写入
{
perror("SIOCSIFFLAGS failed.\n");
close(sockfd);
exit(-1);
}
//获取
//ethreq.ifr_flags = 1143
//ethreq.ifr_flags = 1143, IFF_PROMISC = 100
//ethreq.ifr_ifindex = 2
/////////////////////获得本级网卡索引号,我还不明白具体意思。
if (ioctl(sockfd, SIOCGIFINDEX, ðreq) < 0)
{
perror("SIOCGIFINDEX failed.\n");
close(sockfd);
exit(-1);
}
printf("ethreq.ifr_ifindex = %d\n", ethreq.ifr_ifindex);
struct sockaddr_ll addr;
memset(&addr, 0, sizeof(addr));
addr.sll_family = AF_PACKET;
// ifindex needs to be obtained
addr.sll_ifindex = ethreq.ifr_ifindex;
int rc = bind(sockfd, (struct sockaddr *)&addr, sizeof(addr));
if (rc < 0)
{
close(sockfd);
perror("socket bind fail\n");
return -1;
}
printf("begin recv!\n");
////////////////////
fd_set rfds;
int selectrc;
int len, tempi;
uint8_t buf[1024];
struct timeval *timeout;
while(1)
{
FD_ZERO(&rfds);
FD_SET(sockfd, &rfds);
selectrc = select(sockfd + 1, &rfds, NULL, NULL, NULL);//时间为NULL,表示阻塞。
printf("select is finish!\n");
if(selectrc <= 0)
{
if ((selectrc == -1) && (errno != EINTR)) {
printf("socket select fail errno=0x%x\n", errno);
} else if (selectrc == 0) {
printf("Periodic run HsmConnect\n");
}
continue;
}
if (FD_ISSET(sockfd, &rfds))
{
len = recv(sockfd, buf, sizeof(buf), 0);
if (len > 0){
printf("recv str:");
for(tempi = 0; tempi < len; tempi++)
{
printf("%d ", buf[tempi]);
}
printf("\n");
} else if (len < 0) {
if (errno != ENETDOWN) {
printf("recv return -1 errno=0x%x -- Recreate socket\n", errno);
close(sockfd);
sockfd = -1;
goto codebegin;
}
} else {
printf("recv return 0\n");
close(sockfd);
sockfd = -1;
goto codebegin;
}
}
}
printf("code break!\n");
return 1;
}