linux – loopback接口上的原始套接字可能吗?

前端之家收集整理的这篇文章主要介绍了linux – loopback接口上的原始套接字可能吗?前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我们正试图通过原始套接字与侦听 Linux环回接口的服务器通信,似乎服务器没有从我们那里获得单个数据包.我们发送的数据包在Wireshark中可见.

是否可以在环回上使用原始套接字? (请不要问我们为什么需要它:这里解释起来太复杂了)

编辑:这是我们打开它的方式

  1. _I_RawSocket = socket( PF_PACKET,SOCK_RAW,htons(ETH_P_ALL)))
  2.  
  3. memset( &ifr,sizeof( ifr ) );
  4. strcpy( ifr.ifr_ifrn.ifrn_name,_InterfaceName);
  5.  
  6. ioctl( _I_RawSocket,SIOCGIFINDEX,&ifr )
  7.  
  8. memset( &sll,sizeof( sll ) );
  9. sll.sll_family = AF_PACKET;
  10. sll.sll_ifindex = ifr.ifr_ifindex;
  11. sll.sll_protocol = htons( ETH_P_ALL );
  12.  
  13. bind( _I_RawSocket,(struct sockaddr *) &sll,sizeof( sll ))

服务器是lighttpd,可通过localhost上的普通套接字访问.
netstat –raw打印空表但我绝对相信我们在普通eth设备上有两个功能原始套接字.

解决方法

原始套接字使用bind()和connect()表现得特别不稳定,但我无法确认您的问题在于它们.我建议你遵循一个更简单的方法

寄件人

  1. #include <sys/socket.h>
  2. #include <sys/types.h>
  3. #include <netinet/ip.h>
  4. #include <arpa/inet.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9. #define DEST "127.0.0.1"
  10.  
  11. int main(int argc,char **argv)
  12. {
  13.  
  14. int s;
  15. struct sockaddr_in dst_addr;
  16. char packet[50];
  17.  
  18. struct iphdr *ip = (struct iphdr *)packet;
  19.  
  20. if((s = socket(AF_INET,IPPROTO_RAW)) < 0) {
  21. perror("error:");
  22. exit(EXIT_FAILURE);
  23. }
  24.  
  25. dst_addr.sin_family = AF_INET;
  26. dst_addr.sin_port = 0; /* not needed in SOCK_RAW */
  27. inet_pton(AF_INET,DEST,(struct in_addr *)&dst_addr.sin_addr.s_addr);
  28. memset(dst_addr.sin_zero,sizeof(dst_addr.sin_zero));
  29.  
  30. memset(packet,'A',sizeof(packet)); /* payload will be all As */
  31.  
  32. ip->ihl = 5;
  33. ip->version = 4;
  34. ip->tos = 0;
  35. ip->tot_len = htons(40);
  36. ip->frag_off = 0; /* NF */
  37. ip->ttl = 64;
  38. ip->protocol = IPPROTO_RAW; /* this has to be IPPROTO_RAW */
  39. ip->check = 0;
  40. ip->saddr = dst_addr.sin_addr.s_addr;
  41. ip->daddr = dst_addr.sin_addr.s_addr;
  42.  
  43. while(42) {
  44. sleep(5);
  45. if (sendto(s,packet,sizeof(packet),(struct sockaddr *)&dst_addr,(socklen_t)sizeof(dst_addr)) < 0)
  46. perror("uh oh:");
  47. }
  48. return(0);
  49. }

接收器

  1. #include <sys/socket.h>
  2. #include <sys/types.h>
  3. #include <netinet/ip.h>
  4. #include <arpa/inet.h>
  5. #include <string.h>
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8.  
  9.  
  10. int main(int argc,char **argv)
  11. {
  12. int s;
  13. struct sockaddr_in src_addr;
  14. char packet[50];
  15.  
  16. if ((s = socket(AF_INET,IPPROTO_RAW)) < 0) {
  17. perror("error:");
  18. exit(EXIT_FAILURE);
  19. }
  20.  
  21. memset(packet,sizeof(packet));
  22. socklen_t *len = (socklen_t *)sizeof(src_addr);
  23. int fromlen = sizeof(src_addr);
  24.  
  25. while(42) {
  26. if (recvfrom(s,&packet,(struct sockaddr *)&src_addr,&fromlen) < 0)
  27. perror("uh oh:");
  28.  
  29. int i = sizeof(struct iphdr); /* print the payload */
  30. for(; i < sizeof(packet); i++) {
  31. printf("%c",packet[i]);
  32. }
  33. printf("\n");
  34. }
  35. return(0);
  36. }

我希望这些行为完全像你想要的那样.阅读man 7 raw,了解为什么这有效的血腥细节,更重要的是man 7数据包,如果你想扩展它.另外,请注意IPPROTO_RAW意味着IP_HDRINCL套接字选项,这就是我们自己构建ip头的原因 – 尽管IP校验和和总长度仍由内核计算和填充.

编辑:此外,如果您想要一个原始套接字用于将有效数据发送到像lighttpd这样的应用程序,您必须将协议参数与socket()匹配,并为IP头字段提供有效值.正确的以太网头不是必需的 – 内核堆栈将为您填充唯一重要的字段.

猜你在找的Linux相关文章