全部博文(230)
分类: LINUX
2007-10-28 23:29:21
We are going to begin with looking at some of the sample code provided in the man page of libipq. Its not completely obvious whats going on here with the direction and flow of packets, so I'll try and explain as we go.
Before you try running the code, you need to do a couple things:
- modprobe iptable_filter
- modprobe ip_queue
- iptables rule to direct packets to QUEUE
The ones we will be using are:
- iptables -A OUTPUT -p icmp -j QUEUE
- iptables -A INPUT -p tcp -j QUEUE
- iptables -A INPUT -p udp -j QUEUE
The code begins... We have some includes, one of which is for libipq, and the other is netfilter. We use the libipq one for all of the functions prefixed with ipq_ and the netfilter header is for some of the constants we use through out. Other useful headers include the ip header, tcp header, and any other packet type that you might want to be able to map into a structure.
#include <linux/netfilter.h>
#include <libipq.h>
#include <stdio.h>
#define BUFSIZE 2048
static void die(struct ipq_handle *h)
{
ipq_perror("passer");
ipq_destroy_handle(h);
exit(1);
}
int main(int argc, char **argv)
{
int status;
unsigned char buf[BUFSIZE];
Here we need a ipq_handle in order to use later when we want to do things, such as read packets and do any other libipq operations. Note we also have a buf[BUFSIZE] above this, which is a static sized buffer for packet data. We create the handle, and move or die trying.
struct ipq_handle *h;
h = ipq_create_handle(0, PF_INET);
if (!h)
die(h);
status = ipq_set_mode(h, IPQ_COPY_PACKET, BUFSIZE);
if (status < 0)
die(h);
do{
Next we read the contents of a packet, with ipq_read. This says to read into buf, for a maximum size of BUFSIZE (we don't want to overflow the buffer right...). The last arg, in this case 0, is the timeout for the read operation. This is the same as a select() function timeout.
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 ",
ipq_get_msgerr(buf));
break;
Based on the message type, we can determine an error (NLMSG_ERROR) or if we got a packet (IPQM_PACKET). Then we use the packet_msg_t to access the packet, and then set the verdict (ACCEPT or DROP). ACCEPT allows the packet through the netfilter hooks, and into the appropriate service. DROP makes the packet disappear.
Also in the IPQM_PACKET block we have some additional code which is not in the man page. This is just an example of how to access parts of the packets, such as the IP layer header and the TCP header. To point the headers at the right places you basically just need the size of each previous header. Then by offsetting from the m->payload pointer we can access the different portions of the packet. Once we have this, you can get any of the data contained in the header, such as the port in this example.
ipq_destroy_handle(h);
return 0;
}
注:
libipq提供了以下函数: