Re: question when using options in headers..

"Mustafa Abu Sedera" <[email protected]>
Newsgroups gmane.comp.security.libnet
Message-ID <[email protected]>
First of all, thank you very much, Mike Shiffman, for your reply.

I tried out these things (and other) the last week and still have problems 
and kindly ask for your help.

I am writing a program which captures packets using libpcap from 
eth0(subnet) then resends them from eth1(main LAN) with a different source 
IP (kind of NATing). After I capture the packet I rebuild it depending on 
it's protocol so that libnet computes the checksums for me as they change 
after this packet alternation.

I use tcpdump to sniff the packets going out from eth1 and get a false 
checksum for my tcp packets and i noticed only those, which contain options. 
for icmp packets I don't get errors and they work fine because i get 
replies. udp i didn't test yet.

If you please could take a look at the attached file which contains the 
function i use, don't worry it isn't too long and easy to understand. i 
spent about the whole day debugging and couldn't find out what's wrong.
And i still don't know wether to use ptags or libnet_clear_packet() so if 
you have any suggestions please tell me.
Sorry for the long massage.
Best regards.

>From: Mike Schiffman <[email protected]>
>To: "Mustafa Abu Sedera" <[email protected]>
>CC: [email protected]
>Subject: Re: question when using options in headers..
>Date: Wed, 28 Jan 2004 09:01:51 -0800
>
>q1: Yes that is correct ordering. See sample/tcp1.c for a sample 
>application using TCP options. To answer the second part: Not using the 
>options builder function. Since the options string will actually have its 
>own pblock, if you save existing ptags, then call builder functions inside 
>of a loop using those ptags, the next call to a builder function WITHOUT a 
>saved ptag will generate a new pblock at the end of the list. Two things 
>you can try: 1) place your TCP or IP options inside the payload and adjust 
>the appropriate header values. 2) try calling an options builder with a 0 
>sized payload and save its ptag. I kinda doubt this second one will work 
>though; there is a ton of pointer math and indirection going on inside the 
>options builders.
>
>q2: It all depends on your needs. If you're only sending packets one at a 
>time with a fire and forget mentality, use only one context. If you need to 
>send multiple packets over and over again, use the cq interface.
>
>q3: I just tested the advanced mode and it worked fine as of 1.1.2-rc-05. 
>Can you be more specific with your error? Are you sure you initialized the 
>library properly?

_________________________________________________________________
Protect your PC - get McAfee.com VirusScan Online 
http://clinic.mcafee.com/clinic/ibuy/campaign.asp?cid=3963
route_packet.h (application/octet-stream, 6.4 KB)
/*route_pkt() should route the captured pkt from sub-ether(SE) to network-ether(NE)
by replacing the source IP with that of the NE */


