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

[复制链接]
 楼主| keer_zu 发表于 2023-11-20 17:12 | 显示全部楼层 |阅读模式
本帖最后由 keer_zu 于 2023-11-20 17:18 编辑

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

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

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

  20. int main (int argc, char **argv)
  21. {
  22.     int i, datalen,frame_length, sd, bytes;
  23.     char *interface= "ens33";//"enp1s0";;
  24.     uint8_t data[IP_MAXPACKET];
  25.     uint8_t src_mac[6];
  26.     uint8_t dst_mac[6];;
  27.     uint8_t ether_frame[IP_MAXPACKET];
  28.     struct sockaddr_ll device;
  29.     struct ifreq ifr = { 0 };

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

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

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

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

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

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

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

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

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

  92.     ether_frame[12] = ETH_P_DEAN / 256;
  93.     ether_frame[13] = ETH_P_DEAN % 256;

  94.     // data
  95.     memcpy (ether_frame + 14 , data, datalen);
  96.    
  97.     // Submit request for a raw socket descriptor.
  98.     if ((sd = socket (PF_PACKET, SOCK_RAW, htons (ETH_P_DEAN))) < 0)
  99.         {//创建正真发送的socket
  100.         perror ("socket() failed ");
  101.         exit (EXIT_FAILURE);
  102.     }
  103.     // Send ethernet frame to socket.
  104.     if ((bytes = sendto (sd, ether_frame, frame_length, 0, (struct sockaddr *) &device, sizeof (device))) <= 0)
  105.         {
  106.         perror ("sendto() failed");
  107.         exit (EXIT_FAILURE);
  108.     }
  109.     printf ("send num=%d,read num=%d\n",frame_length,bytes);     
  110.     // Close socket descriptor.
  111.     close (sd);

  112.     return (EXIT_SUCCESS);
  113. }





只能采用其它方式。

 楼主| keer_zu 发表于 2023-11-20 17:13 | 显示全部楼层


实现实例代码如下:

  1. #include <stdlib.h>
  2. #include <stdio.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include <sys/types.h>
  6. #include <sys/ioctl.h>
  7. #include <arpa/inet.h>
  8. #include <net/bpf.h>
  9. #include <net/ethertypes.h>
  10. #include <net/if_ether.h>
  11. #include <unistd.h>           // close()
  12. #include <string.h>           // strcpy, memset(), and memcpy()
  13. #include <netdb.h>            // struct addrinfo
  14. #include <sys/types.h>        // needed for socket(), uint8_t, uint16_t, uint32_t
  15. #include <netinet/in.h>       // IPPROTO_ICMP, INET_ADDRSTRLEN
  16. #include <netinet/ip.h>       // struct ip and IP_MAXPACKET (which is 65535)
  17. #include <netinet/ip_icmp.h>  // struct icmp, ICMP_ECHO
  18. #include <arpa/inet.h>        // inet_pton() and inet_ntop()
  19. #include <sys/ioctl.h>        // macro ioctl is defined
  20. #include <net/if.h>           // struct ifreq
  21. #include <errno.h>            // errno, perror()
  22. #define ETH_P_DEAN 0x8874 //自定义的以太网协议type
  23. #static int bpf = 0;

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

  27.         int  datalen,frame_length;
  28.         uint8_t data[IP_MAXPACKET];
  29.         uint8_t src_mac[6];
  30.         uint8_t dst_mac[6];;
  31.         uint8_t ether_frame[IP_MAXPACKET];
  32. //-------------------------------------------------------------------------------
  33.     /* using BPF device */
  34.     char bpfname[16] = {"/dev/bpf\0"};
  35.     int i=0;

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

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

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

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

  59.     /* set immediate: returns on packet arrived instead of when buffer full */
  60.     int setimmediate = 1;
  61.     if( ioctl(bpf, BIOCIMMEDIATE, &setimmediate) == -1){
  62.         printf("Could set IO immediate");
  63.     }
  64.     /* set promiscuous mode */   
  65. //    int promiscuous = 1;
  66. //    if( ioctl(bpf, BIOCPROMISC, &promiscuous) == -1){
  67. //        printf("Could get disable BIOCPROMISC");
  68. //    }

  69. //---------------------------------------------------------------------------------------------------

  70.     // Set destination MAC address: you need to fill these out
  71.             dst_mac[0] = 0x10;
  72.             dst_mac[1] = 0x78;
  73.             dst_mac[2] = 0xd2;
  74.             dst_mac[3] = 0xc6;
  75.             dst_mac[4] = 0x2f;
  76.             dst_mac[5] = 0x89;
  77. //---------------------------------------------------------------------------------------------------

  78.             src_mac[0] = 0x11;//设置目的网卡地址
  79.             src_mac[1] = 0x78;
  80.             src_mac[2] = 0xd2;
  81.             src_mac[3] = 0xc6;
  82.             src_mac[4] = 0x2f;
  83.             src_mac[5] = 0x89;

  84. //---------------------------------------------------------------

  85.               datalen = 12;
  86.               data[0] = 'h';
  87.               data[1] = 'e';
  88.               data[2] = 'l';
  89.               data[3] = 'l';
  90.               data[4] = 'o';
  91.               data[5] = ' ';
  92.               data[6] = 'w';
  93.               data[7] = 'o';
  94.               data[8] = 'r';
  95.               data[9] = 'l';
  96.               data[10] = 'd';
  97.               data[11] = '!';
  98. //-------------------------------------------------------------------------------------------------------

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

  101.            memcpy (ether_frame, dst_mac, 6);
  102.            memcpy (ether_frame + 6, src_mac, 6);

  103.            ether_frame[12] = ETH_P_DEAN / 256;
  104.            ether_frame[13] = ETH_P_DEAN % 256;

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

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

  113.     close(bpf);
  114.     return 0;
  115. }
  116. //----------------------------------------------------------------------------------------------


您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

1478

主题

12917

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部
个人签名:qq群:49734243 Email:zukeqiang@gmail.com

1478

主题

12917

帖子

55

粉丝
快速回复 在线客服 返回列表 返回顶部