Re: 2.6.8.1 ip_rt_bug using libipq to reroute packets to loopback,works on 2.4.x

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

 



Hi,

there's a open issue about ip_queue in 2.6, I suggest you discussing it in netfilter-devel mailling list. Could you tell which is exactly that error message? if any oops, could you post it, you feedback could help a lot.

regards,
Pablo

J Leven wrote:

Hi,

I'm trying to use libipq to take all outbound packets destined for a
particular address (192.168.1.44) and reroute them to loopback.  I
have the program below, it works just fine in 2.4.x kernels but
produces a ip_rt_bug message in the 2.6 series.  Is there something I
am missing in the iptables configuration for 2.6, or is there a
workaround for this?
To test this, run setup_iptables.sh, compile and run test_server.c (on port 80)
and ipqtest.c.	Then "telnet 192.168.1.44 80".  The
expected behavior (that on 2.4 kernel), is a successful connection to
test_server.

Thanks in advance,
Jay

--------------------------------------------------------------
--------------------------- IPQTEST.C ------------------------
--------------------------------------------------------------
/* Compile with cc -lipq */
#include <linux/netfilter.h>
#include <libipq.h>
#include <stdio.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>

#define BUFSIZE 2048

struct in_addr dot_44;
struct in_addr loopback;

inline u_int16_t checksum_update_32(
	u_int16_t old_check,
	u_int32_t old,
	u_int32_t new)
{
	u_int32_t l;

	old_check = ~old_check;
	old = ~old;

	l = (u_int32_t)old_check + (old >> 16) + (old & 0xffff)
+ (new >> 16) + (new & 0xffff);
	return ~((u_int16_t)(l >> 16) + (l & 0xffff));
}

static void filter(
	unsigned char *packet)
{
	struct iphdr *ip;
	struct tcphdr *tcp;

	ip = (struct iphdr *)packet;
	if (ip->protocol == IPPROTO_TCP)
	{
		tcp = (struct tcphdr *)(((u_int32_t *)ip) + ip->ihl);

		if (ip->saddr == loopback.s_addr)
		{
			ip->check = checksum_update_32(

				ip->check,
				ip->saddr,
				dot_44.s_addr);
			tcp->check = checksum_update_32(
				tcp->check,
				ip->saddr,
				dot_44.s_addr);
			ip->saddr = dot_44.s_addr;
		}
		if (ip->daddr == dot_44.s_addr)
		{
			ip->check = checksum_update_32(
				ip->check,
				ip->daddr,
				loopback.s_addr);
			tcp->check = checksum_update_32(
				tcp->check,
				ip->daddr,
				loopback.s_addr);
			ip->daddr = loopback.s_addr;
		}
	}
}

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];
	struct ipq_handle *h;

	inet_aton("192.168.1.44", &(dot_44));
	inet_aton("127.0.0.1", &(loopback));

	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{
		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: {
			ipq_packet_msg_t *m = ipq_get_packet(buf);

fprintf(stderr, "----------------
Accepting packet ----------------\n");
if (m->data_len < sizeof(struct iphdr)) {
fprintf(
stderr,
"XXX BUG: %d < %d\n",
m->data_len,
sizeof(struct iphdr));
}
filter(m->payload);
status = ipq_set_verdict(
h,
m->packet_id,
NF_ACCEPT,
m->data_len,
m->payload);
if (status < 0)
die(h);
break;
}


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

	ipq_destroy_handle(h);
	return 0;
}
--------------------------------------------------------------
------------------------- TEST_SERVER.C ----------------------
--------------------------------------------------------------
#include <string.h>
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <unistd.h>
#include <sys/select.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>

int my_recv(
	int csock,
	char *bufptr,
	int read_len)
{
	fd_set fds;
	int rval;

	FD_ZERO(&fds);
	FD_SET(csock, &fds);
	do {
		select(csock + 1, &fds, NULL, NULL, NULL);

		rval = recv(csock, bufptr, read_len, 0); /* req1 */
		if (rval > 0)
		{
			bufptr += rval;
			read_len -= rval;
		}
		else if (rval < 0
				 && (errno == EAGAIN
					 || errno == EINTR
					 || errno == EWOULDBLOCK))
		{
			continue;
		}
		else
		{
			return -1;
		}
	} while (read_len);

	return 0;
}

int my_send(
	int csock,
	char *bufptr,
	int send_len)
{
	fd_set fds;
	int rval;

	FD_ZERO(&fds);
	FD_SET(csock, &fds);
	do {
		select(csock + 1, NULL, &fds, NULL, NULL);

		rval = send(csock, bufptr, send_len, 0); /* req1 */
		if (rval > 0)
		{
			bufptr += rval;
			send_len -= rval;
		}
		else if (rval < 0
				 && (errno == EAGAIN
					 || errno == EINTR
					 || errno == EWOULDBLOCK))
		{
			continue;
		}
		else
		{
			return -1;
		}
	} while (send_len);

	return 0;
}

static void usage() {
fprintf(stderr, "\nusage : test_server -p port\n");
exit(-1);
}


int main(int argc, char **argv) {
	int ssock, csock[2000];
	struct sockaddr_in saddr;
	char res1[2048];
	char buf[204800];
	int sz, on, rval, i=0;
	int c, port;
	fd_set fds;
	
   /* get command line params */
   while ((c = getopt(argc, argv, "p:")) != -1) {
		switch(c) {
		  case 'p':
			  port = atoi(optarg); i++;
			  break;
	      default:
			  usage();
		}  /* switch end */
   }  /* while end */

if (i < 1 )
{
usage();
}


	i=0;

	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	saddr.sin_addr.s_addr = INADDR_ANY;

	ssock = socket(PF_INET, SOCK_STREAM, 0);
	on = 1;
	sz = 512 * 1024;
	setsockopt(ssock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
	setsockopt(ssock, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
	setsockopt(ssock, SOL_SOCKET, SO_SNDBUF, &sz, sizeof(sz));
	setsockopt(ssock, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
	fcntl(ssock, F_SETFL, O_NONBLOCK | O_ASYNC);
	bind(ssock, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in));
	listen(ssock, 100);

FD_ZERO(&fds);
FD_SET(ssock, &fds);

while (1)
{
select(ssock + 1, &fds, NULL, NULL, NULL);
csock[i] = accept(ssock, NULL, NULL);
snprintf(res1,sizeof(res1),"[%d] Connected To
Test Server...",i);
printf("%s\n",res1);
my_send(csock[i], res1, strlen(res1)); i++;
}


return 0;
}
--------------------------------------------------------------
------------------------- IPTABLES.SH ------------------------
--------------------------------------------------------------
#!/bin/sh
/sbin/iptables --flush
/sbin/iptables -A OUTPUT -j QUEUE
/sbin/iptables -A INPUT -j QUEUE
/sbin/iptables -A FORWARD -j QUEUE
/sbin/modprobe ip_queue



- : send the line "unsubscribe linux-net" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux