混杂模式

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, &ethreq)) //获取网络接口,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, &ethreq)) //将标志位设置写入
    {
        perror("SIOCSIFFLAGS failed.\n");
        close(sockfd);
        exit(-1);
    }
    //获取
    //ethreq.ifr_flags = 1143
    //ethreq.ifr_flags = 1143, IFF_PROMISC = 100
    //ethreq.ifr_ifindex = 2

    /获得本级网卡索引号,指定网卡。比如有eth和wifi。
    if (ioctl(sockfd, SIOCGIFINDEX, &ethreq) < 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值