Summer of Code 2005: improve libalias - part 1 of 2

With the first part of my previous Summer of Code work, we get:

-made libalias modular:

 -support for 'particular' protocols (like ftp/irc/etcetc) is no more
  hardcoded inside libalias, but it's available through external
  modules loadable at runtime

 -modules are available both in kernel (/boot/kernel/alias_*.ko) and
  user land (/lib/libalias_*)

 -protocols/applications modularized are: cuseeme, ftp, irc, nbt, pptp,
  skinny and smedia

-added logging support for kernel side

-cleanup

After a buildworld, do a 'mergemaster -i' to install the file libalias.conf
in /etc or manually copy it.

During startup (and after every HUP signal) user land applications running
the new libalias will try to read a file in /etc called libalias.conf:
that file contains the list of modules to load.

User land applications affected by this commit are ppp and natd:
if libalias.conf is present in /etc you won't notice any difference.

The only kernel land bit affected by this commit is ng_nat:
if you are using ng_nat, and it doesn't correctly handle
ftp/irc/etcetc sessions anymore, remember to kldload
the correspondent module (i.e. kldload alias_ftp).

General information and details about the inner working are available
in the libalias man page under the section 'MODULAR ARCHITECTURE
(AND ipfw(4) SUPPORT)'.

NOTA BENE: this commit affects _ONLY_ libalias, ipfw in-kernel nat
support will be part of the next libalias-related commit.

Approved by: glebius
Reviewed by: glebius, ru
This commit is contained in:
Paolo Pisati 2006-09-26 23:26:53 +00:00
parent 31e2a87d4d
commit be4f3cd0d9
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=162674
47 changed files with 2245 additions and 318 deletions

View File

@ -12,7 +12,7 @@ BIN1= amd.map apmd.conf auth.conf \
dhclient.conf disktab fbtab freebsd-update.conf \
ftpusers gettytab group \
hosts hosts.allow hosts.equiv hosts.lpd \
inetd.conf login.access login.conf mac.conf motd \
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 \

8
etc/libalias.conf Normal file
View File

@ -0,0 +1,8 @@
# $FreeBSD$
/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

View File

@ -1,16 +1,29 @@
# Copyright 2006 Paolo Pisati <piso@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.
#
# $FreeBSD$
.PATH: ${.CURDIR}/../../sys/netinet/libalias
SUBDIR= libalias modules
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>
.include <bsd.subdir.mk>

View File

@ -0,0 +1,13 @@
# $FreeBSD$
.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
WARNS?= 6
.include <bsd.lib.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.include "../../../sys/modules/libalias/modules/modules.inc"
SUBDIR= ${MODULES}
.include <bsd.subdir.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../../sys/netinet/libalias
SHLIBDIR?= /lib
SHLIB_MAJOR= 4
WARNS?= 1

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_cuseeme
SRCS= alias_cuseeme.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_dummy
SRCS= alias_dummy.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_ftp
SRCS= alias_ftp.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_irc
SRCS= alias_irc.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_nbt
SRCS= alias_nbt.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_pptp
SRCS= alias_pptp.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_skinny
SRCS= alias_skinny.c
.include <bsd.lib.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
LIB= alias_smedia
SRCS= alias_smedia.c
.include <bsd.lib.mk>

View File

@ -970,7 +970,8 @@ void Warn (const char* msg)
static void RefreshAddr (int sig __unused)
{
if (mip->ifName)
LibAliasRefreshModules();
if (mip != NULL && mip->ifName != NULL)
mip->assignAliasAddr = 1;
}

View File

@ -1744,16 +1744,11 @@ netinet/tcp_timer.c optional inet
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
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

View File

@ -1,33 +1,5 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../netinet/libalias
SUBDIR= libalias modules
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>
.include <bsd.subdir.mk>

View File

@ -0,0 +1,8 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../netinet/libalias
KMOD= libalias
SRCS= alias.c alias_db.c alias_proxy.c alias_util.c alias_old.c alias_mod.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,7 @@
# $FreeBSD$
.include "modules.inc"
SUBDIR= ${MODULES}
.include <bsd.subdir.mk>

View File

@ -0,0 +1,3 @@
# $FreeBSD$
.PATH: ${.CURDIR}/../../../../netinet/libalias

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_cuseeme
SRCS= alias_cuseeme.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_dummy
SRCS= alias_dummy.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_ftp
SRCS= alias_ftp.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_irc
SRCS= alias_irc.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,11 @@
# $FreeBSD$
MODULES =
MODULES += cuseeme
MODULES += dummy
MODULES += ftp
MODULES += irc
MODULES += nbt
MODULES += pptp
MODULES += skinny
MODULES += smedia

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_nbt
SRCS= alias_nbt.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_pptp
SRCS= alias_pptp.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_skinny
SRCS= alias_skinny.c
.include <bsd.kmod.mk>

View File

@ -0,0 +1,6 @@
# $FreeBSD$
KMOD= alias_smedia
SRCS= alias_smedia.c
.include <bsd.kmod.mk>

View File

@ -115,7 +115,11 @@ __FBSDID("$FreeBSD$");
#include <sys/param.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,22 +132,14 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
#include <netinet/libalias/alias_mod.h>
#else
#include <err.h>
#include "alias.h"
#include "alias_local.h"
#include "alias_mod.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)
{
@ -725,24 +721,24 @@ UdpAliasIn(struct libalias *la, struct ip *pip)
struct in_addr original_address;
u_short alias_port;
int accumulate;
int r = 0;
int r = 0, error;
struct alias_data ad = {
.lnk = lnk,
.oaddr = &original_address,
.aaddr = &alias_address,
.aport = &alias_port,
.sport = &ud->uh_sport,
.dport = &ud->uh_dport,
.maxpktsize = 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);
/* Walk out chain. */
error = find_handler(IN, UDP, la, pip, &ad);
/* If UDP checksum is not zero, then adjust since destination port */
/* is being unaliased and destination address is being altered. */
@ -774,6 +770,7 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int create)
{
struct udphdr *ud;
struct alias_link *lnk;
int error;
/* Return if proxy-only mode is enabled */
if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY)
@ -787,29 +784,21 @@ UdpAliasOut(struct libalias *la, struct ip *pip, int create)
if (lnk != NULL) {
u_short alias_port;
struct in_addr alias_address;
struct alias_data ad = {
.lnk = lnk,
.oaddr = NULL,
.aaddr = &alias_address,
.aport = &alias_port,
.sport = &ud->uh_sport,
.dport = &ud->uh_dport,
.maxpktsize = 0
};
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);
/* Walk out chain. */
error = find_handler(OUT, UDP, la, pip, &ad);
/* If UDP checksum is not zero, adjust since source port is */
/* being aliased and source address is being altered */
@ -855,15 +844,26 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
struct in_addr proxy_address;
u_short alias_port;
u_short proxy_port;
int accumulate;
int accumulate, error;
/* 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);
/*
* 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 = lnk,
.oaddr = NULL,
.aaddr = NULL,
.aport = NULL,
.sport = &tc->th_sport,
.dport = &tc->th_dport,
.maxpktsize = 0
};
/* Walk out chain. */
error = find_handler(IN, TCP, la, pip, &ad);
alias_address = GetAliasAddress(lnk);
original_address = GetOriginalAddress(lnk);
@ -872,6 +872,28 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
tc->th_dport = GetOriginalPort(lnk);
proxy_port = GetProxyPort(lnk);
/*
* Look 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.
*/
#if 0
struct alias_data ad = {
.lnk = lnk,
.oaddr = &original_address,
.aaddr = &alias_address,
.aport = &alias_port,
.sport = &ud->uh_sport,
.dport = &ud->uh_dport,
.maxpktsize = 0
};
/* Walk out chain. */
error = find_handler(la, pip, &ad);
if (error == EHDNOF)
printf("Protocol handler not found\n");
#endif
/* Adjust TCP checksum since destination port is being unaliased */
/* and destination port is being altered. */
accumulate = alias_port;
@ -926,7 +948,7 @@ TcpAliasIn(struct libalias *la, struct ip *pip)
static int
TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
{
int proxy_type;
int proxy_type, error;
u_short dest_port;
u_short proxy_server_port;
struct in_addr dest_address;
@ -973,6 +995,15 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
u_short alias_port;
struct in_addr alias_address;
int accumulate;
struct alias_data ad = {
.lnk = lnk,
.oaddr = NULL,
.aaddr = &alias_address,
.aport = &alias_port,
.sport = &tc->th_sport,
.dport = &tc->th_dport,
.maxpktsize = maxpacketsize
};
/* Save original destination address, if this is a proxy packet.
Also modify packet to include destination encoding. This may
@ -989,25 +1020,9 @@ TcpAliasOut(struct libalias *la, struct ip *pip, int maxpacketsize, int create)
/* 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);
/* Walk out chain. */
error = find_handler(OUT, TCP, la, pip, &ad);
/* Adjust TCP checksum since source port is being aliased */
/* and source address is being altered */
@ -1208,13 +1223,26 @@ LibAliasIn(struct libalias *la, char *ptr, int maxpacketsize)
case IPPROTO_TCP:
iresult = TcpAliasIn(la, pip);
break;
case IPPROTO_GRE:
if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
AliasHandlePptpGreIn(la, pip) == 0)
case IPPROTO_GRE: {
int error;
struct alias_data ad = {
.lnk = NULL,
.oaddr = NULL,
.aaddr = NULL,
.aport = NULL,
.sport = NULL,
.dport = NULL,
.maxpktsize = 0
};
/* Walk out chain. */
error = find_handler(IN, IP, la, pip, &ad);
if (error == 0)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasIn(la, pip);
break;
}
break;
default:
iresult = ProtoAliasIn(la, pip);
break;
@ -1321,12 +1349,25 @@ LibAliasOutTry(struct libalias *la, char *ptr, /* valid IP packet */
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;
case IPPROTO_GRE: {
int error;
struct alias_data ad = {
.lnk = NULL,
.oaddr = NULL,
.aaddr = NULL,
.aport = NULL,
.sport = NULL,
.dport = NULL,
.maxpktsize = 0
};
/* Walk out chain. */
error = find_handler(OUT, IP, la, pip, &ad);
if (error == 0)
iresult = PKT_ALIAS_OK;
else
iresult = ProtoAliasOut(la, pip, create);
}
break;
default:
iresult = ProtoAliasOut(la, pip, create);
break;
@ -1443,3 +1484,93 @@ LibAliasUnaliasOut(struct libalias *la, char *ptr, /* valid IP packet */
return (iresult);
}
#ifndef _KERNEL
int
LibAliasRefreshModules(void)
{
char buf[256], conf[] = "/etc/libalias.conf";
FILE *fd;
int len;
fd = fopen(conf, "r");
if (fd == NULL)
err(1, "fopen(%s)", conf);
LibAliasUnLoadAllModule();
for (;;) {
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 (0);
}
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 (EINVAL);
}
p = dlsym(handle, "alias_mod");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
return (EINVAL);
}
t = malloc(sizeof(struct dll));
if (t == NULL)
return (ENOMEM);
strncpy(t->name, p->name, DLL_LEN);
t->handle = handle;
if (attach_dll(t) == EEXIST) {
free(t);
fputs("dll conflict", stderr);
return (EEXIST);
}
m = dlsym(t->handle, "handlers");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
return (EINVAL);
}
LibAliasAttachHandlers(m);
return (0);
}
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);
}
return (1);
}
#endif

View File

@ -28,7 +28,7 @@
* $FreeBSD$
*/
/*-
/*
* Alias.h defines the outside world interfaces for the packet aliasing
* software.
*
@ -39,12 +39,16 @@
#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_LOGGING
#define NO_USE_SOCKETS
#endif
@ -180,6 +184,10 @@ void LibAliasSetTarget(struct libalias *, struct in_addr _target_addr);
/* 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.
@ -192,9 +200,7 @@ int LibAliasProxyRule(struct libalias *, const char *_cmd);
* 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,

View File

@ -31,7 +31,10 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#endif
@ -44,8 +47,100 @@ __FBSDID("$FreeBSD$");
#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);
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->oaddr == NULL)
return (-1);
if (ntohs(*ah->dport) == CUSEEME_PORT_NUMBER)
return (0);
return (-1);
}
static int
protohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleCUSeeMeIn(la, pip, *ah->oaddr);
return (0);
}
static int
protohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleCUSeeMeOut(la, pip, ah->lnk);
return (0);
}
/* Kernel module definition. */
struct proto_handler handlers[] = {
{
.pri = 120,
.dir = OUT,
.proto = UDP,
.fingerprint = &fingerprint,
.protohandler = &protohandlerout
},
{
.pri = 120,
.dir = IN,
.proto = UDP,
.fingerprint = &fingerprint,
.protohandler = &protohandlerin
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,7 +172,7 @@ struct client_info {
* counts etc */
};
void
static void
AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *lnk)
{
struct udphdr *ud = ip_next(pip);
@ -100,7 +195,7 @@ AliasHandleCUSeeMeOut(struct libalias *la, struct ip *pip, struct alias_link *ln
}
}
void
static void
AliasHandleCUSeeMeIn(struct libalias *la, struct ip *pip, struct in_addr original_addr)
{
struct in_addr alias_addr;

View File

@ -143,40 +143,32 @@ __FBSDID("$FreeBSD$");
*/
#ifdef _KERNEL
#include <machine/stdarg.h>
#include <sys/param.h>
#else
#include <sys/types.h>
#endif
#include <sys/errno.h>
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/time.h>
#ifdef _KERNEL
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/malloc.h>
#include <sys/module.h>
#else
#include <sys/syslog.h>
#else
#include <stdarg.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/errno.h>
#include <sys/time.h>
#include <unistd.h>
#include <arpa/inet.h>
#endif
/* BSD network include files */
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <sys/socket.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>
#else
#include "alias.h"
#include "alias_local.h"
#include "alias_mod.h"
#endif
static LIST_HEAD(, libalias) instancehead = LIST_HEAD_INITIALIZER(instancehead);
@ -358,10 +350,12 @@ alias_mod_handler(module_t mod, int type, void *data)
switch (type) {
case MOD_LOAD:
error = 0;
handler_chain_init();
break;
case MOD_QUIESCE:
case MOD_UNLOAD:
finishoff();
handler_chain_destroy();
finishoff();
error = 0;
break;
default:
@ -409,12 +403,10 @@ static void ClearFWHole(struct alias_link *);
#endif
#ifndef NO_LOGGING
/* Log file control */
static void ShowAliasStats(struct libalias *);
static void InitPacketAliasLog(struct libalias *);
static int InitPacketAliasLog(struct libalias *);
static void UninitPacketAliasLog(struct libalias *);
#endif
static u_int
StartPointIn(struct in_addr alias_addr,
@ -462,37 +454,55 @@ SeqDiff(u_long x, u_long y)
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
#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);
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
}
}
#endif
/* Internal routines for finding, deleting and adding links
@ -929,12 +939,10 @@ DeleteLink(struct alias_link *lnk)
/* Free memory */
free(lnk);
#ifndef NO_LOGGING
/* Write statistics, if logging enabled */
if (la->packetAliasMode & PKT_ALIAS_LOG) {
ShowAliasStats(la);
}
#endif
}
@ -1072,11 +1080,9 @@ AddLink(struct libalias *la, struct in_addr src_addr,
fprintf(stderr, "malloc() call failed.\n");
#endif
}
#ifndef NO_LOGGING
if (la->packetAliasMode & PKT_ALIAS_LOG) {
ShowAliasStats(la);
}
#endif
return (lnk);
}
@ -2203,30 +2209,40 @@ HouseKeeping(struct libalias *la)
}
}
#ifndef NO_LOGGING
/* Init the log file and enable logging */
static void
static int
InitPacketAliasLog(struct libalias *la)
{
if ((~la->packetAliasMode & PKT_ALIAS_LOG)
&& (la->monitorFile = fopen("/var/log/alias.log", "w"))) {
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;
fprintf(la->monitorFile,
"PacketAlias/InitPacketAliasLog: Packet alias logging enabled.\n");
}
return (1);
}
/* Close the log-file and disable logging. */
static void
UninitPacketAliasLog(struct libalias *la)
{
if (la->monitorFile) {
fclose(la->monitorFile);
la->monitorFile = NULL;
}
if (la->logDesc) {
#ifdef _KERNEL
free(la->logDesc);
#else
fclose(la->logDesc);
#endif
la->logDesc = NULL;
}
la->packetAliasMode &= ~PKT_ALIAS_LOG;
}
#endif
/* Outside world interfaces
@ -2488,6 +2504,9 @@ LibAliasInit(struct libalias *la)
| PKT_ALIAS_RESET_ON_ADDR_CHANGE;
#ifndef NO_FW_PUNCH
la->fireWallFD = -1;
#endif
#ifndef _KERNEL
LibAliasRefreshModules();
#endif
return (la);
}
@ -2498,9 +2517,7 @@ LibAliasUninit(struct libalias *la)
la->deleteAllLinks = 1;
CleanupAliasData(la);
la->deleteAllLinks = 0;
#ifndef NO_LOGGING
UninitPacketAliasLog(la);
#endif
#ifndef NO_FW_PUNCH
UninitPunchFW(la);
#endif
@ -2517,16 +2534,16 @@ LibAliasSetMode(
* do a probe for flag values) */
)
{
#ifndef NO_LOGGING
/* Enable logging? */
if (flags & mask & PKT_ALIAS_LOG) {
InitPacketAliasLog(la); /* Do the enable */
/* Do the enable */
if (InitPacketAliasLog(la) == ENOMEM)
return (-1);
} 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) {

View File

@ -0,0 +1,153 @@
/*-
* Copyright (c) 2005 Paolo Pisati <piso@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>
__FBSDID("$FreeBSD$");
/*
* 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.
*/
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#ifdef _KERNEL
#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);
static 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 -1 value.
*/
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
ah->maxpktsize == 0)
return (-1);
/*
* Fingerprint the incoming packet, if it matches any conditions
* return an OK value.
*/
if (ntohs(*ah->dport) == 123
|| ntohs(*ah->sport) == 456)
return (0); /* I know how to handle it. */
return (-1); /* I don't recognize this packet. */
}
/*
* Wrap in this general purpose function, the real function used to alias the
* packets.
*/
static int
protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleDummy(la, pip, ah);
return (0);
}
/*
* NOTA BENE: the next variable MUST NOT be renamed in any case if you want
* your module to work in userland, cause it's used to find and use all
* the protocol handlers present in every module.
* So WATCH OUT, your module needs this variables and it needs it with
* ITS EXACT NAME: handlers.
*/
struct proto_handler handlers [] = {
{
.pri = 666,
.dir = IN|OUT,
.proto = UDP|TCP,
.fingerprint = &fingerprint,
.protohandler = &protohandler
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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
static void
AliasHandleDummy(struct libalias *la, struct ip *ip, struct alias_data *ah)
{
; /* Dummy. */
}

View File

@ -72,12 +72,13 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/ctype.h>
#include <sys/libkern.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#endif
#include <netinet/in_systm.h>
@ -88,8 +89,81 @@ __FBSDID("$FreeBSD$");
#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);
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
ah->maxpktsize == 0)
return (-1);
if (ntohs(*ah->dport) == FTP_CONTROL_PORT_NUMBER
|| ntohs(*ah->sport) == FTP_CONTROL_PORT_NUMBER)
return (0);
return (-1);
}
static int
protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleFtpOut(la, pip, ah->lnk, ah->maxpktsize);
return (0);
}
struct proto_handler handlers[] = {
{
.pri = 80,
.dir = OUT,
.proto = TCP,
.fingerprint = &fingerprint,
.protohandler = &protohandler
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,7 +186,7 @@ static int ParseFtp227Reply(struct libalias *la, char *, int);
static int ParseFtp229Reply(struct libalias *la, char *, int);
static void NewFtpMessage(struct libalias *la, struct ip *, struct alias_link *, int, int);
void
static void
AliasHandleFtpOut(
struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */

View File

@ -50,14 +50,15 @@ __FBSDID("$FreeBSD$");
/* Includes */
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/libkern.h>
#include <sys/ctype.h>
#include <sys/limits.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#endif
@ -69,15 +70,89 @@ __FBSDID("$FreeBSD$");
#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);
void
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->dport == NULL || ah->lnk == NULL ||
ah->maxpktsize == 0)
return (-1);
if (ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_1
|| ntohs(*ah->dport) == IRC_CONTROL_PORT_NUMBER_2)
return (0);
return (-1);
}
static int
protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleIrcOut(la, pip, ah->lnk, ah->maxpktsize);
return (0);
}
struct proto_handler handlers[] = {
{
.pri = 90,
.dir = OUT,
.proto = TCP,
.fingerprint = &fingerprint,
.protohandler = &protohandler
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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
static void
AliasHandleIrcOut(struct libalias *la,
struct ip *pip, /* IP packet to examine */
struct alias_link *lnk, /* Which link are we on? */

View File

@ -46,18 +46,13 @@
#ifndef _ALIAS_LOCAL_H_
#define _ALIAS_LOCAL_H_
#include <sys/queue.h>
#include <sys/types.h>
#include <sys/sysctl.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. */
#ifdef _KERNEL
#include <sys/malloc.h>
#include <sys/lock.h>
/* XXX: LibAliasSetTarget() uses this constant. */
#define INADDR_NONE 0xffffffff
#endif
@ -116,10 +111,14 @@ struct libalias {
int deleteAllLinks; /* If equal to zero, DeleteLink() */
/* will not remove permanent links */
#ifndef NO_LOGGING
FILE *monitorFile; /* File descriptor for link */
/* log descriptor */
#ifdef _KERNEL
char *logDesc;
#else
FILE *logDesc;
#endif
/* statistics monitoring file */
/* statistics monitoring */
int newDefaultLink; /* Indicates if a new aliasing */
/* link has been created after a */
@ -296,43 +295,6 @@ void HouseKeeping(struct libalias *);
/* 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,
@ -373,6 +335,4 @@ udp_next(struct udphdr *udphdr)
}
#endif
/*lint -restore */
#endif /* !_ALIAS_LOCAL_H_ */

View File

@ -0,0 +1,284 @@
/*-
* Copyright (c) 2005 Paolo Pisati <piso@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.
*
*/
__FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/libkern.h>
#include <sys/param.h>
#include <sys/lock.h>
#include <sys/rwlock.h>
#else
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <errno.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#ifdef _KERNEL
#include <netinet/libalias/alias_local.h>
#include <netinet/libalias/alias_mod.h>
#else
#include "alias_local.h"
#include "alias_mod.h"
#endif
/* Protocol and userland module handlers chains. */
LIST_HEAD(handler_chain, proto_handler) handler_chain = LIST_HEAD_INITIALIZER(foo);
#ifdef _KERNEL
struct rwlock handler_rw;
#endif
SLIST_HEAD(dll_chain, dll) dll_chain = SLIST_HEAD_INITIALIZER(foo);
#ifdef _KERNEL
#define LIBALIAS_LOCK_INIT() \
rw_init(&handler_rw, "Libalias_modules_rwlock")
#define LIBALIAS_LOCK_DESTROY() rw_destroy(&handler_rw)
#define LIBALIAS_WLOCK_ASSERT() \
rw_assert(&handler_rw, RA_WLOCKED)
static __inline void
LIBALIAS_RLOCK(void)
{
rw_rlock(&handler_rw);
}
static __inline void
LIBALIAS_RUNLOCK(void)
{
rw_runlock(&handler_rw);
}
static __inline void
LIBALIAS_WLOCK(void)
{
rw_wlock(&handler_rw);
}
static __inline void
LIBALIAS_WUNLOCK(void)
{
rw_wunlock(&handler_rw);
}
static void
_handler_chain_init(void)
{
if (!rw_initialized(&handler_rw))
LIBALIAS_LOCK_INIT();
}
static void
_handler_chain_destroy(void)
{
if (rw_initialized(&handler_rw))
LIBALIAS_LOCK_DESTROY();
}
#else
#define LIBALIAS_LOCK_INIT() ;
#define LIBALIAS_LOCK_DESTROY() ;
#define LIBALIAS_WLOCK_ASSERT() ;
#define LIBALIAS_RLOCK() ;
#define LIBALIAS_RUNLOCK() ;
#define LIBALIAS_WLOCK() ;
#define LIBALIAS_WUNLOCK() ;
#define _handler_chain_init() ;
#define _handler_chain_destroy() ;
#endif
void
handler_chain_init(void)
{
_handler_chain_init();
}
void
handler_chain_destroy(void)
{
_handler_chain_destroy();
}
static int
_attach_handler(struct proto_handler *p)
{
struct proto_handler *b = NULL;
LIBALIAS_WLOCK_ASSERT();
LIST_FOREACH(b, &handler_chain, entries) {
if ((b->pri == p->pri) &&
(b->dir == p->dir) &&
(b->proto == p->proto))
return (EEXIST); /* Priority conflict. */
if (b->pri > p->pri) {
LIST_INSERT_BEFORE(b, p, entries);
return (0);
}
}
/* End of list or found right position, inserts here. */
if (b)
LIST_INSERT_AFTER(b, p, entries);
else
LIST_INSERT_HEAD(&handler_chain, p, entries);
return (0);
}
static int
_detach_handler(struct proto_handler *p)
{
struct proto_handler *b, *b_tmp;;
LIBALIAS_WLOCK_ASSERT();
LIST_FOREACH_SAFE(b, &handler_chain, entries, b_tmp) {
if (b == p) {
LIST_REMOVE(b, entries);
return (0);
}
}
return (ENOENT); /* Handler not found. */
}
int
LibAliasAttachHandlers(struct proto_handler *_p)
{
int i, error = -1;
LIBALIAS_WLOCK();
for (i=0; 1; i++) {
if (*((int *)&_p[i]) == EOH)
break;
error = _attach_handler(&_p[i]);
if (error != 0)
break;
}
LIBALIAS_WUNLOCK();
return (error);
}
int
LibAliasDetachHandlers(struct proto_handler *_p)
{
int i, error = -1;
LIBALIAS_WLOCK();
for (i=0; 1; i++) {
if (*((int *)&_p[i]) == EOH)
break;
error = _detach_handler(&_p[i]);
if (error != 0)
break;
}
LIBALIAS_WUNLOCK();
return (error);
}
int
detach_handler(struct proto_handler *_p)
{
int error = -1;
LIBALIAS_WLOCK();
error = _detach_handler(_p);
LIBALIAS_WUNLOCK();
return (error);
}
int
find_handler(int8_t dir, int8_t proto, struct libalias *la, struct ip *pip,
struct alias_data *ad)
{
struct proto_handler *p;
int error = ENOENT;
LIBALIAS_RLOCK();
LIST_FOREACH(p, &handler_chain, entries) {
if ((p->dir & dir) && (p->proto & proto))
if (p->fingerprint(la, pip, ad) == 0) {
error = p->protohandler(la, pip, ad);
break;
}
}
LIBALIAS_RUNLOCK();
return (error);
}
struct proto_handler *
first_handler(void)
{
return (LIST_FIRST(&handler_chain));
}
/* Dll manipulation code - this code is not thread safe... */
int
attach_dll(struct dll *p)
{
struct dll *b;
SLIST_FOREACH(b, &dll_chain, next) {
if (!strncmp(b->name, p->name, DLL_LEN))
return (EEXIST); /* Dll name conflict. */
}
SLIST_INSERT_HEAD(&dll_chain, p, next);
return (0);
}
void *
detach_dll(char *p)
{
struct dll *b = NULL, *b_tmp;
void *error = NULL;
SLIST_FOREACH_SAFE(b, &dll_chain, next, b_tmp)
if (!strncmp(b->name, p, DLL_LEN)) {
SLIST_REMOVE(&dll_chain, b, dll, next);
error = b;
break;
}
return (error);
}
struct dll *
walk_dll_chain(void)
{
struct dll *t;
t = SLIST_FIRST(&dll_chain);
if (t == NULL)
return (NULL);
SLIST_REMOVE_HEAD(&dll_chain, next);
return (t);
}

View File

@ -0,0 +1,157 @@
/*-
* Copyright (c) 2005 Paolo Pisati <piso@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.
*
* $FreeBSD$
*/
/*
* Alias_mod.h defines the outside world interfaces for the packet aliasing
* modular framework
*/
#ifndef _ALIAS_MOD_H_
#define _ALIAS_MOD_H_
#ifdef _KERNEL
MALLOC_DECLARE(M_ALIAS);
/* 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
#endif
/* Protocol handlers struct & function. */
/* Packet flow direction. */
#define IN 1
#define OUT 2
/* Working protocol. */
#define IP 1
#define TCP 2
#define UDP 4
/*
* 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 *oaddr; /* Original address. */
struct in_addr *aaddr; /* Alias address. */
uint16_t *aport; /* Alias port. */
uint16_t *sport, *dport; /* Source & destination port */
uint16_t maxpktsize; /* Max packet size. */
};
/*
* 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. */
uint8_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);
LIST_ENTRY(proto_handler) entries;
};
/*
* 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().
*/
SLIST_ENTRY(dll) next;
};
/* Functions used with protocol handlers. */
void handler_chain_init(void);
void handler_chain_destroy(void);
int LibAliasAttachHandlers(struct proto_handler *);
int LibAliasDetachHandlers(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);
/* End of handlers. */
#define EOH -1
/*
* 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_ */

View File

@ -43,27 +43,147 @@ __FBSDID("$FreeBSD$");
/* 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/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <arpa/inet.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/udp.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
#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 *);
static int
fingerprint1(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
ah->aaddr == NULL || ah->aport == NULL)
return (-1);
if (ntohs(*ah->dport) == NETBIOS_DGM_PORT_NUMBER
|| ntohs(*ah->sport) == NETBIOS_DGM_PORT_NUMBER)
return (0);
return (-1);
}
static int
protohandler1(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleUdpNbt(la, pip, ah->lnk, ah->aaddr, *ah->aport);
return (0);
}
static int
fingerprint2(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
ah->aaddr == NULL || ah->aport == NULL)
return (-1);
if (ntohs(*ah->dport) == NETBIOS_NS_PORT_NUMBER
|| ntohs(*ah->sport) == NETBIOS_NS_PORT_NUMBER)
return (0);
return (-1);
}
static int
protohandler2in(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleUdpNbtNS(la, pip, ah->lnk, ah->aaddr, ah->aport,
ah->oaddr, ah->dport);
return (0);
}
static int
protohandler2out(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleUdpNbtNS(la, pip, ah->lnk, &pip->ip_src, ah->sport,
ah->aaddr, ah->aport);
return (0);
}
/* Kernel module definition. */
struct proto_handler handlers[] = {
{
.pri = 130,
.dir = IN|OUT,
.proto = UDP,
.fingerprint = &fingerprint1,
.protohandler = &protohandler1
},
{
.pri = 140,
.dir = IN,
.proto = UDP,
.fingerprint = &fingerprint2,
.protohandler = &protohandler2in
},
{
.pri = 140,
.dir = OUT,
.proto = UDP,
.fingerprint = &fingerprint2,
.protohandler = &protohandler2out
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,7 +332,7 @@ AliasHandleName(u_char * p, char *pmax)
#define DGM_POSITIVE_RES 0x15
#define DGM_NEGATIVE_RES 0x16
int
static int
AliasHandleUdpNbt(
struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */
@ -640,7 +760,7 @@ AliasHandleResource(
return ((u_char *) q);
}
int
static int
AliasHandleUdpNbtNS(
struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */

View File

@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/proc.h>
#else
#include <sys/types.h>
#include <stdlib.h>

View File

@ -39,6 +39,169 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
/* Includes */
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/limits.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <stdio.h>
#endif
#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 *);
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
return (-1);
if (ntohs(*ah->dport) == PPTP_CONTROL_PORT_NUMBER
|| ntohs(*ah->sport) == PPTP_CONTROL_PORT_NUMBER)
return (0);
return (-1);
}
static int
fingerprintgre(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
return (0);
}
static int
protohandlerin(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandlePptpIn(la, pip, ah->lnk);
return (0);
}
static int
protohandlerout(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandlePptpOut(la, pip, ah->lnk);
return (0);
}
static int
protohandlergrein(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (la->packetAliasMode & PKT_ALIAS_PROXY_ONLY ||
AliasHandlePptpGreIn(la, pip) == 0)
return (0);
return (-1);
}
static int
protohandlergreout(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (AliasHandlePptpGreOut(la, pip) == 0)
return (0);
return (-1);
}
/* Kernel module definition. */
struct proto_handler handlers[] = {
{
.pri = 200,
.dir = IN,
.proto = TCP,
.fingerprint = &fingerprint,
.protohandler = &protohandlerin
},
{
.pri = 210,
.dir = OUT,
.proto = TCP,
.fingerprint = &fingerprint,
.protohandler = &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.
*/
{
.pri = INT_MAX,
.dir = IN,
.proto = IP,
.fingerprint = &fingerprintgre,
.protohandler = &protohandlergrein
},
{
.pri = INT_MAX,
.dir = OUT,
.proto = IP,
.fingerprint = &fingerprintgre,
.protohandler = &protohandlergreout
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,26 +228,6 @@ __FBSDID("$FreeBSD$");
*/
/* 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
*/
@ -153,7 +296,7 @@ typedef struct pptpCallIds *PptpCallId;
static PptpCallId AliasVerifyPptp(struct ip *, u_int16_t *);
void
static void
AliasHandlePptpOut(struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */
struct alias_link *lnk)
@ -225,7 +368,7 @@ AliasHandlePptpOut(struct libalias *la,
}
}
void
static void
AliasHandlePptpIn(struct libalias *la,
struct ip *pip, /* IP packet to examine/patch */
struct alias_link *lnk)
@ -328,8 +471,7 @@ AliasVerifyPptp(struct ip *pip, u_int16_t * ptype)
return (PptpCallId) (hptr + 1);
}
int
static int
AliasHandlePptpGreOut(struct libalias *la, struct ip *pip)
{
GreHdr *gr;
@ -353,8 +495,7 @@ AliasHandlePptpGreOut(struct libalias *la, struct ip *pip)
return (0);
}
int
static int
AliasHandlePptpGreIn(struct libalias *la, struct ip *pip)
{
GreHdr *gr;

View File

@ -58,30 +58,24 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/ctype.h>
#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>
#include <string.h>
#endif
/* BSD IPV4 includes */
#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 <arpa/inet.h>
#include "alias.h" /* Public API functions for libalias */
#include "alias_local.h" /* Functions used by alias*.c */
#endif

View File

@ -32,26 +32,92 @@
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#endif
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.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
AliasHandleSkinny(struct libalias *, struct ip *, struct alias_link *);
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL)
return (-1);
if (la->skinnyPort != 0 && (ntohs(*ah->sport) == la->skinnyPort ||
ntohs(*ah->dport) == la->skinnyPort))
return (0);
return (-1);
}
static int
protohandler(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
AliasHandleSkinny(la, pip, ah->lnk);
return (0);
}
struct proto_handler handlers[] = {
{
.pri = 110,
.dir = IN|OUT,
.proto = TCP,
.fingerprint = &fingerprint,
.protohandler = &protohandler
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,7 +299,7 @@ alias_skinny_opnrcvch_ack(struct libalias *la, struct OpenReceiveChannelAck *opn
return (0);
}
void
static void
AliasHandleSkinny(struct libalias *la, struct ip *pip, struct alias_link *lnk)
{
size_t hlen, tlen, dlen;

View File

@ -100,8 +100,11 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/libkern.h>
#include <sys/systm.h>
#include <sys/kernel.h>
#include <sys/module.h>
#else
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
@ -111,13 +114,92 @@ __FBSDID("$FreeBSD$");
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <netinet/udp.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
#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);
static int
fingerprint(struct libalias *la, struct ip *pip, struct alias_data *ah)
{
if (ah->dport == NULL || ah->sport == NULL || ah->lnk == NULL ||
ah->maxpktsize == 0)
return (-1);
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 (0);
return (-1);
}
static 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->aport, IPPROTO_UDP);
else AliasHandleRtspOut(la, pip, ah->lnk, ah->maxpktsize);
return (0);
}
struct proto_handler handlers[] = {
{
.pri = 100,
.dir = OUT,
.proto = TCP|UDP,
.fingerprint = &fingerprint,
.protohandler = &protohandler
},
{ EOH }
};
static int
mod_handler(module_t mod, int type, void *data)
{
int error;
switch (type) {
case MOD_LOAD:
error = 0;
LibAliasAttachHandlers(handlers);
break;
case MOD_UNLOAD:
error = 0;
LibAliasDetachHandlers(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,7 +474,7 @@ alias_pna_out(struct libalias *la, struct ip *pip,
return (0);
}
void
static void
AliasHandleRtspOut(struct libalias *la, struct ip *pip, struct alias_link *lnk, int maxpacketsize)
{
int hlen, tlen, dlen;

View File

@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$");
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/proc.h>
#else
#include <sys/types.h>
#include <stdio.h>

View File

@ -893,6 +893,9 @@ added support for PPTP and RTSP.
added support for RTSP/PNA.
.An Ruslan Ermilov Aq ru@FreeBSD.org
added support for PPTP and LSNAT as well as general hacking.
.An Paolo Pisati Aq piso@FreeBSD.org
made the library modular, moving support for all
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,3 +1014,429 @@ If this results in a conflict, then port numbers are randomly chosen until
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 Xr ipfw 4 Sh SUPPORT)
One of the latest improvements to
.Nm libalias was to make its support
for new protocols independent from the rest of the library, giving it
the ability to load/unload at run-time support for new protocols.
To achieve this feature, all the code for protocol handling was moved
to a series of modules outside of the main library.
These modules are compiled from the same sources but works in a
different ways, depending on whether they are compiled to work inside a kernel
or as part of the userland library.
.Ss LIBALIAS MODULES IN KERNEL LAND
When compiled to be parts of a kernel,
.Nm libalias
modules are plain simple KLDs:
.Pp
.Bl -item -compact
.It
.Pa /boot/kernel/alias_cuseeme.ko
.It
.Pa /boot/kernel/alias_dummy.ko
.It
.Pa /boot/kernel/alias_ftp.ko
.It
.Pa /boot/kernel/alias_irc.ko
.It
.Pa /boot/kernel/alias_nbt.ko
.It
.Pa /boot/kernel/alias_pptp.ko
.It
.Pa /boot/kernel/alias_skinny.ko
.It
.Pa /boot/kernel/alias_smedia.ko
.El
.Pp
To add support for new protocol just kldload its module, for example:
.Pp
.Dl "kldload alias_ftp
.Pp
and when you don't need it anymore, you can unload it:
.Pp
.Dl "kldunload alias_ftp
.Ss LIBALIAS MODULES IN USERLAND
Due to the differences between kernel and userland (no kld mechanism,
many different address spaces, etc etc), we had to change a bit how to
handle modules loading/tracking/unloading in userland.
.Pp
While compiled for a userland
.Nm libalias
all the modules are plain libraries:
.Pp
.Bl -item -compact
.It
.Pa /usr/lib/libalias_cuseeme.a
.It
.Pa /usr/lib/libalias_cuseeme.so -> /lib/libalias_cuseeme.so.4
.It
.Pa /usr/lib/libalias_cuseeme_p.a
.It
.Pa /usr/lib/libalias_dummy.a
.It
.Pa /usr/lib/libalias_dummy.so -> /lib/libalias_dummy.so.4
.It
.Pa /usr/lib/libalias_dummy_p.a
.It
.Pa /usr/lib/libalias_ftp.a
.It
.Pa /usr/lib/libalias_ftp.so -> /lib/libalias_ftp.so.4
.It
.Pa /usr/lib/libalias_ftp_p.a
.It
.Pa /usr/lib/libalias_irc.a
.It
.Pa /usr/lib/libalias_irc.so -> /lib/libalias_irc.so.4
.It
.Pa /usr/lib/libalias_irc_p.a
.It
.Pa /usr/lib/libalias_nbt.a
.It
.Pa /usr/lib/libalias_nbt.so -> /lib/libalias_nbt.so.4
.It
.Pa /usr/lib/libalias_nbt_p.a
.It
.Pa /usr/lib/libalias_pptp.a
.It
.Pa /usr/lib/libalias_pptp.so -> /lib/libalias_pptp.so.4
.It
.Pa /usr/lib/libalias_pptp_p.a
.It
.Pa /usr/lib/libalias_skinny.a
.It
.Pa /usr/lib/libalias_skinny.so -> /lib/libalias_skinny.so.4
.It
.Pa /usr/lib/libalias_skinny_p.a
.It
.Pa /usr/lib/libalias_smedia.a
.It
.Pa /usr/lib/libalias_smedia.so -> /lib/libalias_smedia.so.4
.It
.Pa /usr/lib/libalias_smedia_p.a
.El
.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
.Nm libalias
in /etc you should
find a file called libalias.conf with the following contents (or
similar):
.Pp
.Bl -item -compact
.It
.Pa /usr/lib/libalias_cuseeme.so
.It
.Pa /usr/lib/libalias_ftp.so
.It
.Pa /usr/lib/libalias_irc.so
.It
.Pa /usr/lib/libalias_nbt.so
.It
.Pa /usr/lib/libalias_pptp.so
.It
.Pa /usr/lib/libalias_skinny.so
.It
.Pa /usr/lib/libalias_smedia.so
.El
.Pp
this file contains the paths to the modules that
.Nm 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
.Dl "kill -HUP <process pid>
.Ss MODULAR ARCHITECURE: HOW IT WORKS
The modular architecture of
.Nm libalias
work (almost) the same when it's
running inside kernel or in userland. From alias_mod.c:
.Bd -literal
/* protocol and userland 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
.Nm libalias
correctly nat it.
.Pp
When a packet enters
.Nm libalias
, if it meets a module hook,
handler_chain is searched 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
.Nm 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);
.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,
.Nm 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 userland
.Nm libalias
modules loaded.
.Pp
When an application calls LibAliasRefreshModules(),
.Nm 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 userland, 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
.Nm 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 USERLAND LIBALIAS MODULES
If you have any application that uses
.Nm libalias
and you want to add it
support for 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)
.An {
.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
.Ss LOGGING SUPPORT IN KERNEL LAND
.Pp
While working as kld,
.Nm 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
.Nm 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.