netfilter-devel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Caching packets with libipq
@ 2009-01-16  1:41 David Murray
  2009-01-16  7:22 ` Eric Leblond
  0 siblings, 1 reply; 5+ messages in thread
From: David Murray @ 2009-01-16  1:41 UTC (permalink / raw)
  To: netfilter-devel

Hi,

I am trying to build a TCP proxy that is capable of reordering out of 
order TCP segments before delivering them to the end machine. I plan on 
doing this by analyzing the TCP sequence numbers but for now I am just 
trying to get familiar with netfilter.

I am currently writing this using libipq. The reason that I am not 
using the newer libnetfilter is because there seems to be way more 
documentation and examples for libipq rather than libnetfilter. Using 
libipq I am able to print out packet details and NF_ACCEPT or NF_DROP, 
however, the problem I am having is with copying and storing packets.

The program plan is to anticipate the next sequence number for a each 
flow so: nxt_seq_num  = curr_pkt_seq_num + curr_pkt_data_payload. If I 
detect that one packet is missing I want to buffer up to ten packets 
waiting for the delayed packet.

If a segment is missing from the sequence I want to copy packets into 
memory and NF_DROP until the correct segment arrives. We can then 
replay our buffered packets, and the TCP receiver will receive the 
packets in order.

Currently, I am just trying to see if this is possible in libipq 
because I have not found any similar examples of caching packets in 
libipq. So, in the code snippet below I am trying to cache the 50th 
packet, and then NF_DROP it from the queue. The program should then 
NF_ACCEPT packet 51 and inject packet 50. So if the program was working 
correctly, I would be rearranging the sequence of frames such that 
packets would arrive: 48, 49, 51, 50, 52

The problem is that it appears that packet 50 is never being replayed 
and from the terminal I am getting  a ?Received error message 2?. I 
have been unable to get further information on what this error message 
means. Interestingly, when replaying the cached packet I am still able 
to print out information from it, eg TCP sequence number and 
destination IP address.

Can anyone provide any advice as to how I can narrow this problem down 
further.

Thanks for your time
Dave

status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
     if (status < 0)
    die(h);
        do {
    status = ipq_read(h, buf, BUFSIZE, 0);
    if (status < 0)
      die(h);
                  switch (ipq_message_type(buf)) {
                 case NLMSG_ERROR: {
        fprintf(stderr, "Received error message %d\n",
        ipq_get_msgerr(buf));
        break;
        }

        case IPQM_PACKET: /* got a packet */ {

        ipq_packet_msg_t *m = ipq_get_packet(buf);
                       struct iphdr *ip = (struct iphdr*) m->payload;
        struct tcphdr *tcp = (struct tcphdr*) (m->payload + (4 * ip->ihl));

        int unsigned payload_length = (unsigned int) ntohs(ip->tot_len) 
- ((ip->ihl << 2) + (tcp->doff << 2));
                       if (payload_length > 0) {
                         if (count != 50) {

            printf("This is frame %d dest port %u and seq num %u, size 
%d\n", count, htons(tcp->dest), ntohl(tcp->seq), m->data_len);
            status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
                    }
                           if (count == 50) {

            printf("Not sending 50th packet\n");
            printf("The frame was %d dest port %u and seq num %u, size 
%d\n", count, htons(tcp->dest), ntohl(tcp->seq), m->data_len);
            printf("Chaching instead!\n");

            free(store);            store = (ipq_packet_msg_t 
*)calloc(1, BUFSIZE);
             store->packet_id = m->packet_id;        /* ID of queued packet */
            store->mark = m->mark;                  /* Netfilter mark value */
            store->timestamp_sec = m->timestamp_sec;               
store->timestamp_usec = m->timestamp_usec;                store->hook = 
m->hook;           /* Netfilter hook we rode in on */
            store->hw_protocol = m->hw_protocol;              
store->hw_type = m->hw_type;       /* Hardware type */
            store->data_len = m->data_len;         /* Length of packet data */
            memcpy(store->payload, m->payload, m->data_len);

            status = ipq_set_verdict(h, m->packet_id, NF_DROP, 0, NULL);
            printf("Status: %d\n", status);             }
           if (count == 51) {

            struct iphdr *ip = (struct iphdr*) store->payload;
            struct tcphdr *tcp = (struct tcphdr*) (store->payload + (4 
* ip->ihl));
            printf("Replaying missed frame 50 dest port %u and seq num 
%u, size %d\n", htons(tcp->dest), ntohl(tcp->seq), store->data_len);

            printf("Payload: %s\n", store->payload);
            status = ipq_set_verdict(h, store->packet_id, NF_ACCEPT, 
store->data_len, store->payload);
            printf("Status: %d\n", status);
            }

          count++;
          }

        else {
          status = ipq_set_verdict(h, m->packet_id, NF_ACCEPT, 0, NULL);
          }

        break;
        }
                             default:
        fprintf(stderr, "Unknown message type!\n");
        break;
      }     } while (1);



^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2009-01-19  3:24 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-01-16  1:41 Caching packets with libipq David Murray
2009-01-16  7:22 ` Eric Leblond
2009-01-19  0:31   ` David Murray
2009-01-19  0:47     ` Pablo Neira Ayuso
2009-01-19  3:06       ` David Murray

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).