Libalias modules and ipfw nat for HEAD
Paolo Pisati
p.pisati at oltrelinux.com
Sun Jun 18 15:36:26 UTC 2006
Hi,
attached is the final patch for HEAD of my soc2005 work about
ipfw and libalias.
Please take a look at it and reprt any problem you'll find,
cause i would like to commit it ASAP.
There are no fundamental differences between this patch and
the previous one: i just merged all the documentation into
ipfw.8 and libalias.3.
If you want to know exactly what we get with this patch:
http://wikitest.freebsd.org/Libalias
bye
--
Paolo
Piso's first law: nothing works as expected!
-------------- next part --------------
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/etc/Makefile /home/flag/src/freebsd7/src/etc/Makefile
*** /home/flag/src/freebsd7_vanilla/src/etc/Makefile Wed May 3 17:14:46 2006
--- /home/flag/src/freebsd7/src/etc/Makefile Sun Jun 11 18:59:46 2006
***************
*** 11,17 ****
crontab csh.cshrc csh.login csh.logout devd.conf devfs.conf \
dhclient.conf disktab fbtab ftpusers gettytab group \
hosts hosts.allow hosts.equiv hosts.lpd \
! inetd.conf login.access login.conf mac.conf motd \
netconfig network.subr networks newsyslog.conf nsswitch.conf \
portsnap.conf pf.conf pf.os phones profile protocols \
rc rc.bsdextended rc.firewall rc.firewall6 rc.initdiskless \
--- 11,17 ----
crontab csh.cshrc csh.login csh.logout devd.conf devfs.conf \
dhclient.conf disktab fbtab ftpusers gettytab group \
hosts hosts.allow hosts.equiv hosts.lpd \
! inetd.conf libalias.conf login.access login.conf mac.conf motd \
netconfig network.subr networks newsyslog.conf nsswitch.conf \
portsnap.conf pf.conf pf.os phones profile protocols \
rc rc.bsdextended rc.firewall rc.firewall6 rc.initdiskless \
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/etc/libalias.conf /home/flag/src/freebsd7/src/etc/libalias.conf
*** /home/flag/src/freebsd7_vanilla/src/etc/libalias.conf Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/etc/libalias.conf Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,7 ----
+ /usr/lib/libalias_cuseeme.so
+ /usr/lib/libalias_ftp.so
+ /usr/lib/libalias_irc.so
+ /usr/lib/libalias_nbt.so
+ /usr/lib/libalias_pptp.so
+ /usr/lib/libalias_skinny.so
+ /usr/lib/libalias_smedia.so
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/Makefile /home/flag/src/freebsd7/src/lib/libalias/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/Makefile Fri Jul 22 19:18:59 2005
--- /home/flag/src/freebsd7/src/lib/libalias/Makefile Sun Jun 11 19:01:50 2006
***************
*** 1,16 ****
# $FreeBSD: src/lib/libalias/Makefile,v 1.31 2005/07/22 17:18:59 kensmith Exp $
!
! .PATH: ${.CURDIR}/../../sys/netinet/libalias
!
! LIB= alias
! SHLIBDIR?= /lib
! SHLIB_MAJOR= 5
! MAN= libalias.3
! SRCS= alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c \
! alias_nbt.c alias_pptp.c alias_proxy.c alias_skinny.c alias_smedia.c \
! alias_util.c alias_old.c
! INCS= alias.h
! WARNS?= 6
! NO_WERROR=
!
! .include <bsd.lib.mk>
--- 1,12 ----
# $FreeBSD: src/lib/libalias/Makefile,v 1.31 2005/07/22 17:18:59 kensmith Exp $
! SUBDIR= lib-cuseeme \
! lib-dummy \
! lib-ftp \
! lib-irc \
! lib-libalias \
! lib-nbt \
! lib-pptp \
! lib-skinny \
! lib-smedia
!
! .include <bsd.subdir.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-cuseeme/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-cuseeme/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-cuseeme/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-cuseeme/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_cuseeme
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_cuseeme.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-dummy/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-dummy/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-dummy/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-dummy/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_dummy
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_dummy.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-ftp/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-ftp/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-ftp/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-ftp/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_ftp
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_ftp.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-irc/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-irc/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-irc/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-irc/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_irc
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_irc.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-libalias/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-libalias/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-libalias/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-libalias/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,14 ----
+ # $FreeBSD: src/lib/libalias/Makefile,v 1.30.2.1 2005/07/22 17:29:02 kensmith Exp $
+
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 5
+ MAN= libalias.3
+ SRCS= alias.c alias_db.c alias_proxy.c alias_util.c alias_old.c alias_mod.c
+ INCS= alias.h alias_mod.h
+ WARNS?= 6
+ NO_WERROR=
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-nbt/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-nbt/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-nbt/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-nbt/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_nbt
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_nbt.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-pptp/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-pptp/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-pptp/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-pptp/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_pptp
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_pptp.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-skinny/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-skinny/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-skinny/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-skinny/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_skinny
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_skinny.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-smedia/Makefile /home/flag/src/freebsd7/src/lib/libalias/lib-smedia/Makefile
*** /home/flag/src/freebsd7_vanilla/src/lib/libalias/lib-smedia/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/lib/libalias/lib-smedia/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,11 ----
+ .PATH: ${.CURDIR}/../../../sys/netinet/libalias
+
+ LIB= alias_smedia
+ SHLIBDIR?= /lib
+ SHLIB_MAJOR= 4
+ SRCS= alias_smedia.c
+ INCS= alias_mod.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.lib.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sbin/ipfw/ipfw.8 /home/flag/src/freebsd7/src/sbin/ipfw/ipfw.8
*** /home/flag/src/freebsd7_vanilla/src/sbin/ipfw/ipfw.8 Wed May 24 15:09:55 2006
--- /home/flag/src/freebsd7/src/sbin/ipfw/ipfw.8 Sun Jun 18 16:10:14 2006
***************
*** 2027,2032 ****
--- 2027,2124 ----
If no socket is bound to the destination port, or if the divert module is
not loaded, or if the kernel was not compiled with divert socket support,
the packets are dropped.
+ .Sh IPFW NAT
+ To support nat operations inside ipfw, the syntax was extended with a
+ new action: nat.
+ Then, to configure/handle nat instances the following syntax was
+ added (trying to follow closely pipe|queue options):
+ .Bd -ragged -offset indent
+ .Bk -words
+ .Cm nat
+ .Ar nat_number
+ .Cm config
+ .Ar options
+ .Ek
+ .Ed
+ .Pp
+ where
+ .Ar options
+ is one or more mandatory fields that can assume the
+ following values:
+ .Bl -tag -width indent
+ .It Cm ip Ar ip_address
+ Define an ip address to use for aliasing
+ .It Cm if Ar nic
+ Use ip addres of NIC for aliasing, dynamically changing
+ it if NIC's ip address change
+ .It Cm log
+ Enable logging on this nat instance
+ .It Cm deny_in
+ Deny any incoming connection from outside world
+ .It Cm same_ports
+ Try to leave the alias port numbers unchanged from
+ the actual local port numbers
+ .It Cm unreg_only
+ Traffic on the local network not originating from an
+ unregistered address spaces will be ignored
+ .It Cm reset
+ Reset table of the packet aliasing engine on address change
+ .It Cm reverse
+ Reverse the way libalias handles aliasing
+ .It Cm proxy_only
+ Obey transparent proxy rules only, packet aliasing is not performed
+ .El
+ .Pp
+ For more information about aliasing modes, take a look
+ at libalias(
+ .Xr libalias 3
+ ).
+ .Pp
+ Other commands to manipulate nats are:
+ .Bd -ragged -offset indent
+ .Bk -words
+ .Cm nat
+ .Ar nat_number
+ .Cm show
+ .Cm config
+ .Ek
+ .Ed
+ .Pp
+ to see nat configuration of
+ .Ar nat_number
+ .
+ .Pp
+ .Bd -ragged -offset indent
+ .Bk -words
+ .Cm nat
+ .Ar nat_number
+ .Cm show
+ .Ek
+ .Ed
+ .Pp
+ to see the logs of
+ .Ar nat_number
+ (if any)
+ .Pp
+ In these two previous examples
+ .Ar nat_number
+ could be a single number to see the configuration of that
+ instance (i.e. 123, a range of numbers (i.e 333-555) to see the
+ configurations all the instances in that range or nothing, to see all
+ the configured instances.
+ .Pp
+ See Section
+ .Sx EXAMPLES
+ for some examples on how to use nat.
+ .Sh REDIRECT AND LSNAT SUPPORT IN IPFW
+ Redirect and LSNAT support follow closely the syntax used in natd: refer to natd's man page
+ for syntax details.
+ The only difference between natd's redirect and ipfw redirect is:
+ instead of redirect_[addr|port|prot] i chose redir_[addr|port|proto].
+ .Pp
+ See Section
+ .Sx EXAMPLES
+ for some examples on how to do redirect and lsnat.
.Sh SYSCTL VARIABLES
A set of
.Xr sysctl 8
***************
*** 2406,2411 ****
--- 2498,2552 ----
Otherwise, e.g.\& if
you cannot access your box, the ruleset will be disabled after
the sleep terminates thus restoring the previous situation.
+ .Ss NAT, REDIRECT AND LSNAT
+ First redirect all the traffic to nat instance 123:
+ .Pp
+ .Dl "ipfw add nat 123 all from any to any"
+ .Pp
+ Then to configure nat instance 123 to alias all the outgoing traffic with ip
+ 192.168.0.123, blocking all incoming connections, trying to keep
+ same ports on both sides, clearing aliasing table on address change
+ and keeping a log of traffic/link statistics:
+ .Pp
+ .Dl "ipfw nat 123 config ip 192.168.0.123 log deny_in reset same_ports"
+ .Pp
+ Or to change address of instance 123, aliasing table will be cleared (see
+ reset option):
+ .Pp
+ .Dl "ipfw nat 123 config ip 10.0.0.1"
+ .Pp
+ To see configuration of nat instance 123:
+ .Pp
+ .Dl "ipfw nat 123 show config"
+ .Pp
+ To show logs of all the instances in range 111-999:
+ .Pp
+ .Dl "ipfw nat 111-999 show"
+ .Pp
+ To see configurations of all instances:
+ .Pp
+ .Dl "ipfw nat show config"
+ .Pp
+ Or a redirect rule with mixed modes could looks like:
+ .Pp
+ .Dl "ipfw nat 123 config redir_addr 10.0.0.1 10.0.0.66"
+ .Dl " redir_port tcp 192.168.0.1:80 500"
+ .Dl " redir_proto udp 192.168.1.43 192.168.1.1"
+ .Dl " redir_addr 192.168.0.10,192.168.0.11"
+ .Dl " 10.0.0.100 # LSNAT"
+ .Dl " redir_port tcp 192.168.0.1:80,192.168.0.10:22"
+ .Dl " 500 # LSNAT"
+ .Pp
+ or it could be splitted in:
+ .Pp
+ .Dl "ipfw nat 1 config redir_addr 10.0.0.1 10.0.0.66"
+ .Dl "ipfw nat 2 config redir_port tcp 192.168.0.1:80 500"
+ .Dl "ipfw nat 3 config redir_proto udp 192.168.1.43 192.168.1.1"
+ .Dl "ipfw nat 4 config redir_addr 192.168.0.10,192.168.0.11,192.168.0.12"
+ .Dl " 10.0.0.100"
+ .Dl "ipfw nat 5 config redir_port tcp"
+ .Dl " 192.168.0.1:80,192.168.0.10:22,192.168.0.20:25 500"
+ .Pp
.Sh SEE ALSO
.Xr cpp 1 ,
.Xr m4 1 ,
***************
*** 2446,2451 ****
--- 2587,2597 ----
API based upon code written by
.An Daniel Boulet
for BSDI.
+ .Pp
+ .An -nosplit
+ In-kernel NAT support written by
+ .An Paolo Pisati Aq piso at FreeBSD.org
+ as part of a Summer of Code 2005 project.
.Pp
Work on
.Xr dummynet 4
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sbin/ipfw/ipfw2.c /home/flag/src/freebsd7/src/sbin/ipfw/ipfw2.c
*** /home/flag/src/freebsd7_vanilla/src/sbin/ipfw/ipfw2.c Fri Jun 2 07:17:17 2006
--- /home/flag/src/freebsd7/src/sbin/ipfw/ipfw2.c Sun Jun 11 18:57:26 2006
***************
*** 48,53 ****
--- 48,54 ----
#include <fcntl.h>
#include <net/if.h>
+ #include <net/if_dl.h>
#include <net/pfvar.h>
#include <net/route.h> /* def. of struct route */
#include <netinet/in.h>
***************
*** 59,70 ****
--- 60,73 ----
#include <netinet/ip_dummynet.h>
#include <netinet/tcp.h>
#include <arpa/inet.h>
+ #include <alias.h>
int
do_resolv, /* Would try to resolve all */
do_time, /* Show time stamps */
do_quiet, /* Be quiet in add and flush */
do_pipe, /* this cmd refers to a pipe */
+ do_nat, /* nat configuration */
do_sort, /* field to sort results (0 = no) */
do_dynamic, /* display dynamic rules */
do_expired, /* display expired dynamic rules */
***************
*** 218,223 ****
--- 221,227 ----
TOK_RESET,
TOK_UNREACH,
TOK_CHECKSTATE,
+ TOK_NAT,
TOK_ALTQ,
TOK_LOG,
***************
*** 280,285 ****
--- 284,301 ----
TOK_DROPTAIL,
TOK_PROTO,
TOK_WEIGHT,
+ TOK_IP,
+ TOK_IF,
+ TOK_LOG,
+ TOK_DENY_INC,
+ TOK_SAME_PORTS,
+ TOK_UNREG_ONLY,
+ TOK_RESET_ADDR,
+ TOK_ALIAS_REV,
+ TOK_PROXY_ONLY,
+ TOK_REDIR_ADDR,
+ TOK_REDIR_PORT,
+ TOK_REDIR_PROTO,
TOK_IPV6,
TOK_FLOWID,
***************
*** 322,327 ****
--- 338,359 ----
{ NULL, 0 } /* terminator */
};
+ struct _s_x nat_params[] = {
+ { "ip", TOK_IP },
+ { "if", TOK_IF },
+ { "log", TOK_LOG },
+ { "deny_in", TOK_DENY_INC },
+ { "same_ports", TOK_SAME_PORTS },
+ { "unreg_only", TOK_UNREG_ONLY },
+ { "reset", TOK_RESET_ADDR },
+ { "reverse", TOK_ALIAS_REV },
+ { "proxy_only", TOK_PROXY_ONLY },
+ { "redir_addr", TOK_REDIR_ADDR },
+ { "redir_port", TOK_REDIR_PORT },
+ { "redir_proto", TOK_REDIR_PROTO },
+ { NULL, 0 } /* terminator */
+ };
+
struct _s_x rule_actions[] = {
{ "accept", TOK_ACCEPT },
{ "pass", TOK_ACCEPT },
***************
*** 346,351 ****
--- 378,384 ----
{ "unreach", TOK_UNREACH },
{ "check-state", TOK_CHECKSTATE },
{ "//", TOK_COMMENT },
+ { "nat", TOK_NAT},
{ NULL, 0 } /* terminator */
};
***************
*** 453,459 ****
{
static int s = -1; /* the socket */
int i;
!
if (test_only)
return 0;
--- 486,492 ----
{
static int s = -1; /* the socket */
int i;
!
if (test_only)
return 0;
***************
*** 464,470 ****
if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
! optname == IP_FW_TABLE_GETSIZE)
i = getsockopt(s, IPPROTO_IP, optname, optval,
(socklen_t *)optlen);
else
--- 497,504 ----
if (optname == IP_FW_GET || optname == IP_DUMMYNET_GET ||
optname == IP_FW_ADD || optname == IP_FW_TABLE_LIST ||
! optname == IP_FW_TABLE_GETSIZE || optname == IP_FW_NAT_GET_CONFIG ||
! optname == IP_FW_NAT_GET_LOG)
i = getsockopt(s, IPPROTO_IP, optname, optval,
(socklen_t *)optlen);
else
***************
*** 1520,1525 ****
--- 1554,1563 ----
tagptr = cmd;
break;
+ case O_NAT:
+ printf("nat %u", cmd->arg1);
+ break;
+
default:
printf("** unrecognized action %d len %d ",
cmd->opcode, cmd->len);
***************
*** 2583,2595 ****
"add [num] [set N] [prob x] RULE-BODY\n"
"{pipe|queue} N config PIPE-BODY\n"
"[pipe|queue] {zero|delete|show} [N{,N}]\n"
"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
"\n"
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
"ACTION: check-state | allow | count | deny | unreach{,6} CODE |\n"
" skipto N | {divert|tee} PORT | forward ADDR |\n"
! " pipe N | queue N\n"
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
"ADDR: [ MAC dst src ether_type ] \n"
" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
--- 2621,2636 ----
"add [num] [set N] [prob x] RULE-BODY\n"
"{pipe|queue} N config PIPE-BODY\n"
"[pipe|queue] {zero|delete|show} [N{,N}]\n"
+ "nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|reset|\n"
+ " reverse|proxy_only|redir_addr linkspec| redir_port linkspec|\n"
+ " redir_proto linkspec}\n"
"set [disable N... enable N...] | move [rule] X to Y | swap X Y | show\n"
"table N {add ip[/bits] [value] | delete ip[/bits] | flush | list}\n"
"\n"
"RULE-BODY: check-state [PARAMS] | ACTION [PARAMS] ADDR [OPTION_LIST]\n"
"ACTION: check-state | allow | count | deny | unreach{,6} CODE |\n"
" skipto N | {divert|tee} PORT | forward ADDR |\n"
! " pipe N | queue N | nat N\n"
"PARAMS: [log [logamount LOGLIMIT]] [altq QUEUE_NAME]\n"
"ADDR: [ MAC dst src ether_type ] \n"
" [ ip from IPADDR [ PORT ] to IPADDR [ PORTLIST ] ]\n"
***************
*** 3098,3104 ****
/* Rule number */
while (ac && isdigit(**av)) {
i = atoi(*av); av++; ac--;
! if (do_pipe) {
if (do_pipe == 1)
p.pipe_nr = i;
else
--- 3139,3152 ----
/* Rule number */
while (ac && isdigit(**av)) {
i = atoi(*av); av++; ac--;
! if (do_nat) {
! exitval = do_cmd(IP_FW_NAT_DEL, &i, sizeof i);
! if (exitval) {
! exitval = EX_UNAVAILABLE;
! warn("rule %u not available",
! i);
! }
! } else if (do_pipe) {
if (do_pipe == 1)
p.pipe_nr = i;
else
***************
*** 3123,3129 ****
exit(exitval);
}
-
/*
* fill the interface structure. We do not check the name as we can
* create interfaces dynamically, so checking them at insert time
--- 3171,3176 ----
***************
*** 3147,3152 ****
--- 3194,3946 ----
errx(EX_DATAERR, "bad ip address ``%s''", arg);
}
+ /*
+ * Search for interface with name "ifn", and fill n accordingly:
+ *
+ * n->ip ip address of interface "ifn"
+ * n->if_name copy of interface name "ifn"
+ */
+ static void
+ set_addr_dynamic(const char *ifn, struct cfg_nat *n)
+ {
+ size_t needed;
+ int mib[6];
+ char *buf, *lim, *next;
+ struct if_msghdr *ifm;
+ struct ifa_msghdr *ifam;
+ struct sockaddr_dl *sdl;
+ struct sockaddr_in *sin;
+ int ifIndex, ifMTU;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0;
+ mib[3] = AF_INET; /* Only IP addresses please */
+ mib[4] = NET_RT_IFLIST;
+ mib[5] = 0; /* ifIndex??? */
+ /*
+ * Get interface data.
+ */
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) == -1)
+ err(1, "iflist-sysctl-estimate");
+ if ((buf = malloc(needed)) == NULL)
+ errx(1, "malloc failed");
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) == -1)
+ err(1, "iflist-sysctl-get");
+ lim = buf + needed;
+ /*
+ * Loop through interfaces until one with
+ * given name is found. This is done to
+ * find correct interface index for routing
+ * message processing.
+ */
+ ifIndex = 0;
+ next = buf;
+ while (next < lim) {
+ ifm = (struct if_msghdr *)next;
+ next += ifm->ifm_msglen;
+ if (ifm->ifm_version != RTM_VERSION) {
+ if (verbose)
+ warnx("routing message version %d "
+ "not understood", ifm->ifm_version);
+ continue;
+ }
+ if (ifm->ifm_type == RTM_IFINFO) {
+ sdl = (struct sockaddr_dl *)(ifm + 1);
+ if (strlen(ifn) == sdl->sdl_nlen &&
+ strncmp(ifn, sdl->sdl_data, sdl->sdl_nlen) == 0) {
+ ifIndex = ifm->ifm_index;
+ ifMTU = ifm->ifm_data.ifi_mtu;
+ break;
+ }
+ }
+ }
+ if (!ifIndex)
+ errx(1, "unknown interface name %s", ifn);
+ /*
+ * Get interface address.
+ */
+ sin = NULL;
+ while (next < lim) {
+ ifam = (struct ifa_msghdr *)next;
+ next += ifam->ifam_msglen;
+ if (ifam->ifam_version != RTM_VERSION) {
+ if (verbose)
+ warnx("routing message version %d "
+ "not understood", ifam->ifam_version);
+ continue;
+ }
+ if (ifam->ifam_type != RTM_NEWADDR)
+ break;
+ if (ifam->ifam_addrs & RTA_IFA) {
+ int i;
+ char *cp = (char *)(ifam + 1);
+
+ for (i = 1; i < RTA_IFA; i <<= 1)
+ if (ifam->ifam_addrs & i)
+ cp += SA_SIZE((struct sockaddr *)cp);
+ if (((struct sockaddr *)cp)->sa_family == AF_INET) {
+ sin = (struct sockaddr_in *)cp;
+ break;
+ }
+ }
+ }
+ if (sin == NULL)
+ errx(1, "%s: cannot get interface address", ifn);
+
+ n->ip = sin->sin_addr;
+ strncpy(n->if_name, ifn, IF_NAMESIZE);
+
+ free(buf);
+ }
+
+ /*
+ * XXX: the following functions, macros and definitions come from natd.c:
+ * it would be better to move them outside of natd.c, in a file
+ * (redirect_support.[ch]?) shared by ipfw and natd, but for now i can live
+ * with it...
+ */
+
+ /*
+ * Definition of a port range, and macros to deal with values.
+ * FORMAT: HI 16-bits == first port in range, 0 == all ports.
+ * LO 16-bits == number of ports in range
+ * NOTES: - Port values are not stored in network byte order.
+ */
+
+ #define port_range u_long
+
+ #define GETLOPORT(x) ((x) >> 0x10)
+ #define GETNUMPORTS(x) ((x) & 0x0000ffff)
+ #define GETHIPORT(x) (GETLOPORT((x)) + GETNUMPORTS((x)))
+
+ /* Set y to be the low-port value in port_range variable x. */
+ #define SETLOPORT(x,y) ((x) = ((x) & 0x0000ffff) | ((y) << 0x10))
+
+ /* Set y to be the number of ports in port_range variable x. */
+ #define SETNUMPORTS(x,y) ((x) = ((x) & 0xffff0000) | (y))
+
+ static void
+ StrToAddr (const char* str, struct in_addr* addr)
+ {
+ struct hostent* hp;
+
+ if (inet_aton (str, addr))
+ return;
+
+ hp = gethostbyname (str);
+ if (!hp)
+ errx (1, "unknown host %s", str);
+
+ memcpy (addr, hp->h_addr, sizeof (struct in_addr));
+ }
+
+ static int
+ StrToPortRange (const char* str, const char* proto, port_range *portRange)
+ {
+ char* sep;
+ struct servent* sp;
+ char* end;
+ u_short loPort;
+ u_short hiPort;
+
+ /* First see if this is a service, return corresponding port if so. */
+ sp = getservbyname (str,proto);
+ if (sp) {
+ SETLOPORT(*portRange, ntohs(sp->s_port));
+ SETNUMPORTS(*portRange, 1);
+ return 0;
+ }
+
+ /* Not a service, see if it's a single port or port range. */
+ sep = strchr (str, '-');
+ if (sep == NULL) {
+ SETLOPORT(*portRange, strtol(str, &end, 10));
+ if (end != str) {
+ /* Single port. */
+ SETNUMPORTS(*portRange, 1);
+ return 0;
+ }
+
+ /* Error in port range field. */
+ errx (EX_DATAERR, "%s/%s: unknown service", str, proto);
+ }
+
+ /* Port range, get the values and sanity check. */
+ sscanf (str, "%hu-%hu", &loPort, &hiPort);
+ SETLOPORT(*portRange, loPort);
+ SETNUMPORTS(*portRange, 0); /* Error by default */
+ if (loPort <= hiPort)
+ SETNUMPORTS(*portRange, hiPort - loPort + 1);
+
+ if (GETNUMPORTS(*portRange) == 0)
+ errx (EX_DATAERR, "invalid port range %s", str);
+
+ return 0;
+ }
+
+ static int
+ StrToProto (const char* str)
+ {
+ if (!strcmp (str, "tcp"))
+ return IPPROTO_TCP;
+
+ if (!strcmp (str, "udp"))
+ return IPPROTO_UDP;
+
+ errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str);
+ }
+
+ static int
+ StrToAddrAndPortRange (const char* str, struct in_addr* addr, char* proto, port_range *portRange)
+ {
+ char* ptr;
+
+ ptr = strchr (str, ':');
+ if (!ptr)
+ errx (EX_DATAERR, "%s is missing port number", str);
+
+ *ptr = '\0';
+ ++ptr;
+
+ StrToAddr (str, addr);
+ return StrToPortRange (ptr, proto, portRange);
+ }
+
+ /* end of stuff taken from natd.c */
+
+ #define INC_ARGCV() do { \
+ (*_av)++; \
+ (*_ac)--; \
+ av = *_av; \
+ ac = *_ac; \
+ } while(0)
+
+ /*
+ * The next 3 functions add support for the addr, port and proto redirect and
+ * their logic is loosely based on SetupAddressRedirect(), SetupPortRedirect()
+ * and SetupProtoRedirect() from natd.c.
+ *
+ * Every setup_* function fills at least one redirect entry
+ * (struct cfg_redir) and zero or more server pool entry (struct cfg_spool)
+ * in buf.
+ *
+ * The format of data in buf is:
+ *
+ *
+ * cfg_nat cfg_redir cfg_spool ...... cfg_spool
+ *
+ * ------------------------------------- ------------
+ * | | .....X ... | | | | .....
+ * ------------------------------------- ...... ------------
+ * ^
+ * spool_cnt n=0 ...... n=(X-1)
+ *
+ * len points to the amount of available space in buf
+ * space counts the memory consumed by every function
+ *
+ * XXX - Every function get all the argv params so it
+ * has to check, in optional parameters, that the next
+ * args is a valid option for the redir entry and not
+ * another token. Only redir_port and redir_proto are
+ * affected by this.
+ */
+
+ static int
+ setup_redir_addr(char *spool_buf, int len,
+ int *_ac, char ***_av)
+ {
+ char **av = *_av, *sep; /* token separator */
+ /* temporary buffer used to hold server pool ip's */
+ char tmp_spool_buf[NAT_BUF_LEN];
+ int ac = *_ac, i, space = 0, lsnat = 0;
+ int sof_redir = sizeof(struct cfg_redir);
+ struct cfg_redir *r;
+
+ if (len >= sof_redir) {
+ r = (struct cfg_redir *)spool_buf;
+ /* skip cfg_redir at beginning of buf */
+ spool_buf = &spool_buf[sof_redir];
+ space = sof_redir;
+ len -= sof_redir;
+ } else
+ goto nospace;
+ r->mode = REDIR_ADDR;
+ /* extract local address */
+ if (ac == 0)
+ errx(EX_DATAERR, "redir_addr: missing local address");
+ sep = strchr(*av, ',');
+ if (sep) { /* LSNAT redirection syntax. */
+ r->laddr.s_addr = INADDR_NONE;
+ /* preserve av, copy spool servers to tmp_spool_buf */
+ strncpy(tmp_spool_buf, *av, strlen(*av)+1);
+ lsnat = 1;
+ } else
+ StrToAddr(*av, &r->laddr);
+ INC_ARGCV();
+
+ /* extract public address */
+ if (ac == 0)
+ errx(EX_DATAERR, "redir_addr: missing public address");
+ StrToAddr(*av, &r->paddr);
+ INC_ARGCV();
+
+ /* setup LSNAT server pool */
+ if (sep) {
+ int sof_spool = sizeof(struct cfg_spool);
+ struct cfg_spool *tmp;
+
+ sep = strtok(tmp_spool_buf, ",");
+ while (sep != NULL) {
+ tmp = (struct cfg_spool *)spool_buf;
+ if (len < sof_spool)
+ goto nospace;
+ len -= sof_spool;
+ space += sof_spool;
+ StrToAddr(sep, &tmp->addr);
+ tmp->port = ~0;
+ r->spool_cnt++;
+ /* point to the next possible cfg_spool */
+ spool_buf = &spool_buf[sof_spool];
+ sep = strtok(NULL, ",");
+ }
+ }
+ return(space);
+ nospace:
+ errx(EX_DATAERR, "redir_addr: buf is too small\n");
+ }
+
+ static int
+ setup_redir_port(char *spool_buf, int len,
+ int *_ac, char ***_av)
+ {
+ char **av = *_av, *sep, *protoName;
+ char tmp_spool_buf[NAT_BUF_LEN];
+ int ac = *_ac, space = 0, lsnat = 0;
+ int sof_redir = sizeof(struct cfg_redir);
+ struct cfg_redir *r;
+ u_short numLocalPorts = 0;
+ port_range portRange;
+
+ if (len >= sof_redir) {
+ r = (struct cfg_redir *)spool_buf;
+ /* skip cfg_redir at beginning of buf */
+ spool_buf = &spool_buf[sof_redir];
+ space = sof_redir;
+ len -= sof_redir;
+ } else
+ goto nospace;
+ r->mode = REDIR_PORT;
+ /*
+ * Extract protocol.
+ */
+ if (ac == 0)
+ errx (EX_DATAERR, "redirect_port: missing protocol");
+ r->proto = StrToProto(*av);
+ protoName = *av;
+ INC_ARGCV();
+
+ /*
+ * Extract local address.
+ */
+ if (ac == 0)
+ errx (EX_DATAERR, "redirect_port: missing local address");
+
+ sep = strchr(*av, ',');
+ if (sep) { /* LSNAT redirection syntax. */
+ r->laddr.s_addr = INADDR_NONE;
+ r->lport = ~0;
+ numLocalPorts = 1;
+ /* preserve av, copy spool servers to tmp_spool_buf */
+ strncpy(tmp_spool_buf, *av, strlen(*av)+1);
+ lsnat = 1;
+ } else {
+ if ( StrToAddrAndPortRange (*av, &r->laddr, protoName, &portRange) != 0 )
+ errx (EX_DATAERR, "redirect_port: invalid local port range");
+
+ r->lport = GETLOPORT(portRange);
+ numLocalPorts = GETNUMPORTS(portRange);
+ }
+ INC_ARGCV();
+
+ /*
+ * Extract public port and optionally address.
+ */
+ if (ac == 0)
+ errx (EX_DATAERR, "redirect_port: missing public port");
+
+ sep = strchr (*av, ':');
+ if (sep) {
+ if (StrToAddrAndPortRange (*av, &r->paddr, protoName, &portRange) != 0 )
+ errx (EX_DATAERR, "redirect_port: invalid public port range");
+ } else {
+ r->paddr.s_addr = INADDR_ANY;
+ if (StrToPortRange (*av, protoName, &portRange) != 0)
+ errx (EX_DATAERR, "redirect_port: invalid public port range");
+ }
+
+ r->pport = GETLOPORT(portRange);
+ r->pport_cnt = GETNUMPORTS(portRange);
+ INC_ARGCV();
+
+ /*
+ * Extract remote address and optionally port.
+ */
+ /*
+ * isalpha(**av) => we've to check that next parameter is really an
+ * option for this redirect entry, else stop here processing arg[cv]
+ */
+ if (ac != 0 && !isalpha(**av)) {
+ sep = strchr (*av, ':');
+ if (sep) {
+ if (StrToAddrAndPortRange (*av, &r->raddr, protoName, &portRange) != 0)
+ errx (EX_DATAERR, "redirect_port: invalid remote port range");
+ } else {
+ SETLOPORT(portRange, 0);
+ SETNUMPORTS(portRange, 1);
+ StrToAddr (*av, &r->raddr);
+ }
+ INC_ARGCV();
+ } else {
+ SETLOPORT(portRange, 0);
+ SETNUMPORTS(portRange, 1);
+ r->raddr.s_addr = INADDR_ANY;
+ }
+ r->rport = GETLOPORT(portRange);
+ r->rport_cnt = GETNUMPORTS(portRange);
+
+ /*
+ * Make sure port ranges match up, then add the redirect ports.
+ */
+ if (numLocalPorts != r->pport_cnt)
+ errx(EX_DATAERR, "redirect_port: port ranges must be equal in size");
+
+ /* Remote port range is allowed to be '0' which means all ports. */
+ if (r->rport_cnt != numLocalPorts && (r->rport_cnt != 1 || r->rport != 0))
+ errx(EX_DATAERR, "redirect_port: remote port must be 0 or equal to local port range in size");
+
+ /*
+ * Setup LSNAT server pool.
+ */
+ if (lsnat) {
+ int sof_spool = sizeof(struct cfg_spool);
+ struct cfg_spool *tmp;
+
+ sep = strtok(tmp_spool_buf, ",");
+ while (sep != NULL) {
+ tmp = (struct cfg_spool *)spool_buf;
+ if (len < sof_spool)
+ goto nospace;
+ len -= sof_spool;
+ space += sof_spool;
+ if (StrToAddrAndPortRange(sep, &tmp->addr, protoName, &portRange) != 0)
+ errx(EX_DATAERR, "redirect_port: invalid local port range");
+ if (GETNUMPORTS(portRange) != 1)
+ errx(EX_DATAERR, "redirect_port: local port must be single in this context");
+ tmp->port = GETLOPORT(portRange);
+ r->spool_cnt++;
+ /* point to the next possible cfg_spool */
+ spool_buf = &spool_buf[sof_spool];
+ sep = strtok(NULL, ",");
+ }
+ }
+ return(space);
+ nospace:
+ errx(EX_DATAERR, "redir_port: buf is too small\n");
+ }
+
+ static int
+ setup_redir_proto(char *spool_buf, int len,
+ int *_ac, char ***_av)
+ {
+ char **av = *_av;
+ int ac = *_ac, i, space;
+ struct protoent *protoent;
+ int sof_redir = sizeof(struct cfg_redir);
+ struct cfg_redir *r;
+
+ if (len >= sof_redir) {
+ r = (struct cfg_redir *)spool_buf;
+ /* skip cfg_redir at beginning of buf */
+ spool_buf = &spool_buf[sof_redir];
+ space = sof_redir;
+ len -= sof_redir;
+ } else
+ goto nospace;
+ r->mode = REDIR_PROTO;
+ /*
+ * Extract protocol.
+ */
+ if (ac == 0)
+ errx(EX_DATAERR, "redirect_proto: missing protocol");
+
+ protoent = getprotobyname(*av);
+ if (protoent == NULL)
+ errx(EX_DATAERR, "redirect_proto: unknown protocol %s", *av);
+ else
+ r->proto = protoent->p_proto;
+
+ INC_ARGCV();
+
+ /*
+ * Extract local address.
+ */
+ if (ac == 0)
+ errx(EX_DATAERR, "redirect_proto: missing local address");
+ else
+ StrToAddr(*av, &r->laddr);
+
+ INC_ARGCV();
+
+ /*
+ * Extract optional public address.
+ */
+ if (ac == 0) {
+ r->paddr.s_addr = INADDR_ANY;
+ r->raddr.s_addr = INADDR_ANY;
+ } else {
+ /* see above in setup_redir_port() */
+ if (!isalpha(**av)) {
+ StrToAddr(*av, &r->paddr);
+ INC_ARGCV();
+
+ /*
+ * Extract optional remote address.
+ */
+ /* see above in setup_redir_port() */
+ if (ac!=0 && !isalpha(**av)) {
+ StrToAddr(*av, &r->raddr);
+ INC_ARGCV();
+ }
+ }
+ }
+ return(space);
+ nospace:
+ errx(EX_DATAERR, "redir_proto: buf is too small\n");
+ }
+
+ static void
+ show_nat(int ac, char **av);
+
+ static void
+ print_nat_config(char *buf) {
+ struct cfg_nat *n = (struct cfg_nat *)buf;
+ int i, cnt, flag = 1, off = sizeof(*n);
+ int sof_redir = sizeof(struct cfg_redir);
+ int sof_spool = sizeof(struct cfg_spool);
+ struct cfg_redir *t;
+ struct cfg_spool *s;
+ struct protoent *p;
+
+ printf("ipfw nat %u config", n->id);
+ if (strlen(n->if_name) != 0)
+ printf(" if %s", n->if_name);
+ else if (n->ip.s_addr != 0)
+ printf(" ip %s", inet_ntoa(n->ip));
+ while (n->mode != 0) {
+ if (n->mode & PKT_ALIAS_LOG) {
+ printf(" log");
+ n->mode &= ~PKT_ALIAS_LOG;
+ } else if (n->mode & PKT_ALIAS_DENY_INCOMING) {
+ printf(" deny_in");
+ n->mode &= ~PKT_ALIAS_DENY_INCOMING;
+ } else if (n->mode & PKT_ALIAS_SAME_PORTS) {
+ printf(" same_ports");
+ n->mode &= ~PKT_ALIAS_SAME_PORTS;
+ } else if (n->mode & PKT_ALIAS_UNREGISTERED_ONLY) {
+ printf(" unreg_only");
+ n->mode &= ~PKT_ALIAS_UNREGISTERED_ONLY;
+ } else if (n->mode & PKT_ALIAS_RESET_ON_ADDR_CHANGE) {
+ printf(" reset");
+ n->mode &= ~PKT_ALIAS_RESET_ON_ADDR_CHANGE;
+ } else if (n->mode & PKT_ALIAS_REVERSE) {
+ printf(" reverse");
+ n->mode &= ~PKT_ALIAS_REVERSE;
+ } else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
+ printf(" proxy_only");
+ n->mode &= ~PKT_ALIAS_PROXY_ONLY;
+ }
+ }
+ /* print all the redirect's data configuration */
+ for (cnt=0; cnt < n->redir_cnt; cnt++) {
+ t = (struct cfg_redir *)&buf[off];
+ off += sof_redir;
+ switch(t->mode) {
+ case REDIR_ADDR:
+ printf(" redir_addr");
+ if (t->spool_cnt == 0)
+ printf(" %s", inet_ntoa(t->laddr));
+ else
+ for (i=0; i<t->spool_cnt; i++) {
+ s = (struct cfg_spool *)&buf[off];
+ if (i)
+ printf(",");
+ else
+ printf(" ");
+ printf("%s", inet_ntoa(s->addr));
+ off += sof_spool;
+ }
+ printf(" %s", inet_ntoa(t->paddr));
+ break;
+ case REDIR_PORT:
+ p = getprotobynumber(t->proto);
+ printf(" redir_port %s ", p->p_name);
+ if (!t->spool_cnt) {
+ printf("%s:%u", inet_ntoa(t->laddr), t->lport);
+ if (t->pport_cnt > 1)
+ printf("-%u", t->lport+t->pport_cnt-1);
+ } else
+ for (i=0; i<t->spool_cnt; i++) {
+ s = (struct cfg_spool *)&buf[off];
+ if (i)
+ printf(",");
+ printf("%s:%u", inet_ntoa(s->addr), s->port);
+ off += sof_spool;
+ }
+
+ printf(" ");
+ if (t->paddr.s_addr)
+ printf("%s:", inet_ntoa(t->paddr));
+ printf("%u", t->pport);
+ if (!t->spool_cnt && t->pport_cnt>1)
+ printf("-%u", t->pport+t->pport_cnt-1);
+
+ if (t->raddr.s_addr) {
+ printf(" %s", inet_ntoa(t->raddr));
+ if (t->rport) {
+ printf(":%u", t->rport);
+ if (!t->spool_cnt && t->rport_cnt>1)
+ printf("-%u", t->rport+t->rport_cnt-1);
+ }
+ }
+ break;
+ case REDIR_PROTO:
+ p = getprotobynumber(t->proto);
+ printf(" redir_proto %s %s", p->p_name,
+ inet_ntoa(t->laddr));
+ if (t->paddr.s_addr != 0) {
+ printf(" %s", inet_ntoa(t->paddr));
+ if (t->raddr.s_addr)
+ printf(" %s", inet_ntoa(t->raddr));
+ }
+ break;
+ default:
+ errx(EX_DATAERR, "unknown redir mode");
+ break;
+ }
+ }
+ printf("\n");
+ }
+
+ static void
+ config_nat(int ac, char **av)
+ {
+ struct cfg_nat *n; /* nat instance configuration */
+ struct in_addr ip;
+ int i, len = NAT_BUF_LEN;
+ /* offset in buf: save space for a n at the beginning */
+ int off=sizeof(*n);
+ char *id, buf[NAT_BUF_LEN]; /* buffer for serialized data */
+
+ memset(buf, 0, sizeof(buf));
+ n = (struct cfg_nat *)buf;
+
+ av++; ac--;
+ /* Nat id */
+ if (ac && isdigit(**av)) {
+ id = *av;
+ i = atoi(*av); av++; ac--;
+ n->id = i;
+ } else errx(EX_DATAERR, "missing nat id");
+ if (ac == 0) errx(EX_DATAERR, "missing option");
+
+ while (ac > 0) {
+ int tok = match_token(nat_params, *av);
+ int sof_redir = sizeof(struct cfg_redir);
+
+ ac--; av++;
+
+ switch(tok) {
+ case TOK_IP:
+ if (ac == 0) errx(EX_DATAERR, "missing option");
+ if (!inet_aton(av[0], &(n->ip)))
+ errx(EX_DATAERR, "bad ip address ``%s''", av[0]);
+ ac--; av++;
+ break;
+
+ case TOK_IF:
+ set_addr_dynamic(av[0], n);
+ ac--; av++;
+ break;
+
+ case TOK_LOG:
+ n->mode |= PKT_ALIAS_LOG;
+ break;
+
+ case TOK_DENY_INC:
+ n->mode |= PKT_ALIAS_DENY_INCOMING;
+ break;
+
+ case TOK_SAME_PORTS:
+ n->mode |= PKT_ALIAS_SAME_PORTS;
+ break;
+
+ case TOK_UNREG_ONLY:
+ n->mode |= PKT_ALIAS_UNREGISTERED_ONLY;
+ break;
+
+ case TOK_RESET_ADDR:
+ n->mode |= PKT_ALIAS_RESET_ON_ADDR_CHANGE;
+ break;
+
+ case TOK_ALIAS_REV:
+ n->mode |= PKT_ALIAS_REVERSE;
+ break;
+
+ case TOK_PROXY_ONLY:
+ n->mode |= PKT_ALIAS_PROXY_ONLY;
+ break;
+
+ /*
+ * all the setup_redir_* functions work directly in the final
+ * buffer, see above for details
+ */
+ case TOK_REDIR_ADDR:
+ case TOK_REDIR_PORT:
+ case TOK_REDIR_PROTO:
+ switch(tok) {
+ case TOK_REDIR_ADDR:
+ i = setup_redir_addr(&buf[off], len, &ac, &av);
+ break;
+
+ case TOK_REDIR_PORT:
+ i = setup_redir_port(&buf[off], len, &ac, &av);
+ break;
+
+ case TOK_REDIR_PROTO:
+ i = setup_redir_proto(&buf[off], len, &ac, &av);
+ break;
+ }
+ n->redir_cnt++;
+ off += i;
+ len -= i;
+ break;
+
+ default:
+ errx(EX_DATAERR, "unrecognised option ``%s''", av[-1]);
+ }
+ }
+
+ i = do_cmd(IP_FW_NAT_CFG, buf, off);
+ if (i)
+ err(1, "setsockopt(%s)", "IP_FW_NAT_CFG");
+
+ /* after every rule modification, we show the resultant rule */
+ int _ac = 3;
+ char *_av[] = {"show", "config", id};
+ show_nat(_ac, _av);
+ }
+
static void
config_pipe(int ac, char **av)
{
***************
*** 3999,4004 ****
--- 4793,4806 ----
ac++; av--; /* go back... */
break;
+ case TOK_NAT:
+ action->opcode = O_NAT;
+ action->len = F_INSN_SIZE(ipfw_insn_nat);
+ NEED1("missing nat number");
+ action->arg1 = strtoul(*av, NULL, 10);
+ ac--; av++;
+ break;
+
default:
errx(EX_DATAERR, "invalid action %s\n", av[-1]);
}
***************
*** 4942,4947 ****
--- 5744,5811 ----
errx(EX_USAGE, "invalid table command %s", *av);
}
+ static void
+ show_nat(int ac, char **av) {
+ struct cfg_nat *n;
+ struct cfg_redir *e;
+ int cmd, i, nbytes, do_cfg, do_rule = 0, frule, lrule, nalloc = 1024,
+ size = 0, loop, r;
+ u_int8_t *data = NULL, *p;
+ char **lav, *endptr;
+
+ av++; ac--;
+
+ /* parse parameters */
+ for (cmd = IP_FW_NAT_GET_LOG, do_cfg = 0; ac != 0; ac--, av++) {
+ if (!strncmp(av[0], "config", strlen(av[0]))) {
+ cmd = IP_FW_NAT_GET_CONFIG, do_cfg = 1; continue;
+ }
+ /* convert command line rule # */
+ frule = lrule = strtoul(av[0], &endptr, 10);
+ if (*endptr == '-')
+ lrule = strtoul(endptr+1, &endptr, 10);
+ if (lrule == 0)
+ err(EX_USAGE, "invalid rule number: %s", av[0]);
+ do_rule = 1;
+ }
+
+ nbytes = nalloc;
+ while (nbytes >= nalloc) {
+ nalloc = nalloc * 2;
+ nbytes = nalloc;
+ if ((data = realloc(data, nbytes)) == NULL)
+ err(EX_OSERR, "realloc");
+ if (do_cmd(cmd, data, (uintptr_t)&nbytes) < 0)
+ err(EX_OSERR, "getsockopt(IP_FW_GET_%s)",
+ (cmd == IP_FW_NAT_GET_LOG) ? "LOG" : "CONFIG");
+ }
+ if (nbytes == 0) exit(0);
+ if (do_cfg) {
+ for (i = 0, loop = 1; loop; ) {
+ n = (struct cfg_nat *)&data[i];
+ if (n->next == NULL) loop = 0;
+ if (do_rule)
+ if (!(frule <= n->id && lrule >= n->id)) continue;
+ print_nat_config(&data[i]);
+ i += sizeof(struct cfg_nat);
+ e = (struct cfg_redir *)&data[i];
+ if (e->mode == REDIR_ADDR || e->mode == REDIR_PORT ||
+ e->mode == REDIR_PROTO)
+ i += sizeof(struct cfg_redir) + e->spool_cnt *
+ sizeof(struct cfg_spool);
+ }
+ } else {
+ for (i = 0; 1; i += LIBALIAS_BUF_SIZE + sizeof(int)) {
+ p = &data[i];
+ if (p == data + nbytes) break;
+ bcopy(p, &r, sizeof(int));
+ if (do_rule)
+ if (!(frule <= r && lrule >= r)) continue;
+ printf("nat %u: %s\n", r, p+sizeof(int));
+ }
+ }
+ }
+
/*
* Called with the arguments (excluding program name).
* Returns 0 if successful, 1 if empty command, errx() in case of errors.
***************
*** 5130,5154 ****
}
/*
! * optional: pipe or queue
*/
do_pipe = 0;
! if (_substrcmp(*av, "pipe") == 0)
do_pipe = 1;
else if (_substrcmp(*av, "queue") == 0)
do_pipe = 2;
! if (do_pipe) {
ac--;
av++;
}
NEED1("missing command");
/*
! * For pipes and queues we normally say 'pipe NN config'
! * but the code is easier to parse as 'pipe config NN'
* so we swap the two arguments.
*/
! if (do_pipe > 0 && ac > 1 && isdigit(*av[0])) {
char *p = av[0];
av[0] = av[1];
--- 5994,6021 ----
}
/*
! * optional: pipe, queue or nat
*/
+ do_nat = 0;
do_pipe = 0;
! if (!strncmp(*av, "nat", strlen(*av)))
! do_nat = 1;
! else if (!strncmp(*av, "pipe", strlen(*av)))
do_pipe = 1;
else if (_substrcmp(*av, "queue") == 0)
do_pipe = 2;
! if (do_pipe || do_nat) {
ac--;
av++;
}
NEED1("missing command");
/*
! * For pipes, queues and nats we normally say 'nat|pipe NN config'
! * but the code is easier to parse as 'nat|pipe config NN'
* so we swap the two arguments.
*/
! if ((do_pipe || do_nat) && ac > 1 && isdigit(*av[0])) {
char *p = av[0];
av[0] = av[1];
***************
*** 5157,5164 ****
--- 6024,6035 ----
if (_substrcmp(*av, "add") == 0)
add(ac, av);
+ else if (do_nat && _substrcmp(*av, "show") == 0)
+ show_nat(ac, av);
else if (do_pipe && _substrcmp(*av, "config") == 0)
config_pipe(ac, av);
+ else if (do_nat && _substrcmp(*av, "config") == 0)
+ config_nat(ac, av);
else if (_substrcmp(*av, "delete") == 0)
delete(ac, av);
else if (_substrcmp(*av, "flush") == 0)
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sbin/natd/natd.c /home/flag/src/freebsd7/src/sbin/natd/natd.c
*** /home/flag/src/freebsd7_vanilla/src/sbin/natd/natd.c Mon May 2 12:13:38 2005
--- /home/flag/src/freebsd7/src/sbin/natd/natd.c Sun Jun 11 18:57:26 2006
***************
*** 349,354 ****
--- 349,358 ----
siginterrupt(SIGHUP, 1);
signal (SIGTERM, InitiateShutdown);
signal (SIGHUP, RefreshAddr);
+
+ /* Load all libalias modules */
+ LibAliasRefreshModules();
+
/*
* Set alias address if it has been given.
*/
***************
*** 970,976 ****
static void RefreshAddr (int sig __unused)
{
! if (mip->ifName)
mip->assignAliasAddr = 1;
}
--- 974,981 ----
static void RefreshAddr (int sig __unused)
{
! LibAliasRefreshModules();
! if (mip && mip->ifName)
mip->assignAliasAddr = 1;
}
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/conf/files /home/flag/src/freebsd7/src/sys/conf/files
*** /home/flag/src/freebsd7_vanilla/src/sys/conf/files Fri Jun 9 08:13:45 2006
--- /home/flag/src/freebsd7/src/sys/conf/files Sun Jun 11 18:57:26 2006
***************
*** 1702,1717 ****
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
netinet/libalias/alias.c optional libalias
- netinet/libalias/alias_cuseeme.c optional libalias
netinet/libalias/alias_db.c optional libalias
- netinet/libalias/alias_ftp.c optional libalias
- netinet/libalias/alias_irc.c optional libalias
- netinet/libalias/alias_nbt.c optional libalias
- netinet/libalias/alias_pptp.c optional libalias
netinet/libalias/alias_proxy.c optional libalias
- netinet/libalias/alias_skinny.c optional libalias
- netinet/libalias/alias_smedia.c optional libalias
netinet/libalias/alias_util.c optional libalias
netinet6/ah_aesxcbcmac.c optional ipsec
netinet6/ah_core.c optional ipsec
netinet6/ah_input.c optional ipsec
--- 1702,1712 ----
netinet/tcp_usrreq.c optional inet
netinet/udp_usrreq.c optional inet
netinet/libalias/alias.c optional libalias
netinet/libalias/alias_db.c optional libalias
netinet/libalias/alias_proxy.c optional libalias
netinet/libalias/alias_util.c optional libalias
+ netinet/libalias/alias_old.c optional libalias
+ netinet/libalias/alias_mod.c optional libalias
netinet6/ah_aesxcbcmac.c optional ipsec
netinet6/ah_core.c optional ipsec
netinet6/ah_input.c optional ipsec
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/Makefile Mon Jun 20 10:33:29 2005
--- /home/flag/src/freebsd7/src/sys/modules/libalias/Makefile Sun Jun 11 18:57:26 2006
***************
*** 1,33 ****
! # $FreeBSD: src/sys/modules/libalias/Makefile,v 1.2 2005/06/20 08:33:29 glebius Exp $
! .PATH: ${.CURDIR}/../../netinet/libalias
!
! KMOD= libalias
! SRCS= alias.c alias_cuseeme.c alias_db.c alias_ftp.c alias_irc.c \
! alias_nbt.c alias_pptp.c alias_proxy.c alias_skinny.c alias_smedia.c \
! alias_util.c
! INCS= alias.h
!
! EXPORT_SYMS= LibAliasInit \
! LibAliasUninit \
! LibAliasSetAddress \
! LibAliasSetMode \
! LibAliasSkinnyPort \
! LibAliasIn \
! LibAliasOut \
! LibAliasRedirectPort \
! LibAliasRedirectAddr \
! LibAliasAddServer \
! LibAliasRedirectDynamic \
! LibAliasRedirectDelete \
! LibAliasProxyRule \
! LibAliasRedirectProto \
! LibAliasSaveFragment \
! LibAliasGetFragment \
! LibAliasFragmentIn \
! LibAliasSetTarget \
! LibAliasCheckNewLink \
! LibAliasInternetChecksum \
! LibAliasUnaliasOut
!
! .include <bsd.kmod.mk>
--- 1,11 ----
! SUBDIR= kld-cuseeme \
! kld-dummy \
! kld-ftp \
! kld-irc \
! kld-libalias \
! kld-nbt \
! kld-pptp \
! kld-skinny \
! kld-smedia
! .include <bsd.subdir.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-cuseeme/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-cuseeme/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-cuseeme/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-cuseeme/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_cuseeme
+ SRCS= alias_cuseeme.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-dummy/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-dummy/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-dummy/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-dummy/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_dummy
+ SRCS= alias_dummy.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-ftp/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-ftp/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-ftp/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-ftp/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_ftp
+ SRCS= alias_ftp.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-irc/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-irc/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-irc/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-irc/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_irc
+ SRCS= alias_irc.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-libalias/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-libalias/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-libalias/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-libalias/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,33 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= libalias
+ SRCS= alias.c alias_db.c alias_proxy.c alias_util.c alias_old.c alias_mod.c
+ INCS= alias.h
+
+ EXPORT_SYMS= LibAliasInit \
+ LibAliasUninit \
+ LibAliasSetAddress \
+ LibAliasSetMode \
+ LibAliasSkinnyPort \
+ LibAliasIn \
+ LibAliasOut \
+ LibAliasRedirectPort \
+ LibAliasRedirectAddr \
+ LibAliasAddServer \
+ LibAliasRedirectDynamic \
+ LibAliasRedirectDelete \
+ LibAliasProxyRule \
+ LibAliasRedirectProto \
+ LibAliasSaveFragment \
+ LibAliasGetFragment \
+ LibAliasFragmentIn \
+ LibAliasSetTarget \
+ LibAliasCheckNewLink \
+ LibAliasInternetChecksum \
+ LibAliasUnaliasOut \
+ attach_handler \
+ detach_handler
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-nbt/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-nbt/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-nbt/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-nbt/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_nbt
+ SRCS= alias_nbt.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-pptp/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-pptp/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-pptp/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-pptp/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_pptp
+ SRCS= alias_pptp.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-skinny/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-skinny/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-skinny/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-skinny/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_skinny
+ SRCS= alias_skinny.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-smedia/Makefile /home/flag/src/freebsd7/src/sys/modules/libalias/kld-smedia/Makefile
*** /home/flag/src/freebsd7_vanilla/src/sys/modules/libalias/kld-smedia/Makefile Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/modules/libalias/kld-smedia/Makefile Sun Jun 11 18:57:26 2006
***************
*** 0 ****
--- 1,9 ----
+ .PATH: ${.CURDIR}/../../../netinet/libalias
+
+ KMOD= alias_smedia
+ SRCS= alias_smedia.c
+ INCS= alias.h
+
+ CFLAGS+= -Werror
+
+ .include <bsd.kmod.mk>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/in.h /home/flag/src/freebsd7/src/sys/netinet/in.h
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/in.h Sun May 14 16:22:49 2006
--- /home/flag/src/freebsd7/src/sys/netinet/in.h Sun Jun 11 18:57:26 2006
***************
*** 410,415 ****
--- 410,420 ----
#define IP_FW_GET 54 /* get entire firewall rule chain */
#define IP_FW_RESETLOG 55 /* reset logging counters */
+ #define IP_FW_NAT_CFG 56 /* add/config a nat rule */
+ #define IP_FW_NAT_DEL 57 /* delete a nat rule */
+ #define IP_FW_NAT_GET_CONFIG 58 /* get configuration of a nat rule */
+ #define IP_FW_NAT_GET_LOG 59 /* get log of a nat rule */
+
#define IP_DUMMYNET_CONFIGURE 60 /* add/configure a dummynet pipe */
#define IP_DUMMYNET_DEL 61 /* delete a dummynet pipe from chain */
#define IP_DUMMYNET_FLUSH 62 /* flush dummynet */
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw.h /home/flag/src/freebsd7/src/sys/netinet/ip_fw.h
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw.h Wed May 24 15:09:55 2006
--- /home/flag/src/freebsd7/src/sys/netinet/ip_fw.h Sun Jun 11 18:57:26 2006
***************
*** 124,129 ****
--- 124,130 ----
O_TEE, /* arg1=port number */
O_FORWARD_IP, /* fwd sockaddr */
O_FORWARD_MAC, /* fwd mac */
+ O_NAT, /* nope */
/*
* More opcodes.
***************
*** 307,312 ****
--- 308,372 ----
u_int32_t log_left; /* how many left to log */
} ipfw_insn_log;
+ /*
+ * "syntactic sugar for compiler": used in HOOK_REDIR|SPOOL in ip_fw2.c.
+ *
+ * WARNING: don't move the field "next" in the subsequent cfg_* structs,
+ * it has to be the first.
+ */
+ struct _chain {
+ struct _chain *next;
+ };
+
+ /* Server pool support (LSNAT) */
+ struct cfg_spool {
+ struct cfg_spool *next; /* chain of spool instances */
+ struct in_addr addr;
+ u_short port;
+ };
+
+ /* Redirect modes id */
+ #define REDIR_ADDR 0x01
+ #define REDIR_PORT 0x02
+ #define REDIR_PROTO 0x04
+
+ /* Nat redirect configuration */
+ struct cfg_redir {
+ struct cfg_redir *next; /* chain of redir instances */
+ u_int16_t mode; /* type of redirect mode */
+ struct in_addr laddr; /* local ip address */
+ struct in_addr paddr; /* public ip address */
+ struct in_addr raddr; /* remote ip address */
+ u_short lport; /* local port */
+ u_short pport; /* public port */
+ u_short rport; /* remote port */
+ u_short pport_cnt; /* number of public ports */
+ u_short rport_cnt; /* number of remote ports */
+ int proto; /* protocol: tcp/udp */
+ struct alias_link **alink;
+ u_int16_t spool_cnt; /* number of entry in spool chain */
+ struct cfg_spool *spool_chain; /* chain of spool instances */
+ };
+
+ #define NAT_BUF_LEN 1024
+ /* Nat configuration data struct */
+ struct cfg_nat {
+ struct cfg_nat *next; /* chain of nat instances */
+ int id; /* nat id */
+ struct in_addr ip; /* nat ip address */
+ char if_name[IF_NAMESIZE]; /* interface name */
+ int mode; /* aliasing mode */
+ struct libalias *lib; /* libalias instance */
+ int redir_cnt; /* number of entry in spool chain */
+ struct cfg_redir *redir_chain; /* chain of redir instances */
+ };
+
+ /* Nat command */
+ typedef struct _ipfw_insn_nat {
+ ipfw_insn o;
+ struct cfg_nat *nat;
+ } ipfw_insn_nat;
+
/* Apply ipv6 mask on ipv6 addr */
#define APPLY_MASK(addr,mask) \
(addr)->__u6_addr.__u6_addr32[0] &= (mask)->__u6_addr.__u6_addr32[0]; \
***************
*** 483,488 ****
--- 543,549 ----
IP_FW_DUMMYNET,
IP_FW_NETGRAPH,
IP_FW_NGTEE,
+ IP_FW_NAT,
};
/* flags for divert mtag */
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw2.c /home/flag/src/freebsd7/src/sys/netinet/ip_fw2.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw2.c Thu Jun 8 13:27:45 2006
--- /home/flag/src/freebsd7/src/sys/netinet/ip_fw2.c Sun Jun 11 18:57:26 2006
***************
*** 46,51 ****
--- 46,52 ----
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/condvar.h>
+ #include <sys/eventhandler.h>
#include <sys/malloc.h>
#include <sys/mbuf.h>
#include <sys/kernel.h>
***************
*** 55,60 ****
--- 56,62 ----
#include <sys/proc.h>
#include <sys/rwlock.h>
#include <sys/socket.h>
+ #include <sys/types.h>
#include <sys/socketvar.h>
#include <sys/sysctl.h>
#include <sys/syslog.h>
***************
*** 78,84 ****
#include <netinet/tcpip.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
!
#include <netgraph/ng_ipfw.h>
#include <altq/if_altq.h>
--- 80,87 ----
#include <netinet/tcpip.h>
#include <netinet/udp.h>
#include <netinet/udp_var.h>
! #include <netinet/libalias/alias.h>
! #include <netinet/libalias/alias_local.h>
#include <netgraph/ng_ipfw.h>
#include <altq/if_altq.h>
***************
*** 296,301 ****
--- 299,360 ----
#endif /* INET6 */
#endif /* SYSCTL_NODE */
+ MODULE_DEPEND(ipfw, libalias, 1, 1, 1);
+
+ struct _nat_chain {
+ struct cfg_nat *chain;
+ struct mtx mtx; /* lock guarding rule list */
+ int busy_count; /* busy count for rw locks */
+ int want_write;
+ struct cv cv;
+ } nat_chain;
+
+ #define NAT_LOCK_INIT(_chain) \
+ mtx_init(&(_chain)->mtx, "NAT instances", NULL, \
+ MTX_DEF | MTX_RECURSE)
+ #define NAT_LOCK_DESTROY(_chain) mtx_destroy(&(_chain)->mtx)
+ #define NAT_WLOCK_ASSERT(_chain) do { \
+ mtx_assert(&(_chain)->mtx, MA_OWNED); \
+ NET_ASSERT_GIANT(); \
+ } while (0)
+
+ static __inline void
+ NAT_RLOCK(struct _nat_chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->busy_count++;
+ mtx_unlock(&chain->mtx);
+ }
+
+ static __inline void
+ NAT_RUNLOCK(struct _nat_chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->busy_count--;
+ if (chain->busy_count == 0 && chain->want_write)
+ cv_signal(&chain->cv);
+ mtx_unlock(&chain->mtx);
+ }
+
+ static __inline void
+ NAT_WLOCK(struct _nat_chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->want_write++;
+ while (chain->busy_count > 0)
+ cv_wait(&chain->cv, &chain->mtx);
+ }
+
+ static __inline void
+ NAT_WUNLOCK(struct _nat_chain *chain)
+ {
+ chain->want_write--;
+ cv_signal(&chain->cv);
+ mtx_unlock(&chain->mtx);
+ }
+
+ static eventhandler_tag ifaddr_event_tag;
+
static int fw_deny_unknown_exthdrs = 1;
***************
*** 853,858 ****
--- 912,920 ----
snprintf(SNPARGS(action2, 0), "Ngtee %d",
cmd->arg1);
break;
+ case O_NAT:
+ action = "Nat";
+ break;
default:
action = "UNKNOWN";
break;
***************
*** 1964,1969 ****
--- 2026,2294 ----
return match;
}
+ /* FIX for 5.x and 4.x branch: m_move_pkthdr is not mbuf_cluster safe there */
+ #if __FreeBSD_version > 600000
+ static void
+ mym_move_pkthdr(struct mbuf *to, struct mbuf *from) {
+ m_move_pkthdr(to, from);
+ }
+ #else
+ /*
+ * "Move" mbuf pkthdr from "from" to "to".
+ * "from" must have M_PKTHDR set, and "to" must be empty.
+ */
+ static void
+ mym_move_pkthdr(struct mbuf *to, struct mbuf *from)
+ {
+
+ #ifdef MAC
+ /*
+ * XXXMAC: It could be this should also occur for non-MAC?
+ */
+ if (to->m_flags & M_PKTHDR)
+ m_tag_delete_chain(to, NULL);
+ #endif
+ to->m_flags = (from->m_flags & M_COPYFLAGS) | (to->m_flags & M_EXT);
+ if ((to->m_flags & M_EXT) == 0)
+ to->m_data = to->m_pktdat;
+ to->m_pkthdr = from->m_pkthdr; /* especially tags */
+ SLIST_INIT(&from->m_pkthdr.tags); /* purge tags from src */
+ from->m_flags &= ~M_PKTHDR;
+ }
+ #endif
+
+ /*
+ * m_megapullup() function is a big hack. (from ng_nat.c)
+ *
+ * It allocates an mbuf with cluster and copies the whole
+ * chain into cluster, so that it is all contigous and the
+ * whole packet can be accessed via char pointer.
+ * This is required, because libalias doesn't have idea
+ * about mbufs.
+ *
+ * On success, m_megapullup returns an mbuf with cluster
+ * containing the input packet, on failure NULL.
+ * In both cases, the input packet is consumed.
+ */
+ static struct mbuf *
+ m_megapullup(struct mbuf *m, int len) {
+ struct mbuf *mcl;
+ caddr_t cp;
+
+ if (len > MCLBYTES)
+ goto bad;
+
+ if ((mcl = m_getcl(M_DONTWAIT, MT_DATA, M_PKTHDR)) == NULL)
+ goto bad;
+
+ cp = mtod(mcl, caddr_t);
+ m_copydata(m, 0, len, cp);
+ mym_move_pkthdr(mcl, m);
+ mcl->m_len = mcl->m_pkthdr.len;
+ m_freem(m);
+
+ return (mcl);
+ bad:
+ m_freem(m);
+ return (NULL);
+ }
+
+ static void
+ flush_nat_ptrs(const int i) {
+ struct ip_fw *rule;
+
+ IPFW_WLOCK(&layer3_chain);
+ for (rule = layer3_chain.rules; rule; rule = rule->next) {
+ ipfw_insn_nat *cmd = (ipfw_insn_nat *)ACTION_PTR(rule);
+
+ if (cmd->o.opcode != O_NAT)
+ continue;
+ if (cmd->nat != NULL && cmd->nat->id == i)
+ cmd->nat = NULL;
+ }
+ IPFW_WUNLOCK(&layer3_chain);
+ }
+
+ static struct cfg_nat *
+ lookup_nat(const int i) {
+ struct cfg_nat *ptr;
+
+ for (ptr = nat_chain.chain; ptr != NULL; ptr = ptr->next)
+ if (ptr->id == i) return(ptr);
+ return(NULL);
+ }
+
+ /* attach p to b chain */
+ static void
+ hook_entry(struct _chain **b, struct _chain *p) {
+
+ /* XXX better to make an in-order addition... */
+ for(; *b != NULL; b = &((*b)->next))
+ ;
+ *b = p;
+ }
+
+ /* remove p from b chain */
+ static void
+ unhook_entry(struct _chain **b, struct _chain *p) {
+
+ NAT_WLOCK_ASSERT(&nat_chain);
+ for(; *b != p; b = &((*b)->next))
+ ;
+ *b = p->next;
+ }
+
+ #define HOOK_NAT(b, p) do { \
+ NAT_WLOCK_ASSERT(&nat_chain); \
+ hook_entry((struct _chain **)b, (struct _chain *)p); \
+ } while (0)
+
+ #define UNHOOK_NAT(b, p) do { \
+ NAT_WLOCK_ASSERT(&nat_chain); \
+ unhook_entry((struct _chain **)b, (struct _chain *)p); \
+ } while (0)
+
+ #define HOOK_REDIR(b, p) do { \
+ hook_entry((struct _chain **)b, (struct _chain *)p); \
+ } while (0)
+
+ #define HOOK_SPOOL(b, p) do { \
+ hook_entry((struct _chain **)b, (struct _chain *)p); \
+ } while (0)
+
+ static void
+ del_redir_spool_cfg(struct cfg_nat *n, struct cfg_redir *r) {
+ struct cfg_redir *tmp_r;
+ struct cfg_spool *tmp_s;
+ int i, num;
+
+ while(r) {
+ num = 1; /* number of alias_link to delete */
+ switch(r->mode) {
+ case REDIR_PORT:
+ num = r->pport_cnt;
+ case REDIR_ADDR:
+ case REDIR_PROTO:
+ /* delete all libalias redirect entry */
+ for (i = 0; i < num; i++)
+ LibAliasRedirectDelete(n->lib,
+ r->alink[i]);
+ /* del spool cfg if any */
+ while(r->spool_chain) {
+ tmp_s = r->spool_chain->next;
+ free(r->spool_chain, M_IPFW);
+ r->spool_chain = tmp_s;
+ }
+ tmp_r = r->next;
+ free(r->alink, M_IPFW);
+ free(r, M_IPFW);
+ r = tmp_r;
+ break;
+ default:
+ printf("unknown redirect mode: %u\n", r->mode);
+ /* XXX - panic?!?!? */
+ break;
+ }
+ }
+ n->redir_chain = NULL;
+ }
+
+ static int
+ add_redir_spool_cfg(char *buf, struct cfg_nat *ptr) {
+ int sof_alinkp = sizeof(struct alias_link *);
+ int sof_redir = sizeof(struct cfg_redir);
+ int sof_spool = sizeof(struct cfg_spool);
+ struct cfg_redir *r, *ser_r;
+ struct cfg_spool *s, *ser_s;
+ int cnt, off, i;
+
+ for(cnt=0, off = 0; cnt<ptr->redir_cnt; cnt++) {
+ ser_r = (struct cfg_redir *)&buf[off];
+ r = malloc(sof_redir, M_IPFW, M_NOWAIT | M_ZERO);
+ if (r == NULL) {
+ /* try to recover:
+ * set the actual number of redir entries
+ * that were hooked succesfully
+ */
+ ptr->redir_cnt = cnt;
+ del_redir_spool_cfg(ptr, ptr->redir_chain);
+ // XXX - NAT_WUNLOCK...
+ return (ENOSPC);
+ }
+ memcpy(r, ser_r, sof_redir);
+ off += sof_redir;
+ r->alink = malloc(sof_alinkp*r->pport_cnt,
+ M_IPFW, M_NOWAIT | M_ZERO);
+ if (r->alink == NULL) {
+ r->pport_cnt = 0;
+ del_redir_spool_cfg(ptr, ptr->redir_chain);
+ // XXX - NAT_WUNLOCK...
+ return (ENOSPC);
+ }
+ switch(r->mode) {
+ case REDIR_ADDR:
+ {
+ r->alink[0] = LibAliasRedirectAddr(ptr->lib,
+ r->laddr,
+ r->paddr);
+ }
+ break;
+ case REDIR_PORT:
+ for (i = 0 ; i < r->pport_cnt; i++) {
+ /* If remotePort is all ports, set it to 0. */
+ u_short remotePortCopy = r->rport + i;
+ if (r->rport_cnt == 1 && r->rport == 0)
+ remotePortCopy = 0;
+ r->alink[i] = LibAliasRedirectPort (ptr->lib, r->laddr,
+ htons(r->lport + i),
+ r->raddr,
+ htons(remotePortCopy),
+ r->paddr,
+ htons(r->pport + i),
+ r->proto);
+ if (r->alink[i] == NULL) {
+ r->alink[0] = NULL;
+ break;
+ }
+ }
+ break;
+ case REDIR_PROTO:
+ r->alink[0] = LibAliasRedirectProto(ptr->lib,
+ r->laddr,
+ r->raddr,
+ r->paddr,
+ r->proto);
+ break;
+ default:
+ printf("unknown redirect mode: %u\n", r->mode);
+ break;
+ }
+ if (r->alink[0] == NULL) { /* panic?!?!? */
+ free(r->alink, M_IPFW);
+ printf("previous LibAliasRedirect* returned NULL!!!\n");
+ } else /* handles LSNAT */
+ for (i=0; i<r->spool_cnt; i++) {
+ ser_s = (struct cfg_spool *)&buf[off];
+ s = malloc(sof_redir, M_IPFW, M_NOWAIT | M_ZERO);
+ if (s == NULL) {
+ r->spool_cnt = i;
+ del_redir_spool_cfg(ptr, r);
+ return (ENOSPC);
+ }
+ memcpy(s, ser_s, sof_spool);
+ LibAliasAddServer(ptr->lib, r->alink[0], // XXX - what about RedirectPort with many alink?
+ s->addr,
+ htons(s->port));
+ off += sof_spool;
+ /* hook spool entry */
+ HOOK_SPOOL(&r->spool_chain, s);
+ }
+ /* and finally hook this redir entry */
+ HOOK_REDIR(&ptr->redir_chain, r);
+ }
+ return(1);
+ }
+
/*
* The main check routine for the firewall.
*
***************
*** 3138,3143 ****
--- 3463,3625 ----
IP_FW_NETGRAPH : IP_FW_NGTEE;
goto done;
+ case O_NAT: {
+ struct cfg_nat *t;
+ struct mbuf *mcl;
+ /* XXX - libalias duct tape */
+ int ldt = 0;
+ char *c;
+
+ args->rule = f; /* report matching rule */
+ retval = 0;
+ t = ((ipfw_insn_nat *)cmd)->nat;
+ if (t == NULL) {
+ NAT_RLOCK(&nat_chain);
+ t = lookup_nat(cmd->arg1);
+ if (t == NULL) {
+ retval = IP_FW_DENY;
+ goto done;
+ } else ((ipfw_insn_nat *)cmd)->nat = t;
+ }
+ if ((mcl = m_megapullup(m, m->m_pkthdr.len)) == NULL)
+ goto badnat;
+ ip = mtod(mcl, struct ip *);
+ /*
+ * XXX - workaround for host-byte-order 4.x BSD well_known_bug:
+ * due to 4.x BSD legacy, some fields in layer-3 packet COULD be
+ * in host byte order instead of network byte order, so we have
+ * to manually swap it before passing mbuf to libalias...
+ */
+ if (args->eh == NULL) { /* host byte order */
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ }
+
+ /*
+ * XXX - libalias checksum offload 'duct tape':
+ *
+ * locally generated packets have only pseudo-header
+ * checksum calculated and libalias will screw it[1],
+ * so mark them for later fix.
+ * Moreover there are cases when libalias modify tcp
+ * packet data[2], mark it for later fix too.
+ *
+ * [1] libalias was never meant to run in kernel, so
+ * it doesn't have any knowledge about checksum
+ * offloading, and it expects a packet with a full
+ * internet checksum. Unfortunately, packets
+ * generated locally will have just the pseudo
+ * header calculated, and when libalias tries to
+ * adjust the checksum it will actually screw it.
+ *
+ * [2] when libalias modify tcp's data content,
+ * full TCP checksum has to be recomputed:
+ * the problem is that libalias doesn't have any
+ * idea about checksum offloading
+ * To workaround this, we do not do checksumming
+ * in LibAlias, but only mark the packets in th_x2
+ * field. If we receive a marked packet, we
+ * calculate correct checksum for it aware of
+ * offloading.
+ * Why such a terrible hack instead of
+ * recalculating checksum for each packet?
+ * Because the previous checksum was not checked!
+ * Recalculating checksums for EVERY packet will
+ * hide ALL transmission errors. Yes, marked packets
+ * still suffer from this problem. But, sigh, natd(8)
+ * has this problem, too.
+ *
+ * TODO:
+ * -make libalias mbuf aware (so it can handle
+ * delayed checksum)
+ * -maybe shrink the api? do we really need 23
+ * functions?
+ */
+
+ if (mcl->m_pkthdr.rcvif == NULL &&
+ mcl->m_pkthdr.csum_flags & CSUM_DELAY_DATA) {
+ ldt = 1;
+ }
+
+ c = mtod(mcl, char *);
+ if (oif == NULL)
+ retval = LibAliasIn(t->lib, c, MCLBYTES);
+ else
+ retval = LibAliasOut(t->lib, c, MCLBYTES);
+ if (retval != PKT_ALIAS_OK) {
+ /* XXX - should i add some logging ? */
+ m_free(mcl);
+ badnat:
+ args->m = NULL;
+ retval = IP_FW_DENY;
+ goto done;
+ }
+ mcl->m_pkthdr.len = mcl->m_len = ntohs(ip->ip_len);
+
+ /*
+ * XXX - libalias checksum offload
+ * 'duct tape' (see above)
+ */
+
+ if ((ip->ip_off & htons(IP_OFFMASK)) == 0 &&
+ ip->ip_p == IPPROTO_TCP) {
+ struct tcphdr *th = (struct tcphdr *)(ip + 1);
+
+ if (th->th_x2)
+ ldt = 1;
+ }
+
+ if (ldt) {
+ struct tcphdr *th;
+ struct udphdr *uh;
+ u_short cksum;
+
+ ip->ip_len = ntohs(ip->ip_len);
+ cksum = in_pseudo(
+ ip->ip_src.s_addr,
+ ip->ip_dst.s_addr,
+ htons(ip->ip_p + ip->ip_len - (ip->ip_hl << 2))
+ );
+
+ switch(ip->ip_p) {
+ case IPPROTO_TCP:
+ th = (struct tcphdr *)(ip + 1);
+ /* maybe it was set in libalias... */
+ th->th_x2 = 0;
+ th->th_sum = cksum;
+ mcl->m_pkthdr.csum_data =
+ offsetof(struct tcphdr,
+ th_sum);
+ break;
+ case IPPROTO_UDP:
+ uh = (struct udphdr *)(ip + 1);
+ uh->uh_sum = cksum;
+ mcl->m_pkthdr.csum_data =
+ offsetof(struct udphdr,
+ uh_sum);
+ break;
+
+ }
+ /* no hw checksum offloading: do it by ourself */
+ if ((mcl->m_pkthdr.csum_flags & CSUM_DELAY_DATA) == 0) {
+ in_delayed_cksum(mcl);
+ mcl->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
+ }
+ ip->ip_len = htons(ip->ip_len);
+ }
+
+ /* XXX - swap again some fields... see above */
+ if (args->eh == NULL) { /* host byte order */
+ ip->ip_len = ntohs(ip->ip_len);
+ ip->ip_off = ntohs(ip->ip_off);
+ }
+
+ args->m = mcl;
+ retval = IP_FW_NAT;
+ NAT_RUNLOCK(&nat_chain);
+ goto done;
+ }
+
default:
panic("-- unknown opcode %d\n", cmd->opcode);
} /* end of switch() on opcodes */
***************
*** 3707,3712 ****
--- 4189,4198 ----
return EINVAL;
else
goto check_size;
+ case O_NAT:
+ if (cmdlen != F_INSN_SIZE(ipfw_insn_nat))
+ goto bad_size;
+ goto check_action;
case O_FORWARD_MAC: /* XXX not implemented yet */
case O_CHECK_STATE:
case O_COUNT:
***************
*** 3860,3865 ****
--- 4346,4377 ----
}
+ static void
+ ifaddr_change(void *arg __unused, struct ifnet *ifp) {
+ struct cfg_nat *ptr;
+ struct ifaddr *ifa;
+
+ NAT_WLOCK(&nat_chain);
+ /* find every nat entry...*/
+ for (ptr = nat_chain.chain; ptr; ptr = ptr->next) {
+ /* ...using nic 'ifp->if_xname' as dynamic alias address */
+ if (strncmp(ptr->if_name, ifp->if_xname, IF_NAMESIZE) == 0) {
+ mtx_lock(&ifp->if_addr_mtx);
+ TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ if (ifa->ifa_addr->sa_family != AF_INET)
+ continue;
+ ptr->ip = ((struct sockaddr_in *)
+ (ifa->ifa_addr))->sin_addr;
+ LibAliasSetAddress(ptr->lib, ptr->ip);
+ }
+ mtx_unlock(&ifp->if_addr_mtx);
+ }
+ }
+ NAT_WUNLOCK(&nat_chain);
+ }
+
/**
* {set|get}sockopt parser.
*/
***************
*** 4085,4090 ****
--- 4597,4750 ----
}
break;
+ case IP_FW_NAT_CFG:
+ {
+ struct cfg_nat *ptr, *ser_n;
+ char *buf;
+ int err=0;
+
+ buf = malloc(NAT_BUF_LEN, M_IPFW, M_NOWAIT | M_ZERO);
+ if (buf == NULL)
+ return (ENOSPC);
+
+ error = sooptcopyin(sopt, buf, NAT_BUF_LEN, sizeof(struct cfg_nat));
+ ser_n = (struct cfg_nat *)buf;
+
+ /* FIND/CREATE NAT RULE */
+ NAT_WLOCK(&nat_chain);
+ ptr = lookup_nat(ser_n->id);
+ if (ptr == NULL) { /* new rule: allocate and init new instance */
+ ptr = malloc(sizeof(struct cfg_nat), M_IPFW, M_NOWAIT | M_ZERO);
+ if (ptr == NULL) {
+ free(buf, M_IPFW);
+ NAT_WUNLOCK(&nat_chain);
+ return (ENOSPC);
+ }
+ ptr->lib = LibAliasInit(NULL);
+ if (ptr->lib == NULL) {
+ free(ptr, M_IPFW);
+ free(buf, M_IPFW);
+ NAT_WUNLOCK(&nat_chain);
+ return(EINVAL);
+ }
+ } else { /* entry already present: temporarly unhook it */
+ UNHOOK_NAT(&nat_chain.chain, ptr);
+ flush_nat_ptrs(ser_n->id);
+ }
+ NAT_WUNLOCK(&nat_chain);
+
+ /* BASIC NAT CONFIGURATION */
+ ptr->id = ser_n->id;
+ /*
+ * XXX - what if this rule doesn't nat any ip and just redirect?
+ * do we set aliasaddress to 0.0.0.0? is it correct?
+ */
+ ptr->ip = ser_n->ip;
+ ptr->redir_cnt = ser_n->redir_cnt;
+ ptr->mode = ser_n->mode;
+ LibAliasSetMode(ptr->lib, ser_n->mode, ser_n->mode);
+ LibAliasSetAddress(ptr->lib, ptr->ip);
+ memcpy(ptr->if_name, ser_n->if_name, IF_NAMESIZE);
+
+ /* REDIR AND LSNAT CONFIGURATION */
+ del_redir_spool_cfg(ptr, ptr->redir_chain); /* delete old cfgs */
+ err = add_redir_spool_cfg(&buf[(sizeof(struct cfg_nat))],
+ ptr); /* add new entries */
+ free(buf, M_IPFW);
+ if (err == 1) {
+ NAT_WLOCK(&nat_chain);
+ HOOK_NAT(&nat_chain.chain, ptr);
+ NAT_WUNLOCK(&nat_chain);
+ } else /* something bad happened, redir cfg not added */
+ return(EINVAL);
+ }
+ break;
+
+ case IP_FW_NAT_DEL:
+ {
+ struct cfg_nat *ptr;
+ int i;
+
+ error = sooptcopyin(sopt, &i, sizeof i, sizeof i);
+ NAT_WLOCK(&nat_chain);
+ ptr = lookup_nat(i);
+ if (ptr == NULL) {
+ error = EINVAL;
+ NAT_WUNLOCK(&nat_chain);
+ break;
+ }
+ UNHOOK_NAT(&nat_chain.chain, ptr);
+ NAT_WUNLOCK(&nat_chain);
+ flush_nat_ptrs(i);
+ del_redir_spool_cfg(ptr, ptr->redir_chain);
+ LibAliasUninit(ptr->lib);
+ free(ptr, M_IPFW);
+ }
+ break;
+
+ case IP_FW_NAT_GET_CONFIG:
+ {
+ u_int8_t *data;
+ struct cfg_nat *n;
+ struct cfg_redir *r;
+ struct cfg_spool *s;
+ int sof_nat = sizeof(struct cfg_nat);
+ int sof_redir = sizeof(struct cfg_redir);
+ int sof_spool = sizeof(struct cfg_spool);
+ int off = 0;
+
+ data = malloc(NAT_BUF_LEN, M_IPFW, M_NOWAIT | M_ZERO);
+ if (data == NULL)
+ return (ENOSPC);
+ NAT_RLOCK(&nat_chain);
+ /* serialize all the data */
+ for (n = nat_chain.chain; (n && (off + sof_nat < NAT_BUF_LEN));
+ n = n->next) {
+ bcopy(n, &data[off], sof_nat);
+ off += sof_nat;
+ for (r = n->redir_chain; (r && (off + sof_redir < NAT_BUF_LEN));
+ r = r->next) {
+ bcopy(r, &data[off], sof_redir);
+ off += sof_redir;
+ for (s = r->spool_chain; (s && (off + sof_spool < NAT_BUF_LEN));
+ s = s->next) {
+ bcopy(s, &data[off], sof_spool);
+ off += sof_spool;
+ }
+ }
+ }
+ NAT_RUNLOCK(&nat_chain);
+
+ error = sooptcopyout(sopt, data, NAT_BUF_LEN);
+ free(data, M_IPFW);
+ }
+ break;
+
+ case IP_FW_NAT_GET_LOG:
+ {
+ u_int8_t *data = NULL;
+ struct cfg_nat *ptr;
+ int sof = LIBALIAS_BUF_SIZE;
+ int i, size, cnt = 0;
+
+ NAT_RLOCK(&nat_chain);
+ for (ptr = nat_chain.chain, size = i = 0; ptr; ptr = ptr->next) {
+ if (ptr->lib->logDesc == NULL) continue;
+ cnt++;
+ size = cnt * (sof + sizeof(int));
+ data = realloc(data, size, M_IPFW, M_NOWAIT | M_ZERO);
+ if (data == NULL) return (ENOSPC);
+ bcopy(&ptr->id, &data[i], sizeof(int));
+ i += sizeof(int);
+ bcopy(ptr->lib->logDesc, &data[i], sof);
+ i += sof;
+ }
+ NAT_RUNLOCK(&nat_chain);
+ error = sooptcopyout(sopt, data, size);
+ free(data, M_IPFW);
+ }
+ break;
+
default:
printf("ipfw: ipfw_ctl invalid option %d\n", sopt->sopt_name);
error = EINVAL;
***************
*** 4256,4263 ****
}
ip_fw_ctl_ptr = ipfw_ctl;
ip_fw_chk_ptr = ipfw_chk;
! callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL);
!
return (0);
}
--- 4916,4928 ----
}
ip_fw_ctl_ptr = ipfw_ctl;
ip_fw_chk_ptr = ipfw_chk;
! callout_reset(&ipfw_timeout, hz, ipfw_tick, NULL);
! nat_chain.chain = NULL;
! nat_chain.busy_count = 0;
! nat_chain.want_write = 0;
! NAT_LOCK_INIT(&nat_chain);
! ifaddr_event_tag = EVENTHANDLER_REGISTER(ifaddr_event, ifaddr_change,
! NULL, EVENTHANDLER_PRI_ANY);
return (0);
}
***************
*** 4265,4276 ****
--- 4930,4952 ----
ipfw_destroy(void)
{
struct ip_fw *reap;
+ struct cfg_nat *ptr, *ptr_temp;
ip_fw_chk_ptr = NULL;
ip_fw_ctl_ptr = NULL;
callout_drain(&ipfw_timeout);
IPFW_WLOCK(&layer3_chain);
flush_tables(&layer3_chain);
+ NAT_WLOCK(&nat_chain);
+ for (ptr = nat_chain.chain; ptr; ptr = ptr_temp) {
+ ptr_temp = ptr->next;
+ del_redir_spool_cfg(ptr, ptr->redir_chain);
+ LibAliasUninit(ptr->lib);
+ free(ptr, M_IPFW);
+ }
+ NAT_WUNLOCK(&nat_chain);
+ EVENTHANDLER_DEREGISTER(ifaddr_event, ifaddr_event_tag);
+ NAT_LOCK_DESTROY(&nat_chain);
layer3_chain.reap = NULL;
free_chain(&layer3_chain, 1 /* kill default rule */);
reap = layer3_chain.reap, layer3_chain.reap = NULL;
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw_pfil.c /home/flag/src/freebsd7/src/sys/netinet/ip_fw_pfil.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/ip_fw_pfil.c Fri May 12 06:41:27 2006
--- /home/flag/src/freebsd7/src/sys/netinet/ip_fw_pfil.c Sun Jun 11 18:57:26 2006
***************
*** 189,194 ****
--- 189,197 ----
if (!NG_IPFW_LOADED)
goto drop;
return ng_ipfw_input_p(m0, NG_IPFW_IN, &args, 0);
+
+ case IP_FW_NAT:
+ goto again; /* continue with packet */
default:
KASSERT(0, ("%s: unknown retval", __func__));
***************
*** 315,320 ****
--- 318,326 ----
goto drop;
return ng_ipfw_input_p(m0, NG_IPFW_OUT, &args, 0);
+ case IP_FW_NAT:
+ goto again; /* continue with packet */
+
default:
KASSERT(0, ("%s: unknown retval", __func__));
}
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias.c Tue Jun 28 00:21:42 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias.c Sun Jun 11 18:57:26 2006
***************
*** 113,121 ****
--- 113,128 ----
#ifdef _KERNEL
#include <sys/param.h>
+ #include <sys/proc.h>
+ #include <sys/types.h>
+ #include <sys/systm.h>
#else
#include <sys/types.h>
+ #include <stdlib.h>
#include <stdio.h>
+ #include <dlfcn.h>
+ #include <errno.h>
+ #include <string.h>
#endif
#include <netinet/in_systm.h>
***************
*** 128,149 ****
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
#else
#include "alias.h"
#include "alias_local.h"
#endif
- #define NETBIOS_NS_PORT_NUMBER 137
- #define NETBIOS_DGM_PORT_NUMBER 138
- #define FTP_CONTROL_PORT_NUMBER 21
- #define IRC_CONTROL_PORT_NUMBER_1 6667
- #define IRC_CONTROL_PORT_NUMBER_2 6668
- #define CUSEEME_PORT_NUMBER 7648
- #define RTSP_CONTROL_PORT_NUMBER_1 554
- #define RTSP_CONTROL_PORT_NUMBER_2 7070
- #define TFTP_PORT_NUMBER 69
- #define PPTP_CONTROL_PORT_NUMBER 1723
-
static __inline int
twowords(void *p)
{
--- 135,147 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias.h"
#include "alias_local.h"
+ #include "alias_mod.h"
#endif
static __inline int
twowords(void *p)
{
***************
*** 725,748 ****
struct in_addr original_address;
u_short alias_port;
int accumulate;
! int r = 0;
alias_address = GetAliasAddress(lnk);
original_address = GetOriginalAddress(lnk);
alias_port = ud->uh_dport;
ud->uh_dport = GetOriginalPort(lnk);
! /* Special processing for IP encoding protocols */
! if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
! AliasHandleCUSeeMeIn(la, pip, original_address);
! /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
! else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
! || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
! r = AliasHandleUdpNbt(la, pip, lnk, &original_address, ud->uh_dport);
! else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
! || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
! r = AliasHandleUdpNbtNS(la, pip, lnk, &alias_address, &alias_port,
! &original_address, &ud->uh_dport);
/* If UDP checksum is not zero, then adjust since destination port */
/* is being unaliased and destination address is being altered. */
--- 723,748 ----
struct in_addr original_address;
u_short alias_port;
int accumulate;
! int r = 0, err;
! struct alias_data ad = {
! lnk,
! &original_address,
! &alias_address,
! &alias_port,
! &ud->uh_sport,
! &ud->uh_dport,
! 0 /* maxpacketsize */
! };
alias_address = GetAliasAddress(lnk);
original_address = GetOriginalAddress(lnk);
alias_port = ud->uh_dport;
ud->uh_dport = GetOriginalPort(lnk);
! /* walk out chain */
! err = find_handler(IN, UDP, la, pip, &ad);
! if (err == EHDNOF)
! ;
/* If UDP checksum is not zero, then adjust since destination port */
/* is being unaliased and destination address is being altered. */
***************
*** 774,779 ****
--- 774,780 ----
{
struct udphdr *ud;
struct alias_link *lnk;
+ int err;
/* Return if proxy-only mode is enabled */
if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
***************
*** 787,815 ****
if (lnk != NULL) {
u_short alias_port;
struct in_addr alias_address;
alias_address = GetAliasAddress(lnk);
alias_port = GetAliasPort(lnk);
! /* Special processing for IP encoding protocols */
! if (ntohs(ud->uh_dport) == CUSEEME_PORT_NUMBER)
! AliasHandleCUSeeMeOut(la, pip, lnk);
! /* If NETBIOS Datagram, It should be alias address in UDP Data, too */
! else if (ntohs(ud->uh_dport) == NETBIOS_DGM_PORT_NUMBER
! || ntohs(ud->uh_sport) == NETBIOS_DGM_PORT_NUMBER)
! AliasHandleUdpNbt(la, pip, lnk, &alias_address, alias_port);
! else if (ntohs(ud->uh_dport) == NETBIOS_NS_PORT_NUMBER
! || ntohs(ud->uh_sport) == NETBIOS_NS_PORT_NUMBER)
! AliasHandleUdpNbtNS(la, pip, lnk, &pip->ip_src, &ud->uh_sport,
! &alias_address, &alias_port);
! /*
! * We don't know in advance what TID the TFTP server will choose,
! * so we create a wilcard link (destination port is unspecified)
! * that will match any TID from a given destination.
! */
! else if (ntohs(ud->uh_dport) == TFTP_PORT_NUMBER)
! FindRtspOut(la, pip->ip_src, pip->ip_dst,
! ud->uh_sport, alias_port, IPPROTO_UDP);
/* If UDP checksum is not zero, adjust since source port is */
/* being aliased and source address is being altered */
--- 788,810 ----
if (lnk != NULL) {
u_short alias_port;
struct in_addr alias_address;
+ struct alias_data ad = {
+ lnk,
+ NULL, /* original address */
+ &alias_address,
+ &alias_port,
+ &ud->uh_sport,
+ &ud->uh_dport,
+ 0 /* maxpacketsize */
+ };
alias_address = GetAliasAddress(lnk);
alias_port = GetAliasPort(lnk);
! /* walk out chain */
! err = find_handler(OUT, UDP, la, pip, &ad);
! if (err == EHDNOF)
! ;
/* If UDP checksum is not zero, adjust since source port is */
/* being aliased and source address is being altered */
***************
*** 855,869 ****
struct in_addr proxy_address;
u_short alias_port;
u_short proxy_port;
! int accumulate;
! /* Special processing for IP encoding protocols */
! if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
! || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
! AliasHandlePptpIn(la, pip, lnk);
! else if (la->skinnyPort != 0 && (ntohs(tc->th_dport) == la->skinnyPort
! || ntohs(tc->th_sport) == la->skinnyPort))
! AliasHandleSkinny(la, pip, lnk);
alias_address = GetAliasAddress(lnk);
original_address = GetOriginalAddress(lnk);
--- 850,878 ----
struct in_addr proxy_address;
u_short alias_port;
u_short proxy_port;
! int accumulate, err;
! /*
! * XXX - the init of MANY vars is a bit below, but
! * aliashandlepptpin seems to need the destination port
! * that came within the packet and not the original one
! * looks below [*]
! */
!
! struct alias_data ad = {
! lnk,
! NULL, /* original address */
! NULL, /* alias address */
! NULL, /* alias port */
! &tc->th_sport,
! &tc->th_dport,
! 0 /* maxpacketsize */
! };
!
! /* walk out chain */
! err = find_handler(IN, TCP, la, pip, &ad);
! if (err == EHDNOF)
! ;
alias_address = GetAliasAddress(lnk);
original_address = GetOriginalAddress(lnk);
***************
*** 872,877 ****
--- 881,908 ----
tc->th_dport = GetOriginalPort(lnk);
proxy_port = GetProxyPort(lnk);
+ /*
+ * XXX - [*] looks above, if anyone is going to add
+ * find_handler AFTER this aliashandlepptpin/point, please redo
+ * alias_data too.
+ * Uncommenting the piece here below should be enough.
+ */
+
+ /* struct alias_data ad = { */
+ /* lnk, */
+ /* &original_address, */
+ /* &alias_address, */
+ /* &alias_port, */
+ /* &ud->uh_sport, */
+ /* &ud->uh_dport, */
+ /* 0 /\* maxpacketsize *\/ */
+ /* }; */
+
+ /* /\* walk out chain *\/ */
+ /* err = find_handler(la, pip, &ad); */
+ /* if (err == EHDNOF) */
+ /* printf("Protocol handler not found\n"); */
+
/* Adjust TCP checksum since destination port is being unaliased */
/* and destination port is being altered. */
accumulate = alias_port;
***************
*** 926,932 ****
static int
TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
{
! int proxy_type;
u_short dest_port;
u_short proxy_server_port;
struct in_addr dest_address;
--- 957,963 ----
static int
TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
{
! int proxy_type, err;
u_short dest_port;
u_short proxy_server_port;
struct in_addr dest_address;
***************
*** 973,978 ****
--- 1004,1018 ----
u_short alias_port;
struct in_addr alias_address;
int accumulate;
+ struct alias_data ad = {
+ lnk,
+ NULL, /* original address */
+ &alias_address,
+ &alias_port,
+ &tc->th_sport,
+ &tc->th_dport,
+ maxpacketsize
+ };
/* Save original destination address, if this is a proxy packet.
Also modify packet to include destination encoding. This may
***************
*** 989,1013 ****
/* Monitor TCP connection state */
TcpMonitorOut(pip, lnk);
!
! /* Special processing for IP encoding protocols */
! if (ntohs(tc->th_dport) == FTP_CONTROL_PORT_NUMBER
! || ntohs(tc->th_sport) == FTP_CONTROL_PORT_NUMBER)
! AliasHandleFtpOut(la, pip, lnk, maxpacketsize);
! else if (ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_1
! || ntohs(tc->th_dport) == IRC_CONTROL_PORT_NUMBER_2)
! AliasHandleIrcOut(la, pip, lnk, maxpacketsize);
! else if (ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_1
! || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_1
! || ntohs(tc->th_dport) == RTSP_CONTROL_PORT_NUMBER_2
! || ntohs(tc->th_sport) == RTSP_CONTROL_PORT_NUMBER_2)
! AliasHandleRtspOut(la, pip, lnk, maxpacketsize);
! else if (ntohs(tc->th_dport) == PPTP_CONTROL_PORT_NUMBER
! || ntohs(tc->th_sport) == PPTP_CONTROL_PORT_NUMBER)
! AliasHandlePptpOut(la, pip, lnk);
! else if (la->skinnyPort != 0 && (ntohs(tc->th_sport) == la->skinnyPort
! || ntohs(tc->th_dport) == la->skinnyPort))
! AliasHandleSkinny(la, pip, lnk);
/* Adjust TCP checksum since source port is being aliased */
/* and source address is being altered */
--- 1029,1039 ----
/* Monitor TCP connection state */
TcpMonitorOut(pip, lnk);
!
! /* walk out chain */
! err = find_handler(OUT, TCP, la, pip, &ad);
! if (err == EHDNOF)
! ;
/* Adjust TCP checksum since source port is being aliased */
/* and source address is being altered */
***************
*** 1208,1220 ****
case IPPROTO_TCP:
iresult = TcpAliasIn(la, pip);
break;
! case IPPROTO_GRE:
! if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
! AliasHandlePptpGreIn(la, pip) == 0)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasIn(la, pip);
! break;
default:
iresult = ProtoAliasIn(la, pip);
break;
--- 1234,1261 ----
case IPPROTO_TCP:
iresult = TcpAliasIn(la, pip);
break;
! case IPPROTO_GRE: {
! int err;
! struct alias_data ad = {
! NULL,
! NULL,
! NULL,
! NULL,
! NULL,
! NULL,
! 0
! };
!
! /* walk out chain */
! err = find_handler(IN, IP, la, pip, &ad);
! if (err == EHDNOF)
! ;
! if (err == OK)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasIn(la, pip);
! }
! break;
default:
iresult = ProtoAliasIn(la, pip);
break;
***************
*** 1321,1332 ****
case IPPROTO_TCP:
iresult = TcpAliasOut(la, pip, maxpacketsize, create);
break;
! case IPPROTO_GRE:
! if (AliasHandlePptpGreOut(la, pip) == 0)
! iresult = PKT_ALIAS_OK;
! else
! iresult = ProtoAliasOut(la, pip, create);
! break;
default:
iresult = ProtoAliasOut(la, pip, create);
break;
--- 1362,1388 ----
case IPPROTO_TCP:
iresult = TcpAliasOut(la, pip, maxpacketsize, create);
break;
! case IPPROTO_GRE: {
! int err;
! struct alias_data ad = {
! NULL,
! NULL,
! NULL,
! NULL,
! NULL,
! NULL,
! 0
! };
! /* walk out chain */
! err = find_handler(OUT, IP, la, pip, &ad);
! if (err == EHDNOF)
! ;
! if (err == OK)
! iresult = PKT_ALIAS_OK;
! else
! iresult = ProtoAliasOut(la, pip, create);
! }
! break;
default:
iresult = ProtoAliasOut(la, pip, create);
break;
***************
*** 1443,1445 ****
--- 1499,1592 ----
return (iresult);
}
+
+ #ifndef _KERNEL
+
+ int
+ LibAliasRefreshModules(void) {
+ char buf[256], conf[] = "/etc/libalias.conf";
+ FILE *fd;
+ struct dll *t;
+ struct proto_handler *p;
+ int len;
+
+ fd = fopen(conf, "r");
+ if (fd == NULL) {
+ strcpy(buf, "cannot open config file ");
+ strcat(buf, conf);
+ perror(buf);
+ exit(-1);
+ }
+
+ LibAliasUnLoadAllModule();
+
+ while (1) {
+ fgets(buf, 256, fd);
+ if feof(fd) break;
+ len = strlen(buf);
+ if (len > 1) {
+ buf[len - 1] = '\0';
+ printf("Loading %s\n", buf);
+ LibAliasLoadModule(buf);
+ }
+ }
+ return (OK);
+ }
+
+ int
+ LibAliasLoadModule(char *path) {
+ struct dll *t;
+ void *handle;
+ struct proto_handler *m;
+ const char *error;
+ moduledata_t *p;
+
+ handle = dlopen (path, RTLD_LAZY);
+ if (!handle) {
+ fputs (dlerror(), stderr);
+ return (NOK);
+ }
+
+ p = dlsym(handle, "alias_mod");
+ if ((error = dlerror()) != NULL) {
+ fputs(error, stderr);
+ return (NOK);
+ }
+
+ t = malloc(sizeof(struct dll));
+ if (t == NULL)
+ return (ENOMEM);
+ strncpy(t->name, p->name, DLL_LEN);
+ t->handle = handle;
+ if (attach_dll(t) == EHDCON) {
+ free(t);
+ fputs("dll conflict", stderr);
+ return (NOK);
+ }
+
+ m = dlsym(t->handle, "handlers");
+ if ((error = dlerror()) != NULL) {
+ fputs(error, stderr);
+ return (NOK);
+ }
+
+ attach_handlers(m);
+ return (OK);
+ }
+
+ int
+ LibAliasUnLoadAllModule(void) {
+ struct dll *t;
+ struct proto_handler *p;
+
+ /* unload all modules then reload everything */
+ while ((p = first_handler()) != NULL) {
+ detach_handler(p);
+ }
+ while ((t = walk_dll_chain()) != NULL) {
+ dlclose(t->handle);
+ free(t);
+ }
+ }
+
+ #endif
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias.h /home/flag/src/freebsd7/src/sys/netinet/libalias/alias.h
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias.h Thu May 5 23:53:17 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias.h Sun Jun 11 18:57:26 2006
***************
*** 39,51 ****
#ifndef _ALIAS_H_
#define _ALIAS_H_
#ifdef _KERNEL
/*
! * The kernel version of libalias does not support these features.
*/
#define NO_FW_PUNCH
- #define NO_LOGGING
#define NO_USE_SOCKETS
#endif
/*
--- 39,56 ----
#ifndef _ALIAS_H_
#define _ALIAS_H_
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #include <netinet/ip.h>
+
+ #define LIBALIAS_BUF_SIZE 128
#ifdef _KERNEL
/*
! * The kernel version of libalias does not support these features...
*/
#define NO_FW_PUNCH
#define NO_USE_SOCKETS
+
#endif
/*
***************
*** 180,200 ****
/* Transparent proxying routines. */
int LibAliasProxyRule(struct libalias *, const char *_cmd);
/*
* Mode flags and other constants.
*/
-
/* Mode flags, set using PacketAliasSetMode() */
/*
* If PKT_ALIAS_LOG is set, a message will be printed to /var/log/alias.log
* every time a link is created or deleted. This is useful for debugging.
*/
- #ifndef NO_LOGGING
#define PKT_ALIAS_LOG 0x01
- #endif
/*
* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g. to ftp,
--- 185,206 ----
/* Transparent proxying routines. */
int LibAliasProxyRule(struct libalias *, const char *_cmd);
+ /* Module handling API */
+ int LibAliasLoadModule(char *);
+ int LibAliasUnLoadAllModule(void);
+ int LibAliasRefreshModules(void);
/*
* Mode flags and other constants.
*/
/* Mode flags, set using PacketAliasSetMode() */
/*
* If PKT_ALIAS_LOG is set, a message will be printed to /var/log/alias.log
* every time a link is created or deleted. This is useful for debugging.
*/
#define PKT_ALIAS_LOG 0x01
/*
* If PKT_ALIAS_DENY_INCOMING is set, then incoming connections (e.g. to ftp,
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_cuseeme.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_cuseeme.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_cuseeme.c Thu May 5 23:55:17 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_cuseeme.c Sun Jun 11 18:57:26 2006
***************
*** 31,37 ****
--- 31,47 ----
#ifdef _KERNEL
#include <sys/param.h>
+ #include <sys/proc.h>
+ #include <sys/ctype.h>
+ #include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
#else
+ #include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#endif
***************
*** 44,51 ****
--- 54,142 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #define CUSEEME_PORT_NUMBER 7648
+
+ static void
+ AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip,
+ struct alias_link *lnk);
+
+ static void
+ AliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip,
+ struct in_addr original_addr);
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->original_address == NULL)
+ return (NOK);
+ if (ntohs(*ah->dport) == CUSEEME_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleCUSeeMeIn(la, pip, *ah->original_address);
+ return (OK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleCUSeeMeOut(la, pip, ah->lnk);
+ return (OK);
+ }
+
+ /* Kernel module definition. */
+ struct proto_handler handlers[] = {{120, OUT, UDP, &fingerprint, &protohandlerout},
+ {120, IN, UDP, &fingerprint, &protohandlerin}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_cuseeme", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_cuseeme, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_cuseeme, 1);
+ MODULE_DEPEND(alias_cuseeme, libalias, 1, 1, 1);
#endif
/* CU-SeeMe Data Header */
***************
*** 77,82 ****
--- 168,176 ----
* counts etc */
};
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *lnk)
{
***************
*** 100,105 ****
--- 194,202 ----
}
}
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip, struct in_addr original_addr)
{
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_db.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_db.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_db.c Tue Sep 20 00:31:45 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_db.c Sun Jun 11 18:57:27 2006
***************
*** 143,150 ****
--- 143,152 ----
*/
#ifdef _KERNEL
+ #include <machine/stdarg.h>
#include <sys/param.h>
#else
+ #include <stdarg.h>
#include <sys/types.h>
#endif
***************
*** 156,168 ****
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#else
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
- #include <arpa/inet.h>
#endif
/* BSD network include files */
--- 158,171 ----
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/kernel.h>
+ #include <sys/types.h>
#include <sys/malloc.h>
#include <sys/module.h>
+ #include <sys/syslog.h>
#else
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#endif
/* BSD network include files */
***************
*** 171,187 ****
#include <netinet/ip.h>
#include <netinet/tcp.h>
! #ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
#else
#include "alias.h"
#include "alias_local.h"
#endif
static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
-
/*
Constants (note: constants are also defined
near relevant functions or structs)
--- 174,193 ----
#include <netinet/ip.h>
#include <netinet/tcp.h>
! #ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
+ #include <net/if.h>
+ #include <netinet/in_var.h>
#else
#include "alias.h"
#include "alias_local.h"
+ #include "alias_mod.h"
#endif
static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
/*
Constants (note: constants are also defined
near relevant functions or structs)
***************
*** 350,355 ****
--- 356,368 ----
MODULE_VERSION(libalias, 1);
+ /* Use kernel allocator. */
+ #if defined(_SYS_MALLOC_H_)
+ #define malloc(x) malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
+ #define calloc(x, n) malloc(x*n)
+ #define free(x) free(x, M_ALIAS)
+ #endif
+
static int
alias_mod_handler(module_t mod, int type, void *data)
{
***************
*** 358,373 ****
switch (type) {
case MOD_LOAD:
error = 0;
break;
case MOD_QUIESCE:
case MOD_UNLOAD:
! finishoff();
error = 0;
break;
default:
error = EINVAL;
}
-
return (error);
}
--- 371,389 ----
switch (type) {
case MOD_LOAD:
error = 0;
+ handler_chain_init();
break;
+ #if __FreeBSD_version >= 500000
case MOD_QUIESCE:
+ #endif
case MOD_UNLOAD:
! handler_chain_destroy();
! finishoff();
error = 0;
break;
default:
error = EINVAL;
}
return (error);
}
***************
*** 409,420 ****
#endif
- #ifndef NO_LOGGING
/* Log file control */
static void ShowAliasStats(struct libalias *);
! static void InitPacketAliasLog(struct libalias *);
static void UninitPacketAliasLog(struct libalias *);
- #endif
static u_int
StartPointIn(struct in_addr alias_addr,
--- 425,434 ----
#endif
/* Log file control */
static void ShowAliasStats(struct libalias *);
! static int InitPacketAliasLog(struct libalias *);
static void UninitPacketAliasLog(struct libalias *);
static u_int
StartPointIn(struct in_addr alias_addr,
***************
*** 462,498 ****
return (ntohl(y) - ntohl(x));
}
- #ifndef NO_LOGGING
static void
! ShowAliasStats(struct libalias *la)
! {
! /* Used for debugging */
! if (la->monitorFile) {
! fprintf(la->monitorFile,
! "icmp=%d, udp=%d, tcp=%d, pptp=%d, proto=%d, frag_id=%d frag_ptr=%d",
! la->icmpLinkCount,
! la->udpLinkCount,
! la->tcpLinkCount,
! la->pptpLinkCount,
! la->protoLinkCount,
! la->fragmentIdLinkCount,
! la->fragmentPtrLinkCount);
!
! fprintf(la->monitorFile, " / tot=%d (sock=%d)\n",
! la->icmpLinkCount + la->udpLinkCount
! + la->tcpLinkCount
! + la->pptpLinkCount
! + la->protoLinkCount
! + la->fragmentIdLinkCount
! + la->fragmentPtrLinkCount,
! la->sockCount);
! fflush(la->monitorFile);
}
}
- #endif
/* Internal routines for finding, deleting and adding links
--- 476,528 ----
return (ntohl(y) - ntohl(x));
}
+ #ifdef _KERNEL
static void
! AliasLog(char * str, const char * format, ...) {
! va_list ap;
!
! va_start(ap, format);
! vsnprintf(str, LIBALIAS_BUF_SIZE, format, ap);
! log(LOG_SECURITY | LOG_INFO, "%s\n", str);
! va_end(ap);
! }
! #else
! static void
! AliasLog(FILE * stream, const char * format, ...) {
! va_list ap;
!
! va_start(ap, format);
! vfprintf(stream, format, ap);
! va_end(ap);
! fflush(stream);
! }
! #endif
! static void
! ShowAliasStats(struct libalias *la) {
! /* Used for debugging */
! if (la->logDesc) {
! int tot = la->icmpLinkCount + la->udpLinkCount +
! la->tcpLinkCount + la->pptpLinkCount +
! la->protoLinkCount + la->fragmentIdLinkCount +
! la->fragmentPtrLinkCount;
!
! AliasLog(la->logDesc,
! "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
! la->icmpLinkCount,
! la->udpLinkCount,
! la->tcpLinkCount,
! la->pptpLinkCount,
! la->protoLinkCount,
! la->fragmentIdLinkCount,
! la->fragmentPtrLinkCount, tot);
! #ifndef _KERNEL
! AliasLog(la->logDesc, " (sock=%u)\n", la->sockCount);
! #endif
}
}
/* Internal routines for finding, deleting and adding links
***************
*** 929,940 ****
/* Free memory */
free(lnk);
- #ifndef NO_LOGGING
/* Write statistics, if logging enabled */
if (la->packetAliasMode & PKT_ALIAS_LOG) {
ShowAliasStats(la);
}
- #endif
}
--- 959,968 ----
***************
*** 1013,1019 ****
switch (link_type) {
struct tcp_dat *aux_tcp;
! case LINK_ICMP:
la->icmpLinkCount++;
break;
case LINK_UDP:
--- 1041,1047 ----
switch (link_type) {
struct tcp_dat *aux_tcp;
! case LINK_ICMP:
la->icmpLinkCount++;
break;
case LINK_UDP:
***************
*** 1072,1082 ****
fprintf(stderr, "malloc() call failed.\n");
#endif
}
- #ifndef NO_LOGGING
if (la->packetAliasMode & PKT_ALIAS_LOG) {
ShowAliasStats(la);
}
- #endif
return (lnk);
}
--- 1100,1108 ----
***************
*** 2203,2232 ****
}
}
- #ifndef NO_LOGGING
/* Init the log file and enable logging */
! static void
InitPacketAliasLog(struct libalias *la)
{
! if ((~la->packetAliasMode & PKT_ALIAS_LOG)
! && (la->monitorFile = fopen("/var/log/alias.log", "w"))) {
la->packetAliasMode |= PKT_ALIAS_LOG;
- fprintf(la->monitorFile,
- "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
}
}
/* Close the log-file and disable logging. */
static void
UninitPacketAliasLog(struct libalias *la)
{
! if (la->monitorFile) {
! fclose(la->monitorFile);
! la->monitorFile = NULL;
! }
la->packetAliasMode &= ~PKT_ALIAS_LOG;
}
- #endif
/* Outside world interfaces
--- 2229,2267 ----
}
}
/* Init the log file and enable logging */
! static int
InitPacketAliasLog(struct libalias *la)
{
! if (~la->packetAliasMode & PKT_ALIAS_LOG) {
! #ifdef _KERNEL
! if ((la->logDesc = malloc(LIBALIAS_BUF_SIZE)))
! ;
! #else
! if ((la->logDesc = fopen("/var/log/alias.log", "w")))
! fprintf(la->logDesc, "PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
! #endif
! else
! return(ENOMEM); /* log initialization failed */
la->packetAliasMode |= PKT_ALIAS_LOG;
}
+ return(1);
}
/* Close the log-file and disable logging. */
static void
UninitPacketAliasLog(struct libalias *la)
{
! if (la->logDesc) {
! #ifdef _KERNEL
! free(la->logDesc);
! #else
! fclose(la->logDesc);
! #endif
! la->logDesc = NULL;
! }
la->packetAliasMode &= ~PKT_ALIAS_LOG;
}
/* Outside world interfaces
***************
*** 2498,2510 ****
la->deleteAllLinks = 1;
CleanupAliasData(la);
la->deleteAllLinks = 0;
- #ifndef NO_LOGGING
UninitPacketAliasLog(la);
- #endif
#ifndef NO_FW_PUNCH
UninitPunchFW(la);
#endif
! LIST_REMOVE(la, instancelist);
free(la);
}
--- 2533,2543 ----
la->deleteAllLinks = 1;
CleanupAliasData(la);
la->deleteAllLinks = 0;
UninitPacketAliasLog(la);
#ifndef NO_FW_PUNCH
UninitPunchFW(la);
#endif
! LIST_REMOVE(la, instancelist);
free(la);
}
***************
*** 2517,2532 ****
* do a probe for flag values) */
)
{
- #ifndef NO_LOGGING
/* Enable logging? */
if (flags & mask & PKT_ALIAS_LOG) {
! InitPacketAliasLog(la); /* Do the enable */
} else
/* _Disable_ logging? */
if (~flags & mask & PKT_ALIAS_LOG) {
UninitPacketAliasLog(la);
}
- #endif
#ifndef NO_FW_PUNCH
/* Start punching holes in the firewall? */
if (flags & mask & PKT_ALIAS_PUNCH_FW) {
--- 2550,2565 ----
* do a probe for flag values) */
)
{
/* Enable logging? */
if (flags & mask & PKT_ALIAS_LOG) {
! /* Do the enable */
! if (InitPacketAliasLog(la) == ENOMEM)
! return(-1);
} else
/* _Disable_ logging? */
if (~flags & mask & PKT_ALIAS_LOG) {
UninitPacketAliasLog(la);
}
#ifndef NO_FW_PUNCH
/* Start punching holes in the firewall? */
if (flags & mask & PKT_ALIAS_PUNCH_FW) {
***************
*** 2560,2566 ****
--- 2593,2604 ----
/* Firewall include files */
#include <net/if.h>
+
+ #if __FreeBSD__ < 5
+ #include <netinet/ip_fw2.h>
+ #else
#include <netinet/ip_fw.h>
+ #endif
#include <string.h>
#include <err.h>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_dummy.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_dummy.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_dummy.c Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_dummy.c Sun Jun 11 18:57:27 2006
***************
*** 0 ****
--- 1,160 ----
+ /*-
+ * Copyright (c) 2005 Paolo Pisati <piso at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #include <sys/cdefs.h>
+
+ /*
+ * Alias_dummy is just an empty skeleton used to demostrate how to write
+ * a module for libalias, that will run unalterated in userland or in
+ * kernel land
+ */
+
+ /* Includes */
+ #ifdef _KERNEL
+ #include <sys/param.h>
+ #include <sys/ctype.h>
+ #include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
+ #else
+ #include <errno.h>
+ #include <sys/types.h>
+ #include <ctype.h>
+ #include <stdio.h>
+ #include <string.h>
+ #endif
+
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+
+ #ifdef _KERNEL
+ #include <netinet/libalias/alias.h>
+ #include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
+ #else
+ #include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ static void
+ AliasHandleDummy(struct libalias *la, struct ip *ip, struct alias_data *ah);
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ /*
+ * check here all the data that will be used later, if any field
+ * is empy/NULL, return a NOK value
+ */
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->maxpacketsize == 0)
+ return (NOK);
+ /*
+ * fingerprint the incoming packet, if it matches any conditions
+ * return an OK value
+ */
+ if (ntohs(*ah->dport) == 123
+ || ntohs(*ah->sport) == 456)
+ return (OK); /* i know how to handle it... */
+ return (NOK); /* i don't know this packet... */
+ }
+
+ /*
+ * Wrap in this general purpose function, the real function used to alias the
+ * packets
+ */
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleDummy(la, pip, ah);
+ return (OK);
+ }
+
+ /*
+ * NOTA BENE: these 2 variables MUST NOT be renamed in any case if you want
+ * your module to work in userland, cause they are used to find and use all
+ * the protocol handlers present in every module.
+ * So WATCH OUT, your module needs these 2 variables, and it needs them with
+ * THEIR EXACT NAMES: handlers and entries.
+ */
+
+ struct proto_handler handlers [] = {{666, IN|OUT, UDP|TCP, &fingerprint,
+ &protohandler}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_dummy", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_dummy, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_dummy, 1);
+ MODULE_DEPEND(alias_dummy, libalias, 1, 1, 1);
+ #endif
+
+ #ifdef _KERNEL
+ static
+ #endif
+ void
+ AliasHandleDummy(struct libalias *la, struct ip *ip, struct alias_data *ah) {
+ ; /* dummy */
+ }
+
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_ftp.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_ftp.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_ftp.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_ftp.c Sun Jun 11 18:57:27 2006
***************
*** 73,79 ****
--- 73,86 ----
#include <sys/param.h>
#include <sys/ctype.h>
#include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
#else
+ #include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
***************
*** 88,95 ****
--- 95,171 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #define FTP_CONTROL_PORT_NUMBER 21
+
+ static void
+ AliasHandleFtpOut(struct libalias *, struct ip *, struct alias_link *,
+ int maxpacketsize);
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->maxpacketsize == 0)
+ return (NOK);
+ if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER
+ || ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpacketsize);
+ return (OK);
+ }
+
+ struct proto_handler handlers[] = {{80, OUT, TCP, &fingerprint,
+ &protohandler}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_ftp", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_ftp, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_ftp, 1);
+ MODULE_DEPEND(alias_ftp, libalias, 1, 1, 1);
#endif
#define FTP_CONTROL_PORT_NUMBER 21
***************
*** 112,117 ****
--- 188,196 ----
static int ParseFtp229Reply(struct libalias *la, char *, int);
static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleFtpOut(
struct libalias *la,
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_irc.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_irc.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_irc.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_irc.c Sun Jun 11 18:57:27 2006
***************
*** 52,59 ****
--- 52,70 ----
#include <sys/param.h>
#include <sys/libkern.h>
#include <sys/ctype.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
+ #if __FreeBSD_version < 500000
+ #include <machine/limits.h>
+ #else
#include <sys/limits.h>
+ #endif
#else
+ #include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
***************
*** 69,82 ****
--- 80,165 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
#endif
+ #define IRC_CONTROL_PORT_NUMBER_1 6667
+ #define IRC_CONTROL_PORT_NUMBER_2 6668
+
/* Local defines */
#define DBprintf(a)
+ static void
+ AliasHandleIrcOut(struct libalias *, struct ip *, struct alias_link *,
+ int maxpacketsize);
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->dport == NULL || ah->lnk == NULL ||
+ ah->maxpacketsize == 0)
+ return (NOK);
+ if (ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_1
+ || ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_2)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleIrcOut(la, pip, ah->lnk, ah->maxpacketsize);
+ return (OK);
+ }
+ struct proto_handler handlers[] = {{90, OUT, TCP, &fingerprint,
+ &protohandler}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data) {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_irc", mod_handler, NULL
+ };
+
+ /* Kernel module definition. */
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_irc, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_irc, 1);
+ MODULE_DEPEND(alias_irc, libalias, 1, 1, 1);
+ #endif
+
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleIrcOut(struct libalias *la,
struct ip *pip, /* IP packet to examine */
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_local.h /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_local.h
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_local.h Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_local.h Sun Jun 11 18:57:27 2006
***************
*** 47,59 ****
#define _ALIAS_LOCAL_H_
#include <sys/queue.h>
! /* Use kernel allocator. */
! #if defined(_KERNEL) && defined(_SYS_MALLOC_H_)
! MALLOC_DECLARE(M_ALIAS);
! #define malloc(x) malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
! #define calloc(x, n) malloc(x*n)
! #define free(x) free(x, M_ALIAS)
#endif
/* XXX: LibAliasSetTarget() uses this constant. */
--- 47,66 ----
#define _ALIAS_LOCAL_H_
#include <sys/queue.h>
+ #include <sys/types.h>
+ #include <sys/sysctl.h>
! #ifdef _KERNEL
! #if __FreeBSD_version >= 500000
! #include <sys/param.h>
! #include <sys/lock.h>
! #include <sys/mutex.h>
! #include <sys/proc.h>
! #include <sys/condvar.h>
! #else
! #include <sys/types.h>
! #include <sys/systm.h>
! #endif
#endif
/* XXX: LibAliasSetTarget() uses this constant. */
***************
*** 116,125 ****
int deleteAllLinks; /* If equal to zero, DeleteLink() */
/* will not remove permanent links */
! #ifndef NO_LOGGING
! FILE *monitorFile; /* File descriptor for link */
#endif
! /* statistics monitoring file */
int newDefaultLink; /* Indicates if a new aliasing */
/* link has been created after a */
--- 123,136 ----
int deleteAllLinks; /* If equal to zero, DeleteLink() */
/* will not remove permanent links */
!
! /* log descriptor */
! #ifdef _KERNEL
! char *logDesc;
! #else
! FILE *logDesc;
#endif
! /* statistics monitoring */
int newDefaultLink; /* Indicates if a new aliasing */
/* link has been created after a */
***************
*** 296,338 ****
/* Tcp specfic routines */
/* lint -save -library Suppress flexelint warnings */
- /* FTP routines */
- void
- AliasHandleFtpOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
- int _maxpacketsize);
-
- /* IRC routines */
- void
- AliasHandleIrcOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
- int _maxsize);
-
- /* RTSP routines */
- void
- AliasHandleRtspOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
- int _maxpacketsize);
-
- /* PPTP routines */
- void AliasHandlePptpOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
- void AliasHandlePptpIn(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
- int AliasHandlePptpGreOut(struct libalias *la, struct ip *_pip);
- int AliasHandlePptpGreIn(struct libalias *la, struct ip *_pip);
-
- /* NetBIOS routines */
- int
- AliasHandleUdpNbt(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
- struct in_addr *_alias_address, u_short _alias_port);
- int
- AliasHandleUdpNbtNS(struct libalias *la, struct ip *_pip, struct alias_link *_lnk,
- struct in_addr *_alias_address, u_short * _alias_port,
- struct in_addr *_original_address, u_short * _original_port);
-
- /* CUSeeMe routines */
- void AliasHandleCUSeeMeOut(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
- void AliasHandleCUSeeMeIn(struct libalias *la, struct ip *_pip, struct in_addr _original_addr);
-
- /* Skinny routines */
- void AliasHandleSkinny(struct libalias *la, struct ip *_pip, struct alias_link *_lnk);
-
/* Transparent proxy routines */
int
ProxyCheck(struct libalias *la, struct ip *_pip, struct in_addr *_proxy_server_addr,
--- 307,312 ----
***************
*** 372,378 ****
return ((void *)(udphdr + 1));
}
#endif
-
- /*lint -restore */
#endif /* !_ALIAS_LOCAL_H_ */
--- 346,350 ----
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_mod.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_mod.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_mod.c Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_mod.c Sun Jun 11 18:57:27 2006
***************
*** 0 ****
--- 1,388 ----
+ /*-
+ * Copyright (c) 2005 Paolo Pisati <piso at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+ #ifdef _KERNEL
+ #include <sys/param.h>
+ #include <sys/proc.h>
+ #else
+ #include <stdio.h>
+ #include <string.h>
+ #include <sys/types.h>
+ #endif
+
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #include <netinet/ip.h>
+ #include <netinet/ip_icmp.h>
+ #include <netinet/tcp.h>
+ #include <netinet/udp.h>
+
+ #include <sys/queue.h>
+ #include <sys/types.h>
+ #include <sys/sysctl.h>
+
+ #ifdef _KERNEL
+ #include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
+ #else
+ #include "alias.h"
+ #include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #include <sys/types.h>
+
+ #if __FreeBSD_version >= 500000
+ /* XXX - make the compiler happy... */
+ int strncmp(const char *s1, const char *s2, size_t len);
+ #endif
+
+ /* protocol and userland module handlers chains */
+ struct chain handler_chain, dll_chain;
+
+ #ifdef _KERNEL
+
+ #if __FreeBSD_version >= 500000
+
+ /* Fine grained locking for 5.x, 6.x and 7.x */
+
+ #define LIBALIAS_LOCK_INIT(_chain) \
+ mtx_init(&(_chain)->mtx, "libalias list of proto-handlers", NULL, \
+ MTX_DEF | MTX_RECURSE)
+ #define LIBALIAS_LOCK_DESTROY(_chain) mtx_destroy(&(_chain)->mtx)
+ #define LIBALIAS_WLOCK_ASSERT(_chain) do { \
+ mtx_assert(&(_chain)->mtx, MA_OWNED); \
+ NET_ASSERT_GIANT(); \
+ } while (0)
+
+ static __inline void
+ LIBALIAS_RLOCK(struct chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->busy_count++;
+ mtx_unlock(&chain->mtx);
+ }
+
+ static __inline void
+ LIBALIAS_RUNLOCK(struct chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->busy_count--;
+ if (chain->busy_count == 0 && chain->want_write)
+ cv_signal(&chain->cv);
+ mtx_unlock(&chain->mtx);
+ }
+
+ static __inline void
+ LIBALIAS_WLOCK(struct chain *chain)
+ {
+ mtx_lock(&chain->mtx);
+ chain->want_write++;
+ while (chain->busy_count > 0)
+ cv_wait(&chain->cv, &chain->mtx);
+ }
+
+ static __inline void
+ LIBALIAS_WUNLOCK(struct chain *chain)
+ {
+ chain->want_write--;
+ cv_signal(&chain->cv);
+ mtx_unlock(&chain->mtx);
+ }
+
+ static void
+ _handler_chain_init(struct chain *c) {
+
+ if (!mtx_initialized(&c->mtx))
+ LIBALIAS_LOCK_INIT(c);
+ }
+
+ static void
+ _handler_chain_destroy(struct chain *c) {
+
+ if (mtx_initialized(&c->mtx))
+ LIBALIAS_LOCK_DESTROY(c);
+ }
+ #else
+
+ /* Good old spl*() locking for 4.x */
+ /*
+ * XXX - i'm not sure about mutex & conditional var
+ * conversion that i did using spl*()...
+ */
+
+ #define LIBALIAS_LOCK_INIT(_chain) (_chain)->spl = 0
+ #define LIBALIAS_LOCK_DESTROY(_chain)
+ #define LIBALIAS_WLOCK_ASSERT(_chain) do { \
+ KASSERT(_chain->spl != 0, ("chain not locked")); \
+ } while (0)
+
+ static __inline void
+ LIBALIAS_RLOCK(struct chain *chain)
+ {
+ chain->spl = splimp();
+ }
+
+ static __inline void
+ LIBALIAS_RUNLOCK(struct chain *chain)
+ {
+ splx(chain->spl);
+ }
+
+ static __inline void
+ LIBALIAS_WLOCK(struct chain *chain)
+ {
+ LIBALIAS_RLOCK(chain);
+ }
+
+ static __inline void
+ LIBALIAS_WUNLOCK(struct chain *chain)
+ {
+ LIBALIAS_RUNLOCK(chain);
+ }
+
+ static void
+ _handler_chain_init(struct chain *c) {
+
+ c->spl = 0;
+ }
+
+ static void
+ _handler_chain_destroy(struct chain *c) {
+
+ ;
+ }
+
+ #endif
+ #else
+
+ #define LIBALIAS_LOCK_INIT(_chain) ;
+ #define LIBALIAS_LOCK_DESTROY(_chain) ;
+ #define LIBALIAS_WLOCK_ASSERT(_chain) ;
+
+ static __inline void
+ LIBALIAS_RLOCK(struct chain *chain __unused)
+ {
+ ;
+ }
+
+ static __inline void
+ LIBALIAS_RUNLOCK(struct chain *chain __unused)
+ {
+ ;
+ }
+
+ static __inline void
+ LIBALIAS_WLOCK(struct chain *chain __unused)
+ {
+ ;
+ }
+
+ static __inline void
+ LIBALIAS_WUNLOCK(struct chain *chain __unused)
+ {
+ ;
+ }
+
+ static void
+ _handler_chain_init(struct chain *c __unused) {
+ ;
+ }
+
+ static void
+ _handler_chain_destroy(struct chain *c __unused) {
+ ;
+ }
+
+ #endif
+
+ void
+ handler_chain_init(void) {
+ _handler_chain_init(&handler_chain);
+ }
+
+ void
+ handler_chain_destroy(void) {
+ _handler_chain_destroy(&handler_chain);
+ }
+
+ static int
+ _attach_handler(struct chain *c, struct proto_handler *p) {
+ struct proto_handler **b;
+ int i = 0;
+
+ LIBALIAS_WLOCK_ASSERT(c);
+ b = (struct proto_handler **)&c->chain;
+ p->next = NULL; /* i'm paranoid... */
+ for(; *b != NULL; b = &((*b)->next), i++) {
+ if (((*b)->pri == p->pri) && ((*b)->dir == p->dir) &&
+ ((*b)->proto == p->proto))
+ return (EHDCON); /* priority conflict */
+ if ((*b)->pri > p->pri) {
+ p->next = *b; break;
+ }
+ }
+ /* end of list or got right position, insert here */
+ *b = p;
+ return (OK);
+ }
+
+ static int
+ _detach_handler(struct chain *c, struct proto_handler *p) {
+ struct proto_handler **b;
+
+ LIBALIAS_WLOCK_ASSERT(c);
+ b = (struct proto_handler **)&c->chain;
+ for(; (*b != NULL) && (*b != p); b = &((*b)->next))
+ ;
+ if (*b == p) *b = p->next;
+ else return (EHDNOF); /* handler not found */
+ return (OK);
+ }
+
+ int
+ attach_handlers(struct proto_handler *_p) {
+ int i, res = NOK;
+
+ LIBALIAS_WLOCK(&handler_chain);
+ for (i=0; 1; i++) {
+ if (*((int *)&_p[i]) == EOH) break;
+ res = _attach_handler(&handler_chain, &_p[i]);
+ if (res != OK) break;
+ }
+ LIBALIAS_WUNLOCK(&handler_chain);
+ return (res);
+ }
+
+ int
+ detach_handlers(struct proto_handler *_p) {
+ int i, res = NOK;
+
+ LIBALIAS_WLOCK(&handler_chain);
+ for (i=0; 1; i++) {
+ if (*((int *)&_p[i]) == EOH) break;
+ res = _detach_handler(&handler_chain, &_p[i]);
+ if (res != OK) break;
+ }
+ LIBALIAS_WUNLOCK(&handler_chain);
+ return (res);
+ }
+
+ int
+ detach_handler(struct proto_handler *_p) {
+ int res = NOK;
+
+ LIBALIAS_WLOCK(&handler_chain);
+ res = _detach_handler(&handler_chain, _p);
+ LIBALIAS_WUNLOCK(&handler_chain);
+ return (res);
+ }
+
+ int
+ find_handler(int8_t dir, int8_t proto, struct libalias *la, struct ip *pip, struct alias_data *ad) {
+ struct proto_handler *p;
+ int err;
+
+ LIBALIAS_RLOCK(&handler_chain);
+ for (p = handler_chain.chain, err = EHDNOF; p != NULL; p = p->next)
+ if ((p->dir & dir) && (p->proto & proto))
+ if (p->fingerprint(la, pip, ad) == OK) {
+ err = p->protohandler(la, pip, ad);
+ break;
+ }
+ LIBALIAS_RUNLOCK(&handler_chain);
+ return (err);
+ }
+
+ struct proto_handler *
+ first_handler(void) {
+
+ return (handler_chain.chain);
+ }
+
+ static int
+ _attach_dll(struct chain *c, struct dll *p) {
+ struct dll **b;
+ int i = 0;
+
+ LIBALIAS_WLOCK_ASSERT(c);
+ b = (struct dll **)&c->chain;
+ p->next = NULL; /* i'm paranoid... */
+ for(; *b != NULL; b = &((*b)->next), i++)
+ if (!strncmp((*b)->name, p->name, DLL_LEN))
+ return (EHDCON); /* dll name conflict */
+ /* end of list, insert here */
+ *b = p;
+ return (OK);
+ }
+
+ static void *
+ _detach_dll(struct chain *c, char *p) {
+ struct dll **b;
+ void *err = NULL;
+
+ LIBALIAS_WLOCK_ASSERT(c);
+ b = (struct dll **)&c->chain;
+ for(; *b != NULL; b = &((*b)->next))
+ if (!strncmp((*b)->name, p, DLL_LEN)) {
+ err = *b;
+ *b = (*b)->next;
+ break;
+ }
+ return (err);
+ }
+
+ int
+ attach_dll(struct dll *p) {
+ int i;
+
+ LIBALIAS_WLOCK(&dll_chain);
+ i = _attach_dll(&dll_chain, p);
+ LIBALIAS_WUNLOCK(&dll_chain);
+ return (i);
+ }
+
+ void *
+ detach_dll(char *p) {
+ void *i;
+
+ LIBALIAS_WLOCK(&dll_chain);
+ i = _detach_dll(&dll_chain, p);
+ LIBALIAS_WUNLOCK(&dll_chain);
+ return (i);
+ }
+
+ struct dll *
+ walk_dll_chain(void) {
+ struct dll *t, **b = (struct dll **)&dll_chain.chain;
+
+ for(t = *b; *b != NULL;) {
+ *b = (*b)->next;
+ break;
+ }
+ return (t);
+ }
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_mod.h /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_mod.h
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_mod.h Thu Jan 1 01:00:00 1970
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_mod.h Sun Jun 11 18:57:27 2006
***************
*** 0 ****
--- 1,183 ----
+ /*-
+ * Copyright (c) 2005 Paolo Pisati <piso at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ /*-
+ * Alias_mod.h defines the outside world interfaces for the packet aliasing
+ * modular framework
+ */
+
+ #ifndef _ALIAS_MOD_H_
+ #define _ALIAS_MOD_H_
+
+ /* protocol handlers struct & function*/
+
+ /* packet flow direction */
+ #define IN 1
+ #define OUT 2
+
+ /* working protocol */
+ #define IP 1
+ #define TCP 2
+ #define UDP 4
+ #define ICMP 8
+
+ /*
+ * Data passed to protocol handler module, it must be filled
+ * right before calling find_handler() to determine which
+ * module is elegible to be called
+ */
+
+ struct alias_data {
+
+ struct alias_link *lnk;
+ struct in_addr *original_address;
+ struct in_addr *alias_address;
+ u_short *alias_port;
+ u_int16_t *sport, *dport;
+ int maxpacketsize;
+ };
+
+ /*
+ * This structure contains all the information necessary to make
+ * a protocol handler correctly work.
+ */
+
+ struct proto_handler {
+
+ u_int pri; /* handler priority */
+ int16_t dir; /* flow direction */
+ int16_t proto; /* working protocol */
+ int (*fingerprint)(struct libalias *la, /* fingerprint * function */
+ struct ip *pip, struct alias_data *ah);
+ int (*protohandler)(struct libalias *la, /* aliasing * function */
+ struct ip *pip, struct alias_data *ah);
+ struct proto_handler *next;
+ };
+
+ #if __FreeBSD_version >= 500000
+ struct chain {
+
+ void *chain;
+ struct mtx mtx; /* lock guarding list */
+ int busy_count; /* busy count for rw locks */
+ int want_write;
+ struct cv cv;
+ };
+ #else
+ struct chain {
+
+ void *chain;
+ int spl;
+ };
+ #endif
+
+ /*
+ * Used only in userland when libalias needs to keep track of all
+ * module loaded. In kernel land (kld mode) we don't need to care
+ * care about libalias modules cause it's kld to do it for us
+ */
+
+ #define DLL_LEN 32
+ struct dll {
+
+ char name[DLL_LEN]; /* name of module */
+ void *handle; /*
+ * ptr to shared obj obtained through
+ * dlopen() - use this ptr to get access
+ * to any symbols from a loaded module
+ * via dlsym()
+ */
+ struct dll *next;
+ };
+
+ /* functions used with protocol handlers */
+
+ void handler_chain_init(void);
+ void handler_chain_destroy(void);
+ int attach_handlers(struct proto_handler *);
+ int detach_handlers(struct proto_handler *);
+ int detach_handler(struct proto_handler *);
+ int find_handler(int8_t, int8_t, struct libalias *,
+ struct ip *, struct alias_data *);
+ struct proto_handler *first_handler(void);
+
+ /* functions used with dll module */
+
+ void dll_chain_init(void);
+ void dll_chain_destroy(void);
+ int attach_dll(struct dll *);
+ void *detach_dll(char *);
+ struct dll *walk_dll_chain(void);
+
+ /* general condition of success & failure */
+ #define OK 1
+ #define NOK -1
+
+ /* end of handlers */
+ #define EOH -1
+
+ /*
+ * handler/dll conflict - tried to attach a protocol handleror a dll,
+ * but found another one with same priority, direction and working
+ * protocol(proto handler) or name (dll) already in chain
+ */
+
+ #define EHDCON 2
+
+ /*
+ * handler/dll not found - tried to detach/search a protocol module
+ * handler or a dll not present in chain
+ */
+
+ #define EHDNOF 3
+
+ /*
+ * Some defines borrowed from sys/module.h used to compile a kld
+ * in userland as a shared lib
+ */
+
+ #ifndef _KERNEL
+ typedef enum modeventtype {
+ MOD_LOAD,
+ MOD_UNLOAD,
+ MOD_SHUTDOWN,
+ MOD_QUIESCE
+ } modeventtype_t;
+
+ typedef struct module *module_t;
+ typedef int (*modeventhand_t)(module_t, int /* modeventtype_t */, void *);
+
+ /*
+ * Struct for registering modules statically via SYSINIT.
+ */
+ typedef struct moduledata {
+ const char *name; /* module name */
+ modeventhand_t evhand; /* event handler */
+ void *priv; /* extra data */
+ } moduledata_t;
+ #endif
+
+ #endif /* !_ALIAS_MOD_H_ */
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_nbt.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_nbt.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_nbt.c Fri May 6 13:07:49 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_nbt.c Sun Jun 11 18:57:27 2006
***************
*** 45,56 ****
#include <sys/param.h>
#include <sys/ctype.h>
#include <sys/libkern.h>
#else
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
- #include <arpa/inet.h>
#endif
#include <netinet/in_systm.h>
--- 45,62 ----
#include <sys/param.h>
#include <sys/ctype.h>
#include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
#else
+ #include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#endif
#include <netinet/in_systm.h>
***************
*** 62,69 ****
--- 68,175 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #define NETBIOS_NS_PORT_NUMBER 137
+ #define NETBIOS_DGM_PORT_NUMBER 138
+
+ static int
+ AliasHandleUdpNbt(struct libalias *, struct ip *, struct alias_link *,
+ struct in_addr *, u_short);
+
+ static int
+ AliasHandleUdpNbtNS(struct libalias *, struct ip *, struct alias_link *,
+ struct in_addr *, u_short *, struct in_addr *, u_short *);
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint1(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->alias_address == NULL || ah->alias_port == NULL)
+ return (NOK);
+ if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER
+ || ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleUdpNbt(la, pip, ah->lnk, ah->alias_address, *ah->alias_port);
+ return (OK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->alias_address == NULL || ah->alias_port == NULL)
+ return (NOK);
+ if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER
+ || ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler2(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
+ ah->alias_address, ah->alias_port);
+ return (OK);
+ }
+
+ /* Kernel module definition. */
+ struct proto_handler handlers[] = {{130, IN|OUT, UDP, &fingerprint1, &protohandler1},
+ {140, IN|OUT, UDP, &fingerprint2, &protohandler2}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_nbt", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_nbt, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_nbt, 1);
+ MODULE_DEPEND(alias_nbt, libalias, 1, 1, 1);
#endif
typedef struct {
***************
*** 212,217 ****
--- 318,326 ----
#define DGM_POSITIVE_RES 0x15
#define DGM_NEGATIVE_RES 0x16
+ #ifdef _KERNEL
+ static
+ #endif
int
AliasHandleUdpNbt(
struct libalias *la,
***************
*** 640,645 ****
--- 749,757 ----
return ((u_char *) q);
}
+ #ifdef _KERNEL
+ static
+ #endif
int
AliasHandleUdpNbtNS(
struct libalias *la,
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_old.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_old.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_old.c Thu May 5 21:27:32 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_old.c Sun Jun 11 18:57:27 2006
***************
*** 29,34 ****
--- 29,35 ----
#ifdef _KERNEL
#include <sys/param.h>
+ #include <sys/proc.h>
#else
#include <sys/types.h>
#include <stdlib.h>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_pptp.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_pptp.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_pptp.c Thu May 5 23:55:17 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_pptp.c Sun Jun 11 18:57:27 2006
***************
*** 39,44 ****
--- 39,206 ----
#include <sys/cdefs.h>
__FBSDID("$FreeBSD: src/sys/netinet/libalias/alias_pptp.c,v 1.14 2005/05/05 21:55:17 glebius Exp $");
+ /* Includes */
+ #ifdef _KERNEL
+ #if __FreeBSD__ >= 5
+ #include <sys/limits.h>
+ #else
+ #include <machine/limits.h>
+ #endif
+ #include <sys/param.h>
+ #include <sys/proc.h>
+ #include <sys/ctype.h>
+ #include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
+ #else
+ #include <errno.h>
+ #include <limits.h>
+ #include <sys/types.h>
+ #include <stdio.h>
+ #endif
+
+ #include <netinet/in_systm.h>
+ #include <netinet/in.h>
+ #include <netinet/ip.h>
+ #include <netinet/tcp.h>
+
+ #ifdef _KERNEL
+ #include <netinet/libalias/alias.h>
+ #include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
+ #else
+ #include "alias.h"
+ #include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #define PPTP_CONTROL_PORT_NUMBER 1723
+
+ static void
+ AliasHandlePptpOut(struct libalias *, struct ip *, struct alias_link *);
+
+ static void
+ AliasHandlePptpIn(struct libalias *, struct ip *, struct alias_link *);
+
+ static int
+ AliasHandlePptpGreOut(struct libalias *, struct ip *);
+
+ static int
+ AliasHandlePptpGreIn(struct libalias *, struct ip *);
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
+ return (NOK);
+ if (ntohs(*ah->dport) == PPTP_CONTROL_PORT_NUMBER
+ || ntohs(*ah->sport) == PPTP_CONTROL_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprintgre(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ return (OK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandlePptpIn(la, pip, ah->lnk);
+ return (OK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandlePptpOut(la, pip, ah->lnk);
+ return (OK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlergrein(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
+ AliasHandlePptpGreIn(la, pip) == 0)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandlergreout(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (AliasHandlePptpGreOut(la, pip) == 0)
+ return (OK);
+ return (NOK);
+ }
+
+ /* Kernel module definition. */
+ struct proto_handler handlers[] = {{200, IN, TCP, &fingerprint, &protohandlerin},
+ {210, OUT, TCP, &fingerprint, &protohandlerout},
+ /*
+ * WATCH OUT!!! these 2 handlers NEED a priority of INT_MAX (highest possible)
+ * cause they will ALWAYS process packets, so they must be the last one
+ * in chain: look fingerprintgre() above.
+ */
+ {INT_MAX, IN, IP, &fingerprintgre, &protohandlergrein},
+ {INT_MAX, OUT, IP, &fingerprintgre, &protohandlergreout}, {EOH}};
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_pptp", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_pptp, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_pptp, 1);
+ MODULE_DEPEND(alias_pptp, libalias, 1, 1, 1);
+ #endif
+
/*
Alias_pptp.c performs special processing for PPTP sessions under TCP.
Specifically, watch PPTP control messages and alias the Call ID or the
***************
*** 65,90 ****
*/
- /* Includes */
- #ifdef _KERNEL
- #include <sys/param.h>
- #else
- #include <sys/types.h>
- #include <stdio.h>
- #endif
-
- #include <netinet/in_systm.h>
- #include <netinet/in.h>
- #include <netinet/ip.h>
- #include <netinet/tcp.h>
-
- #ifdef _KERNEL
- #include <netinet/libalias/alias.h>
- #include <netinet/libalias/alias_local.h>
- #else
- #include "alias_local.h"
- #endif
-
/*
* PPTP definitions
*/
--- 227,232 ----
***************
*** 153,158 ****
--- 295,303 ----
static PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *);
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandlePptpOut(struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */
***************
*** 225,230 ****
--- 370,378 ----
}
}
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandlePptpIn(struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */
***************
*** 328,334 ****
return (PptpCallId) (hptr + 1);
}
!
int
AliasHandlePptpGreOut(struct libalias *la, struct ip *pip)
{
--- 476,484 ----
return (PptpCallId) (hptr + 1);
}
! #ifdef _KERNEL
! static
! #endif
int
AliasHandlePptpGreOut(struct libalias *la, struct ip *pip)
{
***************
*** 353,359 ****
return (0);
}
!
int
AliasHandlePptpGreIn(struct libalias *la, struct ip *pip)
{
--- 503,511 ----
return (0);
}
! #ifdef _KERNEL
! static
! #endif
int
AliasHandlePptpGreIn(struct libalias *la, struct ip *pip)
{
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_proxy.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_proxy.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_proxy.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_proxy.c Sun Jun 11 18:57:27 2006
***************
*** 60,75 ****
#include <sys/libkern.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/limits.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
- #include <string.h>
#include <netdb.h>
! #include <arpa/inet.h>
#endif
/* BSD IPV4 includes */
--- 60,78 ----
#include <sys/libkern.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
+ #if __FreeBSD_version < 500000
+ #include <machine/limits.h>
+ #else
#include <sys/limits.h>
+ #endif
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <netdb.h>
! #include <string.h>
#endif
/* BSD IPV4 includes */
***************
*** 156,161 ****
--- 159,173 ----
static void ProxyEncodeIpHeader(struct ip *, int);
#ifdef _KERNEL
+
+ /* Use kernel allocator. */
+ #if defined(_SYS_MALLOC_H_)
+ MALLOC_DECLARE(M_ALIAS);
+ #define malloc(x) malloc(x, M_ALIAS, M_NOWAIT|M_ZERO)
+ #define calloc(x, n) malloc(x*n)
+ #define free(x) free(x, M_ALIAS)
+ #endif
+
static int
inet_aton(cp, addr)
const char *cp;
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_skinny.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_skinny.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_skinny.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_skinny.c Sun Jun 11 18:57:27 2006
***************
*** 32,44 ****
#ifdef _KERNEL
#include <sys/param.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
- #include <arpa/inet.h>
#endif
#include <netinet/in_systm.h>
--- 32,52 ----
#ifdef _KERNEL
#include <sys/param.h>
+ #include <sys/proc.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
+ #include <sys/types.h>
+ #include <sys/systm.h>
#else
+ #include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#endif
#include <netinet/in_systm.h>
***************
*** 50,57 ****
--- 58,130 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ static void
+ AliasHandleSkinny(struct libalias *, struct ip *, struct alias_link *);
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
+ return (NOK);
+ if (la->skinnyPort != 0 && (ntohs(*ah->sport) == la->skinnyPort ||
+ ntohs(*ah->dport) == la->skinnyPort))
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ AliasHandleSkinny(la, pip, ah->lnk);
+ return (OK);
+ }
+
+ struct proto_handler handlers[] = {{110, IN|OUT, TCP, &fingerprint,
+ &protohandler}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_skinny", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_skinny, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_skinny, 1);
+ MODULE_DEPEND(alias_skinny, libalias, 1, 1, 1);
#endif
/*
***************
*** 233,238 ****
--- 306,314 ----
return (0);
}
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleSkinny(struct libalias *la, struct ip *pip, struct alias_link *lnk)
{
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_smedia.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_smedia.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_smedia.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_smedia.c Sun Jun 11 18:57:27 2006
***************
*** 101,107 ****
--- 101,114 ----
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/libkern.h>
+ #include <sys/systm.h>
+ #include <sys/kernel.h>
+ #include <sys/types.h>
+ #include <sys/malloc.h>
+ #include <sys/module.h>
+ #include <sys/syslog.h>
#else
+ #include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
***************
*** 116,123 ****
--- 123,206 ----
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
+ #include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
+ #include "alias_mod.h"
+ #endif
+
+ #define RTSP_CONTROL_PORT_NUMBER_1 554
+ #define RTSP_CONTROL_PORT_NUMBER_2 7070
+ #define TFTP_PORT_NUMBER 69
+
+ static void
+ AliasHandleRtspOut(struct libalias *, struct ip *, struct alias_link *,
+ int maxpacketsize);
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
+ ah->maxpacketsize == 0)
+ return (NOK);
+ if (ntohs(*ah->dport) == RTSP_CONTROL_PORT_NUMBER_1
+ || ntohs(*ah->sport) == RTSP_CONTROL_PORT_NUMBER_1
+ || ntohs(*ah->dport) == RTSP_CONTROL_PORT_NUMBER_2
+ || ntohs(*ah->sport) == RTSP_CONTROL_PORT_NUMBER_2
+ || ntohs(*ah->dport) == TFTP_PORT_NUMBER)
+ return (OK);
+ return (NOK);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ if (ntohs(*ah->dport) == TFTP_PORT_NUMBER)
+ FindRtspOut(la, pip->ip_src, pip->ip_dst,
+ *ah->sport, *ah->alias_port, IPPROTO_UDP);
+ else AliasHandleRtspOut(la, pip, ah->lnk, ah->maxpacketsize);
+ return (OK);
+ }
+
+ struct proto_handler handlers[] = {{100, OUT, TCP|UDP, &fingerprint,
+ &protohandler}, {EOH}};
+
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers);
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ moduledata_t alias_mod = {
+ "alias_smedia", mod_handler, NULL
+ };
+
+ #ifdef _KERNEL
+ DECLARE_MODULE(alias_smedia, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
+ MODULE_VERSION(alias_smedia, 1);
+ MODULE_DEPEND(alias_smedia, libalias, 1, 1, 1);
#endif
#define RTSP_CONTROL_PORT_NUMBER_1 554
***************
*** 392,397 ****
--- 475,483 ----
return (0);
}
+ #ifdef _KERNEL
+ static
+ #endif
void
AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, int maxpacketsize)
{
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_util.c /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_util.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/alias_util.c Mon Jun 27 09:36:02 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/alias_util.c Sun Jun 11 18:57:27 2006
***************
*** 45,50 ****
--- 45,51 ----
#ifdef _KERNEL
#include <sys/param.h>
+ #include <sys/proc.h>
#else
#include <sys/types.h>
#include <stdio.h>
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/libalias.3 /home/flag/src/freebsd7/src/sys/netinet/libalias/libalias.3
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/libalias/libalias.3 Thu Nov 24 15:17:35 2005
--- /home/flag/src/freebsd7/src/sys/netinet/libalias/libalias.3 Sun Jun 18 16:09:34 2006
***************
*** 893,898 ****
--- 893,901 ----
added support for RTSP/PNA.
.An Ruslan Ermilov Aq ru at FreeBSD.org
added support for PPTP and LSNAT as well as general hacking.
+ .An Paolo Pisati Aq piso at FreeBSD.org
+ made the library modular, moving support for all
+ the protocols (except for IP, TCP and UDP) to external modules.
.Sh ACKNOWLEDGMENTS
Listed below, in approximate chronological order, are individuals who
have provided valuable comments and/or debugging assistance.
***************
*** 1011,1016 ****
--- 1014,1385 ----
a unique aliasing link can be established.
In an alternate operating mode, the first choice of an aliasing port is also
random and unrelated to the local port number.
+ .Sh Modular architecture (and ipfw support)
+ One of the latest improvement of libalias was to make its support
+ for new protocols independent from the rest of the library, giving it
+ the ability to load/unload at runtime support for new protocols.
+ To achieve this feature, all the code for protocols handling was moved
+ to a series of modules outside of the main library.
+ These modules are compiled from the same source base but works in a
+ different ways, according if they are compiled to work inside a kernel
+ or as part of a user land library.
+ .Ss Libalias modules in kernel land
+ When compiled to be part of a kernel, libalias modules are plain
+ simple kld, installed as default with all the other kernel modules:
+ .Pp
+ .Bd -ragged -offset indent
+ .An -split
+ .An /boot/kernel/alias_cuseeme.ko
+ .An /boot/kernel/alias_dummy.ko
+ .An /boot/kernel/alias_ftp.ko
+ .An /boot/kernel/alias_irc.ko
+ .An /boot/kernel/alias_nbt.ko
+ .An /boot/kernel/alias_pptp.ko
+ .An /boot/kernel/alias_skinny.ko
+ .An /boot/kernel/alias_smedia.ko
+ .Ed
+ .Pp
+ To load a new protocol just kldload it:
+ .Pp
+ kldload alias_ftp # add support for ftp protocol to kernel libalias
+ .Pp
+ and when you don't need it anymore, you can unload it:
+ .Pp
+ kldunload alias_ftp
+ .Pp
+ .Ss Libalias modules in user land
+ Due to the differences between kernel and user land (no kld mechanism,
+ many different address spaces, etc etc), we had to change a bit how to
+ handle modules loading/tracking/unloading in user land.
+ .Pp
+ While compiled for a user land libalias, all the modules are installed
+ in /usr/lib:
+ .Pp
+ .Bd -ragged -offset indent
+ .An -split
+ .An /usr/lib/libalias_cuseeme.a
+ .An /usr/lib/libalias_cuseeme.so -> /lib/libalias_cuseeme.so.4
+ .An /usr/lib/libalias_cuseeme_p.a
+ .An /usr/lib/libalias_dummy.a
+ .An /usr/lib/libalias_dummy.so -> /lib/libalias_dummy.so.4
+ .An /usr/lib/libalias_dummy_p.a
+ .An /usr/lib/libalias_ftp.a
+ .An /usr/lib/libalias_ftp.so -> /lib/libalias_ftp.so.4
+ .An /usr/lib/libalias_ftp_p.a
+ .An /usr/lib/libalias_irc.a
+ .An /usr/lib/libalias_irc.so -> /lib/libalias_irc.so.4
+ .An /usr/lib/libalias_irc_p.a
+ .An /usr/lib/libalias_nbt.a
+ .An /usr/lib/libalias_nbt.so -> /lib/libalias_nbt.so.4
+ .An /usr/lib/libalias_nbt_p.a
+ .An /usr/lib/libalias_pptp.a
+ .An /usr/lib/libalias_pptp.so -> /lib/libalias_pptp.so.4
+ .An /usr/lib/libalias_pptp_p.a
+ .An /usr/lib/libalias_skinny.a
+ .An /usr/lib/libalias_skinny.so -> /lib/libalias_skinny.so.4
+ .An /usr/lib/libalias_skinny_p.a
+ .An /usr/lib/libalias_smedia.a
+ .An /usr/lib/libalias_smedia.so -> /lib/libalias_smedia.so.4
+ .An /usr/lib/libalias_smedia_p.a
+ .Ed
+ .Pp
+ To take advantage of modules, an application must be
+ patched to handle SIGHUP signal and call LibAliasRefreshModules()
+ whenever it receives that signal (see below for details).
+ .Pp
+ If you have correctly installed libalias, in /etc you should
+ find a file called libalias.conf with the following contents (or
+ similar):
+ .Pp
+ .Bd -ragged -offset indent
+ .An -split
+ .An /usr/lib/libalias_cuseeme.so
+ .An /usr/lib/libalias_ftp.so
+ .An /usr/lib/libalias_irc.so
+ .An /usr/lib/libalias_nbt.so
+ .An /usr/lib/libalias_pptp.so
+ .An /usr/lib/libalias_skinny.so
+ .An /usr/lib/libalias_smedia.so
+ .Ed
+ .Pp
+ this file contains the paths to the modules that libalias will load.
+ To load/unload a new module just add its path to libalias.conf and
+ send a SIGHUP signal to the application that needs the new module:
+ .Pp
+ kill -HUP <process pid>
+ .Pp
+ .Sh Modular architecture: how it works
+ The modular architecture of libalias work (almost) the same when it's
+ running inside kernel or in user land. From alias_mod.c:
+ .Bd -literal
+ /* protocol and user land module handlers chains */
+ struct chain handler_chain, dll_chain;
+
+ handler_chain keep tracks of all the protocol handlers loaded, while
+ ddl_chain takes care of userland modules loaded.
+
+ handler_chain is composed of struct proto_handler entries:
+
+ struct proto_handler {
+
+ /* handler priority */
+ int pri;
+ /* flow direction */
+ int16_t dir;
+ /* working protocol */
+ int16_t proto;
+ /* fingerprint * function */
+ int (*fingerprint)(struct libalias *la,
+ struct ip *pip, struct alias_data *ah);
+ /* aliasing * function */
+ int (*protohandler)(struct libalias *la,
+ struct ip *pip, struct alias_data *ah);
+ struct proto_handler *next;
+ };
+ .Ed
+ .Pp
+ where:
+ .Pp
+ pri is the priority assigned to a protocol handler, lower
+ is better.
+ .Pp
+ dir is the direction of packets: ingoing or outgoing.
+ .Pp
+ proto says at which protocol this packet belongs: IP, TCP or UDP
+ .Pp
+ fingerprint points to the fingerprint function while protohandler points
+ to the protocol handler function.
+ .Pp
+ The fingerprint function has the double of scope of checking if the
+ incoming packet is sound and if it belongs to any categories that this
+ module can handle.
+ .Pp
+ The protocol handler function is the function that actually manipulates
+ the packet to make libalias correctly nat it.
+ .Pp
+ When a packet enters libalias, if it meets a module hook,
+ libalias scan handler_chain to see if there's an handler that match
+ this type of packet (it checks protocol and direction of packet), then if
+ more then one handler is found, it starts with the module with
+ a lower priority number: it calls fingerprints and read the result.
+ .Pp
+ If the result value is equal to OK, then it calls the protocol handler
+ of this handler and return, else it skip to the fingerprint function
+ of the next eligible module, till the end of handler_chain
+ .Pp
+ Inside libalias, the module hook looks like this:
+ .Bd -literal
+ struct alias_data ad = {
+ lnk,
+ &original_address,
+ &alias_address,
+ &alias_port,
+ &ud->uh_sport, /* original source port */
+ &ud->uh_dport, /* original dest port */
+ 256 /* maxpacketsize */
+ };
+
+ ...
+
+ /* walk out chain */
+ err = find_handler(IN, UDP, la, pip, &ad);
+ if (err == EHDNOF)
+ ;
+ .Ed
+ all data useful to a module are gathered together in a alias_data
+ structure, then find_handler is called.
+ find_handler is the function responsible of walking out the handler
+ chain, it receives as input parameters:
+ .Pp
+ IN: direction
+ .Pp
+ UDP: working protocol
+ .Pp
+ la: pointer to this instance of libalias
+ .Pp
+ pip: pointer to a struct ip
+ .Pp
+ ad: pointer to struct alias_data (see above)
+ .Pp
+ in this case, find_handler will search only for modules registered for
+ supporting INcoming UDP packets.
+ .Pp
+ As i said earlier, libalias in userland is a bit different, cause we
+ have to take care of module handling too (avoiding duplicate load of
+ module, avoiding module with same name, etc etc) so dll_chain was
+ introduced.
+ .Pp
+ dll_chain contains a list of all user land libalias modules loaded.
+ .Pp
+ When an application calls LibAliasRefreshModules(), libalias first unload
+ all the loaded modules, then reload all the modules listed in
+ /etc/libalias.conf: for every module loaded, a new entry to dll_chain
+ is added.
+ .Pp
+ dll_chain is composed of struct dll entries:
+ .Bd -literal
+ struct dll {
+ /* name of module */
+ char name[DLL_LEN];
+ /*
+ * ptr to shared obj obtained through
+ * dlopen() - use this ptr to get access
+ * to any symbols from a loaded module
+ * via dlsym()
+ */
+ void *handle;
+ struct dll *next;
+ };
+ .Ed
+ name is the name of the module
+ .Pp
+ handle is a pointer to the module obtained through dlopen()
+ .Pp
+ Whenever a module is loaded in user land, an entry is added to
+ dll_chain, than every protocol handler present in that module
+ is resolved and registered in handler_chain.
+ .Ss How to write a module for libalias
+ There's a module (called alias_dummy.[ch]) in libalias that can be
+ used as a skeleton for future work, here we analyse some parts of that
+ module.
+ From alias_dummy.c:
+ .Bd -literal
+ struct proto_handler handlers [] = {{666, IN|OUT, UDP|TCP,
+ &fingerprint, &protohandler}};
+ .Ed
+ .Pp
+ The variable 'handlers' is the 'most important thing' in your module,
+ cause it describes the handlers present and let the outside world use
+ it in an opaque way.
+ .Pp
+ It must ALWAYS be present in every module, and it MUST retain
+ the name 'handlers', else if you'll try to load
+ this module in userland, it will complain about missing symbols: for
+ more info about module load/unload, please refer to
+ LibAliasRefreshModules, LibAliasLoadModule and LibAliasUnloadModule in
+ alias.c
+ .Pp
+ handlers[] contains all the proto_handler structures present in a
+ module.
+ .Bd -literal
+ static int
+ mod_handler(module_t mod, int type, void *data)
+ {
+ int error;
+
+ switch (type) {
+ case MOD_LOAD:
+ error = 0;
+ attach_handlers(handlers);
+ break;
+ case MOD_UNLOAD:
+ error = 0;
+ detach_handlers(handlers;
+ break;
+ default:
+ error = EINVAL;
+ }
+ return (error);
+ }
+ .Ed
+ When running as kld, mod_handler register/deregister the module using
+ attach_handlers/detach_handlers respectively.
+ .Pp
+ Every module must contain at least 2 functions: one fingerprint
+ function and a protocol handler function.
+ .Bd -literal
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah) {
+
+ ...
+ }
+
+ #ifdef _KERNEL
+ static
+ #endif
+ int
+ protohandler(struct libalias *la, struct ip *pip,
+ struct alias_data *ah) {
+
+ ...
+ }
+ .Ed
+ and they must accept exactly these input parameters.
+ .Ss Patching an application for user land libalias modules
+ If you have any application that uses libalias and you want to add it
+ support for libalias modules, then follow this simple 5 steps
+ procedure.
+ .Bd -ragged -offset indent
+ .An -split
+ .An 1) first, figure out which file is the main file of your program
+ .An (let's call it main.c)
+
+ .An 2) add this to the header section of main,c, if not already
+ .An present:
+ .Pp
+ .An #include <signal.h>
+ .Pp
+ .An 3) and this just after the header section:
+ .Pp
+ .An static void signal_handler(int);
+ .Pp
+ .An 4) add this line in the init function of you program or, if it
+ .An doesn't have any init function, put it in main():
+ .Pp
+ .An signal(SIGHUP, signal_handler);
+ .Pp
+ .An 5) and place this function somewhere in main.c:
+ .Pp
+ .An static void
+ .An signal_handler(int sig) {
+ .Pp
+ .An LibAliasRefreshModules();
+ .An }
+ .Pp
+ .An else, if your program already trap SIGHUP signal, just add a call
+ .An to LibAliasRefreshModules() in the function serving that signal.
+ .Pp
+ .An For example, to patch natd to use libalias modules, just add
+ .An the following line to RefreshAddr (int sig __unused):
+ .Pp
+ .An LibAliasRefreshModules()
+ .Pp
+ .An recompile and you are done.
+ .Ed
+ .Pp
+ .Ss Logging support in kernel land
+ .Pp
+ While working as kld, libalias now have log support that
+ happens on a buffer allocated inside struct libalias(from alias_local.h):
+ .Bd -literal
+ struct libalias {
+ ...
+
+ /* log descriptor */
+ #ifdef KERNEL_LOG
+ char *logDesc; /*
+ * ptr to an auto-malloced
+ * memory buffer when libalias
+ * works as kld
+ */
+ #else
+ FILE *logDesc; /*
+ * ptr to /var/log/alias.log
+ * when libalias runs as a
+ * userland lib
+ */
+ #endif
+
+ ...
+ }
+ .Ed
+ so all the applications using libalias, will be able to handle their
+ own logs, if they want, accessing logDesc.
+ Moreover, every change to log buffer is automatically added to syslog
+ with facilities security and info.
.Sh BUGS
PPTP aliasing does not work when more than one internal client
connects to the same external server at the same time, because
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/sys/netinet/raw_ip.c /home/flag/src/freebsd7/src/sys/netinet/raw_ip.c
*** /home/flag/src/freebsd7_vanilla/src/sys/netinet/raw_ip.c Sun May 21 21:28:46 2006
--- /home/flag/src/freebsd7/src/sys/netinet/raw_ip.c Sun Jun 11 18:57:27 2006
***************
*** 378,383 ****
--- 378,385 ----
case IP_FW_GET:
case IP_FW_TABLE_GETSIZE:
case IP_FW_TABLE_LIST:
+ case IP_FW_NAT_GET_CONFIG:
+ case IP_FW_NAT_GET_LOG:
error = suser(curthread);
if (error != 0)
return (error);
***************
*** 443,448 ****
--- 445,452 ----
case IP_FW_TABLE_ADD:
case IP_FW_TABLE_DEL:
case IP_FW_TABLE_FLUSH:
+ case IP_FW_NAT_CFG:
+ case IP_FW_NAT_DEL:
error = suser(curthread);
if (error != 0)
return (error);
diff -rNPc --exclude=CVS /home/flag/src/freebsd7_vanilla/src/usr.sbin/ppp/main.c /home/flag/src/freebsd7/src/usr.sbin/ppp/main.c
*** /home/flag/src/freebsd7_vanilla/src/usr.sbin/ppp/main.c Tue Dec 21 12:12:05 2004
--- /home/flag/src/freebsd7/src/usr.sbin/ppp/main.c Sun Jun 11 18:57:27 2006
***************
*** 328,333 ****
--- 328,334 ----
#ifndef NONAT
PacketAliasInit();
+ LibAliasRefreshModules();
#endif
label = ProcessArgs(argc, argv, &sw);
More information about the freebsd-net
mailing list