Fix ipfilter support.

- Add support for timestamps
 - Add support for rhosts
 - Add get_portmappings_in_range
This commit is contained in:
David Howland 2012-03-18 10:13:10 -04:00
parent 27b5ae6c9b
commit a8e337326c
3 changed files with 166 additions and 23 deletions

View File

@ -131,6 +131,7 @@ struct rdr_desc {
struct rdr_desc * next;
unsigned short eport;
int proto;
unsigned int timestamp;
char str[];
};
@ -138,7 +139,8 @@ struct rdr_desc {
static struct rdr_desc * rdr_desc_list;
static void
add_redirect_desc(unsigned short eport, int proto, const char * desc)
add_redirect_desc(unsigned short eport, int proto,
unsigned int timestamp, const char * desc)
{
struct rdr_desc * p;
size_t l;
@ -150,6 +152,7 @@ add_redirect_desc(unsigned short eport, int proto, const char * desc)
p->next = rdr_desc_list;
p->eport = eport;
p->proto = proto;
p->timestamp = timestamp;
memcpy(p->str, desc, l);
rdr_desc_list = p;
}
@ -175,7 +178,7 @@ del_redirect_desc(unsigned short eport, int proto)
}
static void
get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen)
get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen, unsigned int * timestamp)
{
struct rdr_desc * p;
@ -185,9 +188,11 @@ get_redirect_desc(unsigned short eport, int proto, char * desc, int desclen)
if (p->eport == eport && p->proto == proto)
{
strncpy(desc, p->str, desclen);
*timestamp = p->timestamp;
return;
}
}
return;
}
int init_redirect(void)
@ -221,9 +226,9 @@ void shutdown_redirect(void)
}
int
add_redirect_rule2(const char * ifname, unsigned short eport,
const char * iaddr, unsigned short iport, int proto,
const char * desc)
add_redirect_rule2(const char * ifname, const char * rhost,
unsigned short eport, const char * iaddr, unsigned short iport,
int proto, const char * desc, unsigned int timestamp)
{
struct ipnat ipnat;
struct ipfobj obj;
@ -257,6 +262,12 @@ add_redirect_rule2(const char * ifname, unsigned short eport,
}
#endif
if(rhost && rhost[0] != '\0' && rhost[0] != '*')
{
inet_pton(AF_INET, rhost, &ipnat.in_src[0].in4);
ipnat.in_src[1].in4.s_addr = 0xffffffff;
}
inet_pton(AF_INET, iaddr, &ipnat.in_in[0].in4);
ipnat.in_in[1].in4.s_addr = 0xffffffff;
@ -269,7 +280,7 @@ add_redirect_rule2(const char * ifname, unsigned short eport,
if (r == -1)
syslog(LOG_ERR, "ioctl(SIOCADNAT): %m");
else
add_redirect_desc(eport, proto, desc);
add_redirect_desc(eport, proto, timestamp, desc);
return r;
}
@ -280,6 +291,8 @@ int
get_redirect_rule(const char * ifname, unsigned short eport, int proto,
char * iaddr, int iaddrlen, unsigned short * iport,
char * desc, int desclen,
char * rhost, int rhostlen,
unsigned int * timestamp,
u_int64_t * packets, u_int64_t * bytes)
{
ipfgeniter_t iter;
@ -322,8 +335,10 @@ get_redirect_rule(const char * ifname, unsigned short eport, int proto,
*bytes = 0;
if (iport != NULL)
*iport = ntohs(ipn.in_pnext);
if (desc != NULL)
get_redirect_desc(eport, proto, desc, desclen);
if ((desc != NULL) && (timestamp != NULL))
get_redirect_desc(eport, proto, desc, desclen, timestamp);
if ((rhost != NULL) && (rhostlen > 0))
inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
r = 0;
}
@ -337,6 +352,8 @@ get_redirect_rule_by_index(int index,
char * ifname, unsigned short * eport,
char * iaddr, int iaddrlen, unsigned short * iport,
int * proto, char * desc, int desclen,
char * rhost, int rhostlen,
unsigned int * timestamp,
u_int64_t * packets, u_int64_t * bytes)
{
ipfgeniter_t iter;
@ -387,8 +404,10 @@ get_redirect_rule_by_index(int index,
*packets = 0;
if (bytes != NULL)
*bytes = 0;
if (desc != NULL)
get_redirect_desc(*eport, *proto, desc, desclen);
if ((desc != NULL) && (timestamp != NULL))
get_redirect_desc(*eport, *proto, desc, desclen, timestamp);
if ((rhost != NULL) && (rhostlen > 0))
inet_ntop(AF_INET, &ipn.in_src[0].in4, rhost, rhostlen);
inet_ntop(AF_INET, &ipn.in_in[0].in4, iaddr, iaddrlen);
r = 0;
}
@ -464,8 +483,8 @@ delete_redirect_rule(const char * ifname, unsigned short eport, int proto)
/* thanks to Seth Mos for this function */
int
add_filter_rule2(const char * ifname, const char * iaddr,
unsigned short eport, unsigned short iport,
add_filter_rule2(const char * ifname, const char * rhost,
const char * iaddr, unsigned short eport, unsigned short iport,
int proto, const char * desc)
{
ipfobj_t obj;
@ -507,6 +526,12 @@ add_filter_rule2(const char * ifname, const char * iaddr,
fr.fr_tcpfm = TH_SYN|TH_ACK|TH_RST|TH_FIN|TH_URG|TH_PUSH;
}
if(rhost && rhost[0] != '\0' && rhost[0] != '*')
{
inet_pton(AF_INET, rhost, &fr.fr_saddr);
fr.fr_smask = 0xffffffff;
}
inet_pton(AF_INET, iaddr, &fr.fr_daddr);
fr.fr_dmask = 0xffffffff;
@ -600,3 +625,72 @@ delete_filter_rule(const char * ifname, unsigned short eport, int proto)
return r;
}
unsigned short *
get_portmappings_in_range(unsigned short startport, unsigned short endport,
int proto, unsigned int * number)
{
unsigned short * array;
unsigned int capacity;
unsigned short eport;
ipfgeniter_t iter;
ipfobj_t obj;
ipnat_t ipn;
*number = 0;
if (dev < 0) {
syslog(LOG_ERR, "%s not open", IPNAT_NAME);
return NULL;
}
capacity = 128;
array = calloc(capacity, sizeof(unsigned short));
if(!array)
{
syslog(LOG_ERR, "get_portmappings_in_range() : calloc error");
return NULL;
}
memset(&obj, 0, sizeof(obj));
obj.ipfo_rev = IPFILTER_VERSION;
obj.ipfo_ptr = &iter;
obj.ipfo_size = sizeof(iter);
obj.ipfo_type = IPFOBJ_GENITER;
iter.igi_type = IPFGENITER_IPNAT;
#if IPFILTER_VERSION > 4011300
iter.igi_nitems = 1;
#endif
iter.igi_data = &ipn;
do {
if (ioctl(dev, SIOCGENITER, &obj) == -1) {
syslog(LOG_ERR, "%s:ioctl(SIOCGENITER): %m",
"get_portmappings_in_range");
break;
}
if (strcmp(ipn.in_tag.ipt_tag, group_name) != 0)
continue;
eport = ntohs(ipn.in_pmin);
if( (eport == ntohs(ipn.in_pmax))
&& (ipn.in_p == proto)
&& (startport <= eport) && (eport <= endport) )
{
if(*number >= capacity)
{
/* need to increase the capacity of the array */
capacity += 128;
array = realloc(array, sizeof(unsigned short)*capacity);
if(!array)
{
syslog(LOG_ERR, "get_portmappings_in_range() : realloc(%lu) error", sizeof(unsigned short)*capacity);
*number = 0;
return NULL;
}
}
array[*number] = eport;
(*number)++;
}
} while (ipn.in_next != NULL);
return array;
}

View File

@ -10,12 +10,12 @@
#include "../commonrdr.h"
int
add_redirect_rule2(const char * ifname, unsigned short eport,
add_redirect_rule2(const char * ifname, const char * rhost, unsigned short eport,
const char * iaddr, unsigned short iport, int proto,
const char * desc);
const char * desc, unsigned int timestamp);
int
add_filter_rule2(const char * ifname, const char * iaddr,
add_filter_rule2(const char * ifname, const char * rhost, const char * iaddr,
unsigned short eport, unsigned short iport,
int proto, const char * desc);

View File

@ -1,25 +1,74 @@
/* $Id: testipfrdr.c,v 1.3 2007/10/01 16:21:23 nanard Exp $ */
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <netinet/in.h>
#include <sys/types.h>
#include "ipfrdr.h"
extern void
test_list_nat_rules();
/* test program for ipfrdr.c */
int runtime_flags = 0;
void
list_eports_tcp(void)
{
unsigned short * port_list;
unsigned int number = 0;
unsigned int i;
port_list = get_portmappings_in_range(0, 65535, IPPROTO_TCP, &number);
printf("%u ports redirected (TCP) :", number);
for(i = 0; i < number; i++)
{
printf(" %hu", port_list[i]);
}
printf("\n");
free(port_list);
port_list = get_portmappings_in_range(0, 65535, IPPROTO_UDP, &number);
printf("%u ports redirected (UDP) :", number);
for(i = 0; i < number; i++)
{
printf(" %hu", port_list[i]);
}
printf("\n");
free(port_list);
}
int
main(int argc, char * * argv)
{
char c;
openlog("testipfrdrd", LOG_CONS|LOG_PERROR, LOG_USER);
printf("List nat rules :\n");
test_list_nat_rules();
if(init_redirect() < 0)
{
fprintf(stderr, "init_redirect() failed\n");
return 1;
}
printf("List rdr ports :\n");
list_eports_tcp();
printf("Add redirection !\n");
add_redirect_rule2("ep0", 12345, "1.2.3.4", 54321, IPPROTO_UDP,
"redirection description");
printf("List nat rules :\n");
test_list_nat_rules();
add_redirect_rule2("xennet0", "*", 12345, "192.168.1.100", 54321, IPPROTO_UDP,
"redirection description", 0);
add_redirect_rule2("xennet0", "8.8.8.8", 12345, "192.168.1.100", 54321, IPPROTO_TCP,
"redirection description", 0);
printf("Check redirect rules with \"ipnat -l\" then press any key.\n");
c = getchar();
printf("List rdr ports :\n");
list_eports_tcp();
printf("Delete redirection !\n");
delete_redirect_rule("xennet0", 12345, IPPROTO_UDP);
delete_redirect_rule("xennet0", 12345, IPPROTO_TCP);
printf("List rdr ports :\n");
list_eports_tcp();
return 0;
}