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