int route_packet(libnet_t* l, //initialized LIBNET_RAW4_ADV and "eth1"
                 struct libnet_ether_addr* eth_addr_dev, //MAC addr of sending NIC
                 struct libnet_ethernet_hdr* eth_hdr,struct libnet_ipv4_hdr* ip4_hdr)
                 //points to a valid packet captured with libpcap from eth0
{
    int count;
    u_char* payload = NULL;
    u_int payload_len = 0;
    u_int tcp_hdr_len, ip_hdr_len, pkt_len;
    struct libnet_tcp_hdr* tcp_hdr;
    struct libnet_udp_hdr* udp_hdr;

    //statistics
    static int num_tcp_pkts = 0;
    static int num_icmp_pkts = 0;   
    static int num_udp_pkts = 0;
    
    //these are only used for testing
    u_char src_ip[] = {10, 0, 0, 1};
    u_char dst_ip[] = {10, 131, 72, 115};

    //check for source MAC to avoid looping
    if( 0 == memcmp(eth_hdr->ether_shost, eth_addr_dev, ETHER_ADDR_LEN) )
    {
        //printf("\nSource MAC = device");
        return 0;
    }
        
    // to clear any preaviously stored data in the context
    // check if i should use tags better???
    libnet_clear_packet(l);

    ip_hdr_len = ip4_hdr->ip_hl * 4;
    pkt_len = ntohs( ip4_hdr->ip_len );

    switch( ip4_hdr->ip_p )
    {
        case IPPROTO_ICMP:  //handle icmp as payload because it's checksum won't change
            payload =  (u_char*)ip4_hdr + ip_hdr_len;
            payload_len = pkt_len - ip_hdr_len;
            num_icmp_pkts++;
            break;

        case IPPROTO_TCP:
            tcp_hdr = (struct libnet_tcp_hdr*)( (u_char*)ip4_hdr+ip_hdr_len );

            tcp_hdr_len = tcp_hdr->th_off * 4;

            //if there is a payload
            if( pkt_len > (ip_hdr_len + tcp_hdr_len) ) 
            {
                payload = (u_char*)tcp_hdr + tcp_hdr_len;
                payload_len = pkt_len - ip_hdr_len - tcp_hdr_len;
            }

            //if we have tcp options
            if( tcp_hdr_len > LIBNET_TCP_H)
            {
                if( -1 == libnet_build_tcp_options((u_char*)tcp_hdr+LIBNET_TCP_H,
                                                    tcp_hdr_len - LIBNET_TCP_H, l, 0))
                {
                    printf("\nError in libnet_build_tcp_options(): %s", libnet_geterror(l));
                    return -1;
                }
            }

            if( -1 == libnet_build_tcp(ntohs(tcp_hdr->th_sport),
                                       ntohs(tcp_hdr->th_dport),
                                       ntohl(tcp_hdr->th_seq),
                                       ntohl(tcp_hdr->th_ack),
                                       tcp_hdr->th_flags,
                                       ntohs(tcp_hdr->th_win),
                                       0,   // checksum
                                       ntohs(tcp_hdr->th_urp),
                                       payload_len + tcp_hdr_len, // + LIBNET_TCP_H
                                       payload, // location of payload
                                       payload_len,
                                       l, 0) )
            {
                printf("\nError in libnet_build_tcp() %s",libnet_geterror(l));
                return -1;
            }

            // it will be used again in build IP function, so set back to NULL and 0
            payload = NULL;
            payload_len = 0;

            num_tcp_pkts++;
            break;

        case IPPROTO_UDP:
            udp_hdr = (struct libnet_udp_hdr*)( (u_char*)ip4_hdr+ip_hdr_len );

		//if there is payload
            if( pkt_len > (ip_hdr_len + LIBNET_UDP_H) )
            {
                payload = (u_char*)udp_hdr + LIBNET_UDP_H;
                payload_len = pkt_len - ip_hdr_len - LIBNET_UDP_H;
            }

            if( -1 == libnet_build_udp( ntohs(udp_hdr->uh_sport),
                                        ntohs(udp_hdr->uh_dport),
                                        LIBNET_UDP_H + payload_len,
                                        0,
                                        payload,
                                        payload_len,
                                        l, 0) )
            {
                printf("\nError in libnet_build_udp(): %s", libnet_geterror(l));
                return -1;
            }

            // it will be used again in build IP function, so set back to 0
            payload = NULL;
            payload_len = 0;

            num_udp_pkts++;        
            break;

        default:
            return 0;
    }
    // if pkt have ip options
    if( ip_hdr_len > LIBNET_IPV4_H )
        if( -1 == libnet_build_ipv4_options((u_char*)ip4_hdr+LIBNET_IPV4_H,
                                            ip_hdr_len - LIBNET_IPV4_H, l, 0))
        {
            printf("\nError in libnet_build_ip_options(): %s", libnet_geterror(l));
            return -1;
        };          
        
   if( -1 == libnet_build_ipv4(pkt_len,
                                ip4_hdr->ip_tos,
                                ntohs(ip4_hdr->ip_id),
                                ntohs(ip4_hdr->ip_off),
                                ip4_hdr->ip_ttl,
                                ip4_hdr->ip_p,
                                0,  //checksum
                                *((u_long*)&src_ip), // new src and dst IP addr defined above
                                *((u_long*)&dst_ip), //looks ugly:)
                                payload,
                                payload_len,
                                l, 0) )   
    {
        printf("\nError in libnet_build_ipv4(): %s", libnet_geterror(l));
        return -1;
    }

    // for debugging
    if( -1 == libnet_adv_cull_packet(l, &payload, &payload_len) )
        printf("\nError in libnet_cull_pkt(): %s", libnet_geterror(l) );
    
    else 
    {
        for (count = 0; count < payload_len; count++)
        {
            if( (count%20) == 0 )printf("\n");
            printf("%.2x ",payload[count]);
        }
    }
    fflush (stdout);

    if( -1 == (count = libnet_write(l)) )
    {
        printf("\nError in libnet_write(): %s", libnet_geterror(l));
        return -1;
    }

    printf("\nWrote %d bytes to wire...", count);
    printf("\nstats: %d ICMP\t %d TCP\t %d UDP",num_icmp_pkts,num_tcp_pkts,num_udp_pkts);

    return count;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.