From owner-svn-src-all@FreeBSD.ORG Sat Feb 7 18:49:42 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id AC523106566C; Sat, 7 Feb 2009 18:49:42 +0000 (UTC) (envelope-from piso@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 97CB58FC16; Sat, 7 Feb 2009 18:49:42 +0000 (UTC) (envelope-from piso@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n17Ingwa000959; Sat, 7 Feb 2009 18:49:42 GMT (envelope-from piso@svn.freebsd.org) Received: (from piso@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n17IngZN000950; Sat, 7 Feb 2009 18:49:42 GMT (envelope-from piso@svn.freebsd.org) Message-Id: <200902071849.n17IngZN000950@svn.freebsd.org> From: Paolo Pisati Date: Sat, 7 Feb 2009 18:49:42 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r188294 - in head: sbin sbin/ipfw sys sys/modules/libalias/libalias sys/netinet sys/netinet/libalias X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 07 Feb 2009 18:49:43 -0000 Author: piso Date: Sat Feb 7 18:49:42 2009 New Revision: 188294 URL: http://svn.freebsd.org/changeset/base/188294 Log: Add SCTP NAT support. Submitted by: CAIA (http://caia.swin.edu.au) Added: head/sys/netinet/libalias/alias_sctp.c - copied, changed from r186543, user/piso/sys/netinet/libalias/alias_sctp.c head/sys/netinet/libalias/alias_sctp.h - copied, changed from r186543, user/piso/sys/netinet/libalias/alias_sctp.h Modified: head/sbin/ (props changed) head/sbin/ipfw/ipfw.8 head/sbin/ipfw/nat.c head/sys/ (props changed) head/sys/modules/libalias/libalias/Makefile head/sys/netinet/ip_fw_nat.c head/sys/netinet/libalias/alias.c head/sys/netinet/libalias/alias_db.c head/sys/netinet/libalias/alias_local.h head/sys/netinet/sctp_crc32.c head/sys/netinet/sctp_crc32.h Modified: head/sbin/ipfw/ipfw.8 ============================================================================== --- head/sbin/ipfw/ipfw.8 Sat Feb 7 16:37:02 2009 (r188293) +++ head/sbin/ipfw/ipfw.8 Sat Feb 7 18:49:42 2009 (r188294) @@ -2183,17 +2183,173 @@ Redirect and LSNAT support follow closel See Section .Sx EXAMPLES for some examples on how to do redirect and lsnat. +.Sh SCTP NAT SUPPORT +Sctp nat can be configured in a simillar manner to TCP through the +ipfw command line tool +.Xr ipfw 8 +, the main difference is that +.Nm sctp nat +does not do port +translation. Since the local and global side ports will be the same, +there is no need to specify both. Ports are redirected as follows: +.Bd -ragged -offset indent +.Bk -words +.Cm nat +.Ar nat_number +.Cm config if +.Ar nic +.Cm redirect_port sctp +.Ar ip_address [,addr_list] {[port | port-port] [,ports]} +.Ek +.Ed +.Pp +. +Most +.B sctp nat +configuration can be done in real-time through the +.B sysctl(8) +interface. All may be changed dynamically, though the hash_table size will only +change for new +.Nm nat +instances. See +.Sx SYSCTL VARIABLES +for more info. .Sh SYSCTL VARIABLES A set of .Xr sysctl 8 variables controls the behaviour of the firewall and associated modules -.Pq Nm dummynet , bridge . +.Pq Nm dummynet , bridge , sctp nat . These are shown below together with their default value (but always check with the .Xr sysctl 8 command what value is actually in use) and meaning: .Bl -tag -width indent +.It Va net.inet.ip.alias.sctp.accept_global_ootb_addip: No 0 +Defines how the +.Nm nat +responds to receipt of global OOTB ASCONF-AddIP: +.Bl -tag -width indent +.It Cm 0 +No response (unless a partially matching association exists - +ports and vtags match but global address does not) +.It Cm 1 +.Nm nat +will accept and process all OOTB global AddIP messages. +.El +.Pp +Option 1 should never be selected as this forms a security risk. An attacker can +establish multiple fake associations by sending AddIP messages. +.It Va net.inet.ip.alias.sctp.chunk_proc_limit: No 5 +Defines the maximum number of chunks in an SCTP packet that will be parsed for a +packet that matches an existing association. This value is enforced to be greater or equal +than +.Cm net.inet.ip.alias.sctp.initialising_chunk_proc_limit . +A high value is +a DoS risk yet setting too low a value may result in important control chunks in +the packet not being located and parsed. +.It Va net.inet.ip.alias.sctp.error_on_ootb: No 1 +Defines when the +.Nm nat +responds to any Out-of-the-Blue (OOTB) packets with ErrorM +packets. An OOTB packet is a packet that arrives with no existing association +registered in the +.Nm nat +and is not an INIT or ASCONF-AddIP packet: +.Bl -tag -width indent +.It Cm 0 +ErrorM is never sent in response to OOTB packets. +.It Cm 1 +ErrorM is only sent to OOTB packets received on the local side. +.It Cm 2 +ErrorM is sent to the local side and on the global side ONLY if there is a +partial match (ports and vtags match but the source global IP does not). This +value is only useful if the +.Nm nat +is tracking global IP addresses. +.It Cm 3 +ErrorM is sent in response to all OOTB packets on both the local and global side +(DoS risk). +.El +.Pp +At the moment the default is 0, since the ErrorM packet is not yet +supported by most SCTP stacks. When it is supported, and if not tracking +global addresses, we recommend setting this value to 1 to allow +multi-homed local hosts to function with the +.Nm nat . +To track global addresses, we recommend setting this value to 2 to +allow global hosts to be informed when they need to (re)send an +ASCONF-AddIP. Value 3 should never be chosen (except for debugging) as +the +.Nm nat +will respond to all OOTB global packets (a DoS risk). +.It Va net.inet.ip.alias.sctp.hashtable_size: No 2003 +Size of hash tables used for +.Nm nat +lookups (100 < prime_number > 1000001) +This value sets the +.Nm hash table +size for any future created +.Nm nat +instance and therefore must be set prior to creating a +.Nm nat +instance. +The table sizes my be changed to suit specific needs. If there will be few +concurrent associations, and memory is scarce, you may make these smaller. If +there will be many thousands (or millions) of concurrent associations, you +should make these larger. A prime number is best for the table size. The sysctl +update function will adjust your input value to the next highest prime number. +.It Va net.inet.ip.alias.sctp.holddown_time: No 0 +Hold association in table for this many seconds after receiving a +SHUTDOWN-COMPLETE. This allows endpoints to correct shutdown gracefully if a +shutdown_complete is lost and retransmissions are required. +.It Va net.inet.ip.alias.sctp.init_timer: No 15 +Timeout value while waiting for (INIT-ACK|AddIP-ACK). +This value cannot be 0. +.It Va net.inet.ip.alias.sctp.initialising_chunk_proc_limit: No 2 +Defines the maximum number of chunks in an SCTP packet that will be parsed when +no existing association exists that matches that packet. Ideally this packet +will only be an INIT or ASCONF-AddIP packet. A higher value may become a DoS +risk as malformed packets can consume processing resources. +.It Va net.inet.ip.alias.sctp.param_proc_limit: No 25 +Defines the maximum number of parameters within a chunk that will be parsed in a +packet. As for other similar sysctl variables, larger values pose a DoS risk. +.It Va net.inet.ip.alias.sctp.log_level: No 0 +Level of detail in the system log messages (0 \- minimal, 1 \- event, +2 \- info, 3 \- detail, 4 \- debug, 5 \- max debug). May be a good +option in high loss environments. +.It Va net.inet.ip.alias.sctp.shutdown_time: No 15 +Timeout value while waiting for SHUTDOWN-COMPLETE. +This value cannot be 0. +.It Va net.inet.ip.alias.sctp.track_global_addresses: No 0 +Enables/disables global IP address tracking within the +.Nm nat +and places an +upper limit on the number of addresses tracked for each association: +.Bl -tag -width indent +.It Cm 0 +Global tracking is disabled +.It Cm >1 +Enables tracking, the maximum number of addresses tracked for each +association is limited to this value +.El +.Pp +This variable is fully dynamic, the new value will be adopted for all newly +arriving associations, existing association are treated as they were previously. +Global tracking will decrease the number of collisions within the +.Nm nat +at a cost +of increased processing load, memory usage, complexity, and possible +.Nm nat +state +problems in complex networks with multiple +.Nm nats . +We recommend not tracking +global IP addresses, this will still result in a fully functional +.Nm nat . +.It Va net.inet.ip.alias.sctp.up_timer: No 300 +Timeout value to keep an association up with no traffic. +This value cannot be 0. .It Va net.inet.ip.dummynet.expire : No 1 Lazily delete dynamic pipes/queue once they have no pending traffic. You can disable this by setting the variable to 0, in which case @@ -2718,6 +2874,15 @@ as part of a Summer of Code 2005 project Work on .Nm dummynet traffic shaper supported by Akamba Corp. +.Pp +Sctp +.Nm nat +support has been developed by +.An The Centre for Advanced Internet Architectures (CAIA) Aq http://www.caia.swin.edu.au . +The primary developers and maintainers are David Hayes and Jason But. +For further information visit: +.Aq http://www.caia.swin.edu.au/urp/SONATA +. .Sh BUGS The syntax has grown over the years and sometimes it might be confusing. Unfortunately, backward compatibility prevents cleaning up mistakes Modified: head/sbin/ipfw/nat.c ============================================================================== --- head/sbin/ipfw/nat.c Sat Feb 7 16:37:02 2009 (r188293) +++ head/sbin/ipfw/nat.c Sat Feb 7 18:49:42 2009 (r188294) @@ -257,7 +257,9 @@ StrToProto (const char* str) if (!strcmp (str, "udp")) return IPPROTO_UDP; - errx (EX_DATAERR, "unknown protocol %s. Expected tcp or udp", str); + if (!strcmp (str, "sctp")) + return IPPROTO_SCTP; + errx (EX_DATAERR, "unknown protocol %s. Expected sctp, tcp or udp", str); } static int @@ -433,13 +435,27 @@ setup_redir_port(char *spool_buf, int le strncpy(tmp_spool_buf, *av, strlen(*av)+1); lsnat = 1; } else { - if (StrToAddrAndPortRange (*av, &r->laddr, protoName, - &portRange) != 0) - errx(EX_DATAERR, "redirect_port:" - "invalid local port range"); + /* + * The sctp nat does not allow the port numbers to be mapped to + * new port numbers. Therefore, no ports are to be specified + * in the target port field. + */ + if (r->proto == IPPROTO_SCTP) { + if (strchr (*av, ':')) + errx(EX_DATAERR, "redirect_port:" + "port numbers do not change in sctp, so do not " + "specify them as part of the target"); + else + StrToAddr(*av, &r->laddr); + } else { + if (StrToAddrAndPortRange (*av, &r->laddr, protoName, + &portRange) != 0) + errx(EX_DATAERR, "redirect_port:" + "invalid local port range"); - r->lport = GETLOPORT(portRange); - numLocalPorts = GETNUMPORTS(portRange); + r->lport = GETLOPORT(portRange); + numLocalPorts = GETNUMPORTS(portRange); + } } INC_ARGCV(); @@ -463,6 +479,10 @@ setup_redir_port(char *spool_buf, int le } r->pport = GETLOPORT(portRange); + if (r->proto == IPPROTO_SCTP) { /* so the logic below still works */ + numLocalPorts = GETNUMPORTS(portRange); + r->lport = r->pport; + } r->pport_cnt = GETNUMPORTS(portRange); INC_ARGCV(); @@ -518,14 +538,31 @@ setup_redir_port(char *spool_buf, int le goto nospace; len -= SOF_SPOOL; space += SOF_SPOOL; - if (StrToAddrAndPortRange(sep, &tmp->addr, protoName, - &portRange) != 0) - errx(EX_DATAERR, "redirect_port:" - "invalid local port range"); - if (GETNUMPORTS(portRange) != 1) - errx(EX_DATAERR, "redirect_port: local port" - "must be single in this context"); - tmp->port = GETLOPORT(portRange); + /* + * The sctp nat does not allow the port numbers to be mapped to new port numbers + * Therefore, no ports are to be specified in the target port field + */ + if (r->proto == IPPROTO_SCTP) { + if (strchr (sep, ':')) { + errx(EX_DATAERR, "redirect_port:" + "port numbers do not change in " + "sctp, so do not specify them as " + "part of the target"); + } else { + StrToAddr(sep, &tmp->addr); + tmp->port = r->pport; + } + } else { + if (StrToAddrAndPortRange(sep, &tmp->addr, + protoName, &portRange) != 0) + errx(EX_DATAERR, "redirect_port:" + "invalid local port range"); + if (GETNUMPORTS(portRange) != 1) + errx(EX_DATAERR, "redirect_port: " + "local port must be single in " + "this context"); + tmp->port = GETLOPORT(portRange); + } r->spool_cnt++; /* Point to the next possible cfg_spool. */ spool_buf = &spool_buf[SOF_SPOOL]; Modified: head/sys/modules/libalias/libalias/Makefile ============================================================================== --- head/sys/modules/libalias/libalias/Makefile Sat Feb 7 16:37:02 2009 (r188293) +++ head/sys/modules/libalias/libalias/Makefile Sat Feb 7 18:49:42 2009 (r188294) @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../../netinet/libalias KMOD= libalias -SRCS= alias.c alias_db.c alias_proxy.c alias_util.c alias_mod.c +SRCS= alias.c alias_db.c alias_proxy.c alias_util.c alias_mod.c alias_sctp.c .include Modified: head/sys/netinet/ip_fw_nat.c ============================================================================== --- head/sys/netinet/ip_fw_nat.c Sat Feb 7 16:37:02 2009 (r188293) +++ head/sys/netinet/ip_fw_nat.c Sat Feb 7 18:49:42 2009 (r188294) @@ -326,6 +326,10 @@ ipfw_nat(struct ip_fw_args *args, struct else retval = LibAliasOut(t->lib, c, mcl->m_len + M_TRAILINGSPACE(mcl)); + if (retval == PKT_ALIAS_RESPOND) { + m->m_flags |= M_SKIP_FIREWALL; + retval = PKT_ALIAS_OK; + } if (retval != PKT_ALIAS_OK && retval != PKT_ALIAS_FOUND_HEADER_FRAGMENT) { /* XXX - should i add some logging? */ Modified: head/sys/netinet/libalias/alias.c ============================================================================== --- head/sys/netinet/libalias/alias.c Sat Feb 7 16:37:02 2009 (r188293) +++ head/sys/netinet/libalias/alias.c Sat Feb 7 18:49:42 2009 (r188294) @@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #else #include #include @@ -143,6 +144,17 @@ __FBSDID("$FreeBSD$"); #include "alias_mod.h" #endif +/* + * Define libalias SYSCTL Node + */ +#ifdef SYSCTL_NODE + +SYSCTL_DECL(_net_inet); +SYSCTL_DECL(_net_inet_ip); +SYSCTL_NODE(_net_inet_ip, OID_AUTO, alias, CTLFLAG_RW, NULL, "Libalias sysctl API"); + +#endif + static __inline int twowords(void *p) { @@ -1335,6 +1347,11 @@ LibAliasInLocked(struct libalias *la, ch case IPPROTO_TCP: iresult = TcpAliasIn(la, pip); break; +#ifdef _KERNEL + case IPPROTO_SCTP: + iresult = SctpAlias(la, pip, SN_TO_LOCAL); + break; +#endif case IPPROTO_GRE: { int error; struct alias_data ad = { @@ -1477,10 +1494,15 @@ LibAliasOutLocked(struct libalias *la, c case IPPROTO_UDP: iresult = UdpAliasOut(la, pip, maxpacketsize, create); break; - case IPPROTO_TCP: + case IPPROTO_TCP: iresult = TcpAliasOut(la, pip, maxpacketsize, create); break; - case IPPROTO_GRE: { +#ifdef _KERNEL + case IPPROTO_SCTP: + iresult = SctpAlias(la, pip, SN_TO_GLOBAL); + break; +#endif + case IPPROTO_GRE: { int error; struct alias_data ad = { .lnk = NULL, Modified: head/sys/netinet/libalias/alias_db.c ============================================================================== --- head/sys/netinet/libalias/alias_db.c Sat Feb 7 16:37:02 2009 (r188293) +++ head/sys/netinet/libalias/alias_db.c Sat Feb 7 18:49:42 2009 (r188294) @@ -411,6 +411,8 @@ static void ShowAliasStats(struct libali static int InitPacketAliasLog(struct libalias *); static void UninitPacketAliasLog(struct libalias *); +void SctpShowAliasStats(struct libalias *la); + static u_int StartPointIn(struct in_addr alias_addr, u_short alias_port, @@ -489,15 +491,17 @@ ShowAliasStats(struct libalias *la) /* Used for debugging */ if (la->logDesc) { int tot = la->icmpLinkCount + la->udpLinkCount + + (la->sctpLinkCount>>1) + /* sctp counts half associations */ 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", + "icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u", la->icmpLinkCount, la->udpLinkCount, la->tcpLinkCount, + la->sctpLinkCount>>1, /* sctp counts half associations */ la->pptpLinkCount, la->protoLinkCount, la->fragmentIdLinkCount, @@ -508,6 +512,13 @@ ShowAliasStats(struct libalias *la) } } +void SctpShowAliasStats(struct libalias *la) +{ + + ShowAliasStats(la); +} + + /* Internal routines for finding, deleting and adding links Port Allocation: @@ -1278,6 +1289,11 @@ _FindLinkIn(struct libalias *la, struct src_port = lnk->src_port; } + if (link_type == LINK_SCTP) { + lnk->src_addr = src_addr; + lnk->src_port = src_port; + return(lnk); + } lnk = ReLink(lnk, src_addr, dst_addr, alias_addr, src_port, dst_port, alias_port, @@ -2277,10 +2293,13 @@ LibAliasRedirectPort(struct libalias *la case IPPROTO_TCP: link_type = LINK_TCP; break; + case IPPROTO_SCTP: + link_type = LINK_SCTP; + break; default: #ifdef LIBALIAS_DEBUG fprintf(stderr, "PacketAliasRedirectPort(): "); - fprintf(stderr, "only TCP and UDP protocols allowed\n"); + fprintf(stderr, "only SCTP, TCP and UDP protocols allowed\n"); #endif lnk = NULL; goto getout; @@ -2496,6 +2515,9 @@ LibAliasInit(struct libalias *la) LIST_INIT(&la->linkTableOut[i]); for (i = 0; i < LINK_TABLE_IN_SIZE; i++) LIST_INIT(&la->linkTableIn[i]); +#ifdef _KERNEL + AliasSctpInit(la); +#endif LIBALIAS_LOCK_INIT(la); LIBALIAS_LOCK(la); } else { @@ -2503,6 +2525,10 @@ LibAliasInit(struct libalias *la) la->deleteAllLinks = 1; CleanupAliasData(la); la->deleteAllLinks = 0; +#ifdef _KERNEL + AliasSctpTerm(la); + AliasSctpInit(la); +#endif } la->aliasAddress.s_addr = INADDR_ANY; @@ -2511,6 +2537,7 @@ LibAliasInit(struct libalias *la) la->icmpLinkCount = 0; la->udpLinkCount = 0; la->tcpLinkCount = 0; + la->sctpLinkCount = 0; la->pptpLinkCount = 0; la->protoLinkCount = 0; la->fragmentIdLinkCount = 0; @@ -2539,6 +2566,9 @@ LibAliasUninit(struct libalias *la) { LIBALIAS_LOCK(la); +#ifdef _KERNEL + AliasSctpTerm(la); +#endif la->deleteAllLinks = 1; CleanupAliasData(la); la->deleteAllLinks = 0; @@ -2879,3 +2909,30 @@ LibAliasSetSkinnyPort(struct libalias *l la->skinnyPort = port; LIBALIAS_UNLOCK(la); } + +/* + * Find the address to redirect incoming packets + */ +struct in_addr +FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm) +{ + struct alias_link *lnk; + struct in_addr redir; + + LIBALIAS_LOCK_ASSERT(la); + lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst, + sm->sctp_hdr->dest_port,sm->sctp_hdr->dest_port, LINK_SCTP, 1); + if (lnk != NULL) { + return(lnk->src_addr); /* port redirect */ + } else { + redir = FindOriginalAddress(la,sm->ip_hdr->ip_dst); + if (redir.s_addr == la->aliasAddress.s_addr || + redir.s_addr == la->targetAddress.s_addr) { /* No address found */ + lnk = FindLinkIn(la, sm->ip_hdr->ip_src, sm->ip_hdr->ip_dst, + NO_DEST_PORT, 0, LINK_SCTP, 1); + if (lnk != NULL) + return(lnk->src_addr); /* redirect proto */ + } + return(redir); /* address redirect */ + } +} Modified: head/sys/netinet/libalias/alias_local.h ============================================================================== --- head/sys/netinet/libalias/alias_local.h Sat Feb 7 16:37:02 2009 (r188293) +++ head/sys/netinet/libalias/alias_local.h Sat Feb 7 18:49:42 2009 (r188294) @@ -57,6 +57,10 @@ /* XXX: LibAliasSetTarget() uses this constant. */ #define INADDR_NONE 0xffffffff + +#include +#else +#include "alias_sctp.h" #endif /* Sizes of input and output link tables */ @@ -147,7 +151,29 @@ struct libalias { struct in_addr true_addr; /* in network byte order. */ u_short true_port; /* in host byte order. */ + + /* + * sctp code support + */ + + /* counts associations that have progressed to UP and not yet removed */ + int sctpLinkCount; #ifdef _KERNEL + /* timing queue for keeping track of association timeouts */ + struct sctp_nat_timer sctpNatTimer; + + /* size of hash table used in this instance */ + u_int sctpNatTableSize; + +/* + * local look up table sorted by l_vtag/l_port + */ + LIST_HEAD(sctpNatTableL, sctp_nat_assoc) *sctpTableLocal; +/* + * global look up table sorted by g_vtag/g_port + */ + LIST_HEAD(sctpNatTableG, sctp_nat_assoc) *sctpTableGlobal; + /* * avoid races in libalias: every public function has to use it. */ @@ -199,6 +225,14 @@ struct libalias { /* Prototypes */ /* + * SctpFunction prototypes + * + */ +void AliasSctpInit(struct libalias *la); +void AliasSctpTerm(struct libalias *la); +int SctpAlias(struct libalias *la, struct ip *ip, int direction); + +/* * We do not calculate TCP checksums when libalias is a kernel * module, since it has no idea about checksum offloading. * If TCP data has changed, then we just set checksum to zero, @@ -264,6 +298,8 @@ struct in_addr FindOriginalAddress(struct libalias *la, struct in_addr _alias_addr); struct in_addr FindAliasAddress(struct libalias *la, struct in_addr _original_addr); +struct in_addr +FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm); /* External data access/modification */ int Copied and modified: head/sys/netinet/libalias/alias_sctp.c (from r186543, user/piso/sys/netinet/libalias/alias_sctp.c) ============================================================================== --- user/piso/sys/netinet/libalias/alias_sctp.c Sun Dec 28 17:16:32 2008 (r186543, copy source) +++ head/sys/netinet/libalias/alias_sctp.c Sat Feb 7 18:49:42 2009 (r188294) @@ -1,34 +1,9 @@ -//* $Id$ */ -//#ifndef lint -//static char vcid[] = "$Id$"; -//#endif /* lint */ /** * @file alias_sctp.c * Copyright (c) 2008, Centre for Advanced Internet Architectures * Swinburne University of Technology, Melbourne, Australia * (CRICOS number 00111D). * - * Alias_sctp forms part of the libalias kernel module to handle - * Network Address Translation (NAT) for the SCTP protocol. - * - * This software was developed by David A. Hayes and Jason But - * - * The design is outlined in CAIA technical report number 080618A - * (D. Hayes and J. But, "Alias_sctp Version 0.1: SCTP NAT implementation in IPFW") - * - * Development is part of the CAIA SONATA project, - * proposed by Jason But and Grenville Armitage: - * http://caia.swin.edu.au/urp/sonata/ - * - * - * This project has been made possible in part by a grant from - * the Cisco University Research Program Fund at Community - * Foundation Silicon Valley. - * - * - * - * All rights reserved. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -54,6 +29,23 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * + * Alias_sctp forms part of the libalias kernel module to handle + * Network Address Translation (NAT) for the SCTP protocol. + * + * This software was developed by David A. Hayes and Jason But + * + * The design is outlined in CAIA technical report number 080618A + * (D. Hayes and J. But, "Alias_sctp Version 0.1: SCTP NAT implementation in IPFW") + * + * Development is part of the CAIA SONATA project, + * proposed by Jason But and Grenville Armitage: + * http://caia.swin.edu.au/urp/sonata/ + * + * + * This project has been made possible in part by a grant from + * the Cisco University Research Program Fund at Community + * Foundation Silicon Valley. + * */ /** @mainpage * Alias_sctp is part of the SONATA (http://caia.swin.edu.au/urp/sonata) project @@ -80,6 +72,8 @@ * - Dynamic control of hash-table size */ +/* $FreeBSD$ */ + #ifdef _KERNEL #include #include @@ -107,9 +101,9 @@ */ /* Packet Parsing Functions */ static int sctp_PktParser(struct libalias *la, int direction, struct ip *pip, - struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc); + struct sctp_nat_msg *sm, struct sctp_nat_assoc **passoc); static int GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, - uint32_t *l_vtag, uint32_t *g_vtag, int direction); + uint32_t *l_vtag, uint32_t *g_vtag, int direction); static int IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction); static void AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction); @@ -119,20 +113,20 @@ static int IsADDorDEL(struct libalias *l /* State Machine Functions */ static int ProcessSctpMsg(struct libalias *la, int direction, \ - struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc); + struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc); static int ID_process(struct libalias *la, int direction,\ - struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); + struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); static int INi_process(struct libalias *la, int direction,\ - struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); + struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); static int INa_process(struct libalias *la, int direction,\ - struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); + struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); static int UP_process(struct libalias *la, int direction,\ - struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); + struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); static int CL_process(struct libalias *la, int direction,\ - struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); + struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm); static void TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm,\ - struct sctp_nat_assoc *assoc, int sndrply, int direction); + struct sctp_nat_assoc *assoc, int sndrply, int direction); /* Hash Table Functions */ static struct sctp_nat_assoc* @@ -189,22 +183,6 @@ static void SctpAliasLog(const char *for */ void SctpShowAliasStats(struct libalias *la); -/** @ingroup external - * @brief Find the address to redirect incoming packets - * - * This function is defined in alias_db.c, since it calls static functions in - * this file - * - * Given a destination port for incoming packets to the NAT, discover what - * (if any) internal IP address this packet should be re-directed to - * - * @param la Pointer to the libalias instance - * @param sm Pointer to the incoming message - * - * @return Address to redirect an incoming INIT to - */ -struct in_addr FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm); - #ifdef _KERNEL MALLOC_DEFINE(M_SCTPNAT, "sctpnat", "sctp nat dbs"); @@ -364,9 +342,9 @@ static u_int sysctl_holddown_timer = 0; static u_int sysctl_hashtable_size = SN_DEFAULT_HASH_SIZE; /**< Sets the hash table size for any NEW NAT instances (existing instances retain their existing Hash Table */ /** @brief net.inet.ip.alias.sctp.error_on_ootb */ static u_int sysctl_error_on_ootb = 1; /**< NAT response to receipt of OOTB packet - (0 - No response, 1 - NAT will send ErrorM only to local side, - 2 - NAT will send local ErrorM and global ErrorM if there was a partial association match - 3 - NAT will send ErrorM to both local and global) */ + (0 - No response, 1 - NAT will send ErrorM only to local side, + 2 - NAT will send local ErrorM and global ErrorM if there was a partial association match + 3 - NAT will send ErrorM to both local and global) */ /** @brief net.inet.ip.alias.sctp.accept_global_ootb_addip */ static u_int sysctl_accept_global_ootb_addip = 0; /** 0 - enables tracking but limits the number of global IP addresses to this value) - If set to >=1 the NAT will track that many global IP addresses. This may reduce look up table conflicts, but increases processing */ + If set to >=1 the NAT will track that many global IP addresses. This may reduce look up table conflicts, but increases processing */ #define SN_NO_ERROR_ON_OOTB 0 /**< Send no errorM on out of the blue packets */ #define SN_LOCAL_ERROR_ON_OOTB 1 /**< Send only local errorM on out of the blue packets */ @@ -393,41 +371,41 @@ SYSCTL_DECL(_net_inet_ip_alias); SYSCTL_NODE(_net_inet_ip_alias, OID_AUTO, sctp, CTLFLAG_RW, NULL, "SCTP NAT"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, log_level, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_log_level, 0, sysctl_chg_loglevel, "IU", - "Level of detail (0 - default, 1 - event, 2 - info, 3 - detail, 4 - debug, 5 - max debug)"); + &sysctl_log_level, 0, sysctl_chg_loglevel, "IU", + "Level of detail (0 - default, 1 - event, 2 - info, 3 - detail, 4 - debug, 5 - max debug)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, init_timer, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_init_timer, 0, sysctl_chg_timer, "IU", - "Timeout value (s) while waiting for (INIT-ACK|AddIP-ACK)"); + &sysctl_init_timer, 0, sysctl_chg_timer, "IU", + "Timeout value (s) while waiting for (INIT-ACK|AddIP-ACK)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, up_timer, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_up_timer, 0, sysctl_chg_timer, "IU", - "Timeout value (s) to keep an association up with no traffic"); + &sysctl_up_timer, 0, sysctl_chg_timer, "IU", + "Timeout value (s) to keep an association up with no traffic"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, shutdown_timer, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_shutdown_timer, 0, sysctl_chg_timer, "IU", - "Timeout value (s) while waiting for SHUTDOWN-COMPLETE"); + &sysctl_shutdown_timer, 0, sysctl_chg_timer, "IU", + "Timeout value (s) while waiting for SHUTDOWN-COMPLETE"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, holddown_timer, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_holddown_timer, 0, sysctl_chg_timer, "IU", - "Hold association in table for this many seconds after receiving a SHUTDOWN-COMPLETE"); + &sysctl_holddown_timer, 0, sysctl_chg_timer, "IU", + "Hold association in table for this many seconds after receiving a SHUTDOWN-COMPLETE"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, hashtable_size, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_hashtable_size, 0, sysctl_chg_hashtable_size, "IU", - "Size of hash tables used for NAT lookups (100 < prime_number > 1000001)"); + &sysctl_hashtable_size, 0, sysctl_chg_hashtable_size, "IU", + "Size of hash tables used for NAT lookups (100 < prime_number > 1000001)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, error_on_ootb, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_error_on_ootb, 0, sysctl_chg_error_on_ootb, "IU", - "ErrorM sent on receipt of ootb packet:\n\t0 - none,\n\t1 - to local only,\n\t2 - to local and global if a partial association match,\n\t3 - to local and global (DoS risk)"); + &sysctl_error_on_ootb, 0, sysctl_chg_error_on_ootb, "IU", + "ErrorM sent on receipt of ootb packet:\n\t0 - none,\n\t1 - to local only,\n\t2 - to local and global if a partial association match,\n\t3 - to local and global (DoS risk)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, accept_global_ootb_addip, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_accept_global_ootb_addip, 0, sysctl_chg_accept_global_ootb_addip, "IU", - "NAT response to receipt of global OOTB AddIP:\n\t0 - No response,\n\t1 - NAT will accept OOTB global AddIP messages for processing (Security risk)"); + &sysctl_accept_global_ootb_addip, 0, sysctl_chg_accept_global_ootb_addip, "IU", + "NAT response to receipt of global OOTB AddIP:\n\t0 - No response,\n\t1 - NAT will accept OOTB global AddIP messages for processing (Security risk)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, initialising_chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_initialising_chunk_proc_limit, 0, sysctl_chg_initialising_chunk_proc_limit, "IU", - "Number of chunks that should be processed if there is no current association found:\n\t > 0 (A high value is a DoS risk)"); + &sysctl_initialising_chunk_proc_limit, 0, sysctl_chg_initialising_chunk_proc_limit, "IU", + "Number of chunks that should be processed if there is no current association found:\n\t > 0 (A high value is a DoS risk)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, chunk_proc_limit, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_chunk_proc_limit, 0, sysctl_chg_chunk_proc_limit, "IU", - "Number of chunks that should be processed to find key chunk:\n\t>= initialising_chunk_proc_limit (A high value is a DoS risk)"); + &sysctl_chunk_proc_limit, 0, sysctl_chg_chunk_proc_limit, "IU", + "Number of chunks that should be processed to find key chunk:\n\t>= initialising_chunk_proc_limit (A high value is a DoS risk)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, param_proc_limit, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_param_proc_limit, 0, sysctl_chg_param_proc_limit, "IU", - "Number of parameters (in a chunk) that should be processed to find key parameters:\n\t> 1 (A high value is a DoS risk)"); + &sysctl_param_proc_limit, 0, sysctl_chg_param_proc_limit, "IU", + "Number of parameters (in a chunk) that should be processed to find key parameters:\n\t> 1 (A high value is a DoS risk)"); SYSCTL_PROC(_net_inet_ip_alias_sctp, OID_AUTO, track_global_addresses, CTLTYPE_UINT | CTLFLAG_RW, - &sysctl_track_global_addresses, 0, sysctl_chg_track_global_addresses, "IU", - "Configures the global address tracking option within the NAT:\n\t0 - Global tracking is disabled,\n\t> 0 - enables tracking but limits the number of global IP addresses to this value"); + &sysctl_track_global_addresses, 0, sysctl_chg_track_global_addresses, "IU", + "Configures the global address tracking option within the NAT:\n\t0 - Global tracking is disabled,\n\t> 0 - enables tracking but limits the number of global IP addresses to this value"); #endif /* SYSCTL_NODE */ @@ -440,16 +418,16 @@ SYSCTL_PROC(_net_inet_ip_alias_sctp, OID */ int sysctl_chg_loglevel(SYSCTL_HANDLER_ARGS) { - u_int level = *(u_int *)arg1; - int error; + u_int level = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &level, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &level, 0, req); + if (error) return (error); - sysctl_log_level = (level > SN_LOG_DEBUG_MAX)?(SN_LOG_DEBUG_MAX):(level); - sysctl_log_level = (level < SN_LOG_LOW)?(SN_LOG_LOW):(level); + sysctl_log_level = (level > SN_LOG_DEBUG_MAX)?(SN_LOG_DEBUG_MAX):(level); + sysctl_log_level = (level < SN_LOG_LOW)?(SN_LOG_LOW):(level); - return (0); + return (0); } /** @ingroup sysctl @@ -461,22 +439,22 @@ int sysctl_chg_loglevel(SYSCTL_HANDLER_A */ int sysctl_chg_timer(SYSCTL_HANDLER_ARGS) { - u_int timer = *(u_int *)arg1; - int error; + u_int timer = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &timer, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &timer, 0, req); + if (error) return (error); - timer = (timer > SN_MAX_TIMER)?(SN_MAX_TIMER):(timer); + timer = (timer > SN_MAX_TIMER)?(SN_MAX_TIMER):(timer); - if (((u_int *)arg1) != &sysctl_holddown_timer) - { - timer = (timer < SN_MIN_TIMER)?(SN_MIN_TIMER):(timer); - } + if (((u_int *)arg1) != &sysctl_holddown_timer) + { + timer = (timer < SN_MIN_TIMER)?(SN_MIN_TIMER):(timer); + } - *(u_int *)arg1 = timer; + *(u_int *)arg1 = timer; - return (0); + return (0); } /** @ingroup sysctl @@ -490,20 +468,20 @@ int sysctl_chg_timer(SYSCTL_HANDLER_ARGS */ int sysctl_chg_hashtable_size(SYSCTL_HANDLER_ARGS) { - u_int size = *(u_int *)arg1; - int error; + u_int size = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &size, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &size, 0, req); + if (error) return (error); - size = (size < SN_MIN_HASH_SIZE)?(SN_MIN_HASH_SIZE):((size > SN_MAX_HASH_SIZE)?(SN_MAX_HASH_SIZE):(size)); + size = (size < SN_MIN_HASH_SIZE)?(SN_MIN_HASH_SIZE):((size > SN_MAX_HASH_SIZE)?(SN_MAX_HASH_SIZE):(size)); - size |= 0x00000001; /* make odd */ + size |= 0x00000001; /* make odd */ - for(;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2); - sysctl_hashtable_size = size; + for(;(((size % 3) == 0) || ((size % 5) == 0) || ((size % 7) == 0) || ((size % 11) == 0)); size+=2); + sysctl_hashtable_size = size; - return (0); + return (0); } /** @ingroup sysctl @@ -518,15 +496,15 @@ int sysctl_chg_hashtable_size(SYSCTL_HAN */ int sysctl_chg_error_on_ootb(SYSCTL_HANDLER_ARGS) { - u_int flag = *(u_int *)arg1; - int error; + u_int flag = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &flag, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &flag, 0, req); + if (error) return (error); - sysctl_error_on_ootb = (flag > SN_ERROR_ON_OOTB) ? SN_ERROR_ON_OOTB: flag; + sysctl_error_on_ootb = (flag > SN_ERROR_ON_OOTB) ? SN_ERROR_ON_OOTB: flag; - return (0); + return (0); } /** @ingroup sysctl @@ -537,15 +515,15 @@ int sysctl_chg_error_on_ootb(SYSCTL_HAND */ int sysctl_chg_accept_global_ootb_addip(SYSCTL_HANDLER_ARGS) { - u_int flag = *(u_int *)arg1; - int error; + u_int flag = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &flag, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &flag, 0, req); + if (error) return (error); - sysctl_accept_global_ootb_addip = (flag == 1) ? 1: 0; + sysctl_accept_global_ootb_addip = (flag == 1) ? 1: 0; - return (0); + return (0); } /** @ingroup sysctl @@ -557,17 +535,17 @@ int sysctl_chg_accept_global_ootb_addip( */ int sysctl_chg_initialising_chunk_proc_limit(SYSCTL_HANDLER_ARGS) { - u_int proclimit = *(u_int *)arg1; - int error; + u_int proclimit = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &proclimit, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &proclimit, 0, req); + if (error) return (error); - sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit; - sysctl_chunk_proc_limit = - (sysctl_chunk_proc_limit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : sysctl_chunk_proc_limit; + sysctl_initialising_chunk_proc_limit = (proclimit < 1) ? 1: proclimit; + sysctl_chunk_proc_limit = + (sysctl_chunk_proc_limit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : sysctl_chunk_proc_limit; - return (0); + return (0); } /** @ingroup sysctl @@ -579,16 +557,16 @@ int sysctl_chg_initialising_chunk_proc_l */ int sysctl_chg_chunk_proc_limit(SYSCTL_HANDLER_ARGS) { - u_int proclimit = *(u_int *)arg1; - int error; + u_int proclimit = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &proclimit, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &proclimit, 0, req); + if (error) return (error); - sysctl_chunk_proc_limit = - (proclimit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : proclimit; + sysctl_chunk_proc_limit = + (proclimit < sysctl_initialising_chunk_proc_limit) ? sysctl_initialising_chunk_proc_limit : proclimit; - return (0); + return (0); } @@ -601,16 +579,16 @@ int sysctl_chg_chunk_proc_limit(SYSCTL_H */ int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS) { - u_int proclimit = *(u_int *)arg1; - int error; + u_int proclimit = *(u_int *)arg1; + int error; - error = sysctl_handle_int(oidp, &proclimit, 0, req); - if (error) return (error); + error = sysctl_handle_int(oidp, &proclimit, 0, req); + if (error) return (error); - sysctl_param_proc_limit = - (proclimit < 2) ? 2 : proclimit; + sysctl_param_proc_limit = *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***