【问题标题】:error in ip address received收到的IP地址错误
【发布时间】:2014-06-01 05:53:20
【问题描述】:

我在 C 中实现原始套接字。我有两个程序(比如服务器和客户端)。客户端正在向服务器发送信息,然后服务器正在发送 ACK。客户端已发送信息,服务器已成功接收。现在服务器正在发回 ACK。现在,客户端已经成功解析了以太网头。我在接收 IP 地址时遇到问题。

1. What should be the type of arguments of the function CreateIPHeader()?
2. How to print IP addresses in ParseIPHeader()?
3. What should be the data type of value returned by ParseIPHeader, if I want just the IP addresses?

struct iphdr *CreateIPHeader(char *src_ip,char *dst_ip)
{
struct iphdr *ip_header;
ip_header=malloc(sizeof(struct iphdr));
//OTHER FIELDS OF IP HEADER
ip_header->saddr = inet_ntoa(*((struct in_addr *)(src_ip)));
ip_header->daddr = inet_ntoa(*((struct in_addr *)(dst_ip)));
ip_header->check=ComputeChecksum((unsigned char *)ip_header,ip_header->ihl*4);
printf("\nip to be sent = %s",ip_header->saddr); //printing correct IP
printf("\nip to be rcvd = %s",ip_header->daddr);

return(ip_header);
}

char* ParseIPHeader(unsigned char *packet,int len)
{
struct iphdr *ip_header,*ret_ip;
unsigned char *out;
struct ethhdr *ethernet_header;
out=malloc(2048);
memset(out, 0, 2048);
ethernet_header=(struct ethhdr *) out;
ret_ip=(struct iphdr *) (out + sizeof(struct ethhdr));
if(ntohs(ethernet_header->h_proto)==ETH_P_IP)
{
    if(len>=(sizeof(struct ethhdr)+sizeof(struct iphdr)))
    {
        ip_header=(struct iphdr*)(packet+sizeof(struct ethhdr));
        ret_ip->saddr = ip_header->daddr;
            ret_ip->daddr = ip_header->saddr;
    printf("daddr SENT = %s",ret_ip->daddr);  //how to print them?
        printf("saddr SENT = %s",ret_ip->saddr);
    }
    else
    printf("IP packet does not have full header\n");
}
else
{ 
//not an IP packet
}
return out;
}


int main()
{
unsigned char in[2048];
int len;
char *rcv_ip;
Struct iphdr *ip_header;

    memset(in,0,2048);
len=recvfrom(raw,in,2048,0,(struct sockaddr *)&packet_info,&packet_info_size);
rcv_ip=ParseIPHeader(in,len); /*I want this function to return me the ip addresses which I would use in the next line.*/
ip_header =CreateIPHeader(rcv_ip+5,rcv_ip);

memset(in,0,2048);
memcpy(in+sizeof(struct ethhdr),ip_header,ip_header->ihl*4);

sendrawpacket(raw,in,pkt_len);
    free(ip_header);
return 0;
}

任何帮助将不胜感激。 谢谢:)

【问题讨论】:

  • 所有这些都在那里,因为我已经解析了以太网地址。此外,listen、accept 等调用不是在原始套接字中使用,而是在套接字中使用。
  • printf("Dest IP address: %s \n",(abc->daddr)); 怎么可能是正确的?您将 abc->daddr 强制转换为 C 字符串,这是行不通的。请提供SSCCE,否则很难提供帮助。
  • @cklin 如何给SSCCE?我是新来的。听说过好几次了,不知道怎么给?
  • @cklin 已编辑。请看一次。遍历最后写的main函数。

标签: c linux ip-address raw-sockets


【解决方案1】:

代替:

printf("\nDest Addr %s \n",inet_ntoa(*((struct in_addr *)&((ip_header->daddr)))));

printf("\nSource Addr %s \n",inet_ntoa(*((struct in_addr *)&(ip_header->saddr))));

也许:

printf("\nDest Addr %s \n",inet_ntoa(ip_header->daddr));

printf("\nSource Addr %s \n",inet_ntoa(ip_header->saddr));

【讨论】:

  • 'inet_ntoa' 的参数 1 的类型不兼容这就是我得到的
【解决方案2】:

如果确实是 printf 导致您出现段错误而不是其他原因,那么也许:

struct in_addr dest;
dest.s_addr = ip_header->daddr;
printf("\nDest Addr %s \n", inet_ntoa(dest));

这是因为(假设您使用的是struct iphdr *ip_headerip_header->daddr 的类型为__u32,而inet_ntoa 的类型为struct in_addr

【讨论】:

  • 所以你实际上没有段错误?如果没有 SSCCE,就很难再提供任何帮助。
  • @user3392539 也许你应该告诉我们实际发生了什么。如果执行此代码,则必须更改输出。但也许它没有被执行。那么会发生什么?
  • @nos 我希望 parseipheader() 返回发送者和接收者的 IP 地址。它的返回类型应该是什么?可以是字符数组吗?
【解决方案3】:

有几件事是错误的。

  1. CreateIPHeader

    您将inet_ntoa()inet_aton() 混淆了。创建 IP 标头时,您希望使用类似

    的方式设置 ip_header->saddr
    inet_aton(src_ip, (struct in_addr *) &ip_header->saddr) 
    

    请记住,struct iphdr 中的 s_addrd_addr__u32 类型,而不是 char 数组。因此,当您进行此更改时,CreateIPHeader 中的 printf 语句将中断。

  2. main

    printf 工作的原因是问题 #1。在接收时,您调用CreateIPHeader 创建一个不正确的struct iphdr(见上文),它现在错误地将C 字符串分配给saddrdaddr。后来abc指向了这个不正确的header;你的printf 神奇地工作,因为abc->saddrabc->daddr 实际上 C 字符串。

  3. 您只是覆盖了 packet_buffer 的 iphdr 部分(您的 memcpy 语句)。您还必须更改struct ethhdr 中的h_desth_src 值。

  4. 您确实不需要将 IP 地址转换为 C 字符串,然后再将它们转换回 IP 地址。

  5. 另外,你没有释放ip_header

一般来说,你可以这样做:

int main()
{
    unsigned char in[2048];
    unsigned char out[2048];
    int len;

    memset(in, 0, 2048);
    memset(out, 0, 2048);

    len = recvfrom(raw, in, 2048, 0, 
               (struct sockaddr *) &packet_info, &packet_info_size);

    struct ethhdr *in_eth = (struct ethhdr *) in;
    if (ntohs(ethernet_header->h_proto) == ETH_P_IP && 
        len >= sizeof(struct ethhdr) + sizeof(struct iphdr) {
            struct iphdr *in_ip = (struct iphdr*) (in + sizeof(struct ethhdr));

            /* create outbound packet, starting with eth header */
            struct ethhdr *out_eth = (struct ethhdr *) out;
            /* ... set h_dest and h_src */

            struct iphdr *out_ip = (struct iphdr *) (out + sizeof(struct ethhdr));
            out_ip->saddr = in_ip->daddr;
            out_ip->daddr = in_ip->saddr;
            /* calculate the IPv4 checksum, packet len etc */

            sendrawpacket(raw, out, pkt_len);
        }

    return 0;
};

不保证没有错误。只是在浏览器中写的。

【讨论】:

  • 再次编辑,尽我所能理解。因为我第一次做原始套接字编程所以有点困惑。请通过回答我在帖子中更新的前三个问题来帮助我。 :)
猜你喜欢
  • 2014-01-10
  • 2013-12-22
  • 2014-06-07
  • 1970-01-01
  • 2014-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-29
相关资源
最近更新 更多