Question

I want to learn how to process packets in the user space. Therefore I worked through the example queue handler from the oxygen libnetfilter_queue documentation. [LINK]

So I built the firewall to send incoming ICMP packtes to the queue. I also sent a ping from an other PC to mine and started the program.

BUT the programm stoped during the receive request. - Why?

This are the settings:


-1- The firewall: my firewall sends all incoming ICMP packets to the queue socket 0

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
NFQUEUE    icmp --  anywhere             anywhere             NFQUEUE num 0

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

-2- I pinged my PC and tested the presence of the packets with wireshark. - I got the packets.

-3- The code of the queue handle programm. I added some printf outputs to show where the program stucks. Normaly the program is said to receive the packets and print informations about their header and data.

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <linux/types.h>
#include <linux/netfilter.h>        /* for NF_ACCEPT */

#include <libnetfilter_queue/libnetfilter_queue.h>

/* returns packet id */
static u_int32_t print_pkt (struct nfq_data *tb) 
{
    int id = 0;
    struct nfqnl_msg_packet_hdr *ph;
    struct nfqnl_msg_packet_hw *hwph;
    u_int32_t mark,ifi; 
    int ret;
    char *data;

    ph = nfq_get_msg_packet_hdr(tb);
    if (ph) {
        id = ntohl(ph->packet_id);
        printf("hw_protocol=0x%04x hook=%u id=%u ",
            ntohs(ph->hw_protocol), ph->hook, id);
    }

    hwph = nfq_get_packet_hw(tb);
    if (hwph) {
        int i, hlen = ntohs(hwph->hw_addrlen);

        printf("hw_src_addr=");
        for (i = 0; i < hlen-1; i++)
            printf("%02x:", hwph->hw_addr[i]);
        printf("%02x ", hwph->hw_addr[hlen-1]);
    }
    mark = nfq_get_nfmark(tb);
    if (mark)
        printf("mark=%u ", mark); 

    ifi = nfq_get_indev(tb);

    if (ifi)
        printf("indev=%u ", ifi);

    ifi = nfq_get_outdev(tb); 
    if (ifi)
        printf("outdev=%u ", ifi);

    ifi = nfq_get_physindev(tb); 
    if (ifi)
        printf("physindev=%u ", ifi);

    ifi = nfq_get_physoutdev(tb);
    if (ifi)
        printf("physoutdev=%u ", ifi);

    ret = nfq_get_payload(tb, &data); 
    if (ret >= 0)
        printf("payload_len=%d ", ret);

    fputc('\n', stdout);

    return id;
}


static int cb(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg,  
          struct nfq_data *nfa, void *data)             
{
    u_int32_t id = print_pkt(nfa);
    printf("entering callback\n");
    return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); 
}

int main(int argc, char **argv)
{
    struct nfq_handle *h;
    struct nfq_q_handle *qh;
    int fd = 0;
    int rv;
    char buf[4096] __attribute__ ((aligned));

    printf("opening library handle\n");
    h = nfq_open(); 
    if (!h) {
        fprintf(stderr, "error during nfq_open()\n");
        exit(1);
    }

    printf("unbinding existing nf_queue handler for AF_INET (if any)\n");   
    if (nfq_unbind_pf(h, AF_INET) < 0) {                    
        fprintf(stderr, "error during nfq_unbind_pf()\n");
        exit(1);
    }

    printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
    if (nfq_bind_pf(h, AF_INET) < 0) {
        fprintf(stderr, "error during nfq_bind_pf()\n");
        exit(1);
    }

    printf("binding this socket to queue '0'\n");   
    qh = nfq_create_queue(h, 1, &cb, NULL);         
    if (!qh) {                      
        fprintf(stderr, "error during nfq_create_queue()\n");   
        exit(1);                                                
    }

    printf("setting copy_packet mode\n");
    if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {  /* nfg_set_mode stellt ein, welche Pakete in dieses Programm geladen... */
        fprintf(stderr, "can't set packet_copy mode\n");    /* ...werden sollen. Hier werden metadata und data in das Programm geladen... */
        exit(1);                        /* Die Funktion gibt bei einem Fehler -1 zurück. */
    }

    fd = nfq_fd(h);

    printf("DEBUG: The programm processed nfq_fd(h)!\n nfg_fd is: %u \n", fd);

    rv = recv(fd, buf, sizeof(buf), 0); // temporär kopiert

    printf("DEBUG: The programm arrived the receiver!\n recv is: %u \n", rv);

    while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) {   
        printf("pkt received\n");               
        nfq_handle_packet(h, buf, rv);
    }

    printf("unbinding from queue 0\n");

    nfq_destroy_queue(qh);

#ifdef INSANE
    /* normally, applications SHOULD NOT issue this command, since
     * it detaches other programs/sockets from AF_INET, too ! */
    printf("unbinding from AF_INET\n");
    nfq_unbind_pf(h, AF_INET);
#endif

    printf("closing library handle\n");
    nfq_close(h); /* closing the handler */

    exit(0);
}

-4- This is the output when I'm execute the program.The programm stoped before/during the receive request.

opening library handle
unbinding existing nf_queue handler for AF_INET (if any)
binding nfnetlink_queue as nf_queue handler for AF_INET
binding this socket to queue '0'
setting copy_packet mode
DEBUG: The programm processed nfq_fd(h)!
 nfg_fd is: 3

I hope this informations help to understand what I'm want to do. The main documentation about the libnetfilte_queue is very brief at the recv command.

Happy to found this forum, 4tlas :)

Was it helpful?

Solution

Finally I found the problem. Somehow I had accidently changed the NFQUEUE num of the handler program in this line to one:

qh = nfq_create_queue(h, 1, &cb, NULL);

As result the program waited for packets from NFQUEUE num 1 but my firewall sent all packets to NFQUEUE num 0.

The corrected line:

 qh = nfq_create_queue(h, 0, &cb, NULL);

Ohh man... this was kind of a dumb mistake ;)

I would like to give thanks to everyone who thought about my problem! - 4tlas

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top