Chinaunix首页 | 论坛 | 博客
  • 博客访问: 742745
  • 博文数量: 141
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 1115
  • 用 户 组: 普通用户
  • 注册时间: 2014-03-17 14:32
个人简介

小公司研发总监,既当司令也当兵!

文章分类

全部博文(141)

分类: LINUX

2015-06-03 22:03:19

1.介绍
在linux中提供了PF_PACKET接口可以操作链路层的数据。
 
2.使用方法
定义一个pf_packet = socket(PF_SOCKET, SOCK_RAW, htons(ETH_P_RARP));
就可以利用函数sendto和recefrom来读取和发送链路层的数据包了(当然,发送ARP包,上面第三个参数要变为htons(ETH_P_ARP),或者IP的包为ETH_P_IP,可查看文件/usr/include/linux/if_ether.h文件看到所有支持的协议)。
 
3.在使用SOCK_RAW, SOCK_DGRAM和SOCK_PACKET的区别
在socket的第一个参数使用PF_PACKET的时候,上述三种socket的类型都可以使用。但是有区别。
(1)使用SOCK_RAW发送的数据必须包含链路层的协议头,接受得到的数据包,包含链路层协议头。而使用SOCK_DGRAM则都不含链路层的协议头。
(2)SOCK_PACKET也是可以使用的,但是已经废弃,以后不保证还能支持,不推荐使用。
(3)在使用SOCK_RAW或SOCK_DGRAM和SOCK_PACKET时,在sendto和recvfrom中使用的地址类型不同,前两者使用sockaddr_ll类型的地址,而后者使用sockaddr类型的地址。
(4)如socket的第一个参数使用PF_INET,第二个参数使用SOCK_RAW,则可以得到原始的IP包。
 
4.下面的例子是一个简单的arp协议的server程序
server程序一开始获得除lo接口以外接口的mac地址,等待arp request请求的到来,如果请求的是自己的mac地址,则向客户端发送arp reply,回送自己的ip地址。应我使用的地方,一台机器的ip地址每次dhcp以后都会变。所以该程序还是有一些用处。

点击(此处)折叠或打开

  1. #include <sys/types.h>
  2. #include <sys/time.h>
  3. #include <time.h>
  4. #include <sys/types.h>
  5. #include <sys/socket.h>
  6. #include <netinet/if_ether.h>
  7. #include <net/if_arp.h>
  8. #include <netinet/in.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include <unistd.h>
  12. #include <errno.h>
  13. #include <netinet/if_ether.h>
  14. #include <net/if_arp.h>
  15. #include <net/if.h>
  16. #include <netinet/in.h>
  17. #include <arpa/inet.h>
  18. #include <sys/ioctl.h>
  19. #include <netpacket/packet.h>

  20. //#include <cstdlib>
  21. /* args: yiaddr - what IP to ping
  22.  * ip - our ip
  23.  * mac - our arp address
  24.  * interface - interface to use
  25.  * retn: 1 addr free
  26.  * 0 addr used
  27.  * -1 error
  28.  */
  29. /* FIXME: match response against chaddr */
  30. struct arpMsg
  31. {
  32.     struct ethhdr ethhdr; /* Ethernet header */
  33.     u_short htype; /* hardware type (must be ARPHRD_ETHER) */
  34.     u_short ptype; /* protocol type (must be ETH_P_IP) */
  35.     u_char hlen; /* hardware address length (must be 6) */
  36.     u_char plen; /* protocol address length (must be 4) */
  37.     u_short operation; /* ARP opcode */
  38.     u_char sHaddr[6]; /* sender's hardware address */
  39.     u_char sInaddr[4]; /* sender's IP address */
  40.     u_char tHaddr[6]; /* target's hardware address */
  41.     u_char tInaddr[4]; /* target's IP address */
  42.     u_char pad[18]; /* pad for min. Ethernet payload (60 bytes) */
  43. };
  44. /* miscellaneous defines */
  45. #define MAC_BCAST_ADDR (uint8_t *) "/xff/xff/xff/xff/xff/xff"
  46. #define OPT_CODE 0
  47. #define OPT_LEN 1
  48. #define OPT_DATA 2

  49. struct interface_info
  50. {
  51.     char ifname[64];
  52.     unsigned char ip[4];
  53.     unsigned char mac[6];
  54. };

  55. struct interface_info if_info[10];

  56. int eth_num = 0;

  57. void print_mac(unsigned char *mac_addr)
  58. {
  59.     int i;
  60.     for (i = 0; i < 6; ++i)
  61.     {
  62.         printf("%02X", mac_addr[i]);
  63.         if (i != 5)
  64.             printf(":");
  65.     }
  66.     printf("/n");
  67. }

  68. void print_ip(unsigned char *ip_addr)
  69. {
  70.     int i;
  71.     for (i = 0; i < 4; ++i)
  72.     {
  73.         printf("%d", ip_addr[i]);
  74.         if (i != 3)
  75.             printf(".");
  76.     }
  77.     printf("/n");
  78. }

  79. int get_iface_index(int fd, const char *interface_name)
  80. {
  81.     struct ifreq ifr;
  82.     memset(&ifr, 0, sizeof(ifr));
  83.     strcpy(ifr.ifr_name, interface_name);
  84.     if (ioctl(fd, SIOCGIFINDEX, &ifr) == -1)
  85.     {
  86.         return (-1);
  87.     }
  88.     return ifr.ifr_ifindex;
  89. }

  90. int get_interfaces()
  91. {
  92.     int sock;
  93.     int len = 64;
  94.     int last_len = 0;
  95.     char *pBuff = NULL;
  96.     int interface_num = 0;
  97.     int i;

  98.     struct ifconf interface_conf;
  99.     struct ifreq ifreq1;
  100.     struct sockaddr_in *psockaddr_in = NULL;

  101.     if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
  102.     {
  103.         perror("Could not create socket for geting interface info");
  104.         exit(1);
  105.     }

  106.     while (1)
  107.     {
  108.         pBuff = (char *)malloc(len);
  109.         interface_conf.ifc_len = len;
  110.         interface_conf.ifc_buf = pBuff;
  111.         if (ioctl(sock, SIOCGIFCONF, &interface_conf) < 0)
  112.         {
  113.             perror("ioctl error");
  114.         }
  115.         else
  116.         {
  117.             if (interface_conf.ifc_len == last_len)
  118.             {
  119.                 break;
  120.             }
  121.             else
  122.             {
  123.                 last_len = interface_conf.ifc_len;
  124.             }
  125.         }
  126.         len += 2 * sizeof(struct ifreq);
  127.         free(pBuff);
  128.     }

  129.     interface_num = last_len / sizeof(struct ifreq);

  130.     for (i = 0; i < interface_num; ++i)
  131.     {
  132.         strcpy(ifreq1.ifr_name, interface_conf.ifc_ifcu.ifcu_req[i].ifr_name);
  133.         if (strcmp(ifreq1.ifr_name, "lo") == 0)
  134.         {
  135.             continue;
  136.         }
  137.         if (ioctl(sock, SIOCGIFHWADDR, &ifreq1) < 0)
  138.         {
  139.             continue;
  140.         }
  141.         memcpy(if_info[eth_num].mac, ifreq1.ifr_hwaddr.sa_data, 6);
  142.         strcpy(if_info[eth_num].ifname, ifreq1.ifr_name);
  143.         psockaddr_in = (struct sockaddr_in *)&interface_conf.ifc_req[i].ifr_addr;
  144.         memcpy(if_info[eth_num].ip, &(psockaddr_in->sin_addr.s_addr), 4);
  145.         printf("Interface name: %s", if_info[eth_num].ifname);
  146.         printf(" ip address: ");
  147.         print_ip(if_info[eth_num].ip);
  148.         printf(" mac address:");
  149.         print_mac(if_info[eth_num].mac);
  150.         eth_num++;
  151.     }

  152.     free(pBuff);
  153.     close(sock);
  154. }

  155. int equal_mac(unsigned char *mac1, unsigned char *mac2)
  156. {
  157.     int i;

  158.     for (i = 0; i < 6; ++i)
  159.     {
  160.         if (mac1[i] != mac2[i])
  161.             return 0;
  162.     }
  163.     return 1;
  164. }

  165. int main()
  166. {
  167.     int timeout = 2;
  168.     int optval = 1;
  169.     int s; /* socket */
  170.     int rv = 1; /* return value */
  171.     struct sockaddr_ll addr; /* for interface name */
  172.     struct arpMsg arp;
  173.     struct arpMsg *parp;

  174.     fd_set fdset;
  175.     struct timeval tm;
  176.     time_t prevTime;
  177.     u_int32_t ip;
  178.     u_int32_t yiaddr;
  179.     struct in_addr my_ip;
  180.     struct in_addr dst_ip;

  181.     struct sockaddr_ll from;
  182.     int lllen;

  183.     char buff[2000];
  184.     int nLen;
  185.     char szBuffer[4096];
  186.     int i;

  187.     if ((s = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RARP))) == -1)
  188.     {
  189.         printf("Could not open raw socket/n");
  190.         return -1;
  191.     }

  192.     if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval)) == -1)
  193.     {
  194.         printf("Could not setsocketopt on raw socket/n");
  195.         close(s);
  196.         return -1;
  197.     }

  198.     memset(&addr, 0, sizeof(addr));
  199.     addr.sll_family = AF_PACKET;
  200.     addr.sll_ifindex = get_iface_index(s, "eth0");
  201.     addr.sll_protocol = htons(ETH_P_ARP);

  202.     if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) == -1)
  203.     {
  204.         perror("getsockname");
  205.         return;
  206.     }

  207.     printf("go into get_interfaces\n");
  208.     get_interfaces();

  209.     printf("out get_interfaces\n");
  210.     memset(szBuffer, 0, sizeof(szBuffer));
  211.     lllen = sizeof(from);
  212.     while ((nLen = recvfrom(s, szBuffer, sizeof(szBuffer), MSG_TRUNC, (struct sockaddr *)&from, &lllen)) > 0)
  213.     {
  214.         parp = (struct arpMsg *)szBuffer;
  215.         printf("The request is from");
  216.         printf(" [%02X:%02X:%02X:%02X:%02X:%02X]\n", from.sll_addr[0], from.sll_addr[1],
  217.                from.sll_addr[2], from.sll_addr[3], from.sll_addr[4], from.sll_addr[5]);
  218.         print_ip(parp->sInaddr);

  219.         /* send arp request */
  220.         memset(&arp, 0, sizeof(arp));
  221.         memcpy(arp.ethhdr.h_dest, parp->sHaddr, 6); // MAC DA
  222.         memcpy(arp.ethhdr.h_source, parp->tHaddr, 6); // MAC SA
  223.         arp.ethhdr.h_proto = htons(ETH_P_RARP); // protocol type (Ethernet)
  224.         arp.htype = htons(ARPHRD_ETHER); // hardware type
  225.         arp.ptype = htons(ETH_P_IP); // protocol type (ARP message)
  226.         arp.hlen = 6; // hardware address length
  227.         arp.plen = 4; // protocol address length
  228.         arp.operation = htons(4); // RARP reply code
  229.         memcpy(arp.sInaddr, if_info[i].ip, 4); // source IP address
  230.         memcpy(arp.sHaddr, parp->tHaddr, 6); // source hardware address
  231.         memcpy(arp.tInaddr, parp->sInaddr, 4); // target IP address
  232.         memcpy(arp.tHaddr, parp->sHaddr, 6);

  233.         printf("send reply to requsted\n");
  234.         if (sendto(s, &arp, sizeof(arp), 0, (struct sockaddr *)&from, sizeof(from)) < 0)
  235.         {
  236.             perror("Unabele to send arp request");
  237.             return 0;
  238.         }
  239.         else
  240.             printf("send reply/n");
  241.     }
  242.     close(s);
  243.     return 0;
  244. }


阅读(5105) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~