打印

【原创】在qnx上实现基于二层网络的自定义类型协议

[复制链接]
14563|1
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
keer_zu|  楼主 | 2023-11-20 17:12 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 keer_zu 于 2023-11-20 17:18 编辑

因为qnx的socket不支持PF_PACKET类型这个参数,


所以无法使用linux下的方式:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>           // close()
#include <string.h>           // strcpy, memset(), and memcpy()
#include <netdb.h>            // struct addrinfo
#include <sys/types.h>        // needed for socket(), uint8_t, uint16_t, uint32_t
#include <sys/socket.h>       // needed for socket()
#include <netinet/in.h>       // IPPROTO_ICMP, INET_ADDRSTRLEN
#include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
#include <netinet/ip_icmp.h>  // struct icmp, ICMP_ECHO
#include <arpa/inet.h>        // inet_pton() and inet_ntop()
#include <sys/ioctl.h>        // macro ioctl is defined
#include <bits/ioctls.h>      // defines values for argument "request" of ioctl.
#include <net/if.h>           // struct ifreq
#include <linux/if_ether.h>   // ETH_P_IP = 0x0800, ETH_P_IPV6 = 0x86DD
#include <linux/if_packet.h>  // struct sockaddr_ll (see man 7 packet)
#include <net/ethernet.h>

#include <errno.h>            // errno, perror()
#define ETH_P_DEAN 0x8899 //自定义的以太网协议type

int main (int argc, char **argv)
{
    int i, datalen,frame_length, sd, bytes;
    char *interface= "ens33";//"enp1s0";;
    uint8_t data[IP_MAXPACKET];
    uint8_t src_mac[6];
    uint8_t dst_mac[6];;
    uint8_t ether_frame[IP_MAXPACKET];
    struct sockaddr_ll device;
    struct ifreq ifr = { 0 };

    // Submit request for a socket descriptor to look up interface.
    if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_ALL))) < 0)
        {//第一次创建socket是为了获取本地网卡信息
        perror ("socket() failed to get socket descriptor for using ioctl() ");
        exit (EXIT_FAILURE);
    }

    // Use ioctl() to look up interface name and get its MAC address.
    //memset (&ifr, 0, sizeof (ifr));
    snprintf (ifr.ifr_name, sizeof (ifr.ifr_name), "%s", interface);
    if (ioctl (sd, SIOCGIFHWADDR, &ifr) < 0)
        {
        perror ("ioctl() failed to get source MAC address ");
        return (EXIT_FAILURE);
    }
    close (sd);

    // Copy source MAC address.
    memcpy (src_mac, ifr.ifr_hwaddr.sa_data, 6);

    // Report source MAC address to stdout.
    printf ("MAC address for interface %s is ", interface);
    for (i=0; i<5; i++)
        {
        printf("%02x:", src_mac[i]);
    }
    printf ("%02x\n", src_mac[5]);

    // Find interface index from interface name and store index in
    // struct sockaddr_ll device, which will be used as an argument of sendto().
    memset (&device, 0, sizeof (device));
    if ((device.sll_ifindex = if_nametoindex (interface)) == 0)
        {
        perror ("if_nametoindex() failed to obtain interface index ");
        exit (EXIT_FAILURE);
    }
    printf ("Index for interface %s is %i\n", interface, device.sll_ifindex);

    dst_mac[0] = 0x00;//设置目的网卡地址 00:50:56:97:fd:cc //00:0c:29:7b:00:8b
    dst_mac[1] = 0x0c;//0x0c;
    dst_mac[2] = 0x29;//0x29;
    dst_mac[3] = 0x7b;//0x84;
    dst_mac[4] = 0x00;//0xa4;
    dst_mac[5] = 0x8b;//0xa4;

    // Fill out sockaddr_ll.
    device.sll_family = AF_PACKET;
    memcpy (device.sll_addr, src_mac, 6);
    device.sll_halen = htons (6);

    // 发送的data,长度可以任意,但是抓包时看到最小数据长度为46,这是以太网协议规定以太网帧数据域部分最小为46字节,不足的自动补零处理
    datalen = 12;
    data[0] = 'h';
    data[1] = 'e';
    data[2] = 'l';
    data[3] = 'l';
    data[4] = 'o';
    data[5] = ' ';
    data[6] = 'w';
    data[7] = 'o';
    data[8] = 'r';
    data[9] = 'l';
    data[10] = 'd';
    data[11] = '!';

    // Fill out ethernet frame header.
    frame_length = 6 + 6 + 2   + datalen;
    // Destination and Source MAC addresses
    memcpy (ether_frame, dst_mac, 6);
    memcpy (ether_frame + 6, src_mac, 6);

    ether_frame[12] = ETH_P_DEAN / 256;
    ether_frame[13] = ETH_P_DEAN % 256;

    // data
    memcpy (ether_frame + 14 , data, datalen);
   
    // Submit request for a raw socket descriptor.
    if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_DEAN))) < 0)
        {//创建正真发送的socket
        perror ("socket() failed ");
        exit (EXIT_FAILURE);
    }
    // Send ethernet frame to socket.
    if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0)
        {
        perror ("sendto() failed");
        exit (EXIT_FAILURE);
    }
    printf ("send num=%d,read num=%d\n",frame_length,bytes);     
    // Close socket descriptor.
    close (sd);

    return (EXIT_SUCCESS);
}





