收到的IP地址错误

时间:2014-04-17 05:05:12

标签: c linux ip-address raw-sockets

我在C中实现原始套接字。我有两个程序(比如服务器和客户端)。客户端正在向服务器发送信息,然后服务器正在发送ACK。客户端已发送信息,服务器已成功接收。现在服务器正在发回ACK。现在,Client已成功解析以太网头。我收到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;
}

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

3 个答案:

答案 0 :(得分:0)

而不是:

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));

答案 1 :(得分:0)

如果确实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类型为__u32inet_ntoa需要struct in_addr

答案 2 :(得分:0)

有几件事情有误。

  1. CreateIPHeader

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

    之类的内容设置ip_header->saddr
    inet_aton(src_ip, (struct in_addr *) &ip_header->saddr) 
    

    请注意,s_addr中的d_addrstruct iphdr属于__u32类型,而非char数组。因此,当您进行此更改时,printf中的CreateIPHeader语句将会中断。

  2. main

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

  3. 您只覆盖了packet_buffer的iphdr部分(您的memcpy声明)。您还必须更改h_dest中的h_srcstruct ethhdr值。

  4. 您确实无需将IP地址转换为C字符串,然后将其转换回IP地址。

  5. 此外,您还没有释放ip_header

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

    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;
    };
    

    不保证没有错误。刚刚在浏览器中写了它。