-1

I am implementing raw sockets in C. I have two programs (say server and client). Client is sending info to server and then server is sending ACK. Client has sent info and server has successfully received it. Now server is sending back ACK. Now, Client has parsed ethernet header successfully. I have problem in receiving the IP address.

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

Any help would be appreciated. Thanks :)

user3392539
  • 71
  • 1
  • 2
  • 11
  • all those things are there as I have parsed ethernet address. Also, listen, accept, etc. calls are not used in raw sockets but sockets. – user3392539 Apr 17 '14 at 05:13
  • How is it possible that `printf("Dest IP address: %s \n",(abc->daddr));` is correct? You are coercing `abc->daddr` into a C string, which is not going to work. Please provide a SSCCE, otherwise it's hard to help. – cklin Apr 17 '14 at 05:15
  • @cklin How to give SSCCE? I am new here. Heard of this several times but don't know how to give it? – user3392539 Apr 17 '14 at 05:25
  • http://meta.stackexchange.com/questions/22754/sscce-how-to-provide-examples-for-programming-questions – cklin Apr 17 '14 at 05:26
  • @cklin edited. Please see this once. Go through main function written in the last. – user3392539 Apr 17 '14 at 06:27

3 Answers3

0

Instead of:

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

Perhaps:

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

printf("\nSource Addr %s \n",inet_ntoa(ip_header->saddr));
Mahonri Moriancumer
  • 5,993
  • 2
  • 18
  • 28
0

If indeed the printf is causing you to segfault and not something else, then perhaps:

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

This is because (assuming you are using struct iphdr *ip_header) ip_header->daddr has a type of __u32 and inet_ntoa takes a struct in_addr.

cklin
  • 900
  • 4
  • 16
  • So you're not actually segfaulting? Without an SSCCE it's hard to help any further. – cklin Apr 17 '14 at 05:35
  • @user3392539 Perhaps you should tell us what actually happens. There has to be a change in output if this code is executed. But perhaps it isn't executed. So what happens ? – nos Apr 17 '14 at 09:47
  • @nos I want parseipheader() to return me the ip address of both sender and receiver. What should be its return type? Can it be character array? – user3392539 Apr 17 '14 at 09:49
0

There are a couple things wrong.

  1. CreateIPHeader

    You are confusing inet_ntoa() with inet_aton(). When creating the IP header, you want to set ip_header->saddr using something like

    inet_aton(src_ip, (struct in_addr *) &ip_header->saddr) 
    

    Remember, the s_addr and d_addr in struct iphdr are of type __u32, not char arrays. Thus, when you make this change, the printf statements in CreateIPHeader will break.

  2. main

    The reason why your printf's are working is due to Problem #1. On receive, you call CreateIPHeader to create an incorrect struct iphdr (see above), which now incorrectly has C-strings assigned to saddr and daddr. Later, abc points to this incorrect header; your printf's magically work because abc->saddr and abc->daddr actually are C strings.

  3. You are only overwriting the iphdr portion of packet_buffer (your memcpy statement). You must also change the h_dest and h_src values in struct ethhdr.

  4. You really don't need to convert the IP addresses into a C string and then convert them back into IP addresses.

  5. Also, you aren't freeing ip_header.

In general, you can do something like this:

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

No guarantee that's bug-free. Just wrote it in the browser.

cklin
  • 900
  • 4
  • 16
  • edited again with as much I could understand. Since I am doing raw socket programming the first time so a bit confused. Please help me by giving the answer of first three questions I updated in my post. :) – user3392539 Apr 17 '14 at 09:18