只能采用其它方式。

使用特权

评论回复

相关帖子

沙发
keer_zu|  楼主 | 2023-11-20 17:13 | 只看该作者


实现实例代码如下:

#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <net/bpf.h>
#include <net/ethertypes.h>
#include <net/if_ether.h>
#include <unistd.h>           // close()
#include <string.h>           // strcpy, memset(), and memcpy()
#include <netdb.h>            // struct addrinfo
#include <sys/types.h>        // needed for socket(), uint8_t, uint16_t, uint32_t
#include <netinet/in.h>       // IPPROTO_ICMP, INET_ADDRSTRLEN
#include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
#include <netinet/ip_icmp.h>  // struct icmp, ICMP_ECHO
#include <arpa/inet.h>        // inet_pton() and inet_ntop()
#include <sys/ioctl.h>        // macro ioctl is defined
#include <net/if.h>           // struct ifreq
#include <errno.h>            // errno, perror()
#define ETH_P_DEAN 0x8874 //自定义的以太网协议type
#static int bpf = 0;

int main(int argc, char **argv)
{
//---------------------------------------------------------------------------//数据包结构体定义

        int  datalen,frame_length;
        uint8_t data[IP_MAXPACKET];
        uint8_t src_mac[6];
        uint8_t dst_mac[6];;
        uint8_t ether_frame[IP_MAXPACKET];
//-------------------------------------------------------------------------------
    /* using BPF device */
    char bpfname[16] = {"/dev/bpf\0"};
    int i=0;

    /* opening autocloning BFP device */
    bpf = open(bpfname, O_RDWR);

    if (bpf < 0){
        /* no autocloning BPF found: fall back to iteration */
        for(i=0; i<128; i++){
            snprintf(bpfname, sizeof(bpfname), "/dev/bpf%d", i);
            bpf = open(bpfname, O_RDWR);

            if(bpf != -1)
                break;
        }
        if(bpf < 0){
            printf("Error: could not open any /dev/bpf device.\n");
        }
    }  
    printf("Opened BPF device \"%s\"\n", bpfname);

    /* binding with real interface */
    const char* ifname = "wm0";
    struct ifreq iface;
    strncpy(iface.ifr_name, ifname, sizeof(ifname));
    if( ioctl(bpf, BIOCSETIF, &iface) > 0){
        printf("Could not bind %s to BPF\n", ifname);
    }
    printf("Associated with \"%s\"\n", ifname);

    /* set immediate: returns on packet arrived instead of when buffer full */
    int setimmediate = 1;
    if( ioctl(bpf, BIOCIMMEDIATE, &setimmediate) == -1){
        printf("Could set IO immediate");
    }
    /* set promiscuous mode */   
//    int promiscuous = 1;
//    if( ioctl(bpf, BIOCPROMISC, &promiscuous) == -1){
//        printf("Could get disable BIOCPROMISC");
//    }

//---------------------------------------------------------------------------------------------------

    // Set destination MAC address: you need to fill these out
            dst_mac[0] = 0x10;
            dst_mac[1] = 0x78;
            dst_mac[2] = 0xd2;
            dst_mac[3] = 0xc6;
            dst_mac[4] = 0x2f;
            dst_mac[5] = 0x89;
//---------------------------------------------------------------------------------------------------

            src_mac[0] = 0x11;//设置目的网卡地址
            src_mac[1] = 0x78;
            src_mac[2] = 0xd2;
            src_mac[3] = 0xc6;
            src_mac[4] = 0x2f;
            src_mac[5] = 0x89;

//---------------------------------------------------------------

              datalen = 12;
              data[0] = 'h';
              data[1] = 'e';
              data[2] = 'l';
              data[3] = 'l';
              data[4] = 'o';
              data[5] = ' ';
              data[6] = 'w';
              data[7] = 'o';
              data[8] = 'r';
              data[9] = 'l';
              data[10] = 'd';
              data[11] = '!';
//-------------------------------------------------------------------------------------------------------

           frame_length = 6 + 6 + 2   + datalen;
           // Destination and Source MAC addresses

           memcpy (ether_frame, dst_mac, 6);
           memcpy (ether_frame + 6, src_mac, 6);

           ether_frame[12] = ETH_P_DEAN / 256;
           ether_frame[13] = ETH_P_DEAN % 256;

     // data  package
           memcpy (ether_frame + 14 , data, datalen);
//-------------------------------------------------------------------------------------------------
/* 进行数据包的读写    */

    while(!stop)
    {
        write(bpf, ether_frame, frame_length);
        printf("data package is sending!\n");

    close(bpf);
    return 0;
}
//----------------------------------------------------------------------------------------------


使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1350

主题

12427

帖子

53

粉丝