Caching packets with libipq

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux