diff options
Diffstat (limited to 'sys/netinet')
-rw-r--r-- | sys/netinet/libalias/alias.c | 291 | ||||
-rw-r--r-- | sys/netinet/libalias/alias.h | 14 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_cuseeme.c | 99 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_db.c | 149 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_dummy.c | 153 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_ftp.c | 82 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_irc.c | 83 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_local.h | 64 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_mod.c | 284 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_mod.h | 157 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_nbt.c | 138 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_old.c | 1 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_pptp.c | 193 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_proxy.c | 12 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_skinny.c | 80 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_smedia.c | 88 | ||||
-rw-r--r-- | sys/netinet/libalias/alias_util.c | 1 | ||||
-rw-r--r-- | sys/netinet/libalias/libalias.3 | 429 |
18 files changed, 2052 insertions, 266 deletions
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c index aa2bed9..0120c19 100644 --- a/sys/netinet/libalias/alias.c +++ b/sys/netinet/libalias/alias.c @@ -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; + + /* + * 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 + }; -/* 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); + /* 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 diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h index 2c50943..4a809f4 100644 --- a/sys/netinet/libalias/alias.h +++ b/sys/netinet/libalias/alias.h @@ -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, diff --git a/sys/netinet/libalias/alias_cuseeme.c b/sys/netinet/libalias/alias_cuseeme.c index 171a6f9..f255942 100644 --- a/sys/netinet/libalias/alias_cuseeme.c +++ b/sys/netinet/libalias/alias_cuseeme.c @@ -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; diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c index 281d5f5..1061c74 100644 --- a/sys/netinet/libalias/alias_db.c +++ b/sys/netinet/libalias/alias_db.c @@ -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 @@ -2489,6 +2505,9 @@ LibAliasInit(struct libalias *la) #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) { diff --git a/sys/netinet/libalias/alias_dummy.c b/sys/netinet/libalias/alias_dummy.c new file mode 100644 index 0000000..fc6a0f9 --- /dev/null +++ b/sys/netinet/libalias/alias_dummy.c @@ -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. */ +} + diff --git a/sys/netinet/libalias/alias_ftp.c b/sys/netinet/libalias/alias_ftp.c index d91e1cd..6016f1b 100644 --- a/sys/netinet/libalias/alias_ftp.c +++ b/sys/netinet/libalias/alias_ftp.c @@ -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 */ diff --git a/sys/netinet/libalias/alias_irc.c b/sys/netinet/libalias/alias_irc.c index defdb56..e9a8d09 100644 --- a/sys/netinet/libalias/alias_irc.c +++ b/sys/netinet/libalias/alias_irc.c @@ -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); + +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 -void +static void AliasHandleIrcOut(struct libalias *la, struct ip *pip, /* IP packet to examine */ struct alias_link *lnk, /* Which link are we on? */ diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h index 4dc2e0a..1dc50c8 100644 --- a/sys/netinet/libalias/alias_local.h +++ b/sys/netinet/libalias/alias_local.h @@ -46,18 +46,13 @@ #ifndef _ALIAS_LOCAL_H_ #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 +#include <sys/types.h> +#include <sys/sysctl.h> -/* 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_ */ diff --git a/sys/netinet/libalias/alias_mod.c b/sys/netinet/libalias/alias_mod.c new file mode 100644 index 0000000..71192e9 --- /dev/null +++ b/sys/netinet/libalias/alias_mod.c @@ -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); +} diff --git a/sys/netinet/libalias/alias_mod.h b/sys/netinet/libalias/alias_mod.h new file mode 100644 index 0000000..5e193e9 --- /dev/null +++ b/sys/netinet/libalias/alias_mod.h @@ -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_ */ diff --git a/sys/netinet/libalias/alias_nbt.c b/sys/netinet/libalias/alias_nbt.c index 303cf3f..0d17870 100644 --- a/sys/netinet/libalias/alias_nbt.c +++ b/sys/netinet/libalias/alias_nbt.c @@ -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 */ diff --git a/sys/netinet/libalias/alias_old.c b/sys/netinet/libalias/alias_old.c index e885fdc..528f6be 100644 --- a/sys/netinet/libalias/alias_old.c +++ b/sys/netinet/libalias/alias_old.c @@ -29,6 +29,7 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL #include <sys/param.h> +#include <sys/proc.h> #else #include <sys/types.h> #include <stdlib.h> diff --git a/sys/netinet/libalias/alias_pptp.c b/sys/netinet/libalias/alias_pptp.c index 0ce69a4..b4fd9d0 100644 --- a/sys/netinet/libalias/alias_pptp.c +++ b/sys/netinet/libalias/alias_pptp.c @@ -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; diff --git a/sys/netinet/libalias/alias_proxy.c b/sys/netinet/libalias/alias_proxy.c index f683ba0..699e421 100644 --- a/sys/netinet/libalias/alias_proxy.c +++ b/sys/netinet/libalias/alias_proxy.c @@ -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 diff --git a/sys/netinet/libalias/alias_skinny.c b/sys/netinet/libalias/alias_skinny.c index f109f74..91307ac 100644 --- a/sys/netinet/libalias/alias_skinny.c +++ b/sys/netinet/libalias/alias_skinny.c @@ -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; diff --git a/sys/netinet/libalias/alias_smedia.c b/sys/netinet/libalias/alias_smedia.c index c314a65..58f844b 100644 --- a/sys/netinet/libalias/alias_smedia.c +++ b/sys/netinet/libalias/alias_smedia.c @@ -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; diff --git a/sys/netinet/libalias/alias_util.c b/sys/netinet/libalias/alias_util.c index dc70bc1..4cdbaf8 100644 --- a/sys/netinet/libalias/alias_util.c +++ b/sys/netinet/libalias/alias_util.c @@ -45,6 +45,7 @@ __FBSDID("$FreeBSD$"); #ifdef _KERNEL #include <sys/param.h> +#include <sys/proc.h> #else #include <sys/types.h> #include <stdio.h> diff --git a/sys/netinet/libalias/libalias.3 b/sys/netinet/libalias/libalias.3 index 4605e76..55a0c3e 100644 --- a/sys/netinet/libalias/libalias.3 +++ b/sys/netinet/libalias/libalias.3 @@ -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. |