summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/in.c25
-rw-r--r--sys/netinet/in.h2
-rw-r--r--sys/netinet/in_pcb.c66
-rw-r--r--sys/netinet/in_pcb.h2
-rw-r--r--sys/netinet/ip_divert.c13
-rw-r--r--sys/netinet/ip_fw2.c10
-rw-r--r--sys/netinet/ip_fw_nat.c3
-rw-r--r--sys/netinet/ip_ipsec.c11
-rw-r--r--sys/netinet/ip_output.c50
-rw-r--r--sys/netinet/libalias/alias.c17
-rw-r--r--sys/netinet/libalias/alias.h12
-rw-r--r--sys/netinet/libalias/alias_db.c115
-rw-r--r--sys/netinet/libalias/alias_ftp.c1
-rw-r--r--sys/netinet/libalias/alias_irc.c1
-rw-r--r--sys/netinet/libalias/alias_local.h76
-rw-r--r--sys/netinet/libalias/alias_nbt.c1
-rw-r--r--sys/netinet/libalias/alias_sctp.c2826
-rw-r--r--sys/netinet/libalias/alias_sctp.h104
-rw-r--r--sys/netinet/raw_ip.c37
-rw-r--r--sys/netinet/sctp_auth.c6
-rw-r--r--sys/netinet/sctp_constants.h68
-rw-r--r--sys/netinet/sctp_crc32.c211
-rw-r--r--sys/netinet/sctp_crc32.h12
-rw-r--r--sys/netinet/sctp_input.c46
-rw-r--r--sys/netinet/sctp_os_bsd.h5
-rw-r--r--sys/netinet/sctp_output.c806
-rw-r--r--sys/netinet/sctp_pcb.c44
-rw-r--r--sys/netinet/sctp_pcb.h1
-rw-r--r--sys/netinet/sctp_sysctl.c18
-rw-r--r--sys/netinet/sctp_uio.h8
-rw-r--r--sys/netinet/sctp_usrreq.c22
-rw-r--r--sys/netinet/sctputil.c332
-rw-r--r--sys/netinet/sctputil.h2
-rw-r--r--sys/netinet/tcp_input.c70
-rw-r--r--sys/netinet/tcp_subr.c2
-rw-r--r--sys/netinet/tcp_syncache.c2
-rw-r--r--sys/netinet/tcp_timer.c1
-rw-r--r--sys/netinet/tcp_usrreq.c13
-rw-r--r--sys/netinet/tcp_var.h3
-rw-r--r--sys/netinet/udp_usrreq.c101
-rw-r--r--sys/netinet/udp_var.h4
-rw-r--r--sys/netinet/vinet.h4
42 files changed, 2670 insertions, 2483 deletions
diff --git a/sys/netinet/in.c b/sys/netinet/in.c
index 3f11e82..bf1ebae 100644
--- a/sys/netinet/in.c
+++ b/sys/netinet/in.c
@@ -41,7 +41,9 @@ __FBSDID("$FreeBSD$");
#include <sys/malloc.h>
#include <sys/priv.h>
#include <sys/socket.h>
+#include <sys/jail.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/sysctl.h>
#include <sys/vimage.h>
@@ -261,13 +263,19 @@ in_control(struct socket *so, u_long cmd, caddr_t data, struct ifnet *ifp,
LIST_FOREACH(iap, INADDR_HASH(dst.s_addr), ia_hash)
if (iap->ia_ifp == ifp &&
iap->ia_addr.sin_addr.s_addr == dst.s_addr) {
- ia = iap;
+ if (td == NULL || prison_check_ip4(
+ td->td_ucred, &dst) == 0)
+ ia = iap;
break;
}
if (ia == NULL)
TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) {
iap = ifatoia(ifa);
if (iap->ia_addr.sin_family == AF_INET) {
+ if (td != NULL &&
+ prison_check_ip4(td->td_ucred,
+ &iap->ia_addr.sin_addr) != 0)
+ continue;
ia = iap;
break;
}
@@ -995,9 +1003,6 @@ in_purgemaddrs(struct ifnet *ifp)
struct in_multi *inm;
struct in_multi *oinm;
-#ifdef DIAGNOSTIC
- printf("%s: purging ifp %p\n", __func__, ifp);
-#endif
IFF_LOCKGIANT(ifp);
IN_MULTI_LOCK();
LIST_FOREACH_SAFE(inm, &V_in_multihead, inm_link, oinm) {
@@ -1106,9 +1111,10 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
hashkey = sin->sin_addr.s_addr;
lleh = &llt->lle_head[LLATBL_HASH(hashkey, LLTBL_HASHMASK)];
LIST_FOREACH(lle, lleh, lle_next) {
+ struct sockaddr_in *sa2 = (struct sockaddr_in *)L3_ADDR(lle);
if (lle->la_flags & LLE_DELETED)
continue;
- if (bcmp(L3_ADDR(lle), l3addr, sizeof(struct sockaddr_in)) == 0)
+ if (sa2->sin_addr.s_addr == sin->sin_addr.s_addr)
break;
}
if (lle == NULL) {
@@ -1153,7 +1159,7 @@ in_lltable_lookup(struct lltable *llt, u_int flags, const struct sockaddr *l3add
lle = (void *)-1;
}
- if (lle != NULL && lle != (void *)-1) {
+ if (LLE_IS_VALID(lle)) {
if (flags & LLE_EXCLUSIVE)
LLE_WLOCK(lle);
else
@@ -1192,6 +1198,9 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
/* skip deleted entries */
if ((lle->la_flags & (LLE_DELETED|LLE_VALID)) != LLE_VALID)
continue;
+ /* Skip if jailed and not a valid IP of the prison. */
+ if (prison_if(wr->td->td_ucred, L3_ADDR(lle)) != 0)
+ continue;
/*
* produce a msg made of:
* struct rt_msghdr;
@@ -1200,6 +1209,10 @@ in_lltable_dump(struct lltable *llt, struct sysctl_req *wr)
*/
bzero(&arpc, sizeof(arpc));
arpc.rtm.rtm_msglen = sizeof(arpc);
+ arpc.rtm.rtm_version = RTM_VERSION;
+ arpc.rtm.rtm_type = RTM_GET;
+ arpc.rtm.rtm_flags = RTF_UP;
+ arpc.rtm.rtm_addrs = RTA_DST | RTA_GATEWAY;
arpc.sin.sin_family = AF_INET;
arpc.sin.sin_len = sizeof(arpc.sin);
arpc.sin.sin_addr.s_addr = SIN(lle)->sin_addr.s_addr;
diff --git a/sys/netinet/in.h b/sys/netinet/in.h
index b969bdf..591e766 100644
--- a/sys/netinet/in.h
+++ b/sys/netinet/in.h
@@ -441,6 +441,8 @@ __END_DECLS
#define IP_FAITH 22 /* bool; accept FAITH'ed connections */
#define IP_ONESBCAST 23 /* bool: send all-ones broadcast */
+#define IP_NONLOCALOK 24 /* bool: allow bind to spoof non-local addresses;
+ requires kernel compile option IP_NONLOCALBIND */
#define IP_FW_TABLE_ADD 40 /* add entry */
#define IP_FW_TABLE_DEL 41 /* delete entry */
diff --git a/sys/netinet/in_pcb.c b/sys/netinet/in_pcb.c
index 6d1c2aa..3014bc3 100644
--- a/sys/netinet/in_pcb.c
+++ b/sys/netinet/in_pcb.c
@@ -35,6 +35,7 @@
__FBSDID("$FreeBSD$");
#include "opt_ddb.h"
+#include "opt_inet.h"
#include "opt_ipsec.h"
#include "opt_inet6.h"
#include "opt_mac.h"
@@ -312,7 +313,10 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
return (EINVAL);
if ((so->so_options & (SO_REUSEADDR|SO_REUSEPORT)) == 0)
wild = INPLOOKUP_WILDCARD;
- if (nam) {
+ if (nam == NULL) {
+ if ((error = prison_local_ip4(cred, &laddr)) != 0)
+ return (error);
+ } else {
sin = (struct sockaddr_in *)nam;
if (nam->sa_len != sizeof (*sin))
return (EINVAL);
@@ -324,8 +328,9 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
if (sin->sin_family != AF_INET)
return (EAFNOSUPPORT);
#endif
- if (prison_local_ip4(cred, &sin->sin_addr))
- return (EINVAL);
+ error = prison_local_ip4(cred, &sin->sin_addr);
+ if (error)
+ return (error);
if (sin->sin_port != *lportp) {
/* Don't allow the port to change. */
if (*lportp != 0)
@@ -346,7 +351,16 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
} else if (sin->sin_addr.s_addr != INADDR_ANY) {
sin->sin_port = 0; /* yech... */
bzero(&sin->sin_zero, sizeof(sin->sin_zero));
- if (ifa_ifwithaddr((struct sockaddr *)sin) == 0)
+ /*
+ * Is the address a local IP address?
+ * If INP_NONLOCALOK is set, then the socket may be bound
+ * to any endpoint address, local or not.
+ */
+ if (
+#if defined(IP_NONLOCALBIND)
+ ((inp->inp_flags & INP_NONLOCALOK) == 0) &&
+#endif
+ (ifa_ifwithaddr((struct sockaddr *)sin) == 0))
return (EADDRNOTAVAIL);
}
laddr = sin->sin_addr;
@@ -381,8 +395,6 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
t->inp_cred->cr_uid))
return (EADDRINUSE);
}
- if (prison_local_ip4(cred, &sin->sin_addr))
- return (EADDRNOTAVAIL);
t = in_pcblookup_local(pcbinfo, sin->sin_addr,
lport, wild, cred);
if (t && (t->inp_vflag & INP_TIMEWAIT)) {
@@ -416,9 +428,6 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
u_short first, last, aux;
int count;
- if (prison_local_ip4(cred, &laddr))
- return (EINVAL);
-
if (inp->inp_flags & INP_HIGHPORT) {
first = V_ipport_hifirstauto; /* sysctl */
last = V_ipport_hilastauto;
@@ -483,8 +492,6 @@ in_pcbbind_setup(struct inpcb *inp, struct sockaddr *nam, in_addr_t *laddrp,
} while (in_pcblookup_local(pcbinfo, laddr,
lport, wild, cred));
}
- if (prison_local_ip4(cred, &laddr))
- return (EINVAL);
*laddrp = laddr.s_addr;
*lportp = lport;
return (0);
@@ -604,7 +611,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -615,8 +622,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_getip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -641,7 +647,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
/* Jailed. */
/* 1. Check if the iface address belongs to the jail. */
sin = (struct sockaddr_in *)sro.ro_rt->rt_ifa->ifa_addr;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)sro.ro_rt->rt_ifa;
laddr->s_addr = ia->ia_addr.sin_addr.s_addr;
goto done;
@@ -657,7 +663,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred, &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -668,8 +674,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_getip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -719,7 +724,8 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
if (sa->sa_family != AF_INET)
continue;
sin = (struct sockaddr_in *)sa;
- if (prison_check_ip4(cred, &sin->sin_addr)) {
+ if (prison_check_ip4(cred,
+ &sin->sin_addr) == 0) {
ia = (struct in_ifaddr *)ifa;
break;
}
@@ -731,8 +737,7 @@ in_pcbladdr(struct inpcb *inp, struct in_addr *faddr, struct in_addr *laddr,
}
/* 3. As a last resort return the 'default' jail address. */
- if (prison_getip4(cred, laddr) != 0)
- error = EADDRNOTAVAIL;
+ error = prison_get_ip4(cred, laddr);
goto done;
}
@@ -766,7 +771,7 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
struct sockaddr_in *sin = (struct sockaddr_in *)nam;
struct in_ifaddr *ia;
struct inpcb *oinp;
- struct in_addr laddr, faddr, jailia;
+ struct in_addr laddr, faddr;
u_short lport, fport;
int error;
@@ -799,15 +804,11 @@ in_pcbconnect_setup(struct inpcb *inp, struct sockaddr *nam,
* choose the broadcast address for that interface.
*/
if (faddr.s_addr == INADDR_ANY) {
- if (cred != NULL && jailed(cred)) {
- if (prison_getip4(cred, &jailia) != 0)
- return (EADDRNOTAVAIL);
- faddr.s_addr = jailia.s_addr;
- } else {
- faddr =
- IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->
- sin_addr;
- }
+ faddr =
+ IA_SIN(TAILQ_FIRST(&V_in_ifaddrhead))->sin_addr;
+ if (cred != NULL &&
+ (error = prison_get_ip4(cred, &faddr)) != 0)
+ return (error);
} else if (faddr.s_addr == (u_long)INADDR_BROADCAST &&
(TAILQ_FIRST(&V_in_ifaddrhead)->ia_ifp->if_flags &
IFF_BROADCAST))
@@ -1365,7 +1366,8 @@ in_pcblookup_hash(struct inpcbinfo *pcbinfo, struct in_addr faddr,
injail = jailed(inp->inp_cred);
if (injail) {
- if (!prison_check_ip4(inp->inp_cred, &laddr))
+ if (prison_check_ip4(inp->inp_cred,
+ &laddr) != 0)
continue;
} else {
if (local_exact != NULL)
diff --git a/sys/netinet/in_pcb.h b/sys/netinet/in_pcb.h
index 01636fe..acc6404 100644
--- a/sys/netinet/in_pcb.h
+++ b/sys/netinet/in_pcb.h
@@ -411,6 +411,8 @@ void inp_4tuple_get(struct inpcb *inp, uint32_t *laddr, uint16_t *lp,
#define INP_FAITH 0x200 /* accept FAITH'ed connections */
#define INP_RECVTTL 0x400 /* receive incoming IP TTL */
#define INP_DONTFRAG 0x800 /* don't fragment packet */
+#define INP_NONLOCALOK 0x1000 /* Allow bind to spoof any address */
+ /* - requires options IP_NONLOCALBIND */
#define IN6P_IPV6_V6ONLY 0x008000 /* restrict AF_INET6 socket for v6 */
diff --git a/sys/netinet/ip_divert.c b/sys/netinet/ip_divert.c
index d6eb16f..c2e3191 100644
--- a/sys/netinet/ip_divert.c
+++ b/sys/netinet/ip_divert.c
@@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$");
#include "opt_inet.h"
#include "opt_ipfw.h"
#include "opt_mac.h"
+#include "opt_sctp.h"
#ifndef INET
#error "IPDIVERT requires INET."
#endif
@@ -76,6 +77,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_var.h>
#include <netinet/ip_fw.h>
#include <netinet/vinet.h>
+#ifdef SCTP
+#include <netinet/sctp_crc32.h>
+#endif
#include <security/mac/mac_framework.h>
@@ -222,7 +226,14 @@ divert_packet(struct mbuf *m, int incoming)
m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
ip->ip_len = htons(ip->ip_len);
}
-
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP) {
+ ip->ip_len = ntohs(ip->ip_len);
+ sctp_delayed_cksum(m);
+ m->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+ ip->ip_len = htons(ip->ip_len);
+ }
+#endif
/*
* Record receive interface address, if any.
* But only for incoming packets.
diff --git a/sys/netinet/ip_fw2.c b/sys/netinet/ip_fw2.c
index 1f2e67d..133166e 100644
--- a/sys/netinet/ip_fw2.c
+++ b/sys/netinet/ip_fw2.c
@@ -197,6 +197,7 @@ SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, default_rule, CTLFLAG_RD,
NULL, IPFW_DEFAULT_RULE, "The default/max possible rule number.");
SYSCTL_UINT(_net_inet_ip_fw, OID_AUTO, tables_max, CTLFLAG_RD,
NULL, IPFW_TABLES_MAX, "The maximum number of tables.");
+#endif /* SYSCTL_NODE */
/*
* Description of dynamic rules.
@@ -277,6 +278,7 @@ static u_int32_t dyn_count; /* # of dynamic rules */
static u_int32_t dyn_max; /* max # of dynamic rules */
#endif /* VIMAGE_GLOBALS */
+#ifdef SYSCTL_NODE
SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_buckets,
CTLFLAG_RW, dyn_buckets, 0, "Number of dyn. buckets");
SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, curr_dyn_buckets,
@@ -302,18 +304,19 @@ SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_short_lifetime,
"Lifetime of dyn. rules for other situations");
SYSCTL_V_INT(V_NET, vnet_ipfw, _net_inet_ip_fw, OID_AUTO, dyn_keepalive,
CTLFLAG_RW, dyn_keepalive, 0, "Enable keepalives for dyn. rules");
-
+#endif /* SYSCTL_NODE */
#ifdef INET6
/*
* IPv6 specific variables
*/
+#ifdef SYSCTL_NODE
SYSCTL_DECL(_net_inet6_ip6);
+#endif /* SYSCTL_NODE */
static struct sysctl_ctx_list ip6_fw_sysctl_ctx;
static struct sysctl_oid *ip6_fw_sysctl_tree;
#endif /* INET6 */
-#endif /* SYSCTL_NODE */
#ifdef VIMAGE_GLOBALS
static int fw_deny_unknown_exthdrs;
@@ -2251,6 +2254,7 @@ ipfw_chk(struct ip_fw_args *args)
if (m->m_flags & M_SKIP_FIREWALL)
return (IP_FW_PASS); /* accept */
+ dst_ip.s_addr = 0; /* make sure it is initialized */
pktlen = m->m_pkthdr.len;
args->f_id.fib = M_GETFIB(m); /* note mbuf not altered) */
proto = args->f_id.proto = 0; /* mark f_id invalid */
@@ -2708,7 +2712,7 @@ check_body:
uint32_t a =
(cmd->opcode == O_IP_DST_LOOKUP) ?
dst_ip.s_addr : src_ip.s_addr;
- uint32_t v;
+ uint32_t v = 0;
match = lookup_table(chain, cmd->arg1, a,
&v);
diff --git a/sys/netinet/ip_fw_nat.c b/sys/netinet/ip_fw_nat.c
index 332c026..6ba0412 100644
--- a/sys/netinet/ip_fw_nat.c
+++ b/sys/netinet/ip_fw_nat.c
@@ -326,12 +326,10 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
else
retval = LibAliasOut(t->lib, c,
mcl->m_len + M_TRAILINGSPACE(mcl));
-#ifdef _ALIAS_SCTP
if (retval == PKT_ALIAS_RESPOND) {
m->m_flags |= M_SKIP_FIREWALL;
retval = PKT_ALIAS_OK;
}
-#endif
if (retval != PKT_ALIAS_OK &&
retval != PKT_ALIAS_FOUND_HEADER_FRAGMENT) {
/* XXX - should i add some logging? */
@@ -407,7 +405,6 @@ ipfw_nat(struct ip_fw_args *args, struct cfg_nat *t, struct mbuf *m)
}
args->m = mcl;
-
return (IP_FW_NAT);
}
diff --git a/sys/netinet/ip_ipsec.c b/sys/netinet/ip_ipsec.c
index a1e082b..77e9aa7 100644
--- a/sys/netinet/ip_ipsec.c
+++ b/sys/netinet/ip_ipsec.c
@@ -31,6 +31,7 @@
__FBSDID("$FreeBSD$");
#include "opt_ipsec.h"
+#include "opt_sctp.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -56,6 +57,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_options.h>
#include <netinet/ip_ipsec.h>
#include <netinet/vinet.h>
+#ifdef SCTP
+#include <netinet/sctp_crc32.h>
+#endif
#include <machine/in_cksum.h>
@@ -328,7 +332,12 @@ ip_ipsec_output(struct mbuf **m, struct inpcb *inp, int *flags, int *error,
in_delayed_cksum(*m);
(*m)->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
-
+#ifdef SCTP
+ if ((*m)->m_pkthdr.csum_flags & CSUM_SCTP) {
+ sctp_delayed_cksum(*m);
+ (*m)->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+ }
+#endif
ip->ip_len = htons(ip->ip_len);
ip->ip_off = htons(ip->ip_off);
diff --git a/sys/netinet/ip_output.c b/sys/netinet/ip_output.c
index 6cda8aa..feacb51 100644
--- a/sys/netinet/ip_output.c
+++ b/sys/netinet/ip_output.c
@@ -33,10 +33,12 @@
__FBSDID("$FreeBSD$");
#include "opt_ipfw.h"
+#include "opt_inet.h"
#include "opt_ipsec.h"
#include "opt_mac.h"
#include "opt_mbuf_stress_test.h"
#include "opt_mpath.h"
+#include "opt_sctp.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -69,6 +71,10 @@ __FBSDID("$FreeBSD$");
#include <netinet/ip_var.h>
#include <netinet/ip_options.h>
#include <netinet/vinet.h>
+#ifdef SCTP
+#include <netinet/sctp.h>
+#include <netinet/sctp_crc32.h>
+#endif
#ifdef IPSEC
#include <netinet/ip_ipsec.h>
@@ -95,6 +101,12 @@ SYSCTL_INT(_net_inet_ip, OID_AUTO, mbuf_frag_size, CTLFLAG_RW,
&mbuf_frag_size, 0, "Fragment outgoing mbufs to this size");
#endif
+#if defined(IP_NONLOCALBIND)
+static int ip_nonlocalok = 0;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, nonlocalok,
+ CTLFLAG_RW|CTLFLAG_SECURE, &ip_nonlocalok, 0, "");
+#endif
+
static void ip_mloopback
(struct ifnet *, struct mbuf *, struct sockaddr_in *, int);
@@ -478,7 +490,10 @@ sendit:
}
m->m_pkthdr.csum_flags |=
CSUM_IP_CHECKED | CSUM_IP_VALID;
-
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
error = netisr_queue(NETISR_IP, m);
goto done;
} else
@@ -495,6 +510,10 @@ sendit:
CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
m->m_pkthdr.csum_data = 0xffff;
}
+#ifdef SCTP
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP)
+ m->m_pkthdr.csum_flags |= CSUM_SCTP_VALID;
+#endif
m->m_pkthdr.csum_flags |=
CSUM_IP_CHECKED | CSUM_IP_VALID;
@@ -529,6 +548,12 @@ passout:
in_delayed_cksum(m);
sw_csum &= ~CSUM_DELAY_DATA;
}
+#ifdef SCTP
+ if (sw_csum & CSUM_SCTP) {
+ sctp_delayed_cksum(m);
+ sw_csum &= ~CSUM_SCTP;
+ }
+#endif
m->m_pkthdr.csum_flags &= ifp->if_hwassist;
/*
@@ -663,7 +688,13 @@ ip_fragment(struct ip *ip, struct mbuf **m_frag, int mtu,
in_delayed_cksum(m0);
m0->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA;
}
-
+#ifdef SCTP
+ if (m0->m_pkthdr.csum_flags & CSUM_SCTP &&
+ (if_hwassist_flags & CSUM_IP_FRAGS) == 0) {
+ sctp_delayed_cksum(m0);
+ m0->m_pkthdr.csum_flags &= ~CSUM_SCTP;
+ }
+#endif
if (len > PAGE_SIZE) {
/*
* Fragment large datagrams such that each segment
@@ -866,6 +897,14 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
return (error);
}
+#if defined(IP_NONLOCALBIND)
+ case IP_NONLOCALOK:
+ if (! ip_nonlocalok) {
+ error = ENOPROTOOPT;
+ break;
+ }
+ /* FALLTHROUGH */
+#endif
case IP_TOS:
case IP_TTL:
case IP_MINTTL:
@@ -892,7 +931,7 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
break;
case IP_MINTTL:
- if (optval > 0 && optval <= MAXTTL)
+ if (optval >= 0 && optval <= MAXTTL)
inp->inp_ip_minttl = optval;
else
error = EINVAL;
@@ -937,6 +976,11 @@ ip_ctloutput(struct socket *so, struct sockopt *sopt)
case IP_DONTFRAG:
OPTSET(INP_DONTFRAG);
break;
+#if defined(IP_NONLOCALBIND)
+ case IP_NONLOCALOK:
+ OPTSET(INP_NONLOCALOK);
+ break;
+#endif
}
break;
#undef OPTSET
diff --git a/sys/netinet/libalias/alias.c b/sys/netinet/libalias/alias.c
index cfef491..9d80da9 100644
--- a/sys/netinet/libalias/alias.c
+++ b/sys/netinet/libalias/alias.c
@@ -111,13 +111,6 @@ __FBSDID("$FreeBSD$");
See HISTORY file for additional revisions.
*/
-/**
- * Modifications to add sctp functionality by David A. Hayes
- * $Id: alias.c 122 2008-06-25 06:50:47Z dhayes $
- * All are inclosed in #ifdef _ALIAS_SCTP
- *
- */
-
#ifdef _KERNEL
#include <sys/param.h>
#include <sys/systm.h>
@@ -144,17 +137,11 @@ __FBSDID("$FreeBSD$");
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
#include <netinet/libalias/alias_mod.h>
-#ifdef _ALIAS_SCTP
-#include <netinet/libalias/alias_sctp.h>
-#endif
#else
#include <err.h>
#include "alias.h"
#include "alias_local.h"
#include "alias_mod.h"
-#ifdef _ALIAS_SCTP
-#include "alias_sctp.h"
-#endif
#endif
/*
@@ -1360,7 +1347,7 @@ LibAliasInLocked(struct libalias *la, char *ptr, int maxpacketsize)
case IPPROTO_TCP:
iresult = TcpAliasIn(la, pip);
break;
-#ifdef _ALIAS_SCTP
+#ifdef _KERNEL
case IPPROTO_SCTP:
iresult = SctpAlias(la, pip, SN_TO_LOCAL);
break;
@@ -1510,7 +1497,7 @@ LibAliasOutLocked(struct libalias *la, char *ptr, /* valid IP packet */
case IPPROTO_TCP:
iresult = TcpAliasOut(la, pip, maxpacketsize, create);
break;
- #ifdef _ALIAS_SCTP
+#ifdef _KERNEL
case IPPROTO_SCTP:
iresult = SctpAlias(la, pip, SN_TO_GLOBAL);
break;
diff --git a/sys/netinet/libalias/alias.h b/sys/netinet/libalias/alias.h
index f3e57de..2aed829 100644
--- a/sys/netinet/libalias/alias.h
+++ b/sys/netinet/libalias/alias.h
@@ -36,13 +36,6 @@
* distribution.
*/
-/**
- * Modifications to add sctp functionality by David A. Hayes
- * $Id: alias.h 122 2008-06-25 06:50:47Z dhayes $
- * All are inclosed in #ifdef _ALIAS_SCTP
- *
- */
-
#ifndef _ALIAS_H_
#define _ALIAS_H_
@@ -52,11 +45,6 @@
#define LIBALIAS_BUF_SIZE 128
#ifdef _KERNEL
-
-#ifndef _ALIAS_SCTP
-#define _ALIAS_SCTP //if ALIAS_SCTP code is to be included
-#endif
-
/*
* The kernel version of libalias does not support these features.
*/
diff --git a/sys/netinet/libalias/alias_db.c b/sys/netinet/libalias/alias_db.c
index 94dfa51..489933f 100644
--- a/sys/netinet/libalias/alias_db.c
+++ b/sys/netinet/libalias/alias_db.c
@@ -141,13 +141,6 @@ __FBSDID("$FreeBSD$");
See HISTORY file for additional revisions.
*/
-/**
- * Modifications to add sctp functionality by David A. Hayes
- * $Id: alias_db.c 177 2008-07-14 04:33:47Z dhayes $
- * All are inclosed in #ifdef _ALIAS_SCTP
- *
- */
-
#ifdef _KERNEL
#include <machine/stdarg.h>
@@ -173,9 +166,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/libalias/alias.h>
#include <netinet/libalias/alias_local.h>
#include <netinet/libalias/alias_mod.h>
-#ifdef _ALIAS_SCTP
-#include <netinet/libalias/alias_sctp.h>
-#endif
#include <net/if.h>
#else
#include "alias.h"
@@ -383,7 +373,6 @@ static moduledata_t alias_mod = {
};
DECLARE_MODULE(alias, alias_mod, SI_SUB_DRIVERS, SI_ORDER_SECOND);
-
#endif
/* Internal utility routines (used only in alias_db.c)
@@ -421,10 +410,8 @@ static void ClearFWHole(struct alias_link *);
static void ShowAliasStats(struct libalias *);
static int InitPacketAliasLog(struct libalias *);
static void UninitPacketAliasLog(struct libalias *);
-#ifdef _ALIAS_SCTP
-struct in_addr FindSctpRedirectAddress(struct libalias *la, struct sctp_nat_msg *sm);
+
void SctpShowAliasStats(struct libalias *la);
-#endif
static u_int
StartPointIn(struct in_addr alias_addr,
@@ -504,25 +491,17 @@ ShowAliasStats(struct libalias *la)
/* Used for debugging */
if (la->logDesc) {
int tot = la->icmpLinkCount + la->udpLinkCount +
-#ifdef _ALIAS_SCTP
(la->sctpLinkCount>>1) + /* sctp counts half associations */
-#endif
la->tcpLinkCount + la->pptpLinkCount +
la->protoLinkCount + la->fragmentIdLinkCount +
la->fragmentPtrLinkCount;
AliasLog(la->logDesc,
-#ifdef _ALIAS_SCTP
"icmp=%u, udp=%u, tcp=%u, sctp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
-#else
- "icmp=%u, udp=%u, tcp=%u, pptp=%u, proto=%u, frag_id=%u frag_ptr=%u / tot=%u",
-#endif
la->icmpLinkCount,
la->udpLinkCount,
la->tcpLinkCount,
-#ifdef _ALIAS_SCTP
la->sctpLinkCount>>1, /* sctp counts half associations */
-#endif
la->pptpLinkCount,
la->protoLinkCount,
la->fragmentIdLinkCount,
@@ -533,12 +512,12 @@ ShowAliasStats(struct libalias *la)
}
}
-#ifdef _ALIAS_SCTP
void SctpShowAliasStats(struct libalias *la)
{
- ShowAliasStats(la);
+
+ ShowAliasStats(la);
}
-#endif
+
/* Internal routines for finding, deleting and adding links
@@ -1003,10 +982,6 @@ AddLink(struct libalias *la, struct in_addr src_addr,
case LINK_TCP:
lnk->expire_time = TCP_EXPIRE_INITIAL;
break;
-#ifdef _ALIAS_SCTP
- case LINK_SCTP: /* treat like LINK_ADDR */
- break;
-#endif
case LINK_PPTP:
lnk->flags |= LINK_PERMANENT; /* no timeout. */
break;
@@ -1067,10 +1042,6 @@ AddLink(struct libalias *la, struct in_addr src_addr,
return (NULL);
}
break;
-#ifdef _ALIAS_SCTP
- case LINK_SCTP: /* treat like LINK_ADDR */
- break;
-#endif
case LINK_PPTP:
la->pptpLinkCount++;
break;
@@ -1317,17 +1288,16 @@ _FindLinkIn(struct libalias *la, struct in_addr dst_addr,
src_addr = lnk->src_addr;
src_port = lnk->src_port;
}
-#ifdef _ALIAS_SCTP
- if(link_type == LINK_SCTP) {
+
+ if (link_type == LINK_SCTP) {
lnk->src_addr = src_addr;
lnk->src_port = src_port;
return(lnk);
}
-#endif
- lnk = ReLink(lnk,
- src_addr, dst_addr, alias_addr,
- src_port, dst_port, alias_port,
- link_type);
+ lnk = ReLink(lnk,
+ src_addr, dst_addr, alias_addr,
+ src_port, dst_port, alias_port,
+ link_type);
}
return (lnk);
}
@@ -2323,11 +2293,9 @@ LibAliasRedirectPort(struct libalias *la, struct in_addr src_addr, u_short src_p
case IPPROTO_TCP:
link_type = LINK_TCP;
break;
-#ifdef _ALIAS_SCTP
case IPPROTO_SCTP:
link_type = LINK_SCTP;
break;
-#endif
default:
#ifdef LIBALIAS_DEBUG
fprintf(stderr, "PacketAliasRedirectPort(): ");
@@ -2547,8 +2515,8 @@ LibAliasInit(struct libalias *la)
LIST_INIT(&la->linkTableOut[i]);
for (i = 0; i < LINK_TABLE_IN_SIZE; i++)
LIST_INIT(&la->linkTableIn[i]);
-#ifdef _ALIAS_SCTP
- AliasSctpInit(la);//***
+#ifdef _KERNEL
+ AliasSctpInit(la);
#endif
LIBALIAS_LOCK_INIT(la);
LIBALIAS_LOCK(la);
@@ -2557,7 +2525,7 @@ LibAliasInit(struct libalias *la)
la->deleteAllLinks = 1;
CleanupAliasData(la);
la->deleteAllLinks = 0;
-#ifdef _ALIAS_SCTP
+#ifdef _KERNEL
AliasSctpTerm(la);
AliasSctpInit(la);
#endif
@@ -2569,9 +2537,7 @@ LibAliasInit(struct libalias *la)
la->icmpLinkCount = 0;
la->udpLinkCount = 0;
la->tcpLinkCount = 0;
-#ifdef _ALIAS_SCTP
la->sctpLinkCount = 0;
-#endif
la->pptpLinkCount = 0;
la->protoLinkCount = 0;
la->fragmentIdLinkCount = 0;
@@ -2600,7 +2566,7 @@ LibAliasUninit(struct libalias *la)
{
LIBALIAS_LOCK(la);
-#ifdef _ALIAS_SCTP
+#ifdef _KERNEL
AliasSctpTerm(la);
#endif
la->deleteAllLinks = 1;
@@ -2943,39 +2909,30 @@ LibAliasSetSkinnyPort(struct libalias *la, unsigned int port)
la->skinnyPort = port;
LIBALIAS_UNLOCK(la);
}
-#ifdef _ALIAS_SCTP
-/**
- * @brief Find the address to redirect incoming packets
- *
- * The function is located in alias_db.c due to calls to static functions
- *
- *
- * @param la pointer to the libalias instance
- * @param sm pointer to the incoming message
- *
- * @return address to redirect an incoming INIT to
+
+/*
+ * 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 */
- }
+ 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 */
+ }
}
-#endif
diff --git a/sys/netinet/libalias/alias_ftp.c b/sys/netinet/libalias/alias_ftp.c
index 243dfae..50fa8d0 100644
--- a/sys/netinet/libalias/alias_ftp.c
+++ b/sys/netinet/libalias/alias_ftp.c
@@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#else
+#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
diff --git a/sys/netinet/libalias/alias_irc.c b/sys/netinet/libalias/alias_irc.c
index fd76e83..8197fb8 100644
--- a/sys/netinet/libalias/alias_irc.c
+++ b/sys/netinet/libalias/alias_irc.c
@@ -56,6 +56,7 @@ __FBSDID("$FreeBSD$");
#include <sys/kernel.h>
#include <sys/module.h>
#else
+#include <ctype.h>
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
diff --git a/sys/netinet/libalias/alias_local.h b/sys/netinet/libalias/alias_local.h
index 4124508..e201394 100644
--- a/sys/netinet/libalias/alias_local.h
+++ b/sys/netinet/libalias/alias_local.h
@@ -42,12 +42,6 @@
*
* <updated several times by original author and Eivind Eklund>
*/
-/**
- * Modifications to add sctp functionality by David A. Hayes
- * $Id: alias_local.h 122 2008-06-25 06:50:47Z dhayes $
- * All are inclosed in #ifdef _ALIAS_SCTP
- *
- */
#ifndef _ALIAS_LOCAL_H_
#define _ALIAS_LOCAL_H_
@@ -56,16 +50,6 @@
#include <sys/sysctl.h>
#ifdef _KERNEL
-/* if alias_sctp is not required, #define _ALIAS_SCTP should be commented out */
-#ifndef _ALIAS_SCTP
-#define _ALIAS_SCTP
-#endif
-#ifdef _ALIAS_SCTP
-#include <netinet/libalias/alias_sctp.h>
-#endif
-#endif
-
-#ifdef _KERNEL
#include <sys/malloc.h>
#include <sys/param.h>
#include <sys/lock.h>
@@ -73,6 +57,10 @@
/* XXX: LibAliasSetTarget() uses this constant. */
#define INADDR_NONE 0xffffffff
+
+#include <netinet/libalias/alias_sctp.h>
+#else
+#include "alias_sctp.h"
#endif
/* Sizes of input and output link tables */
@@ -163,33 +151,29 @@ struct libalias {
struct in_addr true_addr; /* in network byte order. */
u_short true_port; /* in host byte order. */
- /*
- *
- *alias_sctp code
- */
-#ifdef _ALIAS_SCTP
- /*counts associations that have progressed to UP and not yet removed */
- int sctpLinkCount;
- /*Timing queue for keeping track of association timeouts */
- struct sctp_nat_timer sctpNatTimer;
-
- /* Size of hash table used in this instance*/
- u_int sctpNatTableSize;
-/**
- * @brief Local look up table
- *
- * lookup table of sctp_nat_assoc sorted by l_vtag/l_port
- */
- LIST_HEAD(sctpNatTableL, sctp_nat_assoc) *sctpTableLocal;
-/**
- * @brief Global look up table
- *
- * lookup table of sctp_nat_assoc sorted by g_vtag/g_port
- */
- LIST_HEAD(sctpNatTableG, sctp_nat_assoc) *sctpTableGlobal;
-#endif
+ /*
+ * 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.
*/
@@ -240,21 +224,13 @@ struct libalias {
/* Prototypes */
- /*
- *
- *alias_sctp code
- */
-#ifdef _ALIAS_SCTP
/*
* SctpFunction prototypes
*
*/
void AliasSctpInit(struct libalias *la);
void AliasSctpTerm(struct libalias *la);
-
int SctpAlias(struct libalias *la, struct ip *ip, int direction);
-//int SctpAliasOut(struct libalias *la, struct ip *ip);
-#endif
/*
* We do not calculate TCP checksums when libalias is a kernel
@@ -322,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
diff --git a/sys/netinet/libalias/alias_nbt.c b/sys/netinet/libalias/alias_nbt.c
index 0d17870..924ee6a 100644
--- a/sys/netinet/libalias/alias_nbt.c
+++ b/sys/netinet/libalias/alias_nbt.c
@@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
#include <errno.h>
#include <sys/types.h>
#include <stdio.h>
+#include <strings.h>
#endif
#include <netinet/in_systm.h>
diff --git a/sys/netinet/libalias/alias_sctp.c b/sys/netinet/libalias/alias_sctp.c
index 5cb9acc..89dc979 100644
--- a/sys/netinet/libalias/alias_sctp.c
+++ b/sys/netinet/libalias/alias_sctp.c
@@ -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 <machine/stdarg.h>
#include <sys/param.h>
@@ -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 *la, struct sctp_nat_msg *sm, int directio
/* 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 *format, ...);
*/
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; /**< Seconds to hold an association in t
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; /**<NAT responset to receipt of global OOTB AddIP (0 - No response, 1 - NAT will accept OOTB global AddIP messages for processing (Security risk)) */
/** @brief net.inet.ip.alias.sctp.initialising_chunk_proc_limit */
@@ -377,7 +355,7 @@ static u_int sysctl_chunk_proc_limit = 5; /**< A limit on the number of chunks t
static u_int sysctl_param_proc_limit = 25; /**< A limit on the number of parameters (in chunks) that should be searched (DoS prevention) */
/** @brief net.inet.ip.alias.sctp.track_global_addresses */
static u_int sysctl_track_global_addresses = 0; /**< Configures the global address tracking option within the NAT (0 - Global tracking is disabled, > 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_AUTO, track_global_addresses, CTLTYPE_U
*/
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_ARGS)
*/
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_HANDLER_ARGS)
*/
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_HANDLER_ARGS)
*/
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(SYSCTL_HANDLER_ARGS)
*/
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_limit(SYSCTL_HANDLER_ARGS)
*/
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_HANDLER_ARGS)
*/
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 =
+ (proclimit < 2) ? 2 : proclimit;
- return (0);
+ return (0);
}
/** @ingroup sysctl
@@ -622,15 +600,15 @@ int sysctl_chg_param_proc_limit(SYSCTL_HANDLER_ARGS)
*/
int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
{
- u_int num_to_track = *(u_int *)arg1;
- int error;
+ u_int num_to_track = *(u_int *)arg1;
+ int error;
- error = sysctl_handle_int(oidp, &num_to_track, 0, req);
- if (error) return (error);
+ error = sysctl_handle_int(oidp, &num_to_track, 0, req);
+ if (error) return (error);
- sysctl_track_global_addresses = (num_to_track > SN_MAX_GLOBAL_ADDRESSES) ? SN_MAX_GLOBAL_ADDRESSES : num_to_track;
+ sysctl_track_global_addresses = (num_to_track > SN_MAX_GLOBAL_ADDRESSES) ? SN_MAX_GLOBAL_ADDRESSES : num_to_track;
- return (0);
+ return (0);
}
@@ -648,30 +626,30 @@ int sysctl_chg_track_global_addresses(SYSCTL_HANDLER_ARGS)
*/
void AliasSctpInit(struct libalias *la)
{
- /* Initialise association tables*/
- int i;
- la->sctpNatTableSize = sysctl_hashtable_size;
- SN_LOG(SN_LOG_EVENT,
- SctpAliasLog("Initialising SCTP NAT Instance (hash_table_size:%d)\n", la->sctpNatTableSize));
- la->sctpTableLocal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableL));
- la->sctpTableGlobal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableG));
- la->sctpNatTimer.TimerQ = sn_calloc(SN_TIMER_QUEUE_SIZE, sizeof(struct sctpTimerQ));
- /* Initialise hash table */
- for (i = 0; i < la->sctpNatTableSize; i++) {
- LIST_INIT(&la->sctpTableLocal[i]);
- LIST_INIT(&la->sctpTableGlobal[i]);
- }
-
- /* Initialise circular timer Q*/
- for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++)
- LIST_INIT(&la->sctpNatTimer.TimerQ[i]);
+ /* Initialise association tables*/
+ int i;
+ la->sctpNatTableSize = sysctl_hashtable_size;
+ SN_LOG(SN_LOG_EVENT,
+ SctpAliasLog("Initialising SCTP NAT Instance (hash_table_size:%d)\n", la->sctpNatTableSize));
+ la->sctpTableLocal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableL));
+ la->sctpTableGlobal = sn_calloc(la->sctpNatTableSize, sizeof(struct sctpNatTableG));
+ la->sctpNatTimer.TimerQ = sn_calloc(SN_TIMER_QUEUE_SIZE, sizeof(struct sctpTimerQ));
+ /* Initialise hash table */
+ for (i = 0; i < la->sctpNatTableSize; i++) {
+ LIST_INIT(&la->sctpTableLocal[i]);
+ LIST_INIT(&la->sctpTableGlobal[i]);
+ }
+
+ /* Initialise circular timer Q*/
+ for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++)
+ LIST_INIT(&la->sctpNatTimer.TimerQ[i]);
#ifdef _KERNEL
- la->sctpNatTimer.loc_time=time_uptime; /* la->timeStamp is not set yet */
+ la->sctpNatTimer.loc_time=time_uptime; /* la->timeStamp is not set yet */
#else
- la->sctpNatTimer.loc_time=la->timeStamp;
+ la->sctpNatTimer.loc_time=la->timeStamp;
#endif
- la->sctpNatTimer.cur_loc = 0;
- la->sctpLinkCount = 0;
+ la->sctpNatTimer.cur_loc = 0;
+ la->sctpLinkCount = 0;
}
/**
@@ -688,25 +666,25 @@ void AliasSctpInit(struct libalias *la)
*/
void AliasSctpTerm(struct libalias *la)
{
- struct sctp_nat_assoc *assoc1, *assoc2;
- int i;
-
- LIBALIAS_LOCK_ASSERT(la);
- SN_LOG(SN_LOG_EVENT,
- SctpAliasLog("Removing SCTP NAT Instance\n"));
- for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
- assoc1 = LIST_FIRST(&la->sctpNatTimer.TimerQ[i]);
- while (assoc1 != NULL) {
- freeGlobalAddressList(assoc1);
- assoc2 = LIST_NEXT(assoc1, timer_Q);
- sn_free(assoc1);
- assoc1 = assoc2;
- }
- }
-
- sn_free(la->sctpTableLocal);
- sn_free(la->sctpTableGlobal);
- sn_free(la->sctpNatTimer.TimerQ);
+ struct sctp_nat_assoc *assoc1, *assoc2;
+ int i;
+
+ LIBALIAS_LOCK_ASSERT(la);
+ SN_LOG(SN_LOG_EVENT,
+ SctpAliasLog("Removing SCTP NAT Instance\n"));
+ for (i = 0; i < SN_TIMER_QUEUE_SIZE; i++) {
+ assoc1 = LIST_FIRST(&la->sctpNatTimer.TimerQ[i]);
+ while (assoc1 != NULL) {
+ freeGlobalAddressList(assoc1);
+ assoc2 = LIST_NEXT(assoc1, timer_Q);
+ sn_free(assoc1);
+ assoc1 = assoc2;
+ }
+ }
+
+ sn_free(la->sctpTableLocal);
+ sn_free(la->sctpTableGlobal);
+ sn_free(la->sctpNatTimer.TimerQ);
}
/**
@@ -735,122 +713,122 @@ void AliasSctpTerm(struct libalias *la)
int
SctpAlias(struct libalias *la, struct ip *pip, int direction)
{
- int rtnval;
- struct sctp_nat_msg msg;
- struct sctp_nat_assoc *assoc = NULL;
-
- if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) {
- SctpAliasLog("ERROR: Invalid direction\n");
- return(PKT_ALIAS_ERROR);
- }
-
- sctp_CheckTimers(la); /* Check timers */
-
- /* Parse the packet */
- rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo)
- switch (rtnval) {
- case SN_PARSE_OK:
- break;
- case SN_PARSE_ERROR_CHHL:
- /* Not an error if there is a chunk length parsing error and this is a fragmented packet */
- if (ntohs(pip->ip_off) & IP_MF) {
- rtnval = SN_PARSE_OK;
- break;
- }
- SN_LOG(SN_LOG_EVENT,
- logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
- return(PKT_ALIAS_ERROR);
- case SN_PARSE_ERROR_PARTIALLOOKUP:
- if (sysctl_error_on_ootb > SN_LOCALandPARTIAL_ERROR_ON_OOTB) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
- return(PKT_ALIAS_ERROR);
- }
- case SN_PARSE_ERROR_LOOKUP:
- if (sysctl_error_on_ootb == SN_ERROR_ON_OOTB ||
- (sysctl_error_on_ootb == SN_LOCALandPARTIAL_ERROR_ON_OOTB && direction == SN_TO_LOCAL) ||
- (sysctl_error_on_ootb == SN_LOCAL_ERROR_ON_OOTB && direction == SN_TO_GLOBAL)) {
- TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */
- return(PKT_ALIAS_RESPOND);
- }
- default:
- SN_LOG(SN_LOG_EVENT,
- logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
- return(PKT_ALIAS_ERROR);
- }
-
- SN_LOG(SN_LOG_DETAIL,
- logsctpassoc(assoc, "*");
- logsctpparse(direction, &msg);
- );
-
- /* Process the SCTP message */
- rtnval = ProcessSctpMsg(la, direction, &msg, assoc);
-
- SN_LOG(SN_LOG_DEBUG_MAX,
- logsctpassoc(assoc, "-");
- logSctpLocal(la);
- logSctpGlobal(la);
- );
- SN_LOG(SN_LOG_DEBUG, logTimerQ(la));
-
- switch(rtnval){
- case SN_NAT_PKT:
- switch(direction) {
- case SN_TO_LOCAL:
- DifferentialChecksum(&(msg.ip_hdr->ip_sum),
- &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2);
- msg.ip_hdr->ip_dst = assoc->l_addr; /* change dst address to local address*/
- break;
- case SN_TO_GLOBAL:
- DifferentialChecksum(&(msg.ip_hdr->ip_sum),
- &(assoc->a_addr), &(msg.ip_hdr->ip_src), 2);
- msg.ip_hdr->ip_src = assoc->a_addr; /* change src to alias addr*/
- break;
- default:
- rtnval = SN_DROP_PKT; /* shouldn't get here, but if it does drop packet */
- SN_LOG(SN_LOG_LOW, logsctperror("ERROR: Invalid direction", msg.sctp_hdr->v_tag, rtnval, direction));
- break;
- }
- break;
- case SN_DROP_PKT:
- SN_LOG(SN_LOG_DETAIL, logsctperror("SN_DROP_PKT", msg.sctp_hdr->v_tag, rtnval, direction));
- break;
- case SN_REPLY_ABORT:
- case SN_REPLY_ERROR:
- case SN_SEND_ABORT:
- TxAbortErrorM(la, &msg, assoc, rtnval, direction);
- break;
- default:
- // big error, remove association and go to idle and write log messages
- SN_LOG(SN_LOG_LOW, logsctperror("SN_PROCESSING_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
- assoc->state=SN_RM;/* Mark for removal*/
- break;
- }
-
- /* Remove association if tagged for removal */
- if (assoc->state == SN_RM) {
- if (assoc->TableRegister) {
- sctp_RmTimeOut(la, assoc);
- RmSctpAssoc(la, assoc);
- }
- LIBALIAS_LOCK_ASSERT(la);
- freeGlobalAddressList(assoc);
- sn_free(assoc);
- }
- switch(rtnval) {
- case SN_NAT_PKT:
- return(PKT_ALIAS_OK);
- case SN_SEND_ABORT:
- return(PKT_ALIAS_OK);
- case SN_REPLY_ABORT:
- case SN_REPLY_ERROR:
- case SN_REFLECT_ERROR:
- return(PKT_ALIAS_RESPOND);
- case SN_DROP_PKT:
- default:
- return(PKT_ALIAS_ERROR);
- }
+ int rtnval;
+ struct sctp_nat_msg msg;
+ struct sctp_nat_assoc *assoc = NULL;
+
+ if ((direction != SN_TO_LOCAL) && (direction != SN_TO_GLOBAL)) {
+ SctpAliasLog("ERROR: Invalid direction\n");
+ return(PKT_ALIAS_ERROR);
+ }
+
+ sctp_CheckTimers(la); /* Check timers */
+
+ /* Parse the packet */
+ rtnval = sctp_PktParser(la, direction, pip, &msg, &assoc); //using *char (change to mbuf when get code from paolo)
+ switch (rtnval) {
+ case SN_PARSE_OK:
+ break;
+ case SN_PARSE_ERROR_CHHL:
+ /* Not an error if there is a chunk length parsing error and this is a fragmented packet */
+ if (ntohs(pip->ip_off) & IP_MF) {
+ rtnval = SN_PARSE_OK;
+ break;
+ }
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
+ return(PKT_ALIAS_ERROR);
+ case SN_PARSE_ERROR_PARTIALLOOKUP:
+ if (sysctl_error_on_ootb > SN_LOCALandPARTIAL_ERROR_ON_OOTB) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
+ return(PKT_ALIAS_ERROR);
+ }
+ case SN_PARSE_ERROR_LOOKUP:
+ if (sysctl_error_on_ootb == SN_ERROR_ON_OOTB ||
+ (sysctl_error_on_ootb == SN_LOCALandPARTIAL_ERROR_ON_OOTB && direction == SN_TO_LOCAL) ||
+ (sysctl_error_on_ootb == SN_LOCAL_ERROR_ON_OOTB && direction == SN_TO_GLOBAL)) {
+ TxAbortErrorM(la, &msg, assoc, SN_REFLECT_ERROR, direction); /*NB assoc=NULL */
+ return(PKT_ALIAS_RESPOND);
+ }
+ default:
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("SN_PARSE_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
+ return(PKT_ALIAS_ERROR);
+ }
+
+ SN_LOG(SN_LOG_DETAIL,
+ logsctpassoc(assoc, "*");
+ logsctpparse(direction, &msg);
+ );
+
+ /* Process the SCTP message */
+ rtnval = ProcessSctpMsg(la, direction, &msg, assoc);
+
+ SN_LOG(SN_LOG_DEBUG_MAX,
+ logsctpassoc(assoc, "-");
+ logSctpLocal(la);
+ logSctpGlobal(la);
+ );
+ SN_LOG(SN_LOG_DEBUG, logTimerQ(la));
+
+ switch(rtnval){
+ case SN_NAT_PKT:
+ switch(direction) {
+ case SN_TO_LOCAL:
+ DifferentialChecksum(&(msg.ip_hdr->ip_sum),
+ &(assoc->l_addr), &(msg.ip_hdr->ip_dst), 2);
+ msg.ip_hdr->ip_dst = assoc->l_addr; /* change dst address to local address*/
+ break;
+ case SN_TO_GLOBAL:
+ DifferentialChecksum(&(msg.ip_hdr->ip_sum),
+ &(assoc->a_addr), &(msg.ip_hdr->ip_src), 2);
+ msg.ip_hdr->ip_src = assoc->a_addr; /* change src to alias addr*/
+ break;
+ default:
+ rtnval = SN_DROP_PKT; /* shouldn't get here, but if it does drop packet */
+ SN_LOG(SN_LOG_LOW, logsctperror("ERROR: Invalid direction", msg.sctp_hdr->v_tag, rtnval, direction));
+ break;
+ }
+ break;
+ case SN_DROP_PKT:
+ SN_LOG(SN_LOG_DETAIL, logsctperror("SN_DROP_PKT", msg.sctp_hdr->v_tag, rtnval, direction));
+ break;
+ case SN_REPLY_ABORT:
+ case SN_REPLY_ERROR:
+ case SN_SEND_ABORT:
+ TxAbortErrorM(la, &msg, assoc, rtnval, direction);
+ break;
+ default:
+ // big error, remove association and go to idle and write log messages
+ SN_LOG(SN_LOG_LOW, logsctperror("SN_PROCESSING_ERROR", msg.sctp_hdr->v_tag, rtnval, direction));
+ assoc->state=SN_RM;/* Mark for removal*/
+ break;
+ }
+
+ /* Remove association if tagged for removal */
+ if (assoc->state == SN_RM) {
+ if (assoc->TableRegister) {
+ sctp_RmTimeOut(la, assoc);
+ RmSctpAssoc(la, assoc);
+ }
+ LIBALIAS_LOCK_ASSERT(la);
+ freeGlobalAddressList(assoc);
+ sn_free(assoc);
+ }
+ switch(rtnval) {
+ case SN_NAT_PKT:
+ return(PKT_ALIAS_OK);
+ case SN_SEND_ABORT:
+ return(PKT_ALIAS_OK);
+ case SN_REPLY_ABORT:
+ case SN_REPLY_ERROR:
+ case SN_REFLECT_ERROR:
+ return(PKT_ALIAS_RESPOND);
+ case SN_DROP_PKT:
+ default:
+ return(PKT_ALIAS_ERROR);
+ }
}
/**
@@ -889,92 +867,92 @@ SctpAlias(struct libalias *la, struct ip *pip, int direction)
static void
TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int sndrply, int direction)
{
- int sctp_size = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause);
- int ip_size = sizeof(struct ip) + sctp_size;
- int include_error_cause = 1;
- char tmp_ip[ip_size];
-
- if (ntohs(sm->ip_hdr->ip_len) < ip_size) { /* short packet, cannot send error cause */
- include_error_cause = 0;
- ip_size = ip_size - sizeof(struct sctp_error_cause);
- sctp_size = sctp_size - sizeof(struct sctp_error_cause);
- }
- /* Assign header pointers packet */
- struct ip* ip = (struct ip *) tmp_ip;
- struct sctphdr* sctp_hdr = (struct sctphdr *) ((char *) ip + sizeof(*ip));
- struct sctp_chunkhdr* chunk_hdr = (struct sctp_chunkhdr *) ((char *) sctp_hdr + sizeof(*sctp_hdr));
- struct sctp_error_cause* error_cause = (struct sctp_error_cause *) ((char *) chunk_hdr + sizeof(*chunk_hdr));
-
- /* construct ip header */
- ip->ip_v = sm->ip_hdr->ip_v;
- ip->ip_hl = 5; /* 5*32 bit words */
- ip->ip_tos = 0;
- ip->ip_len = htons(ip_size);
- ip->ip_id = sm->ip_hdr->ip_id;
- ip->ip_off = 0;
- ip->ip_ttl = 255;
- ip->ip_p = IPPROTO_SCTP;
- /*
- The definitions below should be removed when they make it into the SCTP stack
- */
+ int sctp_size = sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_error_cause);
+ int ip_size = sizeof(struct ip) + sctp_size;
+ int include_error_cause = 1;
+ char tmp_ip[ip_size];
+
+ if (ntohs(sm->ip_hdr->ip_len) < ip_size) { /* short packet, cannot send error cause */
+ include_error_cause = 0;
+ ip_size = ip_size - sizeof(struct sctp_error_cause);
+ sctp_size = sctp_size - sizeof(struct sctp_error_cause);
+ }
+ /* Assign header pointers packet */
+ struct ip* ip = (struct ip *) tmp_ip;
+ struct sctphdr* sctp_hdr = (struct sctphdr *) ((char *) ip + sizeof(*ip));
+ struct sctp_chunkhdr* chunk_hdr = (struct sctp_chunkhdr *) ((char *) sctp_hdr + sizeof(*sctp_hdr));
+ struct sctp_error_cause* error_cause = (struct sctp_error_cause *) ((char *) chunk_hdr + sizeof(*chunk_hdr));
+
+ /* construct ip header */
+ ip->ip_v = sm->ip_hdr->ip_v;
+ ip->ip_hl = 5; /* 5*32 bit words */
+ ip->ip_tos = 0;
+ ip->ip_len = htons(ip_size);
+ ip->ip_id = sm->ip_hdr->ip_id;
+ ip->ip_off = 0;
+ ip->ip_ttl = 255;
+ ip->ip_p = IPPROTO_SCTP;
+ /*
+ The definitions below should be removed when they make it into the SCTP stack
+ */
#define SCTP_MIDDLEBOX_FLAG 0x02
#define SCTP_NAT_TABLE_COLLISION 0x00b0
#define SCTP_MISSING_NAT 0x00b1
- chunk_hdr->chunk_type = (sndrply & SN_TX_ABORT) ? SCTP_ABORT_ASSOCIATION : SCTP_OPERATION_ERROR;
- chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG;
- if (include_error_cause) {
- error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION);
- error_cause->length = htons(sizeof(struct sctp_error_cause));
- chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause));
- } else {
- chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr));
- }
-
- /* set specific values */
- switch(sndrply) {
- case SN_REFLECT_ERROR:
- chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */
- sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
- break;
- case SN_REPLY_ERROR:
- sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ;
- break;
- case SN_SEND_ABORT:
- sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
- break;
- case SN_REPLY_ABORT:
- sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag;
- break;
- }
+ chunk_hdr->chunk_type = (sndrply & SN_TX_ABORT) ? SCTP_ABORT_ASSOCIATION : SCTP_OPERATION_ERROR;
+ chunk_hdr->chunk_flags = SCTP_MIDDLEBOX_FLAG;
+ if (include_error_cause) {
+ error_cause->code = htons((sndrply & SN_REFLECT_ERROR) ? SCTP_MISSING_NAT : SCTP_NAT_TABLE_COLLISION);
+ error_cause->length = htons(sizeof(struct sctp_error_cause));
+ chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr) + sizeof(struct sctp_error_cause));
+ } else {
+ chunk_hdr->chunk_length = htons(sizeof(*chunk_hdr));
+ }
+
+ /* set specific values */
+ switch(sndrply) {
+ case SN_REFLECT_ERROR:
+ chunk_hdr->chunk_flags |= SCTP_HAD_NO_TCB; /* set Tbit */
+ sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
+ break;
+ case SN_REPLY_ERROR:
+ sctp_hdr->v_tag = (direction == SN_TO_LOCAL) ? assoc->g_vtag : assoc->l_vtag ;
+ break;
+ case SN_SEND_ABORT:
+ sctp_hdr->v_tag = sm->sctp_hdr->v_tag;
+ break;
+ case SN_REPLY_ABORT:
+ sctp_hdr->v_tag = sm->sctpchnk.Init->initiate_tag;
+ break;
+ }
- /* Set send/reply values */
- if (sndrply == SN_SEND_ABORT) { /*pass through NAT */
- ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr;
- ip->ip_dst = (direction == SN_TO_LOCAL) ? assoc->l_addr : sm->ip_hdr->ip_dst;
- sctp_hdr->src_port = sm->sctp_hdr->src_port;
- sctp_hdr->dest_port = sm->sctp_hdr->dest_port;
- } else { /* reply and reflect */
- ip->ip_src = sm->ip_hdr->ip_dst;
- ip->ip_dst = sm->ip_hdr->ip_src;
- sctp_hdr->src_port = sm->sctp_hdr->dest_port;
- sctp_hdr->dest_port = sm->sctp_hdr->src_port;
- }
+ /* Set send/reply values */
+ if (sndrply == SN_SEND_ABORT) { /*pass through NAT */
+ ip->ip_src = (direction == SN_TO_LOCAL) ? sm->ip_hdr->ip_src : assoc->a_addr;
+ ip->ip_dst = (direction == SN_TO_LOCAL) ? assoc->l_addr : sm->ip_hdr->ip_dst;
+ sctp_hdr->src_port = sm->sctp_hdr->src_port;
+ sctp_hdr->dest_port = sm->sctp_hdr->dest_port;
+ } else { /* reply and reflect */
+ ip->ip_src = sm->ip_hdr->ip_dst;
+ ip->ip_dst = sm->ip_hdr->ip_src;
+ sctp_hdr->src_port = sm->sctp_hdr->dest_port;
+ sctp_hdr->dest_port = sm->sctp_hdr->src_port;
+ }
- /* Calculate IP header checksum */
- ip->ip_sum = in_cksum_hdr(ip);
+ /* Calculate IP header checksum */
+ ip->ip_sum = in_cksum_hdr(ip);
- /* calculate SCTP header CRC32 */
- sctp_hdr->checksum = 0;
- sctp_hdr->checksum = sctp_csum_finalize(update_crc32(0xffffffff, (unsigned char *) sctp_hdr, sctp_size));
-
- memcpy(sm->ip_hdr, ip, ip_size);
-
- SN_LOG(SN_LOG_EVENT,SctpAliasLog("%s %s 0x%x (->%s:%u vtag=0x%x crc=0x%x)\n",
- ((sndrply == SN_SEND_ABORT) ? "Sending" : "Replying"),
- ((sndrply & SN_TX_ERROR) ? "ErrorM" : "AbortM"),
- (include_error_cause ? ntohs(error_cause->code) : 0),
- inet_ntoa(ip->ip_dst),ntohs(sctp_hdr->dest_port),
- ntohl(sctp_hdr->v_tag), ntohl(sctp_hdr->checksum)));
+ /* calculate SCTP header CRC32 */
+ sctp_hdr->checksum = 0;
+ sctp_hdr->checksum = sctp_finalize_crc32(update_crc32(0xffffffff, (unsigned char *) sctp_hdr, sctp_size));
+
+ memcpy(sm->ip_hdr, ip, ip_size);
+
+ SN_LOG(SN_LOG_EVENT,SctpAliasLog("%s %s 0x%x (->%s:%u vtag=0x%x crc=0x%x)\n",
+ ((sndrply == SN_SEND_ABORT) ? "Sending" : "Replying"),
+ ((sndrply & SN_TX_ERROR) ? "ErrorM" : "AbortM"),
+ (include_error_cause ? ntohs(error_cause->code) : 0),
+ inet_ntoa(ip->ip_dst),ntohs(sctp_hdr->dest_port),
+ ntohl(sctp_hdr->v_tag), ntohl(sctp_hdr->checksum)));
}
/* ----------------------------------------------------------------------
@@ -1004,209 +982,209 @@ TxAbortErrorM(struct libalias *la, struct sctp_nat_msg *sm, struct sctp_nat_asso
*/
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)
//sctp_PktParser(int direction, struct mbuf *ipak, int ip_hdr_len,struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
{
- struct sctphdr *sctp_hdr;
- struct sctp_chunkhdr *chunk_hdr;
- struct sctp_paramhdr *param_hdr;
- struct in_addr ipv4addr;
- int bytes_left; /* bytes left in ip packet */
- int chunk_length;
- int chunk_count;
- int partial_match = 0;
- // mbuf *mp;
- // int mlen;
-
- // mlen = SCTP_HEADER_LEN(i_pak);
- // mp = SCTP_HEADER_TO_CHAIN(i_pak); /* does nothing in bsd since header and chain not separate */
-
- /*
- * Note, that if the VTag is zero, it must be an INIT
- * Also, I am only interested in the content of INIT and ADDIP chunks
- */
-
- // no mbuf stuff from Paolo yet so ...
- sm->ip_hdr = pip;
- /* remove ip header length from the bytes_left */
- bytes_left = ntohs(pip->ip_len) - (pip->ip_hl << 2);
-
- /* Check SCTP header length and move to first chunk */
- if (bytes_left < sizeof(struct sctphdr)) {
- sm->sctp_hdr = NULL;
- return(SN_PARSE_ERROR_IPSHL); /* packet not long enough*/
- }
-
- sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip);
- bytes_left -= sizeof(struct sctphdr);
+ struct sctphdr *sctp_hdr;
+ struct sctp_chunkhdr *chunk_hdr;
+ struct sctp_paramhdr *param_hdr;
+ struct in_addr ipv4addr;
+ int bytes_left; /* bytes left in ip packet */
+ int chunk_length;
+ int chunk_count;
+ int partial_match = 0;
+ // mbuf *mp;
+ // int mlen;
+
+ // mlen = SCTP_HEADER_LEN(i_pak);
+ // mp = SCTP_HEADER_TO_CHAIN(i_pak); /* does nothing in bsd since header and chain not separate */
+
+ /*
+ * Note, that if the VTag is zero, it must be an INIT
+ * Also, I am only interested in the content of INIT and ADDIP chunks
+ */
+
+ // no mbuf stuff from Paolo yet so ...
+ sm->ip_hdr = pip;
+ /* remove ip header length from the bytes_left */
+ bytes_left = ntohs(pip->ip_len) - (pip->ip_hl << 2);
+
+ /* Check SCTP header length and move to first chunk */
+ if (bytes_left < sizeof(struct sctphdr)) {
+ sm->sctp_hdr = NULL;
+ return(SN_PARSE_ERROR_IPSHL); /* packet not long enough*/
+ }
+
+ sm->sctp_hdr = sctp_hdr = (struct sctphdr *) ip_next(pip);
+ bytes_left -= sizeof(struct sctphdr);
- /* Check for valid ports (zero valued ports would find partially initialised associations */
- if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0)
- return(SN_PARSE_ERROR_PORT);
+ /* Check for valid ports (zero valued ports would find partially initialised associations */
+ if (sctp_hdr->src_port == 0 || sctp_hdr->dest_port == 0)
+ return(SN_PARSE_ERROR_PORT);
- /* Check length of first chunk */
- if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/
- return(SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */
+ /* Check length of first chunk */
+ if (bytes_left < SN_MIN_CHUNK_SIZE) /* malformed chunk - could cause endless loop*/
+ return(SN_PARSE_ERROR_CHHL); /* packet not long enough for this chunk */
- /* First chunk */
- chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr);
+ /* First chunk */
+ chunk_hdr = SN_SCTP_FIRSTCHUNK(sctp_hdr);
- chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
- if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/
- return(SN_PARSE_ERROR_CHHL);
-
- if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) &&
- ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) ||
- (chunk_hdr->chunk_type == SCTP_SHUTDOWN_COMPLETE))) {
- /* T-Bit set */
- if (direction == SN_TO_LOCAL)
- *passoc = FindSctpGlobalT(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
- else
- *passoc = FindSctpLocalT(la, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
- } else {
- /* Proper v_tag settings */
- if (direction == SN_TO_LOCAL)
- *passoc = FindSctpGlobal(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
- else
- *passoc = FindSctpLocal(la, pip->ip_src, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port);
- }
-
- chunk_count = 1;
- /* Real packet parsing occurs below */
- sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/
- sm->chunk_length = 0; /* only care about length for key chunks */
- while (IS_SCTP_CONTROL(chunk_hdr)) {
- switch(chunk_hdr->chunk_type) {
- case SCTP_INITIATION:
- if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- sm->msg = SN_SCTP_INIT;
- sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
- sm->chunk_length = chunk_length;
- /* if no existing association, create a new one */
- if (*passoc == NULL) {
- if (sctp_hdr->v_tag == 0){ //Init requires vtag=0
- *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
- if (*passoc == NULL) {/* out of resources */
- return(SN_PARSE_ERROR_AS_MALLOC);
- }
- /* Initialise association - malloc initialises memory to zeros */
- (*passoc)->state = SN_ID;
- LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
- (*passoc)->TableRegister = SN_NULL_TBL;
- return(SN_PARSE_OK);
- }
- return(SN_PARSE_ERROR_VTAG);
- }
- return(SN_PARSE_ERROR_LOOKUP);
- case SCTP_INITIATION_ACK:
- if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- sm->msg = SN_SCTP_INITACK;
- sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
- sm->chunk_length = chunk_length;
- return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
- case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */
- sm->msg = SN_SCTP_ABORT;
- sm->chunk_length = chunk_length;
- return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP_ABORT):(SN_PARSE_OK));
- case SCTP_SHUTDOWN_ACK:
- if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- if (sm->msg > SN_SCTP_SHUTACK) {
- sm->msg = SN_SCTP_SHUTACK;
- sm->chunk_length = chunk_length;
- }
- break;
- case SCTP_SHUTDOWN_COMPLETE: /* minimum sized chunk */
- if (sm->msg > SN_SCTP_SHUTCOMP) {
- sm->msg = SN_SCTP_SHUTCOMP;
- sm->chunk_length = chunk_length;
- }
- return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
- case SCTP_ASCONF:
- if (sm->msg > SN_SCTP_ASCONF) {
- if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- //leave parameter searching to later, if required
- param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/
- if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) {
- if ((*passoc == NULL) && (direction == SN_TO_LOCAL)) { /* AddIP with no association */
- /* try look up with the ASCONF packet's alternative address */
- ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr;
- *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
- }
- param_hdr = (struct sctp_paramhdr *)
- ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */
- sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */
+ chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
+ if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left)) /* malformed chunk - could cause endless loop*/
+ return(SN_PARSE_ERROR_CHHL);
+
+ if ((chunk_hdr->chunk_flags & SCTP_HAD_NO_TCB) &&
+ ((chunk_hdr->chunk_type == SCTP_ABORT_ASSOCIATION) ||
+ (chunk_hdr->chunk_type == SCTP_SHUTDOWN_COMPLETE))) {
+ /* T-Bit set */
+ if (direction == SN_TO_LOCAL)
+ *passoc = FindSctpGlobalT(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
+ else
+ *passoc = FindSctpLocalT(la, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->dest_port, sctp_hdr->src_port);
} else {
- if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- param_hdr = (struct sctp_paramhdr *)
- ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */
- sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */
+ /* Proper v_tag settings */
+ if (direction == SN_TO_LOCAL)
+ *passoc = FindSctpGlobal(la, pip->ip_src, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
+ else
+ *passoc = FindSctpLocal(la, pip->ip_src, pip->ip_dst, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port);
}
- sm->msg = SN_SCTP_ASCONF;
- sm->sctpchnk.Asconf = param_hdr;
+
+ chunk_count = 1;
+ /* Real packet parsing occurs below */
+ sm->msg = SN_SCTP_OTHER;/* Initialise to largest value*/
+ sm->chunk_length = 0; /* only care about length for key chunks */
+ while (IS_SCTP_CONTROL(chunk_hdr)) {
+ switch(chunk_hdr->chunk_type) {
+ case SCTP_INITIATION:
+ if (chunk_length < sizeof(struct sctp_init_chunk)) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ sm->msg = SN_SCTP_INIT;
+ sm->sctpchnk.Init = (struct sctp_init *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
+ sm->chunk_length = chunk_length;
+ /* if no existing association, create a new one */
+ if (*passoc == NULL) {
+ if (sctp_hdr->v_tag == 0){ //Init requires vtag=0
+ *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
+ if (*passoc == NULL) {/* out of resources */
+ return(SN_PARSE_ERROR_AS_MALLOC);
+ }
+ /* Initialise association - malloc initialises memory to zeros */
+ (*passoc)->state = SN_ID;
+ LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
+ (*passoc)->TableRegister = SN_NULL_TBL;
+ return(SN_PARSE_OK);
+ }
+ return(SN_PARSE_ERROR_VTAG);
+ }
+ return(SN_PARSE_ERROR_LOOKUP);
+ case SCTP_INITIATION_ACK:
+ if (chunk_length < sizeof(struct sctp_init_ack_chunk)) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ sm->msg = SN_SCTP_INITACK;
+ sm->sctpchnk.InitAck = (struct sctp_init_ack *) ((char *) chunk_hdr + sizeof(struct sctp_chunkhdr));
+ sm->chunk_length = chunk_length;
+ return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
+ case SCTP_ABORT_ASSOCIATION: /* access only minimum sized chunk */
+ sm->msg = SN_SCTP_ABORT;
+ sm->chunk_length = chunk_length;
+ return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP_ABORT):(SN_PARSE_OK));
+ case SCTP_SHUTDOWN_ACK:
+ if (chunk_length < sizeof(struct sctp_shutdown_ack_chunk)) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ if (sm->msg > SN_SCTP_SHUTACK) {
+ sm->msg = SN_SCTP_SHUTACK;
+ sm->chunk_length = chunk_length;
+ }
+ break;
+ case SCTP_SHUTDOWN_COMPLETE: /* minimum sized chunk */
+ if (sm->msg > SN_SCTP_SHUTCOMP) {
+ sm->msg = SN_SCTP_SHUTCOMP;
+ sm->chunk_length = chunk_length;
+ }
+ return ((*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK));
+ case SCTP_ASCONF:
+ if (sm->msg > SN_SCTP_ASCONF) {
+ if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv4addr_param))) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ //leave parameter searching to later, if required
+ param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr + sizeof(struct sctp_asconf_chunk)); /*compulsory IP parameter*/
+ if (ntohs(param_hdr->param_type) == SCTP_IPV4_ADDRESS) {
+ if ((*passoc == NULL) && (direction == SN_TO_LOCAL)) { /* AddIP with no association */
+ /* try look up with the ASCONF packet's alternative address */
+ ipv4addr.s_addr = ((struct sctp_ipv4addr_param *) param_hdr)->addr;
+ *passoc = FindSctpGlobal(la, ipv4addr, sctp_hdr->v_tag, sctp_hdr->src_port, sctp_hdr->dest_port, &partial_match);
+ }
+ param_hdr = (struct sctp_paramhdr *)
+ ((char *) param_hdr + sizeof(struct sctp_ipv4addr_param)); /*asconf's compulsory address parameter */
+ sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv4addr_param); /* rest of chunk */
+ } else {
+ if (chunk_length < (sizeof(struct sctp_asconf_chunk) + sizeof(struct sctp_ipv6addr_param))) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ param_hdr = (struct sctp_paramhdr *)
+ ((char *) param_hdr + sizeof(struct sctp_ipv6addr_param)); /*asconf's compulsory address parameter */
+ sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_chunk) - sizeof(struct sctp_ipv6addr_param); /* rest of chunk */
+ }
+ sm->msg = SN_SCTP_ASCONF;
+ sm->sctpchnk.Asconf = param_hdr;
- if (*passoc == NULL) { /* AddIP with no association */
- *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
- if (*passoc == NULL) {/* out of resources */
- return(SN_PARSE_ERROR_AS_MALLOC);
- }
- /* Initialise association - malloc initialises memory to zeros */
- (*passoc)->state = SN_ID;
- LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
- (*passoc)->TableRegister = SN_NULL_TBL;
- return(SN_PARSE_OK);
+ if (*passoc == NULL) { /* AddIP with no association */
+ *passoc = (struct sctp_nat_assoc *) sn_malloc(sizeof(struct sctp_nat_assoc));
+ if (*passoc == NULL) {/* out of resources */
+ return(SN_PARSE_ERROR_AS_MALLOC);
+ }
+ /* Initialise association - malloc initialises memory to zeros */
+ (*passoc)->state = SN_ID;
+ LIST_INIT(&((*passoc)->Gaddr)); /* always initialise to avoid memory problems */
+ (*passoc)->TableRegister = SN_NULL_TBL;
+ return(SN_PARSE_OK);
+ }
+ }
+ break;
+ case SCTP_ASCONF_ACK:
+ if (sm->msg > SN_SCTP_ASCONFACK) {
+ if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/
+ return(SN_PARSE_ERROR_CHHL);
+ //leave parameter searching to later, if required
+ param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr
+ + sizeof(struct sctp_asconf_ack_chunk));
+ sm->msg = SN_SCTP_ASCONFACK;
+ sm->sctpchnk.Asconf = param_hdr;
+ sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_ack_chunk);
+ }
+ break;
+ default:
+ break; /* do nothing*/
+ }
+
+ /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */
+ if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit))
+ return(SN_PARSE_ERROR_LOOKUP);
+
+ /* finished with this chunk, on to the next chunk*/
+ bytes_left-= chunk_length;
+
+ /* Is this the end of the packet ? */
+ if (bytes_left == 0)
+ return (*passoc == NULL)?(SN_PARSE_ERROR_LOOKUP):(SN_PARSE_OK);
+
+ /* Are there enough bytes in packet to at least retrieve length of next chunk ? */
+ if (bytes_left < SN_MIN_CHUNK_SIZE)
+ return(SN_PARSE_ERROR_CHHL);
+
+ chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr);
+
+ /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */
+ chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
+ if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left))
+ return(SN_PARSE_ERROR_CHHL);
+ if(++chunk_count > sysctl_chunk_proc_limit)
+ return(SN_PARSE_OK); /* limit for processing chunks, take what we get */
}
- }
- break;
- case SCTP_ASCONF_ACK:
- if (sm->msg > SN_SCTP_ASCONFACK) {
- if (chunk_length < sizeof(struct sctp_asconf_ack_chunk)) /* malformed chunk*/
- return(SN_PARSE_ERROR_CHHL);
- //leave parameter searching to later, if required
- param_hdr = (struct sctp_paramhdr *) ((char *) chunk_hdr
- + sizeof(struct sctp_asconf_ack_chunk));
- sm->msg = SN_SCTP_ASCONFACK;
- sm->sctpchnk.Asconf = param_hdr;
- sm->chunk_length = chunk_length - sizeof(struct sctp_asconf_ack_chunk);
- }
- break;
- default:
- break; /* do nothing*/
- }
-
- /* if no association is found exit - we need to find an Init or AddIP within sysctl_initialising_chunk_proc_limit */
- if ((*passoc == NULL) && (chunk_count >= sysctl_initialising_chunk_proc_limit))
- return(SN_PARSE_ERROR_LOOKUP);
-
- /* finished with this chunk, on to the next chunk*/
- bytes_left-= chunk_length;
-
- /* Is this the end of the packet ? */
- if (bytes_left == 0)
- return(SN_PARSE_OK);
-
- /* Are there enough bytes in packet to at least retrieve length of next chunk ? */
- if (bytes_left < SN_MIN_CHUNK_SIZE)
- return(SN_PARSE_ERROR_CHHL);
-
- chunk_hdr = SN_SCTP_NEXTCHUNK(chunk_hdr);
-
- /* Is the chunk long enough to not cause endless look and are there enough bytes in packet to read the chunk ? */
- chunk_length = SCTP_SIZE32(ntohs(chunk_hdr->chunk_length));
- if ((chunk_length < SN_MIN_CHUNK_SIZE) || (chunk_length > bytes_left))
- return(SN_PARSE_ERROR_CHHL);
- if(++chunk_count > sysctl_chunk_proc_limit)
- return(SN_PARSE_OK); /* limit for processing chunks, take what we get */
- }
-
- if (*passoc == NULL)
- return (partial_match)?(SN_PARSE_ERROR_PARTIALLOOKUP):(SN_PARSE_ERROR_LOOKUP);
- else
- return(SN_PARSE_OK);
+
+ if (*passoc == NULL)
+ return (partial_match)?(SN_PARSE_ERROR_PARTIALLOOKUP):(SN_PARSE_ERROR_LOOKUP);
+ else
+ return(SN_PARSE_OK);
}
/** @ingroup packet_parser
@@ -1229,57 +1207,57 @@ sctp_PktParser(struct libalias *la, int direction, struct ip *pip,
static int
GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, uint32_t *g_vtag, int direction)
{
- /* To be removed when information is in the sctp headers */
+ /* To be removed when information is in the sctp headers */
#define SCTP_VTAG_PARAM 0xC007
- struct sctp_vtag_param {
- struct sctp_paramhdr ph;/* type=SCTP_VTAG_PARAM */
- uint32_t local_vtag;
- uint32_t remote_vtag;
- } __attribute__((packed));
+ struct sctp_vtag_param {
+ struct sctp_paramhdr ph;/* type=SCTP_VTAG_PARAM */
+ uint32_t local_vtag;
+ uint32_t remote_vtag;
+ } __attribute__((packed));
- struct sctp_vtag_param *vtag_param;
- struct sctp_paramhdr *param;
- int bytes_left;
- int param_size;
- int param_count;
-
- param_count = 1;
- param = sm->sctpchnk.Asconf;
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- bytes_left = sm->chunk_length;
- /* step through Asconf parameters */
- while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) {
- if (ntohs(param->param_type) == SCTP_VTAG_PARAM) {
- vtag_param = (struct sctp_vtag_param *) param;
- switch(direction) {
- /* The Internet draft is a little ambigious as to order of these vtags.
- We think it is this way around. If we are wrong, the order will need
- to be changed. */
- case SN_TO_GLOBAL:
- *g_vtag = vtag_param->local_vtag;
- *l_vtag = vtag_param->remote_vtag;
- break;
- case SN_TO_LOCAL:
- *g_vtag = vtag_param->remote_vtag;
- *l_vtag = vtag_param->local_vtag;
- break;
- }
- return(1); /* found */
- }
-
- bytes_left -= param_size;
- if (bytes_left < SN_MIN_PARAM_SIZE) return(0);
-
- param = SN_SCTP_NEXTPARAM(param);
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (++param_count > sysctl_param_proc_limit) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("Parameter parse limit exceeded (GetAsconfVtags)",
- sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
- return(0); /* not found limit exceeded*/
- }
- }
- return(0); /* not found */
+ struct sctp_vtag_param *vtag_param;
+ struct sctp_paramhdr *param;
+ int bytes_left;
+ int param_size;
+ int param_count;
+
+ param_count = 1;
+ param = sm->sctpchnk.Asconf;
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ bytes_left = sm->chunk_length;
+ /* step through Asconf parameters */
+ while((bytes_left >= param_size) && (bytes_left >= SN_VTAG_PARAM_SIZE)) {
+ if (ntohs(param->param_type) == SCTP_VTAG_PARAM) {
+ vtag_param = (struct sctp_vtag_param *) param;
+ switch(direction) {
+ /* The Internet draft is a little ambigious as to order of these vtags.
+ We think it is this way around. If we are wrong, the order will need
+ to be changed. */
+ case SN_TO_GLOBAL:
+ *g_vtag = vtag_param->local_vtag;
+ *l_vtag = vtag_param->remote_vtag;
+ break;
+ case SN_TO_LOCAL:
+ *g_vtag = vtag_param->remote_vtag;
+ *l_vtag = vtag_param->local_vtag;
+ break;
+ }
+ return(1); /* found */
+ }
+
+ bytes_left -= param_size;
+ if (bytes_left < SN_MIN_PARAM_SIZE) return(0);
+
+ param = SN_SCTP_NEXTPARAM(param);
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (++param_count > sysctl_param_proc_limit) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("Parameter parse limit exceeded (GetAsconfVtags)",
+ sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
+ return(0); /* not found limit exceeded*/
+ }
+ }
+ return(0); /* not found */
}
/** @ingroup packet_parser
@@ -1296,119 +1274,119 @@ GetAsconfVtags(struct libalias *la, struct sctp_nat_msg *sm, uint32_t *l_vtag, u
static void
AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
{
- struct sctp_ipv4addr_param *ipv4_param;
- struct sctp_paramhdr *param = NULL;
- struct sctp_GlobalAddress *G_Addr;
- struct in_addr g_addr = {0};
- int bytes_left = 0;
- int param_size;
- int param_count, addr_param_count = 0;
-
- switch(direction) {
- case SN_TO_GLOBAL: /* does not contain global addresses */
- g_addr = sm->ip_hdr->ip_dst;
- bytes_left = 0; /* force exit */
- break;
- case SN_TO_LOCAL:
- g_addr = sm->ip_hdr->ip_src;
- param_count = 1;
- switch(sm->msg) {
- case SN_SCTP_INIT:
- bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk);
- param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init));
- break;
- case SN_SCTP_INITACK:
- bytes_left = sm->chunk_length - sizeof(struct sctp_init_ack_chunk);
- param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.InitAck + sizeof(struct sctp_init_ack));
- break;
- case SN_SCTP_ASCONF:
- bytes_left = sm->chunk_length;
- param = sm->sctpchnk.Asconf;
- break;
- }
- }
- if (bytes_left >= SN_MIN_PARAM_SIZE)
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- else
- param_size = bytes_left+1; /* force skip loop */
+ struct sctp_ipv4addr_param *ipv4_param;
+ struct sctp_paramhdr *param = NULL;
+ struct sctp_GlobalAddress *G_Addr;
+ struct in_addr g_addr = {0};
+ int bytes_left = 0;
+ int param_size;
+ int param_count, addr_param_count = 0;
+
+ switch(direction) {
+ case SN_TO_GLOBAL: /* does not contain global addresses */
+ g_addr = sm->ip_hdr->ip_dst;
+ bytes_left = 0; /* force exit */
+ break;
+ case SN_TO_LOCAL:
+ g_addr = sm->ip_hdr->ip_src;
+ param_count = 1;
+ switch(sm->msg) {
+ case SN_SCTP_INIT:
+ bytes_left = sm->chunk_length - sizeof(struct sctp_init_chunk);
+ param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.Init + sizeof(struct sctp_init));
+ break;
+ case SN_SCTP_INITACK:
+ bytes_left = sm->chunk_length - sizeof(struct sctp_init_ack_chunk);
+ param = (struct sctp_paramhdr *)((char *)sm->sctpchnk.InitAck + sizeof(struct sctp_init_ack));
+ break;
+ case SN_SCTP_ASCONF:
+ bytes_left = sm->chunk_length;
+ param = sm->sctpchnk.Asconf;
+ break;
+ }
+ }
+ if (bytes_left >= SN_MIN_PARAM_SIZE)
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ else
+ param_size = bytes_left+1; /* force skip loop */
- if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */
- G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
- if (G_Addr == NULL) {/* out of resources */
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
- sm->sctp_hdr->v_tag, 0, direction));
- assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
- sysctl_track_global_addresses=0;
- return;
- }
- G_Addr->g_addr = g_addr;
- if (!Add_Global_Address_to_List(assoc, G_Addr))
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: Address already in list",
- sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- }
-
- /* step through parameters */
- while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
- if (assoc->num_Gaddr >= sysctl_track_global_addresses) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached",
- sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
- return;
- }
- switch(ntohs(param->param_type)) {
- case SCTP_ADD_IP_ADDRESS:
- /* skip to address parameter - leave param_size so bytes left will be calculated properly*/
- param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp;
- case SCTP_IPV4_ADDRESS:
- ipv4_param = (struct sctp_ipv4addr_param *) param;
- /* add addresses to association */
- G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
- if (G_Addr == NULL) {/* out of resources */
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
- sm->sctp_hdr->v_tag, 0, direction));
- assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
- sysctl_track_global_addresses=0;
- return;
- }
- /* add address */
- addr_param_count++;
- if ((sm->msg == SN_SCTP_ASCONF) && (ipv4_param->addr == INADDR_ANY)) { /* use packet address */
- G_Addr->g_addr = g_addr;
- if (!Add_Global_Address_to_List(assoc, G_Addr))
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: Address already in list",
- sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- return; /*shouldn't be any other addresses if the zero address is given*/
- } else {
- G_Addr->g_addr.s_addr = ipv4_param->addr;
- if (!Add_Global_Address_to_List(assoc, G_Addr))
- SN_LOG(SN_LOG_EVENT,
- logsctperror("AddGlobalIPAddress: Address already in list",
- sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- }
- }
+ if ((assoc->state == SN_ID) && ((sm->msg == SN_SCTP_INIT) || (bytes_left < SN_MIN_PARAM_SIZE))) {/* add pkt address */
+ G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
+ if (G_Addr == NULL) {/* out of resources */
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
+ sm->sctp_hdr->v_tag, 0, direction));
+ assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
+ sysctl_track_global_addresses=0;
+ return;
+ }
+ G_Addr->g_addr = g_addr;
+ if (!Add_Global_Address_to_List(assoc, G_Addr))
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: Address already in list",
+ sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
+ }
+
+ /* step through parameters */
+ while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
+ if (assoc->num_Gaddr >= sysctl_track_global_addresses) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: Maximum Number of addresses reached",
+ sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
+ return;
+ }
+ switch(ntohs(param->param_type)) {
+ case SCTP_ADD_IP_ADDRESS:
+ /* skip to address parameter - leave param_size so bytes left will be calculated properly*/
+ param = (struct sctp_paramhdr *) &((struct sctp_asconf_addrv4_param *) param)->addrp;
+ case SCTP_IPV4_ADDRESS:
+ ipv4_param = (struct sctp_ipv4addr_param *) param;
+ /* add addresses to association */
+ G_Addr = (struct sctp_GlobalAddress *) sn_malloc(sizeof(struct sctp_GlobalAddress));
+ if (G_Addr == NULL) {/* out of resources */
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: No resources for adding global address - revert to no tracking",
+ sm->sctp_hdr->v_tag, 0, direction));
+ assoc->num_Gaddr = 0; /* don't track any more for this assoc*/
+ sysctl_track_global_addresses=0;
+ return;
+ }
+ /* add address */
+ addr_param_count++;
+ if ((sm->msg == SN_SCTP_ASCONF) && (ipv4_param->addr == INADDR_ANY)) { /* use packet address */
+ G_Addr->g_addr = g_addr;
+ if (!Add_Global_Address_to_List(assoc, G_Addr))
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: Address already in list",
+ sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
+ return; /*shouldn't be any other addresses if the zero address is given*/
+ } else {
+ G_Addr->g_addr.s_addr = ipv4_param->addr;
+ if (!Add_Global_Address_to_List(assoc, G_Addr))
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("AddGlobalIPAddress: Address already in list",
+ sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
+ }
+ }
- bytes_left -= param_size;
- if (bytes_left < SN_MIN_PARAM_SIZE)
- break;
+ bytes_left -= param_size;
+ if (bytes_left < SN_MIN_PARAM_SIZE)
+ break;
- param = SN_SCTP_NEXTPARAM(param);
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (++param_count > sysctl_param_proc_limit) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("Parameter parse limit exceeded (AddGlobalIPAddress)",
- sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
- break; /* limit exceeded*/
- }
- }
- if (addr_param_count == 0) {
- SN_LOG(SN_LOG_DETAIL,
- logsctperror("AddGlobalIPAddress: no address parameters to add",
+ param = SN_SCTP_NEXTPARAM(param);
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (++param_count > sysctl_param_proc_limit) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("Parameter parse limit exceeded (AddGlobalIPAddress)",
+ sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
+ break; /* limit exceeded*/
+ }
+ }
+ if (addr_param_count == 0) {
+ SN_LOG(SN_LOG_DETAIL,
+ logsctperror("AddGlobalIPAddress: no address parameters to add",
sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- }
+ }
}
/**
@@ -1426,19 +1404,19 @@ AddGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int
*/
static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sctp_GlobalAddress *G_addr)
{
- struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL;
- first_G_Addr = LIST_FIRST(&(assoc->Gaddr));
- if (first_G_Addr == NULL) {
- LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/
- } else {
- LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr)
- return(0); /* already exists, so don't add */
- }
- LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/
- }
- assoc->num_Gaddr++;
- return(1); /* success */
+ struct sctp_GlobalAddress *iter_G_Addr = NULL, *first_G_Addr = NULL;
+ first_G_Addr = LIST_FIRST(&(assoc->Gaddr));
+ if (first_G_Addr == NULL) {
+ LIST_INSERT_HEAD(&(assoc->Gaddr), G_addr, list_Gaddr); /* add new address to beginning of list*/
+ } else {
+ LIST_FOREACH(iter_G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if (G_addr->g_addr.s_addr == iter_G_Addr->g_addr.s_addr)
+ return(0); /* already exists, so don't add */
+ }
+ LIST_INSERT_AFTER(first_G_Addr, G_addr, list_Gaddr); /* add address to end of list*/
+ }
+ assoc->num_Gaddr++;
+ return(1); /* success */
}
/** @ingroup packet_parser
@@ -1457,85 +1435,85 @@ static int Add_Global_Address_to_List(struct sctp_nat_assoc *assoc, struct sct
static void
RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int direction)
{
- struct sctp_asconf_addrv4_param *asconf_ipv4_param;
- struct sctp_paramhdr *param;
- struct sctp_GlobalAddress *G_Addr, *G_Addr_tmp;
- struct in_addr g_addr;
- int bytes_left;
- int param_size;
- int param_count;
-
- if(direction == SN_TO_GLOBAL)
- g_addr = sm->ip_hdr->ip_dst;
- else
- g_addr = sm->ip_hdr->ip_src;
-
- bytes_left = sm->chunk_length;
- param_count = 1;
- param = sm->sctpchnk.Asconf;
- if (bytes_left >= SN_MIN_PARAM_SIZE) {
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- } else {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses",
+ struct sctp_asconf_addrv4_param *asconf_ipv4_param;
+ struct sctp_paramhdr *param;
+ struct sctp_GlobalAddress *G_Addr, *G_Addr_tmp;
+ struct in_addr g_addr;
+ int bytes_left;
+ int param_size;
+ int param_count;
+
+ if(direction == SN_TO_GLOBAL)
+ g_addr = sm->ip_hdr->ip_dst;
+ else
+ g_addr = sm->ip_hdr->ip_src;
+
+ bytes_left = sm->chunk_length;
+ param_count = 1;
+ param = sm->sctpchnk.Asconf;
+ if (bytes_left >= SN_MIN_PARAM_SIZE) {
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ } else {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("RmGlobalIPAddress: truncated packet - cannot remove IP addresses",
sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
- return;
- }
-
- /* step through Asconf parameters */
- while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
- if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) {
- asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param;
- if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */
- LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
- if(G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) {
- if (assoc->num_Gaddr > 1) { /* only delete if more than one */
- LIST_REMOVE(G_Addr, list_Gaddr);
- sn_free(G_Addr);
- assoc->num_Gaddr--;
- } else {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
- sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- }
- }
- }
- return; /*shouldn't be any other addresses if the zero address is given*/
- } else {
- LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
- if(G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) {
- if (assoc->num_Gaddr > 1) { /* only delete if more than one */
- LIST_REMOVE(G_Addr, list_Gaddr);
- sn_free(G_Addr);
- assoc->num_Gaddr--;
- break; /* Since add only adds new addresses, there should be no double entries */
- } else {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
- sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
- }
- }
+ return;
}
- }
- }
- bytes_left -= param_size;
- if (bytes_left == 0) return;
- else if (bytes_left < SN_MIN_PARAM_SIZE) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses",
- sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
- return;
- }
+
+ /* step through Asconf parameters */
+ while((bytes_left >= param_size) && (bytes_left >= sizeof(struct sctp_ipv4addr_param))) {
+ if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS) {
+ asconf_ipv4_param = (struct sctp_asconf_addrv4_param *) param;
+ if (asconf_ipv4_param->addrp.addr == INADDR_ANY) { /* remove all bar pkt address */
+ LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
+ if(G_Addr->g_addr.s_addr != sm->ip_hdr->ip_src.s_addr) {
+ if (assoc->num_Gaddr > 1) { /* only delete if more than one */
+ LIST_REMOVE(G_Addr, list_Gaddr);
+ sn_free(G_Addr);
+ assoc->num_Gaddr--;
+ } else {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
+ sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
+ }
+ }
+ }
+ return; /*shouldn't be any other addresses if the zero address is given*/
+ } else {
+ LIST_FOREACH_SAFE(G_Addr, &(assoc->Gaddr), list_Gaddr, G_Addr_tmp) {
+ if(G_Addr->g_addr.s_addr == asconf_ipv4_param->addrp.addr) {
+ if (assoc->num_Gaddr > 1) { /* only delete if more than one */
+ LIST_REMOVE(G_Addr, list_Gaddr);
+ sn_free(G_Addr);
+ assoc->num_Gaddr--;
+ break; /* Since add only adds new addresses, there should be no double entries */
+ } else {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("RmGlobalIPAddress: Request to remove last IP address (didn't)",
+ sm->sctp_hdr->v_tag, assoc->num_Gaddr, direction));
+ }
+ }
+ }
+ }
+ }
+ bytes_left -= param_size;
+ if (bytes_left == 0) return;
+ else if (bytes_left < SN_MIN_PARAM_SIZE) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("RmGlobalIPAddress: truncated packet - may not have removed all IP addresses",
+ sm->sctp_hdr->v_tag, sysctl_track_global_addresses, direction));
+ return;
+ }
- param = SN_SCTP_NEXTPARAM(param);
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (++param_count > sysctl_param_proc_limit) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("Parameter parse limit exceeded (RmGlobalIPAddress)",
- sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
- return; /* limit exceeded*/
- }
- }
+ param = SN_SCTP_NEXTPARAM(param);
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (++param_count > sysctl_param_proc_limit) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("Parameter parse limit exceeded (RmGlobalIPAddress)",
+ sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
+ return; /* limit exceeded*/
+ }
+ }
}
/** @ingroup packet_parser
@@ -1563,42 +1541,42 @@ RmGlobalIPAddresses(struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc, int d
static int
IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
{
- struct sctp_paramhdr *param;
- int bytes_left;
- int param_size;
- int param_count;
-
- param_count = 1;
- param = sm->sctpchnk.Asconf;
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (param_size == 8)
- return(1); /*success - default acknowledgement of everything */
-
- bytes_left = sm->chunk_length;
- if (bytes_left < param_size)
- return(0); /* not found */
- /* step through Asconf parameters */
- while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
- if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT)
- return(1); /* success - but can't match correlation IDs - should only be one */
- /* check others just in case */
- bytes_left -= param_size;
- if (bytes_left >= SN_MIN_PARAM_SIZE) {
- param = SN_SCTP_NEXTPARAM(param);
- } else {
- return(0);
- }
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (bytes_left < param_size) return(0);
-
- if (++param_count > sysctl_param_proc_limit) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("Parameter parse limit exceeded (IsASCONFack)",
- sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
- return(0); /* not found limit exceeded*/
- }
- }
- return(0); /* not success */
+ struct sctp_paramhdr *param;
+ int bytes_left;
+ int param_size;
+ int param_count;
+
+ param_count = 1;
+ param = sm->sctpchnk.Asconf;
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (param_size == 8)
+ return(1); /*success - default acknowledgement of everything */
+
+ bytes_left = sm->chunk_length;
+ if (bytes_left < param_size)
+ return(0); /* not found */
+ /* step through Asconf parameters */
+ while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
+ if (ntohs(param->param_type) == SCTP_SUCCESS_REPORT)
+ return(1); /* success - but can't match correlation IDs - should only be one */
+ /* check others just in case */
+ bytes_left -= param_size;
+ if (bytes_left >= SN_MIN_PARAM_SIZE) {
+ param = SN_SCTP_NEXTPARAM(param);
+ } else {
+ return(0);
+ }
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (bytes_left < param_size) return(0);
+
+ if (++param_count > sysctl_param_proc_limit) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("Parameter parse limit exceeded (IsASCONFack)",
+ sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
+ return(0); /* not found limit exceeded*/
+ }
+ }
+ return(0); /* not success */
}
/** @ingroup packet_parser
@@ -1616,42 +1594,42 @@ IsASCONFack(struct libalias *la, struct sctp_nat_msg *sm, int direction)
static int
IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
{
- struct sctp_paramhdr *param;
- int bytes_left;
- int param_size;
- int param_count;
-
- param_count = 1;
- param = sm->sctpchnk.Asconf;
- param_size = SCTP_SIZE32(ntohs(param->param_length));
-
- bytes_left = sm->chunk_length;
- if (bytes_left < param_size)
- return(0); /* not found */
- /* step through Asconf parameters */
- while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
- if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS)
- return(SCTP_ADD_IP_ADDRESS);
- else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS)
- return(SCTP_DEL_IP_ADDRESS);
- /* check others just in case */
- bytes_left -= param_size;
- if (bytes_left >= SN_MIN_PARAM_SIZE) {
- param = SN_SCTP_NEXTPARAM(param);
- } else {
- return(0); /*Neither found */
- }
- param_size = SCTP_SIZE32(ntohs(param->param_length));
- if (bytes_left < param_size) return(0);
-
- if (++param_count > sysctl_param_proc_limit) {
- SN_LOG(SN_LOG_EVENT,
- logsctperror("Parameter parse limit exceeded IsADDorDEL)",
- sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
- return(0); /* not found limit exceeded*/
- }
- }
- return(0); /*Neither found */
+ struct sctp_paramhdr *param;
+ int bytes_left;
+ int param_size;
+ int param_count;
+
+ param_count = 1;
+ param = sm->sctpchnk.Asconf;
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+
+ bytes_left = sm->chunk_length;
+ if (bytes_left < param_size)
+ return(0); /* not found */
+ /* step through Asconf parameters */
+ while(bytes_left >= SN_ASCONFACK_PARAM_SIZE) {
+ if (ntohs(param->param_type) == SCTP_ADD_IP_ADDRESS)
+ return(SCTP_ADD_IP_ADDRESS);
+ else if (ntohs(param->param_type) == SCTP_DEL_IP_ADDRESS)
+ return(SCTP_DEL_IP_ADDRESS);
+ /* check others just in case */
+ bytes_left -= param_size;
+ if (bytes_left >= SN_MIN_PARAM_SIZE) {
+ param = SN_SCTP_NEXTPARAM(param);
+ } else {
+ return(0); /*Neither found */
+ }
+ param_size = SCTP_SIZE32(ntohs(param->param_length));
+ if (bytes_left < param_size) return(0);
+
+ if (++param_count > sysctl_param_proc_limit) {
+ SN_LOG(SN_LOG_EVENT,
+ logsctperror("Parameter parse limit exceeded IsADDorDEL)",
+ sm->sctp_hdr->v_tag, sysctl_param_proc_limit, direction));
+ return(0); /* not found limit exceeded*/
+ }
+ }
+ return(0); /*Neither found */
}
/* ----------------------------------------------------------------------
@@ -1683,25 +1661,25 @@ IsADDorDEL(struct libalias *la, struct sctp_nat_msg *sm, int direction)
static int
ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, struct sctp_nat_assoc *assoc)
{
- int rtnval;
-
- switch (assoc->state) {
- case SN_ID: /* Idle */
- rtnval = ID_process(la, direction, assoc, sm);
- if (rtnval != SN_NAT_PKT) {
- assoc->state = SN_RM;/* Mark for removal*/
- }
- return(rtnval);
- case SN_INi: /* Initialising - Init */
- return(INi_process(la, direction, assoc, sm));
- case SN_INa: /* Initialising - AddIP */
- return(INa_process(la, direction, assoc, sm));
- case SN_UP: /* Association UP */
- return(UP_process(la, direction, assoc, sm));
- case SN_CL: /* Association Closing */
- return(CL_process(la, direction, assoc, sm));
- }
- return(SN_PROCESSING_ERROR);
+ int rtnval;
+
+ switch (assoc->state) {
+ case SN_ID: /* Idle */
+ rtnval = ID_process(la, direction, assoc, sm);
+ if (rtnval != SN_NAT_PKT) {
+ assoc->state = SN_RM;/* Mark for removal*/
+ }
+ return(rtnval);
+ case SN_INi: /* Initialising - Init */
+ return(INi_process(la, direction, assoc, sm));
+ case SN_INa: /* Initialising - AddIP */
+ return(INa_process(la, direction, assoc, sm));
+ case SN_UP: /* Association UP */
+ return(UP_process(la, direction, assoc, sm));
+ case SN_CL: /* Association Closing */
+ return(CL_process(la, direction, assoc, sm));
+ }
+ return(SN_PROCESSING_ERROR);
}
/** @ingroup state_machine
@@ -1721,56 +1699,56 @@ ProcessSctpMsg(struct libalias *la, int direction, struct sctp_nat_msg *sm, stru
static int
ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
{
- switch(sm->msg) {
- case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */
- if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL))
- return(SN_DROP_PKT);
- /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */
- if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction))
- return(SN_DROP_PKT);
- case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */
- if (sysctl_track_global_addresses)
- AddGlobalIPAddresses(sm, assoc, direction);
- switch(direction){
- case SN_TO_GLOBAL:
- assoc->l_addr = sm->ip_hdr->ip_src;
- assoc->a_addr = FindAliasAddress(la, assoc->l_addr);
- assoc->l_port = sm->sctp_hdr->src_port;
- assoc->g_port = sm->sctp_hdr->dest_port;
- if(sm->msg == SN_SCTP_INIT)
- assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
- if (AddSctpAssocGlobal(la, assoc)) /* DB clash *///**** need to add dst address
- return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
- if(sm->msg == SN_SCTP_ASCONF) {
- if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */
- return(SN_REPLY_ERROR);
- assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */
- }
- break;
- case SN_TO_LOCAL:
- assoc->l_addr = FindSctpRedirectAddress(la, sm);
- assoc->a_addr = sm->ip_hdr->ip_dst;
- assoc->l_port = sm->sctp_hdr->dest_port;
- assoc->g_port = sm->sctp_hdr->src_port;
- if(sm->msg == SN_SCTP_INIT)
- assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
- if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */
- return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
- if(sm->msg == SN_SCTP_ASCONF) {
- if (AddSctpAssocGlobal(la, assoc)) /* DB clash */ //**** need to add src address
- return(SN_REPLY_ERROR);
- assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */
- }
- break;
- }
- assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa;
- assoc->exp = SN_I_T(la);
- sctp_AddTimeOut(la,assoc);
- return(SN_NAT_PKT);
- default: /* Any other type of SCTP message is not valid in Idle */
- return(SN_DROP_PKT);
- }
- return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
+ switch(sm->msg) {
+ case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk with ADDIP */
+ if (!sysctl_accept_global_ootb_addip && (direction == SN_TO_LOCAL))
+ return(SN_DROP_PKT);
+ /* if this Asconf packet does not contain the Vtag parameters it is of no use in Idle state */
+ if (!GetAsconfVtags(la, sm, &(assoc->l_vtag), &(assoc->g_vtag), direction))
+ return(SN_DROP_PKT);
+ case SN_SCTP_INIT: /* a packet containing an INIT chunk or an ASCONF AddIP */
+ if (sysctl_track_global_addresses)
+ AddGlobalIPAddresses(sm, assoc, direction);
+ switch(direction){
+ case SN_TO_GLOBAL:
+ assoc->l_addr = sm->ip_hdr->ip_src;
+ assoc->a_addr = FindAliasAddress(la, assoc->l_addr);
+ assoc->l_port = sm->sctp_hdr->src_port;
+ assoc->g_port = sm->sctp_hdr->dest_port;
+ if(sm->msg == SN_SCTP_INIT)
+ assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
+ if (AddSctpAssocGlobal(la, assoc)) /* DB clash *///**** need to add dst address
+ return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
+ if(sm->msg == SN_SCTP_ASCONF) {
+ if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_dst)) /* DB clash */
+ return(SN_REPLY_ERROR);
+ assoc->TableRegister |= SN_WAIT_TOLOCAL; /* wait for tolocal ack */
+ }
+ break;
+ case SN_TO_LOCAL:
+ assoc->l_addr = FindSctpRedirectAddress(la, sm);
+ assoc->a_addr = sm->ip_hdr->ip_dst;
+ assoc->l_port = sm->sctp_hdr->dest_port;
+ assoc->g_port = sm->sctp_hdr->src_port;
+ if(sm->msg == SN_SCTP_INIT)
+ assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
+ if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) /* DB clash */
+ return((sm->msg == SN_SCTP_INIT) ? SN_REPLY_ABORT : SN_REPLY_ERROR);
+ if(sm->msg == SN_SCTP_ASCONF) {
+ if (AddSctpAssocGlobal(la, assoc)) /* DB clash */ //**** need to add src address
+ return(SN_REPLY_ERROR);
+ assoc->TableRegister |= SN_WAIT_TOGLOBAL; /* wait for toglobal ack */
+ }
+ break;
+ }
+ assoc->state = (sm->msg == SN_SCTP_INIT) ? SN_INi : SN_INa;
+ assoc->exp = SN_I_T(la);
+ sctp_AddTimeOut(la,assoc);
+ return(SN_NAT_PKT);
+ default: /* Any other type of SCTP message is not valid in Idle */
+ return(SN_DROP_PKT);
+ }
+return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
}
/** @ingroup state_machine
@@ -1789,40 +1767,40 @@ ID_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, str
static int
INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
{
- switch(sm->msg) {
- case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */
- sctp_ResetTimeOut(la, assoc, SN_I_T(la));
- return(SN_NAT_PKT);
- case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */
- switch(direction){
- case SN_TO_LOCAL:
- if (assoc->num_Gaddr) /*If tracking global addresses for this association */
- AddGlobalIPAddresses(sm, assoc, direction);
- assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
- if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_SEND_ABORT);
- }
- break;
- case SN_TO_GLOBAL:
- assoc->l_addr = sm->ip_hdr->ip_src; // Only if not set in Init! *
- assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
- if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_SEND_ABORT);
- }
- break;
- }
- assoc->state = SN_UP;/* association established for NAT */
- sctp_ResetTimeOut(la,assoc, SN_U_T(la));
- return(SN_NAT_PKT);
- case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- default:
- return(SN_DROP_PKT);
- }
- return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
+ switch(sm->msg) {
+ case SN_SCTP_INIT: /* a packet containing a retransmitted INIT chunk */
+ sctp_ResetTimeOut(la, assoc, SN_I_T(la));
+ return(SN_NAT_PKT);
+ case SN_SCTP_INITACK: /* a packet containing an INIT-ACK chunk */
+ switch(direction){
+ case SN_TO_LOCAL:
+ if (assoc->num_Gaddr) /*If tracking global addresses for this association */
+ AddGlobalIPAddresses(sm, assoc, direction);
+ assoc->l_vtag = sm->sctpchnk.Init->initiate_tag;
+ if (AddSctpAssocLocal(la, assoc, sm->ip_hdr->ip_src)) { /* DB clash */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_SEND_ABORT);
+ }
+ break;
+ case SN_TO_GLOBAL:
+ assoc->l_addr = sm->ip_hdr->ip_src; // Only if not set in Init! *
+ assoc->g_vtag = sm->sctpchnk.Init->initiate_tag;
+ if (AddSctpAssocGlobal(la, assoc)) { /* DB clash */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_SEND_ABORT);
+ }
+ break;
+ }
+ assoc->state = SN_UP;/* association established for NAT */
+ sctp_ResetTimeOut(la,assoc, SN_U_T(la));
+ return(SN_NAT_PKT);
+ case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ default:
+ return(SN_DROP_PKT);
+ }
+ return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
}
/** @ingroup state_machine
@@ -1841,36 +1819,36 @@ INi_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, st
static int
INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
{
- switch(sm->msg) {
- case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
- sctp_ResetTimeOut(la,assoc, SN_I_T(la));
- return(SN_NAT_PKT);
- case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */
- switch(direction){
- case SN_TO_LOCAL:
- if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */
- return(SN_DROP_PKT);
- break;
- case SN_TO_GLOBAL:
- if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */
- return(SN_DROP_PKT);
- }
- if (IsASCONFack(la,sm,direction)) {
- assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */
- assoc->state = SN_UP; /* association established for NAT */
- sctp_ResetTimeOut(la,assoc, SN_U_T(la));
- return(SN_NAT_PKT);
- } else {
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- }
- case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- default:
- return(SN_DROP_PKT);
- }
- return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
+ switch(sm->msg) {
+ case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
+ sctp_ResetTimeOut(la,assoc, SN_I_T(la));
+ return(SN_NAT_PKT);
+ case SN_SCTP_ASCONFACK: /* a packet containing an ASCONF chunk with a ADDIP-ACK */
+ switch(direction){
+ case SN_TO_LOCAL:
+ if (!(assoc->TableRegister & SN_WAIT_TOLOCAL)) /* wrong direction */
+ return(SN_DROP_PKT);
+ break;
+ case SN_TO_GLOBAL:
+ if (!(assoc->TableRegister & SN_WAIT_TOGLOBAL)) /* wrong direction */
+ return(SN_DROP_PKT);
+ }
+ if (IsASCONFack(la,sm,direction)) {
+ assoc->TableRegister &= SN_BOTH_TBL; /* remove wait flags */
+ assoc->state = SN_UP; /* association established for NAT */
+ sctp_ResetTimeOut(la,assoc, SN_U_T(la));
+ return(SN_NAT_PKT);
+ } else {
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ }
+ case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ default:
+ return(SN_DROP_PKT);
+ }
+ return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
}
/** @ingroup state_machine
@@ -1889,29 +1867,29 @@ INa_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, str
static int
UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
{
- switch(sm->msg) {
- case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
- assoc->state = SN_CL;
- sctp_ResetTimeOut(la,assoc, SN_C_T(la));
- return(SN_NAT_PKT);
- case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
- if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */
- switch(IsADDorDEL(la,sm,direction)) {
- case SCTP_ADD_IP_ADDRESS:
- AddGlobalIPAddresses(sm, assoc, direction);
- break;
- case SCTP_DEL_IP_ADDRESS:
- RmGlobalIPAddresses(sm, assoc, direction);
- break;
- } /* fall through to default */
- default:
- sctp_ResetTimeOut(la,assoc, SN_U_T(la));
- return(SN_NAT_PKT); /* forward packet */
- }
- return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
+ switch(sm->msg) {
+ case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
+ assoc->state = SN_CL;
+ sctp_ResetTimeOut(la,assoc, SN_C_T(la));
+ return(SN_NAT_PKT);
+ case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ case SN_SCTP_ASCONF: /* a packet containing an ASCONF chunk*/
+ if ((direction == SN_TO_LOCAL) && assoc->num_Gaddr) /*If tracking global addresses for this association & from global side */
+ switch(IsADDorDEL(la,sm,direction)) {
+ case SCTP_ADD_IP_ADDRESS:
+ AddGlobalIPAddresses(sm, assoc, direction);
+ break;
+ case SCTP_DEL_IP_ADDRESS:
+ RmGlobalIPAddresses(sm, assoc, direction);
+ break;
+ } /* fall through to default */
+ default:
+ sctp_ResetTimeOut(la,assoc, SN_U_T(la));
+ return(SN_NAT_PKT); /* forward packet */
+ }
+ return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
}
/** @ingroup state_machine
@@ -1932,25 +1910,25 @@ UP_process(struct libalias *la, int direction, struct sctp_nat_assoc *assoc, str
static int
CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, struct sctp_nat_msg *sm)
{
- switch(sm->msg) {
- case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */
- assoc->state = SN_CL; /* Stay in Close state until timeout */
- if (sysctl_holddown_timer > 0)
- sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/
- else
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
- assoc->state = SN_CL; /* Stay in Close state until timeout */
- sctp_ResetTimeOut(la, assoc, SN_C_T(la));
- return(SN_NAT_PKT);
- case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
- assoc->state = SN_RM;/* Mark for removal*/
- return(SN_NAT_PKT);
- default:
- return(SN_DROP_PKT);
- }
- return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
+ switch(sm->msg) {
+ case SN_SCTP_SHUTCOMP: /* a packet containing a SHUTDOWN-COMPLETE chunk */
+ assoc->state = SN_CL; /* Stay in Close state until timeout */
+ if (sysctl_holddown_timer > 0)
+ sctp_ResetTimeOut(la, assoc, SN_X_T(la));/* allow to stay open for Tbit packets*/
+ else
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ case SN_SCTP_SHUTACK: /* a packet containing a SHUTDOWN-ACK chunk */
+ assoc->state = SN_CL; /* Stay in Close state until timeout */
+ sctp_ResetTimeOut(la, assoc, SN_C_T(la));
+ return(SN_NAT_PKT);
+ case SN_SCTP_ABORT: /* a packet containing an ABORT chunk */
+ assoc->state = SN_RM;/* Mark for removal*/
+ return(SN_NAT_PKT);
+ default:
+ return(SN_DROP_PKT);
+ }
+ return(SN_DROP_PKT);/* shouldn't get here very bad: log, drop and hope for the best */
}
/* ----------------------------------------------------------------------
@@ -1980,27 +1958,27 @@ CL_process(struct libalias *la, int direction,struct sctp_nat_assoc *assoc, stru
static struct sctp_nat_assoc*
FindSctpLocal(struct libalias *la, struct in_addr l_addr, struct in_addr g_addr, uint32_t l_vtag, uint16_t l_port, uint16_t g_port)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
- struct sctp_GlobalAddress *G_Addr = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
+ struct sctp_GlobalAddress *G_Addr = NULL;
- if (l_vtag != 0) { /* an init packet, vtag==0 */
- i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize);
- LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
- if ((assoc->l_vtag == l_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)\
- && (assoc->l_addr.s_addr == l_addr.s_addr)) {
- if (assoc->num_Gaddr) {
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if(G_Addr->g_addr.s_addr == g_addr.s_addr)
- return(assoc);
- }
- } else {
- return(assoc);
+ if (l_vtag != 0) { /* an init packet, vtag==0 */
+ i = SN_TABLE_HASH(l_vtag, l_port, la->sctpNatTableSize);
+ LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
+ if ((assoc->l_vtag == l_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)\
+ && (assoc->l_addr.s_addr == l_addr.s_addr)) {
+ if (assoc->num_Gaddr) {
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if(G_Addr->g_addr.s_addr == g_addr.s_addr)
+ return(assoc);
+ }
+ } else {
+ return(assoc);
+ }
+ }
+ }
}
- }
- }
- }
- return(NULL);
+ return(NULL);
}
/** @ingroup Hash
@@ -2017,29 +1995,29 @@ FindSctpLocal(struct libalias *la, struct in_addr l_addr, struct in_addr g_addr,
static struct sctp_nat_assoc*
FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
- struct sctp_GlobalAddress *G_Addr = NULL;
- struct sctp_GlobalAddress *G_AddrC = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
+ struct sctp_GlobalAddress *G_Addr = NULL;
+ struct sctp_GlobalAddress *G_AddrC = NULL;
- if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */
- i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize);
- LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
- if ((assoc->g_vtag == Cassoc->g_vtag) && (assoc->g_port == Cassoc->g_port) && (assoc->l_port == Cassoc->l_port)) {
- if (assoc->num_Gaddr) {
- LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) {
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if(G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr)
- return(assoc);
- }
- }
- } else {
- return(assoc);
+ if (Cassoc->g_vtag != 0) { /* an init packet, vtag==0 */
+ i = SN_TABLE_HASH(Cassoc->g_vtag, Cassoc->g_port, la->sctpNatTableSize);
+ LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
+ if ((assoc->g_vtag == Cassoc->g_vtag) && (assoc->g_port == Cassoc->g_port) && (assoc->l_port == Cassoc->l_port)) {
+ if (assoc->num_Gaddr) {
+ LIST_FOREACH(G_AddrC, &(Cassoc->Gaddr), list_Gaddr) {
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if(G_Addr->g_addr.s_addr == G_AddrC->g_addr.s_addr)
+ return(assoc);
+ }
+ }
+ } else {
+ return(assoc);
+ }
+ }
+ }
}
- }
- }
- }
- return(NULL);
+ return(NULL);
}
/** @ingroup Hash
@@ -2064,28 +2042,28 @@ FindSctpGlobalClash(struct libalias *la, struct sctp_nat_assoc *Cassoc)
static struct sctp_nat_assoc*
FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t g_port, uint16_t l_port, int *partial_match)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
- struct sctp_GlobalAddress *G_Addr = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
+ struct sctp_GlobalAddress *G_Addr = NULL;
- *partial_match = 0;
- if (g_vtag != 0) { /* an init packet, vtag==0 */
- i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize);
- LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
- if ((assoc->g_vtag == g_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
- *partial_match = 1;
- if (assoc->num_Gaddr) {
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if(G_Addr->g_addr.s_addr == g_addr.s_addr)
- return(assoc);
- }
- } else {
- return(assoc);
+ *partial_match = 0;
+ if (g_vtag != 0) { /* an init packet, vtag==0 */
+ i = SN_TABLE_HASH(g_vtag, g_port, la->sctpNatTableSize);
+ LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
+ if ((assoc->g_vtag == g_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
+ *partial_match = 1;
+ if (assoc->num_Gaddr) {
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if(G_Addr->g_addr.s_addr == g_addr.s_addr)
+ return(assoc);
+ }
+ } else {
+ return(assoc);
+ }
+ }
+ }
}
- }
- }
- }
- return(NULL);
+ return(NULL);
}
/** @ingroup Hash
@@ -2105,29 +2083,29 @@ FindSctpGlobal(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint
static struct sctp_nat_assoc*
FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uint16_t g_port, uint16_t l_port)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL;
- struct sctp_GlobalAddress *G_Addr = NULL;
- int cnt = 0;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL, *lastmatch = NULL;
+ struct sctp_GlobalAddress *G_Addr = NULL;
+ int cnt = 0;
- if (l_vtag != 0) { /* an init packet, vtag==0 */
- i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize);
- LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
- if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
- if (assoc->num_Gaddr) {
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if(G_Addr->g_addr.s_addr == G_Addr->g_addr.s_addr)
- return(assoc); /* full match */
- }
- } else {
- if (++cnt > 1) return(NULL);
- lastmatch = assoc;
+ if (l_vtag != 0) { /* an init packet, vtag==0 */
+ i = SN_TABLE_HASH(l_vtag, g_port, la->sctpNatTableSize);
+ LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
+ if ((assoc->g_vtag == l_vtag) && (assoc->g_port == g_port) && (assoc->l_port == l_port)) {
+ if (assoc->num_Gaddr) {
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if(G_Addr->g_addr.s_addr == G_Addr->g_addr.s_addr)
+ return(assoc); /* full match */
+ }
+ } else {
+ if (++cnt > 1) return(NULL);
+ lastmatch = assoc;
+ }
+ }
+ }
}
- }
- }
- }
- /* If there is more than one match we do not know which local address to send to */
- return( cnt ? lastmatch : NULL );
+ /* If there is more than one match we do not know which local address to send to */
+ return( cnt ? lastmatch : NULL );
}
/** @ingroup Hash
@@ -2147,26 +2125,26 @@ FindSctpLocalT(struct libalias *la, struct in_addr g_addr, uint32_t l_vtag, uin
static struct sctp_nat_assoc*
FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uint16_t l_port, uint16_t g_port)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
- struct sctp_GlobalAddress *G_Addr = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
+ struct sctp_GlobalAddress *G_Addr = NULL;
- if (g_vtag != 0) { /* an init packet, vtag==0 */
- i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize);
- LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
- if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) {
- if (assoc->num_Gaddr) {
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- if(G_Addr->g_addr.s_addr == g_addr.s_addr)
- return(assoc);
- }
- } else {
- return(assoc);
+ if (g_vtag != 0) { /* an init packet, vtag==0 */
+ i = SN_TABLE_HASH(g_vtag, l_port, la->sctpNatTableSize);
+ LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
+ if ((assoc->l_vtag == g_vtag) && (assoc->l_port == l_port) && (assoc->g_port == g_port)) {
+ if (assoc->num_Gaddr) {
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ if(G_Addr->g_addr.s_addr == g_addr.s_addr)
+ return(assoc);
+ }
+ } else {
+ return(assoc);
+ }
+ }
+ }
}
- }
- }
- }
- return(NULL);
+ return(NULL);
}
/** @ingroup Hash
@@ -2188,43 +2166,43 @@ FindSctpGlobalT(struct libalias *la, struct in_addr g_addr, uint32_t g_vtag, uin
static int
AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_addr g_addr)
{
- struct sctp_nat_assoc *found;
-
- LIBALIAS_LOCK_ASSERT(la);
- found = FindSctpLocal(la, assoc->l_addr, g_addr, assoc->l_vtag, assoc->l_port, assoc->g_port);
- /*
- * Note that if a different global address initiated this Init,
- * ie it wasn't resent as presumed:
- * - the local receiver if receiving it for the first time will establish
- * an association with the new global host
- * - if receiving an init from a different global address after sending a
- * lost initack it will send an initack to the new global host, the first
- * association attempt will then be blocked if retried.
- */
- if (found != NULL) {
- if ((found->TableRegister == SN_LOCAL_TBL) && (found->g_port == assoc->g_port)) { /* resent message */
- RmSctpAssoc(la, found);
- sctp_RmTimeOut(la, found);
- freeGlobalAddressList(found);
- sn_free(found);
- } else
- return(SN_ADD_CLASH);
- }
+ struct sctp_nat_assoc *found;
+
+ LIBALIAS_LOCK_ASSERT(la);
+ found = FindSctpLocal(la, assoc->l_addr, g_addr, assoc->l_vtag, assoc->l_port, assoc->g_port);
+ /*
+ * Note that if a different global address initiated this Init,
+ * ie it wasn't resent as presumed:
+ * - the local receiver if receiving it for the first time will establish
+ * an association with the new global host
+ * - if receiving an init from a different global address after sending a
+ * lost initack it will send an initack to the new global host, the first
+ * association attempt will then be blocked if retried.
+ */
+ if (found != NULL) {
+ if ((found->TableRegister == SN_LOCAL_TBL) && (found->g_port == assoc->g_port)) { /* resent message */
+ RmSctpAssoc(la, found);
+ sctp_RmTimeOut(la, found);
+ freeGlobalAddressList(found);
+ sn_free(found);
+ } else
+ return(SN_ADD_CLASH);
+ }
- LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)],
- assoc, list_L);
- assoc->TableRegister |= SN_LOCAL_TBL;
- la->sctpLinkCount++; //increment link count
+ LIST_INSERT_HEAD(&la->sctpTableLocal[SN_TABLE_HASH(assoc->l_vtag, assoc->l_port, la->sctpNatTableSize)],
+ assoc, list_L);
+ assoc->TableRegister |= SN_LOCAL_TBL;
+ la->sctpLinkCount++; //increment link count
- if (assoc->TableRegister == SN_BOTH_TBL) {
- /* libalias log -- controlled by libalias */
- if (la->packetAliasMode & PKT_ALIAS_LOG)
- SctpShowAliasStats(la);
+ if (assoc->TableRegister == SN_BOTH_TBL) {
+ /* libalias log -- controlled by libalias */
+ if (la->packetAliasMode & PKT_ALIAS_LOG)
+ SctpShowAliasStats(la);
- SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
- }
+ SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
+ }
- return(SN_ADD_OK);
+ return(SN_ADD_OK);
}
/** @ingroup Hash
@@ -2245,35 +2223,35 @@ AddSctpAssocLocal(struct libalias *la, struct sctp_nat_assoc *assoc, struct in_a
static int
AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
{
- struct sctp_nat_assoc *found;
-
- LIBALIAS_LOCK_ASSERT(la);
- found = FindSctpGlobalClash(la, assoc);
- if (found != NULL) {
- if ((found->TableRegister == SN_GLOBAL_TBL) && \
- (found->l_addr.s_addr == assoc->l_addr.s_addr) && (found->l_port == assoc->l_port)) { /* resent message */
- RmSctpAssoc(la, found);
- sctp_RmTimeOut(la, found);
- freeGlobalAddressList(found);
- sn_free(found);
- } else
- return(SN_ADD_CLASH);
- }
+ struct sctp_nat_assoc *found;
+
+ LIBALIAS_LOCK_ASSERT(la);
+ found = FindSctpGlobalClash(la, assoc);
+ if (found != NULL) {
+ if ((found->TableRegister == SN_GLOBAL_TBL) && \
+ (found->l_addr.s_addr == assoc->l_addr.s_addr) && (found->l_port == assoc->l_port)) { /* resent message */
+ RmSctpAssoc(la, found);
+ sctp_RmTimeOut(la, found);
+ freeGlobalAddressList(found);
+ sn_free(found);
+ } else
+ return(SN_ADD_CLASH);
+ }
- LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)],
- assoc, list_G);
- assoc->TableRegister |= SN_GLOBAL_TBL;
- la->sctpLinkCount++; //increment link count
+ LIST_INSERT_HEAD(&la->sctpTableGlobal[SN_TABLE_HASH(assoc->g_vtag, assoc->g_port, la->sctpNatTableSize)],
+ assoc, list_G);
+ assoc->TableRegister |= SN_GLOBAL_TBL;
+ la->sctpLinkCount++; //increment link count
- if (assoc->TableRegister == SN_BOTH_TBL) {
- /* libalias log -- controlled by libalias */
- if (la->packetAliasMode & PKT_ALIAS_LOG)
- SctpShowAliasStats(la);
+ if (assoc->TableRegister == SN_BOTH_TBL) {
+ /* libalias log -- controlled by libalias */
+ if (la->packetAliasMode & PKT_ALIAS_LOG)
+ SctpShowAliasStats(la);
- SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
- }
+ SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "^"));
+ }
- return(SN_ADD_OK);
+ return(SN_ADD_OK);
}
/** @ingroup Hash
@@ -2293,33 +2271,33 @@ AddSctpAssocGlobal(struct libalias *la, struct sctp_nat_assoc *assoc)
static void
RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
{
- // struct sctp_nat_assoc *found;
- if (assoc == NULL) {
- /* very bad, log and die*/
- SN_LOG(SN_LOG_LOW,
- logsctperror("ERROR: alias_sctp:RmSctpAssoc(NULL)\n", 0, 0, SN_TO_NODIR));
- return;
- }
- /* log if association is fully up and now closing */
- if (assoc->TableRegister == SN_BOTH_TBL) {
- SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "$"));
- }
- LIBALIAS_LOCK_ASSERT(la);
- if (assoc->TableRegister & SN_LOCAL_TBL) {
- assoc->TableRegister ^= SN_LOCAL_TBL;
- la->sctpLinkCount--; //decrement link count
- LIST_REMOVE(assoc, list_L);
- }
+ // struct sctp_nat_assoc *found;
+ if (assoc == NULL) {
+ /* very bad, log and die*/
+ SN_LOG(SN_LOG_LOW,
+ logsctperror("ERROR: alias_sctp:RmSctpAssoc(NULL)\n", 0, 0, SN_TO_NODIR));
+ return;
+ }
+ /* log if association is fully up and now closing */
+ if (assoc->TableRegister == SN_BOTH_TBL) {
+ SN_LOG(SN_LOG_INFO, logsctpassoc(assoc, "$"));
+ }
+ LIBALIAS_LOCK_ASSERT(la);
+ if (assoc->TableRegister & SN_LOCAL_TBL) {
+ assoc->TableRegister ^= SN_LOCAL_TBL;
+ la->sctpLinkCount--; //decrement link count
+ LIST_REMOVE(assoc, list_L);
+ }
- if (assoc->TableRegister & SN_GLOBAL_TBL) {
- assoc->TableRegister ^= SN_GLOBAL_TBL;
- la->sctpLinkCount--; //decrement link count
- LIST_REMOVE(assoc, list_G);
- }
- // sn_free(assoc); //Don't remove now, remove if needed later
- /* libalias logging -- controlled by libalias log definition */
- if (la->packetAliasMode & PKT_ALIAS_LOG)
- SctpShowAliasStats(la);
+ if (assoc->TableRegister & SN_GLOBAL_TBL) {
+ assoc->TableRegister ^= SN_GLOBAL_TBL;
+ la->sctpLinkCount--; //decrement link count
+ LIST_REMOVE(assoc, list_G);
+ }
+ // sn_free(assoc); //Don't remove now, remove if needed later
+ /* libalias logging -- controlled by libalias log definition */
+ if (la->packetAliasMode & PKT_ALIAS_LOG)
+ SctpShowAliasStats(la);
}
/**
@@ -2333,14 +2311,14 @@ RmSctpAssoc(struct libalias *la, struct sctp_nat_assoc *assoc)
*/
static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
{
- struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL;
- /*free global address list*/
- gaddr1 = LIST_FIRST(&(assoc->Gaddr));
- while (gaddr1 != NULL) {
- gaddr2 = LIST_NEXT(gaddr1, list_Gaddr);
- sn_free(gaddr1);
- gaddr1 = gaddr2;
- }
+ struct sctp_GlobalAddress *gaddr1=NULL,*gaddr2=NULL;
+ /*free global address list*/
+ gaddr1 = LIST_FIRST(&(assoc->Gaddr));
+ while (gaddr1 != NULL) {
+ gaddr2 = LIST_NEXT(gaddr1, list_Gaddr);
+ sn_free(gaddr1);
+ gaddr1 = gaddr2;
+ }
}
/* ----------------------------------------------------------------------
* TIMER QUEUE CODE
@@ -2372,13 +2350,13 @@ static void freeGlobalAddressList(struct sctp_nat_assoc *assoc)
static void
sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
{
- int add_loc;
- LIBALIAS_LOCK_ASSERT(la);
- add_loc = assoc->exp - la->sctpNatTimer.loc_time + la->sctpNatTimer.cur_loc;
- if (add_loc >= SN_TIMER_QUEUE_SIZE)
- add_loc -= SN_TIMER_QUEUE_SIZE;
- LIST_INSERT_HEAD(&la->sctpNatTimer.TimerQ[add_loc], assoc, timer_Q);
- assoc->exp_loc = add_loc;
+ int add_loc;
+ LIBALIAS_LOCK_ASSERT(la);
+ add_loc = assoc->exp - la->sctpNatTimer.loc_time + la->sctpNatTimer.cur_loc;
+ if (add_loc >= SN_TIMER_QUEUE_SIZE)
+ add_loc -= SN_TIMER_QUEUE_SIZE;
+ LIST_INSERT_HEAD(&la->sctpNatTimer.TimerQ[add_loc], assoc, timer_Q);
+ assoc->exp_loc = add_loc;
}
/** @ingroup Timer
@@ -2393,8 +2371,8 @@ sctp_AddTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
static void
sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
{
- LIBALIAS_LOCK_ASSERT(la);
- LIST_REMOVE(assoc, timer_Q);/* Note this is O(1) */
+ LIBALIAS_LOCK_ASSERT(la);
+ LIST_REMOVE(assoc, timer_Q);/* Note this is O(1) */
}
@@ -2412,13 +2390,13 @@ sctp_RmTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc)
static void
sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
{
- if (newexp < assoc->exp) {
- sctp_RmTimeOut(la, assoc);
- assoc->exp = newexp;
- sctp_AddTimeOut(la, assoc);
- } else {
- assoc->exp = newexp;
- }
+ if (newexp < assoc->exp) {
+ sctp_RmTimeOut(la, assoc);
+ assoc->exp = newexp;
+ sctp_AddTimeOut(la, assoc);
+ } else {
+ assoc->exp = newexp;
+ }
}
/** @ingroup Timer
@@ -2440,29 +2418,29 @@ sctp_ResetTimeOut(struct libalias *la, struct sctp_nat_assoc *assoc, int newexp)
void
sctp_CheckTimers(struct libalias *la)
{
- struct sctp_nat_assoc *assoc;
+ struct sctp_nat_assoc *assoc;
- LIBALIAS_LOCK_ASSERT(la);
- while(la->timeStamp >= la->sctpNatTimer.loc_time) {
- while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) {
- assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]);
- //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q);
- LIST_REMOVE(assoc, timer_Q);
- if (la->timeStamp >= assoc->exp) { /* state expired */
- SN_LOG(((assoc->state == SN_CL)?(SN_LOG_DEBUG):(SN_LOG_INFO)),
- logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR));
- RmSctpAssoc(la, assoc);
- freeGlobalAddressList(assoc);
- sn_free(assoc);
- } else {/* state not expired, reschedule timer*/
- sctp_AddTimeOut(la, assoc);
- }
- }
- /* Goto next location in the timer queue*/
- ++la->sctpNatTimer.loc_time;
- if (++la->sctpNatTimer.cur_loc >= SN_TIMER_QUEUE_SIZE)
- la->sctpNatTimer.cur_loc = 0;
- }
+ LIBALIAS_LOCK_ASSERT(la);
+ while(la->timeStamp >= la->sctpNatTimer.loc_time) {
+ while (!LIST_EMPTY(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc])) {
+ assoc = LIST_FIRST(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc]);
+ //SLIST_REMOVE_HEAD(&la->sctpNatTimer.TimerQ[la->sctpNatTimer.cur_loc], timer_Q);
+ LIST_REMOVE(assoc, timer_Q);
+ if (la->timeStamp >= assoc->exp) { /* state expired */
+ SN_LOG(((assoc->state == SN_CL)?(SN_LOG_DEBUG):(SN_LOG_INFO)),
+ logsctperror("Timer Expired", assoc->g_vtag, assoc->state, SN_TO_NODIR));
+ RmSctpAssoc(la, assoc);
+ freeGlobalAddressList(assoc);
+ sn_free(assoc);
+ } else {/* state not expired, reschedule timer*/
+ sctp_AddTimeOut(la, assoc);
+ }
+ }
+ /* Goto next location in the timer queue*/
+ ++la->sctpNatTimer.loc_time;
+ if (++la->sctpNatTimer.cur_loc >= SN_TIMER_QUEUE_SIZE)
+ la->sctpNatTimer.cur_loc = 0;
+ }
}
/* ----------------------------------------------------------------------
@@ -2486,19 +2464,19 @@ sctp_CheckTimers(struct libalias *la)
static void
logsctperror(char* errormsg, uint32_t vtag, int error, int direction)
{
- char dir;
- switch(direction) {
- case SN_TO_LOCAL:
- dir = 'L';
- break;
- case SN_TO_GLOBAL:
- dir = 'G';
- break;
- default:
- dir = '*';
- break;
- }
- SctpAliasLog("->%c %s (vt=%u) %d\n", dir, errormsg, ntohl(vtag), error);
+ char dir;
+ switch(direction) {
+ case SN_TO_LOCAL:
+ dir = 'L';
+ break;
+ case SN_TO_GLOBAL:
+ dir = 'G';
+ break;
+ default:
+ dir = '*';
+ break;
+ }
+ SctpAliasLog("->%c %s (vt=%u) %d\n", dir, errormsg, ntohl(vtag), error);
}
/** @ingroup Logging
@@ -2510,47 +2488,47 @@ logsctperror(char* errormsg, uint32_t vtag, int error, int direction)
static void
logsctpparse(int direction, struct sctp_nat_msg *sm)
{
- char *ploc, *pstate;
- switch(direction) {
- case SN_TO_LOCAL:
- ploc = "TO_LOCAL -";
- break;
- case SN_TO_GLOBAL:
- ploc = "TO_GLOBAL -";
- break;
- default:
- ploc = "";
- }
- switch(sm->msg) {
- case SN_SCTP_INIT:
- pstate = "Init";
- break;
- case SN_SCTP_INITACK:
- pstate = "InitAck";
- break;
- case SN_SCTP_ABORT:
- pstate = "Abort";
- break;
- case SN_SCTP_SHUTACK:
- pstate = "ShutAck";
- break;
- case SN_SCTP_SHUTCOMP:
- pstate = "ShutComp";
- break;
- case SN_SCTP_ASCONF:
- pstate = "Asconf";
- break;
- case SN_SCTP_ASCONFACK:
- pstate = "AsconfAck";
- break;
- case SN_SCTP_OTHER:
- pstate = "Other";
- break;
- default:
- pstate = "***ERROR***";
- break;
- }
- SctpAliasLog("Parsed: %s %s\n", ploc, pstate);
+ char *ploc, *pstate;
+ switch(direction) {
+ case SN_TO_LOCAL:
+ ploc = "TO_LOCAL -";
+ break;
+ case SN_TO_GLOBAL:
+ ploc = "TO_GLOBAL -";
+ break;
+ default:
+ ploc = "";
+ }
+ switch(sm->msg) {
+ case SN_SCTP_INIT:
+ pstate = "Init";
+ break;
+ case SN_SCTP_INITACK:
+ pstate = "InitAck";
+ break;
+ case SN_SCTP_ABORT:
+ pstate = "Abort";
+ break;
+ case SN_SCTP_SHUTACK:
+ pstate = "ShutAck";
+ break;
+ case SN_SCTP_SHUTCOMP:
+ pstate = "ShutComp";
+ break;
+ case SN_SCTP_ASCONF:
+ pstate = "Asconf";
+ break;
+ case SN_SCTP_ASCONFACK:
+ pstate = "AsconfAck";
+ break;
+ case SN_SCTP_OTHER:
+ pstate = "Other";
+ break;
+ default:
+ pstate = "***ERROR***";
+ break;
+ }
+ SctpAliasLog("Parsed: %s %s\n", ploc, pstate);
}
/** @ingroup Logging
@@ -2561,39 +2539,39 @@ logsctpparse(int direction, struct sctp_nat_msg *sm)
*/
static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s)
{
- struct sctp_GlobalAddress *G_Addr = NULL;
- char *sp;
- switch(assoc->state) {
- case SN_ID:
- sp = "ID ";
- break;
- case SN_INi:
- sp = "INi ";
- break;
- case SN_INa:
- sp = "INa ";
- break;
- case SN_UP:
- sp = "UP ";
- break;
- case SN_CL:
- sp = "CL ";
- break;
- case SN_RM:
- sp = "RM ";
- break;
- default:
- sp = "***ERROR***";
- break;
- }
- SctpAliasLog("%sAssoc: %s exp=%u la=%s lv=%u lp=%u gv=%u gp=%u tbl=%d\n",
- s, sp, assoc->exp, inet_ntoa(assoc->l_addr), ntohl(assoc->l_vtag),
- ntohs(assoc->l_port), ntohl(assoc->g_vtag), ntohs(assoc->g_port),
- assoc->TableRegister);
- /* list global addresses */
- LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
- SctpAliasLog("\t\tga=%s\n",inet_ntoa(G_Addr->g_addr));
- }
+ struct sctp_GlobalAddress *G_Addr = NULL;
+ char *sp;
+ switch(assoc->state) {
+ case SN_ID:
+ sp = "ID ";
+ break;
+ case SN_INi:
+ sp = "INi ";
+ break;
+ case SN_INa:
+ sp = "INa ";
+ break;
+ case SN_UP:
+ sp = "UP ";
+ break;
+ case SN_CL:
+ sp = "CL ";
+ break;
+ case SN_RM:
+ sp = "RM ";
+ break;
+ default:
+ sp = "***ERROR***";
+ break;
+ }
+ SctpAliasLog("%sAssoc: %s exp=%u la=%s lv=%u lp=%u gv=%u gp=%u tbl=%d\n",
+ s, sp, assoc->exp, inet_ntoa(assoc->l_addr), ntohl(assoc->l_vtag),
+ ntohs(assoc->l_port), ntohl(assoc->g_vtag), ntohs(assoc->g_port),
+ assoc->TableRegister);
+ /* list global addresses */
+ LIST_FOREACH(G_Addr, &(assoc->Gaddr), list_Gaddr) {
+ SctpAliasLog("\t\tga=%s\n",inet_ntoa(G_Addr->g_addr));
+ }
}
/** @ingroup Logging
@@ -2603,15 +2581,15 @@ static void logsctpassoc(struct sctp_nat_assoc *assoc, char* s)
*/
static void logSctpGlobal(struct libalias *la)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
- SctpAliasLog("G->\n");
- for (i=0; i < la->sctpNatTableSize; i++) {
- LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
- logsctpassoc(assoc, " ");
- }
- }
+ SctpAliasLog("G->\n");
+ for (i=0; i < la->sctpNatTableSize; i++) {
+ LIST_FOREACH(assoc, &la->sctpTableGlobal[i], list_G) {
+ logsctpassoc(assoc, " ");
+ }
+ }
}
/** @ingroup Logging
@@ -2621,15 +2599,15 @@ static void logSctpGlobal(struct libalias *la)
*/
static void logSctpLocal(struct libalias *la)
{
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
- SctpAliasLog("L->\n");
- for (i=0; i < la->sctpNatTableSize; i++) {
- LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
- logsctpassoc(assoc, " ");
- }
- }
+ SctpAliasLog("L->\n");
+ for (i=0; i < la->sctpNatTableSize; i++) {
+ LIST_FOREACH(assoc, &la->sctpTableLocal[i], list_L) {
+ logsctpassoc(assoc, " ");
+ }
+ }
}
/** @ingroup Logging
@@ -2639,18 +2617,18 @@ static void logSctpLocal(struct libalias *la)
*/
static void logTimerQ(struct libalias *la)
{
- static char buf[50];
- u_int i;
- struct sctp_nat_assoc *assoc = NULL;
-
- SctpAliasLog("t->\n");
- for (i=0; i < SN_TIMER_QUEUE_SIZE; i++) {
- LIST_FOREACH(assoc, &la->sctpNatTimer.TimerQ[i], timer_Q) {
- snprintf(buf, 50, " l=%u ",i);
- //SctpAliasLog(la->logDesc," l=%d ",i);
- logsctpassoc(assoc, buf);
- }
- }
+ static char buf[50];
+ u_int i;
+ struct sctp_nat_assoc *assoc = NULL;
+
+ SctpAliasLog("t->\n");
+ for (i=0; i < SN_TIMER_QUEUE_SIZE; i++) {
+ LIST_FOREACH(assoc, &la->sctpNatTimer.TimerQ[i], timer_Q) {
+ snprintf(buf, 50, " l=%u ",i);
+ //SctpAliasLog(la->logDesc," l=%d ",i);
+ logsctpassoc(assoc, buf);
+ }
+ }
}
/** @ingroup Logging
@@ -2665,23 +2643,23 @@ static void logTimerQ(struct libalias *la)
static void
SctpAliasLog(const char *format, ...)
{
- char buffer[LIBALIAS_BUF_SIZE];
- va_list ap;
- va_start(ap, format);
- vsnprintf(buffer, LIBALIAS_BUF_SIZE, format, ap);
- va_end(ap);
- log(LOG_SECURITY | LOG_INFO,
- "alias_sctp: %s", buffer);
+ char buffer[LIBALIAS_BUF_SIZE];
+ va_list ap;
+ va_start(ap, format);
+ vsnprintf(buffer, LIBALIAS_BUF_SIZE, format, ap);
+ va_end(ap);
+ log(LOG_SECURITY | LOG_INFO,
+ "alias_sctp: %s", buffer);
}
#else
static void
SctpAliasLog(FILE *stream, const char *format, ...)
{
- va_list ap;
+ va_list ap;
- va_start(ap, format);
- vfprintf(stream, format, ap);
- va_end(ap);
- fflush(stream);
+ va_start(ap, format);
+ vfprintf(stream, format, ap);
+ va_end(ap);
+ fflush(stream);
}
#endif
diff --git a/sys/netinet/libalias/alias_sctp.h b/sys/netinet/libalias/alias_sctp.h
index f299a6f..7953f43 100644
--- a/sys/netinet/libalias/alias_sctp.h
+++ b/sys/netinet/libalias/alias_sctp.h
@@ -1,34 +1,9 @@
-/*/* $Id$ */
-//#ifndef lint
-//static char vcid[] = "$Id$";
-//#endif /* lint */
/**
* @file alias_sctp.h
* 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
- * with leadership and advice from 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,7 +29,28 @@
* 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
+ * with leadership and advice from 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.
+ *
*/
+
+/* $FreeBSD$ */
+
#ifndef _ALIAS_SCTP_H_
#define _ALIAS_SCTP_H_
@@ -136,27 +132,27 @@
* Information is stored in network byte order (as is libalias)***
*/
struct sctp_nat_assoc {
- uint32_t l_vtag; /**< local side verification tag */
- uint16_t l_port; /**< local side port number */
- uint32_t g_vtag; /**< global side verification tag */
- uint16_t g_port; /**< global side port number */
- struct in_addr l_addr; /**< local ip address */
- struct in_addr a_addr; /**< alias ip address */
- int state; /**< current state of NAT association */
- int TableRegister; /**< stores which look up tables association is registered in */
- int exp; /**< timer expiration in seconds from uptime */
- int exp_loc; /**< current location in timer_Q */
- int num_Gaddr; /**< number of global IP addresses in the list */
- LIST_HEAD(sctpGlobalAddresshead,sctp_GlobalAddress) Gaddr; /**< List of global addresses */
- LIST_ENTRY (sctp_nat_assoc) list_L; /**< Linked list of pointers for Local table*/
- LIST_ENTRY (sctp_nat_assoc) list_G; /**< Linked list of pointers for Global table */
- LIST_ENTRY (sctp_nat_assoc) timer_Q; /**< Linked list of pointers for timer Q */
+ uint32_t l_vtag; /**< local side verification tag */
+ uint16_t l_port; /**< local side port number */
+ uint32_t g_vtag; /**< global side verification tag */
+ uint16_t g_port; /**< global side port number */
+ struct in_addr l_addr; /**< local ip address */
+ struct in_addr a_addr; /**< alias ip address */
+ int state; /**< current state of NAT association */
+ int TableRegister; /**< stores which look up tables association is registered in */
+ int exp; /**< timer expiration in seconds from uptime */
+ int exp_loc; /**< current location in timer_Q */
+ int num_Gaddr; /**< number of global IP addresses in the list */
+ LIST_HEAD(sctpGlobalAddresshead,sctp_GlobalAddress) Gaddr; /**< List of global addresses */
+ LIST_ENTRY (sctp_nat_assoc) list_L; /**< Linked list of pointers for Local table*/
+ LIST_ENTRY (sctp_nat_assoc) list_G; /**< Linked list of pointers for Global table */
+ LIST_ENTRY (sctp_nat_assoc) timer_Q; /**< Linked list of pointers for timer Q */
//Using libalias locking
};
struct sctp_GlobalAddress {
- struct in_addr g_addr;
- LIST_ENTRY (sctp_GlobalAddress) list_Gaddr; /**< Linked list of pointers for Global table */
+ struct in_addr g_addr;
+ LIST_ENTRY (sctp_GlobalAddress) list_Gaddr; /**< Linked list of pointers for Global table */
};
/**
@@ -165,9 +161,9 @@ struct sctp_GlobalAddress {
* The only chunks whose contents are of any interest are the INIT and ASCONF_AddIP
*/
union sctpChunkOfInt {
- struct sctp_init *Init; /**< Pointer to Init Chunk */
- struct sctp_init_ack *InitAck; /**< Pointer to Init Chunk */
- struct sctp_paramhdr *Asconf; /**< Pointer to ASCONF chunk */
+ struct sctp_init *Init; /**< Pointer to Init Chunk */
+ struct sctp_init_ack *InitAck; /**< Pointer to Init Chunk */
+ struct sctp_paramhdr *Asconf; /**< Pointer to ASCONF chunk */
};
@@ -177,15 +173,15 @@ union sctpChunkOfInt {
* Structure containing the relevant information from the SCTP message
*/
struct sctp_nat_msg {
- uint16_t msg; /**< one of the key messages defined above */
+ uint16_t msg; /**< one of the key messages defined above */
#ifdef INET6
- // struct ip6_hdr *ip_hdr; /**< pointer to ip packet header */ /*no inet6 support yet*/
+ // struct ip6_hdr *ip_hdr; /**< pointer to ip packet header */ /*no inet6 support yet*/
#else
- struct ip *ip_hdr; /**< pointer to ip packet header */
+ struct ip *ip_hdr; /**< pointer to ip packet header */
#endif //#ifdef INET6
- struct sctphdr *sctp_hdr; /**< pointer to sctp common header */
- union sctpChunkOfInt sctpchnk; /**< union of pointers to the chunk of interest */
- int chunk_length; /**< length of chunk of interest */
+ struct sctphdr *sctp_hdr; /**< pointer to sctp common header */
+ union sctpChunkOfInt sctpchnk; /**< union of pointers to the chunk of interest */
+ int chunk_length; /**< length of chunk of interest */
};
@@ -195,9 +191,9 @@ struct sctp_nat_msg {
*/
struct sctp_nat_timer {
- int loc_time; /**< time in seconds for the current location in the queue */
- int cur_loc; /**< index of the current location in the circular queue */
- LIST_HEAD(sctpTimerQ,sctp_nat_assoc) *TimerQ; /**< List of associations at this position in the timer Q */
+ int loc_time; /**< time in seconds for the current location in the queue */
+ int cur_loc; /**< index of the current location in the circular queue */
+ LIST_HEAD(sctpTimerQ,sctp_nat_assoc) *TimerQ; /**< List of associations at this position in the timer Q */
};
diff --git a/sys/netinet/raw_ip.c b/sys/netinet/raw_ip.c
index 9fe0eca..27f4b9c 100644
--- a/sys/netinet/raw_ip.c
+++ b/sys/netinet/raw_ip.c
@@ -276,10 +276,8 @@ rip_input(struct mbuf *m, int off)
continue;
if (inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue;
- if (jailed(inp->inp_cred)) {
- if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
- continue;
- }
+ if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
+ continue;
if (last != NULL) {
struct mbuf *n;
@@ -306,10 +304,8 @@ rip_input(struct mbuf *m, int off)
if (inp->inp_faddr.s_addr &&
inp->inp_faddr.s_addr != ip->ip_src.s_addr)
continue;
- if (jailed(inp->inp_cred)) {
- if (!prison_check_ip4(inp->inp_cred, &ip->ip_dst))
- continue;
- }
+ if (prison_check_ip4(inp->inp_cred, &ip->ip_dst) != 0)
+ continue;
if (last != NULL) {
struct mbuf *n;
@@ -370,14 +366,12 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
ip->ip_off = 0;
ip->ip_p = inp->inp_ip_p;
ip->ip_len = m->m_pkthdr.len;
- if (jailed(inp->inp_cred)) {
- if (prison_getip4(inp->inp_cred, &ip->ip_src)) {
- INP_RUNLOCK(inp);
- m_freem(m);
- return (EPERM);
- }
- } else {
- ip->ip_src = inp->inp_laddr;
+ ip->ip_src = inp->inp_laddr;
+ error = prison_get_ip4(inp->inp_cred, &ip->ip_src);
+ if (error != 0) {
+ INP_RUNLOCK(inp);
+ m_freem(m);
+ return (error);
}
ip->ip_dst.s_addr = dst;
ip->ip_ttl = inp->inp_ip_ttl;
@@ -388,10 +382,11 @@ rip_output(struct mbuf *m, struct socket *so, u_long dst)
}
INP_RLOCK(inp);
ip = mtod(m, struct ip *);
- if (!prison_check_ip4(inp->inp_cred, &ip->ip_src)) {
+ error = prison_check_ip4(inp->inp_cred, &ip->ip_src);
+ if (error != 0) {
INP_RUNLOCK(inp);
m_freem(m);
- return (EPERM);
+ return (error);
}
/*
@@ -803,12 +798,14 @@ rip_bind(struct socket *so, struct sockaddr *nam, struct thread *td)
INIT_VNET_INET(so->so_vnet);
struct sockaddr_in *addr = (struct sockaddr_in *)nam;
struct inpcb *inp;
+ int error;
if (nam->sa_len != sizeof(*addr))
return (EINVAL);
- if (!prison_check_ip4(td->td_ucred, &addr->sin_addr))
- return (EADDRNOTAVAIL);
+ error = prison_check_ip4(td->td_ucred, &addr->sin_addr);
+ if (error != 0)
+ return (error);
if (TAILQ_EMPTY(&V_ifnet) ||
(addr->sin_family != AF_INET && addr->sin_family != AF_IMPLINK) ||
diff --git a/sys/netinet/sctp_auth.c b/sys/netinet/sctp_auth.c
index 71715cc..6da97ec 100644
--- a/sys/netinet/sctp_auth.c
+++ b/sys/netinet/sctp_auth.c
@@ -1645,8 +1645,10 @@ sctp_auth_get_cookie_params(struct sctp_tcb *stcb, struct mbuf *m,
bcopy(p_random->random_data, new_key->key, random_len);
}
#else
- keylen = sizeof(*p_random) + random_len + sizeof(*chunks) + num_chunks +
- sizeof(*hmacs) + hmacs_len;
+ keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
+ if (chunks != NULL) {
+ keylen += sizeof(*chunks) + num_chunks;
+ }
new_key = sctp_alloc_key(keylen);
if (new_key != NULL) {
/* copy in the RANDOM */
diff --git a/sys/netinet/sctp_constants.h b/sys/netinet/sctp_constants.h
index cc48d2f..ca9c010 100644
--- a/sys/netinet/sctp_constants.h
+++ b/sys/netinet/sctp_constants.h
@@ -37,8 +37,15 @@ __FBSDID("$FreeBSD$");
#define __sctp_constants_h__
/* IANA assigned port number for SCTP over UDP encapsulation */
-#define SCTP_OVER_UDP_TUNNELING_PORT 9899
-
+/* For freebsd we cannot bind the port at
+ * startup. Otherwise what will happen is
+ * we really won't be bound. The user must
+ * put it into the sysctl... or we need
+ * to build a special timer for this to allow
+ * us to wait 1 second or so after the system
+ * comes up.
+ */
+#define SCTP_OVER_UDP_TUNNELING_PORT 0
/* Number of packets to get before sack sent by default */
#define SCTP_DEFAULT_SACK_FREQ 2
@@ -310,10 +317,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_PARTIAL_DELIVERY_SHIFT 1
-/* Minimum number of bytes read by user before we
- * condsider doing a rwnd update
- */
-
/*
* default HMAC for cookies, etc... use one of the AUTH HMAC id's
* SCTP_HMAC is the HMAC_ID to use
@@ -323,21 +326,6 @@ __FBSDID("$FreeBSD$");
#define SCTP_SIGNATURE_SIZE SCTP_AUTH_DIGEST_LEN_SHA1
#define SCTP_SIGNATURE_ALOC_SIZE SCTP_SIGNATURE_SIZE
-/* DEFINE HERE WHAT CRC YOU WANT TO USE */
-#define SCTP_USECRC_RFC2960 1
-/* #define SCTP_USECRC_FLETCHER 1 */
-/* #define SCTP_USECRC_SSHCRC32 1 */
-/* #define SCTP_USECRC_FASTCRC32 1 */
-/* #define SCTP_USECRC_CRC32 1 */
-/* #define SCTP_USECRC_TCP32 1 */
-/* #define SCTP_USECRC_CRC16SMAL 1 */
-/* #define SCTP_USECRC_CRC16 1 */
-/* #define SCTP_USECRC_MODADLER 1 */
-
-#ifndef SCTP_ADLER32_BASE
-#define SCTP_ADLER32_BASE 65521
-#endif
-
/*
* the SCTP protocol signature this includes the version number encoded in
* the last 4 bits of the signature.
@@ -619,43 +607,16 @@ __FBSDID("$FreeBSD$");
-/*
- * Number of ticks before the soxwakeup() event that is delayed is sent AFTER
- * the accept() call
- */
-
-/*
- * Of course we really don't collect stale cookies, being folks of decerning
- * taste. However we do count them, if we get too many before the association
- * comes up.. we give up. Below is the constant that dictates when we give it
- * up...this is a implemenation dependent treatment. In ours we do not ask
- * for a extension of time, but just retry this many times...
- */
-
/* max number of TSN's dup'd that I will hold */
#define SCTP_MAX_DUP_TSNS 20
/*
* Here we define the types used when setting the retry amounts.
*/
-/* constants for type of set */
-
-/* Maximum TSN's we will summarize in a drop report */
-
/* How many drop re-attempts we make on INIT/COOKIE-ECHO */
#define SCTP_RETRY_DROPPED_THRESH 4
/*
- * And the max we will keep a history of in the tcb which MUST be lower than
- * 256.
- */
-
-/*
- * Here we define the default timers and the default number of attemts we
- * make for each respective side (send/init).
- */
-
-/*
* Maxmium number of chunks a single association can have on it. Note that
* this is a squishy number since the count can run over this if the user
* sends a large message down .. the fragmented chunks don't count until
@@ -763,7 +724,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_DEBUG_INDATA1 0x01000000
#define SCTP_DEBUG_INDATA2 0x02000000 /* unused */
#define SCTP_DEBUG_INDATA3 0x04000000 /* unused */
-#define SCTP_DEBUG_INDATA4 0x08000000 /* unused */
+#define SCTP_DEBUG_CRCOFFLOAD 0x08000000 /* unused */
#define SCTP_DEBUG_USRREQ1 0x10000000 /* unused */
#define SCTP_DEBUG_USRREQ2 0x20000000 /* unused */
#define SCTP_DEBUG_PEEL1 0x40000000
@@ -783,7 +744,7 @@ __FBSDID("$FreeBSD$");
#define SCTP_INITIAL_CWND 4380
-#define SCTP_DEFAULT_MTU 1500 /* emegency default MTU */
+#define SCTP_DEFAULT_MTU 1500 /* emergency default MTU */
/* amount peer is obligated to have in rwnd or I will abort */
#define SCTP_MIN_RWND 1500
@@ -996,13 +957,6 @@ __FBSDID("$FreeBSD$");
*/
#define SCTP_STACK_VTAG_HASH_SIZE 32
-
-/*
- * If we use the per-endpoint model than we do not have a hash table of
- * entries but instead have a single head pointer and we must crawl through
- * the entire list.
- */
-
/*
* Number of seconds of time wait for a vtag.
*/
diff --git a/sys/netinet/sctp_crc32.c b/sys/netinet/sctp_crc32.c
index 7f0e742..3fba39e 100644
--- a/sys/netinet/sctp_crc32.c
+++ b/sys/netinet/sctp_crc32.c
@@ -34,12 +34,16 @@
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/socketvar.h>
+#include <sys/uio.h>
+#include <netinet/sctp.h>
#include <netinet/sctp_os.h>
#include <netinet/sctp_crc32.h>
+#include <netinet/sctp_pcb.h>
-#ifndef SCTP_USE_ADLER32
-
-
+#if !defined(SCTP_WITH_NO_CSUM)
/**
*
* Routine Description:
@@ -80,12 +84,14 @@ __FBSDID("$FreeBSD$");
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o32[256] =
@@ -134,12 +140,14 @@ uint32_t sctp_crc_tableil8_o32[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o40[256] =
@@ -188,12 +196,14 @@ uint32_t sctp_crc_tableil8_o40[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o48[256] =
@@ -242,12 +252,14 @@ uint32_t sctp_crc_tableil8_o48[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o56[256] =
@@ -296,12 +308,14 @@ uint32_t sctp_crc_tableil8_o56[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o64[256] =
@@ -350,12 +364,14 @@ uint32_t sctp_crc_tableil8_o64[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o72[256] =
@@ -404,12 +420,14 @@ uint32_t sctp_crc_tableil8_o72[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o80[256] =
@@ -458,12 +476,14 @@ uint32_t sctp_crc_tableil8_o80[256] =
* The following CRC lookup table was generated automagically using the
* following model parameters:
*
- * Generator Polynomial = ................. 0x1EDC6F41 Generator Polynomial
- * Length = .......... 32 bits Reflected Bits = ....................... TRUE
- * Table Generation Offset = .............. 32 bits Number of Slices =
- * ..................... 8 slices Slice Lengths = ........................ 8
- * 8 8 8 8 8 8 8 Directory Name = ....................... .\ File Name =
- * ............................ 8x256_tables.c
+ * Generator Polynomial = ................. 0x1EDC6F41
+ * Generator Polynomial Length = .......... 32 bits
+ * Reflected Bits = ....................... TRUE
+ * Table Generation Offset = .............. 32 bits
+ * Number of Slices = ..................... 8 slices
+ * Slice Lengths = ........................ 8 8 8 8 8 8 8 8
+ * Directory Name = ....................... .\
+ * File Name = ............................ 8x256_tables.c
*/
uint32_t sctp_crc_tableil8_o88[256] =
@@ -506,6 +526,7 @@ uint32_t sctp_crc_tableil8_o88[256] =
* end of the CRC lookup table crc_tableil8_o88
*/
+
static uint32_t
sctp_crc32c_sb8_64_bit(uint32_t crc,
unsigned char *p_buf,
@@ -662,7 +683,7 @@ uint32_t sctp_crc_c[256] = {
#define SCTP_CRC32C(c,d) (c=(c>>8)^sctp_crc_c[(c^(d))&0xFF])
-uint32_t
+static uint32_t
old_update_crc32(uint32_t crc32c,
unsigned char *buffer,
unsigned int length)
@@ -677,7 +698,7 @@ old_update_crc32(uint32_t crc32c,
uint32_t
-sctp_csum_finalize(uint32_t crc32c)
+sctp_finalize_crc32(uint32_t crc32c)
{
uint32_t result;
@@ -709,4 +730,88 @@ sctp_csum_finalize(uint32_t crc32c)
return (crc32c);
}
+#endif /* !defined(SCTP_WITH_NO_CSUM) */
+
+#if defined(SCTP_WITH_NO_CSUM)
+uint32_t
+sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
+{
+ return (0);
+}
+
+#else
+uint32_t
+sctp_calculate_cksum(struct mbuf *m, uint32_t offset)
+{
+ /*
+ * given a mbuf chain with a packetheader offset by 'offset'
+ * pointing at a sctphdr (with csum set to 0) go through the chain
+ * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
+ * has a side bonus as it will calculate the total length of the
+ * mbuf chain. Note: if offset is greater than the total mbuf
+ * length, checksum=1, pktlen=0 is returned (ie. no real error code)
+ */
+ uint32_t base = 0xffffffff;
+ struct mbuf *at;
+
+ at = m;
+ /* find the correct mbuf and offset into mbuf */
+ while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) {
+ offset -= SCTP_BUF_LEN(at); /* update remaining offset
+ * left */
+ at = SCTP_BUF_NEXT(at);
+ }
+ while (at != NULL) {
+ if ((SCTP_BUF_LEN(at) - offset) > 0) {
+ if ((SCTP_BUF_LEN(at) - offset) < 4) {
+ /* Use old method if less than 4 bytes */
+ base = old_update_crc32(base,
+ (unsigned char *)(SCTP_BUF_AT(at, offset)),
+ (unsigned int)(SCTP_BUF_LEN(at) - offset));
+ } else {
+ base = update_crc32(base,
+ (unsigned char *)(SCTP_BUF_AT(at, offset)),
+ (unsigned int)(SCTP_BUF_LEN(at) - offset));
+ }
+ /* we only offset once into the first mbuf */
+ }
+ if (offset) {
+ if (offset < (uint32_t) SCTP_BUF_LEN(at))
+ offset = 0;
+ else
+ offset -= SCTP_BUF_LEN(at);
+ }
+ at = SCTP_BUF_NEXT(at);
+ }
+ base = sctp_finalize_crc32(base);
+ return (base);
+}
+
#endif
+
+void
+sctp_delayed_cksum(struct mbuf *m)
+{
+ struct ip *ip;
+ uint32_t checksum;
+ uint32_t offset;
+
+ ip = mtod(m, struct ip *);
+ offset = ip->ip_hl << 2;
+ checksum = sctp_calculate_cksum(m, offset);
+ SCTP_STAT_DECR(sctps_sendhwcrc);
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ offset += offsetof(struct sctphdr, checksum);
+
+ if (offset + sizeof(uint32_t) > (uint32_t) (m->m_len)) {
+ printf("delayed m_pullup, m->len: %d off: %d p: %d\n",
+ (uint32_t) m->m_len, offset, ip->ip_p);
+ /*
+ * XXX this shouldn't happen, but if it does, the correct
+ * behavior may be to insert the checksum in the appropriate
+ * next mbuf in the chain.
+ */
+ return;
+ }
+ *(uint32_t *) (m->m_data + offset) = checksum;
+}
diff --git a/sys/netinet/sctp_crc32.h b/sys/netinet/sctp_crc32.h
index 88739ed..2c353d2 100644
--- a/sys/netinet/sctp_crc32.h
+++ b/sys/netinet/sctp_crc32.h
@@ -36,16 +36,12 @@ __FBSDID("$FreeBSD$");
#ifndef __crc32c_h__
#define __crc32c_h__
-#ifndef SCTP_USE_ADLER32
-
#if defined(_KERNEL) || defined(__Userspace__)
+uint32_t sctp_calculate_cksum(struct mbuf *, uint32_t);
+void sctp_delayed_cksum(struct mbuf *);
uint32_t update_crc32(uint32_t, unsigned char *, unsigned int);
-
-uint32_t old_update_crc32(uint32_t, unsigned char *, unsigned int);
-
-uint32_t sctp_csum_finalize(uint32_t);
-
+uint32_t sctp_finalize_crc32(uint32_t);
#endif /* _KERNEL */
-#endif /* !SCTP_USE_ADLER32 */
+
#endif /* __crc32c_h__ */
diff --git a/sys/netinet/sctp_input.c b/sys/netinet/sctp_input.c
index c686fac..2d8a1f2 100644
--- a/sys/netinet/sctp_input.c
+++ b/sys/netinet/sctp_input.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_asconf.h>
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_timer.h>
+#include <netinet/sctp_crc32.h>
#include <netinet/udp.h>
@@ -1384,14 +1385,6 @@ sctp_process_cookie_existing(struct mbuf *m, int iphlen, int offset,
/* FOOBAR */
return (NULL);
}
- /* pre-reserve some space */
-#ifdef INET6
- SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
-#else
- SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
-#endif
- SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
- SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
/* Set the len */
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_paramhdr);
ph = mtod(op_err, struct sctp_paramhdr *);
@@ -2504,15 +2497,6 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
/* FOOBAR */
return (NULL);
}
- /* pre-reserve some space */
-#ifdef INET6
- SCTP_BUF_RESV_UF(op_err, sizeof(struct ip6_hdr));
-#else
- SCTP_BUF_RESV_UF(op_err, sizeof(struct ip));
-#endif
- SCTP_BUF_RESV_UF(op_err, sizeof(struct sctphdr));
- SCTP_BUF_RESV_UF(op_err, sizeof(struct sctp_chunkhdr));
-
/* Set the len */
SCTP_BUF_LEN(op_err) = sizeof(struct sctp_stale_cookie_msg);
scm = mtod(op_err, struct sctp_stale_cookie_msg *);
@@ -2598,9 +2582,9 @@ sctp_handle_cookie_echo(struct mbuf *m, int iphlen, int offset,
}
}
}
- if (to == NULL)
+ if (to == NULL) {
return (NULL);
-
+ }
cookie_len -= SCTP_SIGNATURE_SIZE;
if (*stcb == NULL) {
/* this is the "normal" case... get a new TCB */
@@ -5594,7 +5578,6 @@ sctp_input_with_port(i_pak, off, port)
int refcount_up = 0;
int length, mlen, offset;
-
if (SCTP_GET_PKT_VRFID(i_pak, vrf_id)) {
SCTP_RELEASE_PKT(i_pak);
return;
@@ -5642,6 +5625,11 @@ sctp_input_with_port(i_pak, off, port)
}
ip = mtod(m, struct ip *);
}
+ /* validate mbuf chain length with IP payload length */
+ if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
+ SCTP_STAT_INCR(sctps_hdrops);
+ goto bad;
+ }
sh = (struct sctphdr *)((caddr_t)ip + iphlen);
ch = (struct sctp_chunkhdr *)((caddr_t)sh + sizeof(*sh));
SCTPDBG(SCTP_DEBUG_INPUT1,
@@ -5659,15 +5647,26 @@ sctp_input_with_port(i_pak, off, port)
goto bad;
}
/* validate SCTP checksum */
+ SCTPDBG(SCTP_DEBUG_CRCOFFLOAD,
+ "sctp_input(): Packet of length %d received on %s with csum_flags 0x%x.\n",
+ m->m_pkthdr.len,
+ if_name(m->m_pkthdr.rcvif),
+ m->m_pkthdr.csum_flags);
+ if (m->m_pkthdr.csum_flags & CSUM_SCTP_VALID) {
+ SCTP_STAT_INCR(sctps_recvhwcrc);
+ goto sctp_skip_csum_4;
+ }
check = sh->checksum; /* save incoming checksum */
if ((check == 0) && (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback)) &&
((ip->ip_src.s_addr == ip->ip_dst.s_addr) ||
(SCTP_IS_IT_LOOPBACK(m)))
) {
+ SCTP_STAT_INCR(sctps_recvnocrc);
goto sctp_skip_csum_4;
}
sh->checksum = 0; /* prepare for calc */
- calc_check = sctp_calculate_sum(m, &mlen, iphlen);
+ calc_check = sctp_calculate_cksum(m, iphlen);
+ SCTP_STAT_INCR(sctps_recvswcrc);
if (calc_check != check) {
SCTPDBG(SCTP_DEBUG_INPUT1, "Bad CSUM on SCTP packet calc_check:%x check:%x m:%p mlen:%d iphlen:%d\n",
calc_check, check, m, mlen, iphlen);
@@ -5699,11 +5698,6 @@ sctp_skip_csum_4:
SCTP_STAT_INCR(sctps_hdrops);
goto bad;
}
- /* validate mbuf chain length with IP payload length */
- if (mlen < (SCTP_GET_IPV4_LENGTH(ip) - iphlen)) {
- SCTP_STAT_INCR(sctps_hdrops);
- goto bad;
- }
/*
* Locate pcb and tcb for datagram sctp_findassociation_addr() wants
* IP/SCTP/first chunk header...
diff --git a/sys/netinet/sctp_os_bsd.h b/sys/netinet/sctp_os_bsd.h
index d0e7a18..fcaf715 100644
--- a/sys/netinet/sctp_os_bsd.h
+++ b/sys/netinet/sctp_os_bsd.h
@@ -154,11 +154,8 @@ MALLOC_DECLARE(SCTP_M_SOCKOPT);
#define MOD_IPSEC ipsec
/* then define the macro(s) that hook into the vimage macros */
-#if defined(__FreeBSD__) && __FreeBSD_version >= 800056
#define MODULE_GLOBAL(__MODULE, __SYMBOL) V_ ## __SYMBOL
-#else
-#define MODULE_GLOBAL(__MODULE, __SYMBOL) (__SYMBOL)
-#endif
+
/*
*
*/
diff --git a/sys/netinet/sctp_output.c b/sys/netinet/sctp_output.c
index 9efff50..eac896c 100644
--- a/sys/netinet/sctp_output.c
+++ b/sys/netinet/sctp_output.c
@@ -49,6 +49,7 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_indata.h>
#include <netinet/sctp_bsd_addr.h>
#include <netinet/sctp_input.h>
+#include <netinet/sctp_crc32.h>
#include <netinet/udp.h>
#include <machine/in_cksum.h>
@@ -5213,6 +5214,9 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
int ecn_ok,
struct sctp_tmit_chunk *chk,
int out_of_asoc_ok,
+ uint16_t src_port,
+ uint16_t dest_port,
+ uint32_t v_tag,
uint16_t port,
int so_locked,
#if !defined(__APPLE__) && !defined(SCTP_SO_LOCK_TESTING)
@@ -5237,7 +5241,6 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
struct mbuf *newm;
struct sctphdr *sctphdr;
int packet_length;
- uint32_t csum;
int ret;
uint32_t vrf_id;
sctp_route_t *ro = NULL;
@@ -5263,51 +5266,27 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
if ((auth != NULL) && (stcb != NULL)) {
sctp_fill_hmac_digest_m(m, auth_offset, auth, stcb, auth_keyid);
}
- /* Calculate the csum and fill in the length of the packet */
- sctphdr = mtod(m, struct sctphdr *);
- if (SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
- (stcb) &&
- (to->sa_family == AF_INET) &&
- (stcb->asoc.loopback_scope)) {
- sctphdr->checksum = 0;
- /*
- * This can probably now be taken out since my audit shows
- * no more bad pktlen's coming in. But we will wait a while
- * yet.
- */
- packet_length = sctp_calculate_len(m);
- } else {
- sctphdr->checksum = 0;
- csum = sctp_calculate_sum(m, &packet_length, 0);
- sctphdr->checksum = csum;
- }
-
if (to->sa_family == AF_INET) {
struct ip *ip = NULL;
sctp_route_t iproute;
uint8_t tos_value;
+ int len;
+ len = sizeof(struct ip) + sizeof(struct sctphdr);
if (port) {
- newm = sctp_get_mbuf_for_msg(sizeof(struct ip) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA);
- } else {
- newm = sctp_get_mbuf_for_msg(sizeof(struct ip), 1, M_DONTWAIT, 1, MT_DATA);
+ len += sizeof(struct udphdr);
}
+ newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
if (newm == NULL) {
sctp_m_freem(m);
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
- if (port) {
- SCTP_ALIGN_TO_END(newm, sizeof(struct ip) + sizeof(struct udphdr));
- SCTP_BUF_LEN(newm) = sizeof(struct ip) + sizeof(struct udphdr);
- packet_length += sizeof(struct ip) + sizeof(struct udphdr);
- } else {
- SCTP_ALIGN_TO_END(newm, sizeof(struct ip));
- SCTP_BUF_LEN(newm) = sizeof(struct ip);
- packet_length += sizeof(struct ip);
- }
+ SCTP_ALIGN_TO_END(newm, len);
+ SCTP_BUF_LEN(newm) = len;
SCTP_BUF_NEXT(newm) = m;
m = newm;
+ packet_length = sctp_calculate_len(m);
ip = mtod(m, struct ip *);
ip->ip_v = IPVERSION;
ip->ip_hl = (sizeof(struct ip) >> 2);
@@ -5401,12 +5380,21 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
}
}
if (port) {
- udp = (struct udphdr *)(ip + 1);
+ udp = (struct udphdr *)((caddr_t)ip + sizeof(struct ip));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
udp->uh_ulen = htons(packet_length - sizeof(struct ip));
udp->uh_sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
+ sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
+ } else {
+ sctphdr = (struct sctphdr *)((caddr_t)ip + sizeof(struct ip));
}
+
+ sctphdr->src_port = src_port;
+ sctphdr->dest_port = dest_port;
+ sctphdr->v_tag = v_tag;
+ sctphdr->checksum = 0;
+
/*
* If source address selection fails and we find no route
* then the ip_output should fail as well with a
@@ -5517,7 +5505,25 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
#endif
SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
if (port) {
+ if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
+ (stcb) &&
+ (stcb->asoc.loopback_scope))) {
+ sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip) + sizeof(struct udphdr));
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ } else {
+ SCTP_STAT_INCR(sctps_sendnocrc);
+ }
SCTP_ENABLE_UDP_CSUM(o_pak);
+ } else {
+ if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
+ (stcb) &&
+ (stcb->asoc.loopback_scope))) {
+ m->m_pkthdr.csum_flags = CSUM_SCTP;
+ m->m_pkthdr.csum_data = 0; /* FIXME MT */
+ SCTP_STAT_INCR(sctps_sendhwcrc);
+ } else {
+ SCTP_STAT_INCR(sctps_sendnocrc);
+ }
}
/* send it out. table id is taken from stcb */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -5591,6 +5597,7 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
struct sockaddr_in6 lsa6_storage;
int error;
u_short prev_port = 0;
+ int len;
if (net != NULL) {
flowlabel = net->tos_flowlabel;
@@ -5598,27 +5605,21 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
flowlabel = ((struct in6pcb *)inp)->in6p_flowinfo;
}
+ len = sizeof(struct ip6_hdr) + sizeof(struct sctphdr);
if (port) {
- newm = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA);
- } else {
- newm = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr), 1, M_DONTWAIT, 1, MT_DATA);
+ len += sizeof(struct udphdr);
}
+ newm = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
if (newm == NULL) {
sctp_m_freem(m);
SCTP_LTRACE_ERR_RET(inp, stcb, NULL, SCTP_FROM_SCTP_OUTPUT, ENOMEM);
return (ENOMEM);
}
- if (port) {
- SCTP_ALIGN_TO_END(newm, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
- SCTP_BUF_LEN(newm) = sizeof(struct ip6_hdr) + sizeof(struct udphdr);
- packet_length += sizeof(struct ip6_hdr) + sizeof(struct udphdr);
- } else {
- SCTP_ALIGN_TO_END(newm, sizeof(struct ip6_hdr));
- SCTP_BUF_LEN(newm) = sizeof(struct ip6_hdr);
- packet_length += sizeof(struct ip6_hdr);
- }
+ SCTP_ALIGN_TO_END(newm, len);
+ SCTP_BUF_LEN(newm) = len;
SCTP_BUF_NEXT(newm) = m;
m = newm;
+ packet_length = sctp_calculate_len(m);
ip6h = mtod(m, struct ip6_hdr *);
/*
@@ -5763,12 +5764,21 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
ip6h->ip6_src = lsa6->sin6_addr;
if (port) {
- udp = (struct udphdr *)(ip6h + 1);
+ udp = (struct udphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
udp->uh_dport = port;
udp->uh_ulen = htons(packet_length - sizeof(struct ip6_hdr));
udp->uh_sum = 0;
+ sctphdr = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
+ } else {
+ sctphdr = (struct sctphdr *)((caddr_t)ip6h + sizeof(struct ip6_hdr));
}
+
+ sctphdr->src_port = src_port;
+ sctphdr->dest_port = dest_port;
+ sctphdr->v_tag = v_tag;
+ sctphdr->checksum = 0;
+
/*
* We set the hop limit now since there is a good chance
* that our ro pointer is now filled
@@ -5805,9 +5815,27 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
#endif
SCTP_ATTACH_CHAIN(o_pak, m, packet_length);
if (port) {
+ if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
+ (stcb) &&
+ (stcb->asoc.loopback_scope))) {
+ sctphdr->checksum = sctp_calculate_cksum(m, sizeof(struct ip6_hdr) + sizeof(struct udphdr));
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ } else {
+ SCTP_STAT_INCR(sctps_sendnocrc);
+ }
if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), packet_length - sizeof(struct ip6_hdr))) == 0) {
udp->uh_sum = 0xffff;
}
+ } else {
+ if (!(SCTP_BASE_SYSCTL(sctp_no_csum_on_loopback) &&
+ (stcb) &&
+ (stcb->asoc.loopback_scope))) {
+ m->m_pkthdr.csum_flags = CSUM_SCTP;
+ m->m_pkthdr.csum_data = 0; /* FIXME MT */
+ SCTP_STAT_INCR(sctps_sendhwcrc);
+ } else {
+ SCTP_STAT_INCR(sctps_sendnocrc);
+ }
}
/* send it out. table id is taken from stcb */
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
@@ -5905,7 +5933,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
{
struct mbuf *m, *m_at, *mp_last;
struct sctp_nets *net;
- struct sctp_init_msg *initm;
+ struct sctp_init_chunk *init;
struct sctp_supported_addr_param *sup_addr;
struct sctp_adaptation_layer_indication *ali;
struct sctp_ecn_supported_param *ecn;
@@ -5961,7 +5989,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - mbuf?\n");
return;
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg);
+ SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
/*
* assume peer supports asconf in order to be able to queue local
* address changes while an INIT is in flight and before the assoc
@@ -5969,28 +5997,24 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
*/
stcb->asoc.peer_supports_asconf = 1;
/* Now lets put the SCTP header in place */
- initm = mtod(m, struct sctp_init_msg *);
- initm->sh.src_port = inp->sctp_lport;
- initm->sh.dest_port = stcb->rport;
- initm->sh.v_tag = 0;
- initm->sh.checksum = 0; /* calculate later */
+ init = mtod(m, struct sctp_init_chunk *);
/* now the chunk header */
- initm->msg.ch.chunk_type = SCTP_INITIATION;
- initm->msg.ch.chunk_flags = 0;
+ init->ch.chunk_type = SCTP_INITIATION;
+ init->ch.chunk_flags = 0;
/* fill in later from mbuf we build */
- initm->msg.ch.chunk_length = 0;
+ init->ch.chunk_length = 0;
/* place in my tag */
- initm->msg.init.initiate_tag = htonl(stcb->asoc.my_vtag);
+ init->init.initiate_tag = htonl(stcb->asoc.my_vtag);
/* set up some of the credits. */
- initm->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket),
+ init->init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(inp->sctp_socket),
SCTP_MINIMAL_RWND));
- initm->msg.init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
- initm->msg.init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
- initm->msg.init.initial_tsn = htonl(stcb->asoc.init_seq_number);
+ init->init.num_outbound_streams = htons(stcb->asoc.pre_open_streams);
+ init->init.num_inbound_streams = htons(stcb->asoc.max_inbound_streams);
+ init->init.initial_tsn = htonl(stcb->asoc.init_seq_number);
/* now the address restriction */
- sup_addr = (struct sctp_supported_addr_param *)((caddr_t)initm +
- sizeof(*initm));
+ sup_addr = (struct sctp_supported_addr_param *)((caddr_t)init +
+ sizeof(*init));
sup_addr->ph.param_type = htons(SCTP_SUPPORTED_ADDRTYPE);
#ifdef INET6
/* we support 2 types: IPv6/IPv4 */
@@ -6004,7 +6028,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
sup_addr->addr_type[1] = htons(0); /* this is the padding */
#endif
SCTP_BUF_LEN(m) += sizeof(*sup_addr) + sizeof(uint16_t);
-
/* adaptation layer indication parameter */
ali = (struct sctp_adaptation_layer_indication *)((caddr_t)sup_addr + sizeof(*sup_addr) + sizeof(uint16_t));
ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
@@ -6013,6 +6036,16 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
SCTP_BUF_LEN(m) += sizeof(*ali);
ecn = (struct sctp_ecn_supported_param *)((caddr_t)ali + sizeof(*ali));
+ if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
+ /* Add NAT friendly parameter */
+ struct sctp_paramhdr *ph;
+
+ ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
+ ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
+ ph->param_length = htons(sizeof(struct sctp_paramhdr));
+ SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
+ ecn = (struct sctp_ecn_supported_param *)((caddr_t)ph + sizeof(*ph));
+ }
/* now any cookie time extensions */
if (stcb->asoc.cookie_preserve_req) {
struct sctp_cookie_perserve_param *cookie_preserve;
@@ -6052,19 +6085,22 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
pr_supported->chunk_types[num_ext++] = SCTP_FORWARD_CUM_TSN;
pr_supported->chunk_types[num_ext++] = SCTP_PACKET_DROPPED;
pr_supported->chunk_types[num_ext++] = SCTP_STREAM_RESET;
- if (!SCTP_BASE_SYSCTL(sctp_auth_disable))
+ if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
pr_supported->chunk_types[num_ext++] = SCTP_AUTHENTICATION;
+ }
/*
* EY if the initiator supports nr_sacks, need to report that to
* responder in INIT chunk
*/
- if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off))
+ if (SCTP_BASE_SYSCTL(sctp_nr_sack_on_off)) {
pr_supported->chunk_types[num_ext++] = SCTP_NR_SELECTIVE_ACK;
+ }
p_len = sizeof(*pr_supported) + num_ext;
pr_supported->ph.param_length = htons(p_len);
bzero((caddr_t)pr_supported + p_len, SCTP_SIZE32(p_len) - p_len);
SCTP_BUF_LEN(m) += SCTP_SIZE32(p_len);
+
/* ECN nonce: And now tell the peer we support ECN nonce */
if (SCTP_BASE_SYSCTL(sctp_ecn_nonce)) {
ecn_nonce = (struct sctp_ecn_nonce_supported_param *)
@@ -6073,15 +6109,6 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
ecn_nonce->ph.param_length = htons(sizeof(*ecn_nonce));
SCTP_BUF_LEN(m) += sizeof(*ecn_nonce);
}
- if (SCTP_BASE_SYSCTL(sctp_inits_include_nat_friendly)) {
- /* Add NAT friendly parameter */
- struct sctp_paramhdr *ph;
-
- ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
- ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
- ph->param_length = htons(sizeof(struct sctp_paramhdr));
- SCTP_BUF_LEN(m) += sizeof(sizeof(struct sctp_paramhdr));
- }
/* add authentication parameters */
if (!SCTP_BASE_SYSCTL(sctp_auth_disable)) {
struct sctp_auth_random *randp;
@@ -6160,7 +6187,7 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
mp_last = m_at;
p_len += SCTP_BUF_LEN(m_at);
}
- initm->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr)));
+ init->ch.chunk_length = htons(p_len);
/*
* We sifa 0 here to NOT set IP_DF if its IPv4, we ignore the return
* here since the timer will drive a retranmission.
@@ -6185,7 +6212,9 @@ sctp_send_initiate(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int so_locked
SCTPDBG(SCTP_DEBUG_OUTPUT4, "Sending INIT - calls lowlevel_output\n");
ret = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
- m, 0, NULL, 0, 0, 0, NULL, 0, net->port, so_locked, NULL);
+ m, 0, NULL, 0, 0, 0, NULL, 0,
+ inp->sctp_lport, stcb->rport, htonl(0),
+ net->port, so_locked, NULL);
SCTPDBG(SCTP_DEBUG_OUTPUT4, "lowlevel_output - %d\n", ret);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
sctp_timer_start(SCTP_TIMER_TYPE_INIT, inp, stcb, net);
@@ -6711,7 +6740,7 @@ sctp_send_initiate_ack(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
{
struct sctp_association *asoc;
struct mbuf *m, *m_at, *m_tmp, *m_cookie, *op_err, *mp_last;
- struct sctp_init_msg *initackm_out;
+ struct sctp_init_ack_chunk *initack;
struct sctp_adaptation_layer_indication *ali;
struct sctp_ecn_supported_param *ecn;
struct sctp_prsctp_supported_param *prsctp;
@@ -6776,7 +6805,7 @@ do_a_abort:
sctp_m_freem(op_err);
return;
}
- SCTP_BUF_LEN(m) = sizeof(struct sctp_init_msg);
+ SCTP_BUF_LEN(m) = sizeof(struct sctp_init_chunk);
/* the time I built cookie */
(void)SCTP_GETTIME_TIMEVAL(&stc.time_entered);
@@ -7059,29 +7088,25 @@ do_a_abort:
}
}
/* Now lets put the SCTP header in place */
- initackm_out = mtod(m, struct sctp_init_msg *);
- initackm_out->sh.src_port = inp->sctp_lport;
- initackm_out->sh.dest_port = sh->src_port;
- initackm_out->sh.v_tag = init_chk->init.initiate_tag;
+ initack = mtod(m, struct sctp_init_ack_chunk *);
/* Save it off for quick ref */
stc.peers_vtag = init_chk->init.initiate_tag;
- initackm_out->sh.checksum = 0; /* calculate later */
/* who are we */
memcpy(stc.identification, SCTP_VERSION_STRING,
min(strlen(SCTP_VERSION_STRING), sizeof(stc.identification)));
/* now the chunk header */
- initackm_out->msg.ch.chunk_type = SCTP_INITIATION_ACK;
- initackm_out->msg.ch.chunk_flags = 0;
+ initack->ch.chunk_type = SCTP_INITIATION_ACK;
+ initack->ch.chunk_flags = 0;
/* fill in later from mbuf we build */
- initackm_out->msg.ch.chunk_length = 0;
+ initack->ch.chunk_length = 0;
/* place in my tag */
if ((asoc != NULL) &&
((SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_WAIT) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_INUSE) ||
(SCTP_GET_STATE(asoc) == SCTP_STATE_COOKIE_ECHOED))) {
/* re-use the v-tags and init-seq here */
- initackm_out->msg.init.initiate_tag = htonl(asoc->my_vtag);
- initackm_out->msg.init.initial_tsn = htonl(asoc->init_seq_number);
+ initack->init.initiate_tag = htonl(asoc->my_vtag);
+ initack->init.initial_tsn = htonl(asoc->init_seq_number);
} else {
uint32_t vtag, itsn;
@@ -7101,17 +7126,17 @@ do_a_abort:
*/
goto new_tag;
}
- initackm_out->msg.init.initiate_tag = htonl(vtag);
+ initack->init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
itsn = sctp_select_initial_TSN(&inp->sctp_ep);
- initackm_out->msg.init.initial_tsn = htonl(itsn);
+ initack->init.initial_tsn = htonl(itsn);
SCTP_TCB_LOCK(stcb);
atomic_add_int(&asoc->refcnt, -1);
} else {
vtag = sctp_select_a_tag(inp, inp->sctp_lport, sh->src_port, 1);
- initackm_out->msg.init.initiate_tag = htonl(vtag);
+ initack->init.initiate_tag = htonl(vtag);
/* get a TSN to use too */
- initackm_out->msg.init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
+ initack->init.initial_tsn = htonl(sctp_select_initial_TSN(&inp->sctp_ep));
}
if (hold_inp_lock) {
SCTP_INP_RLOCK(inp);
@@ -7119,7 +7144,7 @@ do_a_abort:
}
}
/* save away my tag to */
- stc.my_vtag = initackm_out->msg.init.initiate_tag;
+ stc.my_vtag = initack->init.initiate_tag;
/* set up some of the credits. */
so = inp->sctp_socket;
@@ -7128,7 +7153,7 @@ do_a_abort:
sctp_m_freem(m);
return;
} else {
- initackm_out->msg.init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(so), SCTP_MINIMAL_RWND));
+ initack->init.a_rwnd = htonl(max(SCTP_SB_LIMIT_RCV(so), SCTP_MINIMAL_RWND));
}
/* set what I want */
his_limit = ntohs(init_chk->init.num_inbound_streams);
@@ -7144,17 +7169,17 @@ do_a_abort:
}
if (his_limit < i_want) {
/* I Want more :< */
- initackm_out->msg.init.num_outbound_streams = init_chk->init.num_inbound_streams;
+ initack->init.num_outbound_streams = init_chk->init.num_inbound_streams;
} else {
/* I can have what I want :> */
- initackm_out->msg.init.num_outbound_streams = htons(i_want);
+ initack->init.num_outbound_streams = htons(i_want);
}
/* tell him his limt. */
- initackm_out->msg.init.num_inbound_streams =
+ initack->init.num_inbound_streams =
htons(inp->sctp_ep.max_open_streams_intome);
/* adaptation layer indication parameter */
- ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initackm_out + sizeof(*initackm_out));
+ ali = (struct sctp_adaptation_layer_indication *)((caddr_t)initack + sizeof(*initack));
ali->ph.param_type = htons(SCTP_ULP_ADAPTATION);
ali->ph.param_length = htons(sizeof(*ali));
ali->indication = ntohl(inp->sctp_ep.adaptation_layer_indicator);
@@ -7183,7 +7208,7 @@ do_a_abort:
ph = (struct sctp_paramhdr *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
ph->param_type = htons(SCTP_HAS_NAT_SUPPORT);
ph->param_length = htons(sizeof(struct sctp_paramhdr));
- SCTP_BUF_LEN(m) += sizeof(sizeof(struct sctp_paramhdr));
+ SCTP_BUF_LEN(m) += sizeof(struct sctp_paramhdr);
}
/* And now tell the peer we do all the extensions */
pr_supported = (struct sctp_supported_chunk_types_param *)(mtod(m, caddr_t)+SCTP_BUF_LEN(m));
@@ -7317,8 +7342,7 @@ do_a_abort:
}
/* Now we must build a cookie */
- m_cookie = sctp_add_cookie(inp, init_pkt, offset, m,
- sizeof(struct sctphdr), &stc, &signature);
+ m_cookie = sctp_add_cookie(inp, init_pkt, offset, m, 0, &stc, &signature);
if (m_cookie == NULL) {
/* memory problem */
sctp_m_freem(m);
@@ -7339,7 +7363,7 @@ do_a_abort:
* Place in the size, but we don't include the last pad (if any) in
* the INIT-ACK.
*/
- initackm_out->msg.ch.chunk_length = htons((p_len - sizeof(struct sctphdr)));
+ initack->ch.chunk_length = htons(p_len);
/*
* Time to sign the cookie, we don't sign over the cookie signature
@@ -7370,11 +7394,12 @@ do_a_abort:
over_addr = &store1;
} else {
over_addr = NULL;
-
}
(void)sctp_lowlevel_chunk_output(inp, NULL, NULL, to, m, 0, NULL, 0, 0,
- 0, NULL, 0, port, SCTP_SO_NOT_LOCKED, over_addr);
+ 0, NULL, 0,
+ inp->sctp_lport, sh->src_port, init_chk->init.initiate_tag,
+ port, SCTP_SO_NOT_LOCKED, over_addr);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
@@ -9164,7 +9189,6 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
struct sctp_nets *net;
struct mbuf *outchain, *endoutchain;
struct sctp_tmit_chunk *chk, *nchk;
- struct sctphdr *shdr;
/* temp arrays for unlinking */
struct sctp_tmit_chunk *data_list[SCTP_MAX_DATA_BUNDLING];
@@ -9177,7 +9201,8 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
int tsns_sent = 0;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
- uint16_t auth_keyid = 0;
+ uint16_t auth_keyid;
+ int override_ok = 1;
int data_auth_reqd = 0;
/*
@@ -9189,6 +9214,7 @@ sctp_med_chunk_output(struct sctp_inpcb *inp,
*num_out = 0;
cwnd_full_ind = 0;
+ auth_keyid = stcb->asoc.authinfo.active_keyid;
if ((asoc->state & SCTP_STATE_SHUTDOWN_PENDING) ||
(asoc->state & SCTP_STATE_SHUTDOWN_RECEIVED) ||
@@ -9532,24 +9558,14 @@ again_one_more_time:
* it is used to do appropriate
* source address selection.
*/
- SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT);
- if (outchain == NULL) {
- /* no memory */
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
- error = ENOBUFS;
- *reason_code = 7;
- continue;
- }
- shdr = mtod(outchain, struct sctphdr *);
- shdr->src_port = inp->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
- outchain, auth_offset, auth, stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, asconf, net->port, so_locked, NULL))) {
+ outchain, auth_offset, auth,
+ stcb->asoc.authinfo.active_keyid,
+ no_fragmentflg, 0, NULL, asconf,
+ inp->sctp_lport, stcb->rport,
+ htonl(stcb->asoc.peer_vtag),
+ net->port, so_locked, NULL))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -9773,24 +9789,15 @@ again_one_more_time:
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, net);
cookie = 0;
}
- SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT);
- if (outchain == NULL) {
- /* no memory */
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
- error = ENOBUFS;
- goto error_out_again;
- }
- shdr = mtod(outchain, struct sctphdr *);
- shdr->src_port = inp->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
outchain,
- auth_offset, auth, stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, asconf, net->port, so_locked, NULL))) {
+ auth_offset, auth,
+ stcb->asoc.authinfo.active_keyid,
+ no_fragmentflg, 0, NULL, asconf,
+ inp->sctp_lport, stcb->rport,
+ htonl(stcb->asoc.peer_vtag),
+ net->port, so_locked, NULL))) {
if (error == ENOBUFS) {
asoc->ifp_had_enobuf = 1;
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -9798,7 +9805,6 @@ again_one_more_time:
if (from_where == 0) {
SCTP_STAT_INCR(sctps_lowlevelerrusr);
}
- error_out_again:
/* error, could not output */
if (hbflag) {
if (*now_filled == 0) {
@@ -9948,8 +9954,16 @@ again_one_more_time:
&auth_offset,
stcb,
SCTP_DATA);
+ auth_keyid = chk->auth_keyid;
+ override_ok = 0;
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ } else if (override_ok) {
+ /*
+ * use this data's
+ * keyid
+ */
auth_keyid = chk->auth_keyid;
+ override_ok = 0;
} else if (auth_keyid != chk->auth_keyid) {
/*
* different keyid,
@@ -10072,25 +10086,6 @@ again_one_more_time:
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
}
/* Now send it, if there is anything to send :> */
- SCTP_BUF_PREPEND(outchain, sizeof(struct sctphdr), M_DONTWAIT);
- if (outchain == NULL) {
- /* out of mbufs */
- SCTP_LTRACE_ERR_RET(inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
- error = ENOBUFS;
- goto errored_send;
- }
- shdr = mtod(outchain, struct sctphdr *);
- shdr->src_port = inp->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
- /*
- * if data auth isn't needed, use the assoc active
- * key
- */
- if (!data_auth_reqd)
- auth_keyid = stcb->asoc.authinfo.active_keyid;
if ((error = sctp_lowlevel_chunk_output(inp,
stcb,
net,
@@ -10102,7 +10097,10 @@ again_one_more_time:
no_fragmentflg,
bundle_at,
data_list[0],
- asconf, net->port, so_locked, NULL))) {
+ asconf,
+ inp->sctp_lport, stcb->rport,
+ htonl(stcb->asoc.peer_vtag),
+ net->port, so_locked, NULL))) {
/* error, we could not output */
if (error == ENOBUFS) {
SCTP_STAT_INCR(sctps_lowlevelerr);
@@ -10111,7 +10109,6 @@ again_one_more_time:
if (from_where == 0) {
SCTP_STAT_INCR(sctps_lowlevelerrusr);
}
- errored_send:
SCTPDBG(SCTP_DEBUG_OUTPUT3, "Gak send error %d\n", error);
if (hbflag) {
if (*now_filled == 0) {
@@ -10727,7 +10724,6 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
struct sctp_tmit_chunk *data_list[SCTP_MAX_DATA_BUNDLING];
struct sctp_tmit_chunk *chk, *fwd;
struct mbuf *m, *endofchain;
- struct sctphdr *shdr;
struct sctp_nets *net = NULL;
uint32_t tsns_sent = 0;
int no_fragmentflg, bundle_at, cnt_thru;
@@ -10735,7 +10731,8 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
int error, i, one_chunk, fwd_tsn, ctl_cnt, tmr_started;
struct sctp_auth_chunk *auth = NULL;
uint32_t auth_offset = 0;
- uint16_t auth_keyid = 0;
+ uint16_t auth_keyid;
+ int override_ok = 1;
int data_auth_reqd = 0;
uint32_t dmtu = 0;
@@ -10746,6 +10743,7 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
*cnt_out = 0;
fwd = NULL;
endofchain = m = NULL;
+ auth_keyid = stcb->asoc.authinfo.active_keyid;
#ifdef SCTP_AUDITING_ENABLED
sctp_audit_log(0xC3, 1);
#endif
@@ -10803,24 +10801,13 @@ sctp_chunk_retransmission(struct sctp_inpcb *inp,
sctp_timer_start(SCTP_TIMER_TYPE_COOKIE, inp, stcb, chk->whoTo);
} else if (chk->rec.chunk_id.id == SCTP_ASCONF)
sctp_timer_start(SCTP_TIMER_TYPE_ASCONF, inp, stcb, chk->whoTo);
-
- SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT);
- if (m == NULL) {
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
- return (ENOBUFS);
- }
- shdr = mtod(m, struct sctphdr *);
- shdr->src_port = inp->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
chk->snd_count++; /* update our count */
-
if ((error = sctp_lowlevel_chunk_output(inp, stcb, chk->whoTo,
(struct sockaddr *)&chk->whoTo->ro._l_addr, m,
auth_offset, auth, stcb->asoc.authinfo.active_keyid,
- no_fragmentflg, 0, NULL, 0, chk->whoTo->port, so_locked, NULL))) {
+ no_fragmentflg, 0, NULL, 0,
+ inp->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
+ chk->whoTo->port, so_locked, NULL))) {
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
}
@@ -10954,8 +10941,12 @@ one_chunk_around:
&auth_offset,
stcb,
SCTP_DATA);
+ auth_keyid = chk->auth_keyid;
+ override_ok = 0;
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ } else if (override_ok) {
auth_keyid = chk->auth_keyid;
+ override_ok = 0;
} else if (chk->auth_keyid != auth_keyid) {
/* different keyid, so done bundling */
break;
@@ -11010,8 +11001,12 @@ one_chunk_around:
&auth_offset,
stcb,
SCTP_DATA);
+ auth_keyid = fwd->auth_keyid;
+ override_ok = 0;
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
+ } else if (override_ok) {
auth_keyid = fwd->auth_keyid;
+ override_ok = 0;
} else if (fwd->auth_keyid != auth_keyid) {
/*
* different keyid,
@@ -11059,28 +11054,13 @@ one_chunk_around:
sctp_timer_start(SCTP_TIMER_TYPE_SEND, inp, stcb, net);
tmr_started = 1;
}
- SCTP_BUF_PREPEND(m, sizeof(struct sctphdr), M_DONTWAIT);
- if (m == NULL) {
- SCTP_LTRACE_ERR_RET_PKT(m, inp, stcb, net, SCTP_FROM_SCTP_OUTPUT, ENOBUFS);
- return (ENOBUFS);
- }
- shdr = mtod(m, struct sctphdr *);
- shdr->src_port = inp->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
- /*
- * if doing DATA auth, use the data chunk(s) key id,
- * otherwise use the assoc's active key id
- */
- if (!data_auth_reqd)
- auth_keyid = stcb->asoc.authinfo.active_keyid;
/* Now lets send it, if there is anything to send :> */
if ((error = sctp_lowlevel_chunk_output(inp, stcb, net,
(struct sockaddr *)&net->ro._l_addr, m,
auth_offset, auth, auth_keyid,
- no_fragmentflg, 0, NULL, 0, net->port, so_locked, NULL))) {
+ no_fragmentflg, 0, NULL, 0,
+ inp->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
+ net->port, so_locked, NULL))) {
/* error, we could not output */
SCTP_STAT_INCR(sctps_lowlevelerr);
return (error);
@@ -12401,7 +12381,6 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
int sz;
uint32_t auth_offset = 0;
struct sctp_auth_chunk *auth = NULL;
- struct sctphdr *shdr;
/*-
* Add an AUTH chunk, if chunk requires it and save the offset into
@@ -12449,23 +12428,12 @@ sctp_send_abort_tcb(struct sctp_tcb *stcb, struct mbuf *operr, int so_locked
abort->ch.chunk_flags = 0;
abort->ch.chunk_length = htons(sizeof(*abort) + sz);
- /* prepend and fill in the SCTP header */
- SCTP_BUF_PREPEND(m_out, sizeof(struct sctphdr), M_DONTWAIT);
- if (m_out == NULL) {
- /* TSNH: no memory */
- return;
- }
- shdr = mtod(m_out, struct sctphdr *);
- shdr->src_port = stcb->sctp_ep->sctp_lport;
- shdr->dest_port = stcb->rport;
- shdr->v_tag = htonl(stcb->asoc.peer_vtag);
- shdr->checksum = 0;
- auth_offset += sizeof(struct sctphdr);
-
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb,
stcb->asoc.primary_destination,
(struct sockaddr *)&stcb->asoc.primary_destination->ro._l_addr,
- m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, NULL, 0, stcb->asoc.primary_destination->port, so_locked, NULL);
+ m_out, auth_offset, auth, stcb->asoc.authinfo.active_keyid, 1, 0, NULL, 0,
+ stcb->sctp_ep->sctp_lport, stcb->rport, htonl(stcb->asoc.peer_vtag),
+ stcb->asoc.primary_destination->port, so_locked, NULL);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
@@ -12475,26 +12443,24 @@ sctp_send_shutdown_complete(struct sctp_tcb *stcb,
{
/* formulate and SEND a SHUTDOWN-COMPLETE */
struct mbuf *m_shutdown_comp;
- struct sctp_shutdown_complete_msg *comp_cp;
+ struct sctp_shutdown_complete_chunk *shutdown_complete;
- m_shutdown_comp = sctp_get_mbuf_for_msg(sizeof(struct sctp_shutdown_complete_msg), 0, M_DONTWAIT, 1, MT_HEADER);
+ m_shutdown_comp = sctp_get_mbuf_for_msg(sizeof(struct sctp_chunkhdr), 0, M_DONTWAIT, 1, MT_HEADER);
if (m_shutdown_comp == NULL) {
/* no mbuf's */
return;
}
- comp_cp = mtod(m_shutdown_comp, struct sctp_shutdown_complete_msg *);
- comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
- comp_cp->shut_cmp.ch.chunk_flags = 0;
- comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk));
- comp_cp->sh.src_port = stcb->sctp_ep->sctp_lport;
- comp_cp->sh.dest_port = stcb->rport;
- comp_cp->sh.v_tag = htonl(stcb->asoc.peer_vtag);
- comp_cp->sh.checksum = 0;
-
- SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_msg);
+ shutdown_complete = mtod(m_shutdown_comp, struct sctp_shutdown_complete_chunk *);
+ shutdown_complete->ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
+ shutdown_complete->ch.chunk_flags = 0;
+ shutdown_complete->ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk));
+ SCTP_BUF_LEN(m_shutdown_comp) = sizeof(struct sctp_shutdown_complete_chunk);
(void)sctp_lowlevel_chunk_output(stcb->sctp_ep, stcb, net,
(struct sockaddr *)&net->ro._l_addr,
- m_shutdown_comp, 0, NULL, 0, 1, 0, NULL, 0, net->port, SCTP_SO_NOT_LOCKED, NULL);
+ m_shutdown_comp, 0, NULL, 0, 1, 0, NULL, 0,
+ stcb->sctp_ep->sctp_lport, stcb->rport,
+ htonl(stcb->asoc.peer_vtag),
+ net->port, SCTP_SO_NOT_LOCKED, NULL);
SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
return;
}
@@ -12532,10 +12498,11 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
if (port) {
len += sizeof(struct udphdr);
}
- mout = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
+ mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
if (mout == NULL) {
return;
}
+ SCTP_BUF_RESV_UF(mout, max_linkhdr);
SCTP_BUF_LEN(mout) = len;
SCTP_BUF_NEXT(mout) = NULL;
iph_out = NULL;
@@ -12596,6 +12563,7 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
#endif /* INET6 */
default:
/* Currently not supported. */
+ sctp_m_freem(mout);
return;
}
if (port) {
@@ -12621,8 +12589,6 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
comp_cp->shut_cmp.ch.chunk_type = SCTP_SHUTDOWN_COMPLETE;
comp_cp->shut_cmp.ch.chunk_length = htons(sizeof(struct sctp_shutdown_complete_chunk));
- /* add checksum */
- comp_cp->sh.checksum = sctp_calculate_sum(mout, NULL, offset_out);
if (iph_out != NULL) {
sctp_route_t ro;
int ret;
@@ -12636,10 +12602,16 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
sctp_packet_log(mout, mlen);
#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
if (port) {
- SCTP_ENABLE_UDP_CSUM(o_pak);
+ comp_cp->sh.checksum = sctp_calculate_cksum(mout, offset_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ SCTP_ENABLE_UDP_CSUM(mout);
+ } else {
+ mout->m_pkthdr.csum_flags = CSUM_SCTP;
+ mout->m_pkthdr.csum_data = 0; /* FIXME MT */
+ SCTP_STAT_INCR(sctps_sendhwcrc);
}
+ SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
/* out it goes */
SCTP_IP_OUTPUT(ret, o_pak, &ro, stcb, vrf_id);
@@ -12660,6 +12632,8 @@ sctp_send_shutdown_complete2(struct mbuf *m, int iphlen, struct sctphdr *sh,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
sctp_packet_log(mout, mlen);
#endif
+ comp_cp->sh.checksum = sctp_calculate_cksum(mout, offset_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
SCTP_ATTACH_CHAIN(o_pak, mout, mlen);
if (port) {
if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr),
@@ -13493,17 +13467,22 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
break;
#endif
default:
+ if (err_cause) {
+ sctp_m_freem(err_cause);
+ }
return;
}
if (port) {
len += sizeof(struct udphdr);
}
- mout = sctp_get_mbuf_for_msg(len, 1, M_DONTWAIT, 1, MT_DATA);
+ mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
if (mout == NULL) {
- if (err_cause)
+ if (err_cause) {
sctp_m_freem(err_cause);
+ }
return;
}
+ SCTP_BUF_RESV_UF(mout, max_linkhdr);
SCTP_BUF_LEN(mout) = len;
SCTP_BUF_NEXT(mout) = err_cause;
iph_out = NULL;
@@ -13556,8 +13535,6 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
#endif /* INET6 */
default:
/* Currently not supported */
- if (err_cause)
- sctp_m_freem(err_cause);
sctp_m_freem(mout);
return;
}
@@ -13608,8 +13585,6 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
abm->msg.ch.chunk_length = htons(sizeof(abm->msg.ch));
}
- /* add checksum */
- abm->sh.checksum = sctp_calculate_sum(mout, NULL, iphlen_out);
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
/* no mbuf's */
sctp_m_freem(mout);
@@ -13637,7 +13612,13 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
#endif
SCTP_ATTACH_CHAIN(o_pak, mout, len);
if (port) {
+ abm->sh.checksum = sctp_calculate_cksum(mout, iphlen_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
SCTP_ENABLE_UDP_CSUM(o_pak);
+ } else {
+ mout->m_pkthdr.csum_flags = CSUM_SCTP;
+ mout->m_pkthdr.csum_data = 0; /* FIXME MT */
+ SCTP_STAT_INCR(sctps_sendhwcrc);
}
SCTP_IP_OUTPUT(ret, o_pak, &ro, stcb, vrf_id);
@@ -13664,6 +13645,8 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
sctp_packet_log(mout, len);
#endif
+ abm->sh.checksum = sctp_calculate_cksum(mout, iphlen_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
SCTP_ATTACH_CHAIN(o_pak, mout, len);
if (port) {
if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
@@ -13679,6 +13662,7 @@ sctp_send_abort(struct mbuf *m, int iphlen, struct sctphdr *sh, uint32_t vtag,
#endif
SCTP_STAT_INCR(sctps_sendpackets);
SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
void
@@ -13686,211 +13670,219 @@ sctp_send_operr_to(struct mbuf *m, int iphlen, struct mbuf *scm, uint32_t vtag,
uint32_t vrf_id, uint16_t port)
{
struct mbuf *o_pak;
- struct sctphdr *ihdr;
- int retcode;
- struct sctphdr *ohdr;
- struct sctp_chunkhdr *ophdr;
- struct ip *iph;
+ struct sctphdr *sh, *sh_out;
+ struct sctp_chunkhdr *ch;
+ struct ip *iph, *iph_out;
struct udphdr *udp = NULL;
struct mbuf *mout;
#ifdef INET6
-#ifdef SCTP_DEBUG
- struct sockaddr_in6 lsa6, fsa6;
+ struct ip6_hdr *ip6, *ip6_out;
#endif
-#endif
- uint32_t val;
- struct mbuf *at;
- int len;
+ int iphlen_out, len;
iph = mtod(m, struct ip *);
- ihdr = (struct sctphdr *)((caddr_t)iph + iphlen);
-
- SCTP_BUF_PREPEND(scm, (sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr)), M_DONTWAIT);
- if (scm == NULL) {
- /* can't send because we can't add a mbuf */
+ sh = (struct sctphdr *)((caddr_t)iph + iphlen);
+ switch (iph->ip_v) {
+ case IPVERSION:
+ len = (sizeof(struct ip) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr));
+ break;
+#ifdef INET6
+ case IPV6_VERSION >> 4:
+ len = (sizeof(struct ip6_hdr) + sizeof(struct sctphdr) + sizeof(struct sctp_chunkhdr));
+ break;
+#endif
+ default:
+ if (scm) {
+ sctp_m_freem(scm);
+ }
return;
}
- ohdr = mtod(scm, struct sctphdr *);
- ohdr->src_port = ihdr->dest_port;
- ohdr->dest_port = ihdr->src_port;
- ohdr->v_tag = vtag;
- ohdr->checksum = 0;
- ophdr = (struct sctp_chunkhdr *)(ohdr + 1);
- ophdr->chunk_type = SCTP_OPERATION_ERROR;
- ophdr->chunk_flags = 0;
- len = 0;
- at = scm;
- while (at) {
- len += SCTP_BUF_LEN(at);
- at = SCTP_BUF_NEXT(at);
+ if (port) {
+ len += sizeof(struct udphdr);
}
- ophdr->chunk_length = htons(len - sizeof(struct sctphdr));
- if (len % 4) {
- /* need padding */
- uint32_t cpthis = 0;
- int padlen;
-
- padlen = 4 - (len % 4);
- m_copyback(scm, len, padlen, (caddr_t)&cpthis);
- len += padlen;
+ mout = sctp_get_mbuf_for_msg(len + max_linkhdr, 1, M_DONTWAIT, 1, MT_DATA);
+ if (mout == NULL) {
+ if (scm) {
+ sctp_m_freem(scm);
+ }
+ return;
}
- val = sctp_calculate_sum(scm, NULL, 0);
+ SCTP_BUF_RESV_UF(mout, max_linkhdr);
+ SCTP_BUF_LEN(mout) = len;
+ SCTP_BUF_NEXT(mout) = scm;
+ iph_out = NULL;
#ifdef INET6
- if (port) {
- mout = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA);
- } else {
- mout = sctp_get_mbuf_for_msg(sizeof(struct ip6_hdr), 1, M_DONTWAIT, 1, MT_DATA);
+ ip6_out = NULL;
+#endif
+ switch (iph->ip_v) {
+ case IPVERSION:
+ iph_out = mtod(mout, struct ip *);
+
+ /* Fill in the IP header for the ABORT */
+ iph_out->ip_v = IPVERSION;
+ iph_out->ip_hl = (sizeof(struct ip) / 4);
+ iph_out->ip_tos = (u_char)0;
+ iph_out->ip_id = 0;
+ iph_out->ip_off = 0;
+ iph_out->ip_ttl = MAXTTL;
+ if (port) {
+ iph_out->ip_p = IPPROTO_UDP;
+ } else {
+ iph_out->ip_p = IPPROTO_SCTP;
+ }
+ iph_out->ip_src.s_addr = iph->ip_dst.s_addr;
+ iph_out->ip_dst.s_addr = iph->ip_src.s_addr;
+ /* let IP layer calculate this */
+ iph_out->ip_sum = 0;
+
+ iphlen_out = sizeof(struct ip);
+ sh_out = (struct sctphdr *)((caddr_t)iph_out + iphlen_out);
+ break;
+#ifdef INET6
+ case IPV6_VERSION >> 4:
+ ip6 = (struct ip6_hdr *)iph;
+ ip6_out = mtod(mout, struct ip6_hdr *);
+
+ /* Fill in the IP6 header for the ABORT */
+ ip6_out->ip6_flow = ip6->ip6_flow;
+ ip6_out->ip6_hlim = MODULE_GLOBAL(MOD_INET6, ip6_defhlim);
+ if (port) {
+ ip6_out->ip6_nxt = IPPROTO_UDP;
+ } else {
+ ip6_out->ip6_nxt = IPPROTO_SCTP;
+ }
+ ip6_out->ip6_src = ip6->ip6_dst;
+ ip6_out->ip6_dst = ip6->ip6_src;
+
+ iphlen_out = sizeof(struct ip6_hdr);
+ sh_out = (struct sctphdr *)((caddr_t)ip6_out + iphlen_out);
+ break;
+#endif /* INET6 */
+ default:
+ /* Currently not supported */
+ sctp_m_freem(mout);
+ return;
}
-#else
+
+ udp = (struct udphdr *)sh_out;
if (port) {
- mout = sctp_get_mbuf_for_msg(sizeof(struct ip) + sizeof(struct udphdr), 1, M_DONTWAIT, 1, MT_DATA);
- } else {
- mout = sctp_get_mbuf_for_msg(sizeof(struct ip), 1, M_DONTWAIT, 1, MT_DATA);
+ udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
+ udp->uh_dport = port;
+ /* set udp->uh_ulen later */
+ udp->uh_sum = 0;
+ iphlen_out += sizeof(struct udphdr);
+ sh_out = (struct sctphdr *)((caddr_t)udp + sizeof(struct udphdr));
}
-#endif
- if (mout == NULL) {
- sctp_m_freem(scm);
- return;
+ sh_out->src_port = sh->dest_port;
+ sh_out->dest_port = sh->src_port;
+ sh_out->v_tag = vtag;
+ sh_out->checksum = 0;
+
+ ch = (struct sctp_chunkhdr *)((caddr_t)sh_out + sizeof(struct sctphdr));
+ ch->chunk_type = SCTP_OPERATION_ERROR;
+ ch->chunk_flags = 0;
+
+ if (scm) {
+ struct mbuf *m_tmp = scm;
+ int cause_len = 0;
+
+ /* get length of the err_cause chain */
+ while (m_tmp != NULL) {
+ cause_len += SCTP_BUF_LEN(m_tmp);
+ m_tmp = SCTP_BUF_NEXT(m_tmp);
+ }
+ len = SCTP_BUF_LEN(mout) + cause_len;
+ if (cause_len % 4) {
+ /* need pad at end of chunk */
+ uint32_t cpthis = 0;
+ int padlen;
+
+ padlen = 4 - (len % 4);
+ m_copyback(mout, len, padlen, (caddr_t)&cpthis);
+ len += padlen;
+ }
+ ch->chunk_length = htons(sizeof(struct sctp_chunkhdr) + cause_len);
+ } else {
+ len = SCTP_BUF_LEN(mout);
+ ch->chunk_length = htons(sizeof(struct sctp_chunkhdr));
}
- SCTP_BUF_NEXT(mout) = scm;
+
if (SCTP_GET_HEADER_FOR_OUTPUT(o_pak)) {
+ /* no mbuf's */
sctp_m_freem(mout);
return;
}
- ohdr->checksum = val;
- switch (iph->ip_v) {
- case IPVERSION:
- {
- /* V4 */
- struct ip *out;
- sctp_route_t ro;
- struct sctp_tcb *stcb = NULL;
-
- SCTP_BUF_LEN(mout) = sizeof(struct ip);
- len += sizeof(struct ip);
- if (port) {
- SCTP_BUF_LEN(mout) += sizeof(struct udphdr);
- len += sizeof(struct udphdr);
- }
- bzero(&ro, sizeof ro);
- out = mtod(mout, struct ip *);
- out->ip_v = iph->ip_v;
- out->ip_hl = (sizeof(struct ip) / 4);
- out->ip_tos = iph->ip_tos;
- out->ip_id = iph->ip_id;
- out->ip_off = 0;
- out->ip_ttl = MAXTTL;
- if (port) {
- out->ip_p = IPPROTO_UDP;
- } else {
- out->ip_p = IPPROTO_SCTP;
- }
- out->ip_sum = 0;
- out->ip_src = iph->ip_dst;
- out->ip_dst = iph->ip_src;
- out->ip_len = len;
- if (port) {
- udp = (struct udphdr *)(out + 1);
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- udp->uh_ulen = htons(len - sizeof(struct ip));
- udp->uh_sum = in_pseudo(out->ip_src.s_addr, out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
- }
+ if (iph_out != NULL) {
+ sctp_route_t ro;
+ struct sctp_tcb *stcb = NULL;
+ int ret;
+
+ /* zap the stack pointer to the route */
+ bzero(&ro, sizeof ro);
+ if (port) {
+ udp->uh_ulen = htons(len - sizeof(struct ip));
+ udp->uh_sum = in_pseudo(iph_out->ip_src.s_addr, iph_out->ip_dst.s_addr, udp->uh_ulen + htons(IPPROTO_UDP));
+ }
+ /* set IPv4 length */
+ iph_out->ip_len = len;
+ /* out it goes */
#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
+ sctp_packet_log(mout, len);
#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
- SCTP_ENABLE_UDP_CSUM(o_pak);
- }
- SCTP_IP_OUTPUT(retcode, o_pak, &ro, stcb, vrf_id);
-
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- break;
+ SCTP_ATTACH_CHAIN(o_pak, mout, len);
+ if (port) {
+ sh_out->checksum = sctp_calculate_cksum(mout, iphlen_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ SCTP_ENABLE_UDP_CSUM(o_pak);
+ } else {
+ mout->m_pkthdr.csum_flags = CSUM_SCTP;
+ mout->m_pkthdr.csum_data = 0; /* FIXME MT */
+ SCTP_STAT_INCR(sctps_sendhwcrc);
}
+ SCTP_IP_OUTPUT(ret, o_pak, &ro, stcb, vrf_id);
+
+ /* Free the route if we got one back */
+ if (ro.ro_rt)
+ RTFREE(ro.ro_rt);
+ }
#ifdef INET6
- case IPV6_VERSION >> 4:
- {
- /* V6 */
- struct route_in6 ro;
- int ret;
- struct sctp_tcb *stcb = NULL;
- struct ifnet *ifp = NULL;
- struct ip6_hdr *out6, *in6;
-
- SCTP_BUF_LEN(mout) = sizeof(struct ip6_hdr);
- len += sizeof(struct ip6_hdr);
- bzero(&ro, sizeof ro);
- if (port) {
- SCTP_BUF_LEN(mout) += sizeof(struct udphdr);
- len += sizeof(struct udphdr);
- }
- in6 = mtod(m, struct ip6_hdr *);
- out6 = mtod(mout, struct ip6_hdr *);
- out6->ip6_flow = in6->ip6_flow;
- out6->ip6_hlim = MODULE_GLOBAL(MOD_INET6, ip6_defhlim);
- if (port) {
- out6->ip6_nxt = IPPROTO_UDP;
- } else {
- out6->ip6_nxt = IPPROTO_SCTP;
- }
- out6->ip6_src = in6->ip6_dst;
- out6->ip6_dst = in6->ip6_src;
- out6->ip6_plen = len - sizeof(struct ip6_hdr);
- if (port) {
- udp = (struct udphdr *)(out6 + 1);
- udp->uh_sport = htons(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port));
- udp->uh_dport = port;
- udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
- udp->uh_sum = 0;
- }
-#ifdef SCTP_DEBUG
- bzero(&lsa6, sizeof(lsa6));
- lsa6.sin6_len = sizeof(lsa6);
- lsa6.sin6_family = AF_INET6;
- lsa6.sin6_addr = out6->ip6_src;
- bzero(&fsa6, sizeof(fsa6));
- fsa6.sin6_len = sizeof(fsa6);
- fsa6.sin6_family = AF_INET6;
- fsa6.sin6_addr = out6->ip6_dst;
-#endif
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "sctp_operr_to calling ipv6 output:\n");
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "src: ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&lsa6);
- SCTPDBG(SCTP_DEBUG_OUTPUT2, "dst ");
- SCTPDBG_ADDR(SCTP_DEBUG_OUTPUT2, (struct sockaddr *)&fsa6);
+ if (ip6_out != NULL) {
+ struct route_in6 ro;
+ int ret;
+ struct sctp_tcb *stcb = NULL;
+ struct ifnet *ifp = NULL;
+ /* zap the stack pointer to the route */
+ bzero(&ro, sizeof(ro));
+ if (port) {
+ udp->uh_ulen = htons(len - sizeof(struct ip6_hdr));
+ }
+ ip6_out->ip6_plen = len - sizeof(*ip6_out);
#ifdef SCTP_PACKET_LOGGING
- if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
- sctp_packet_log(mout, len);
+ if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_LAST_PACKET_TRACING)
+ sctp_packet_log(mout, len);
#endif
- SCTP_ATTACH_CHAIN(o_pak, mout, len);
- if (port) {
- if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
- udp->uh_sum = 0xffff;
- }
+ sh_out->checksum = sctp_calculate_cksum(mout, iphlen_out);
+ SCTP_STAT_INCR(sctps_sendswcrc);
+ SCTP_ATTACH_CHAIN(o_pak, mout, len);
+ if (port) {
+ if ((udp->uh_sum = in6_cksum(o_pak, IPPROTO_UDP, sizeof(struct ip6_hdr), len - sizeof(struct ip6_hdr))) == 0) {
+ udp->uh_sum = 0xffff;
}
- SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id);
-
- SCTP_STAT_INCR(sctps_sendpackets);
- SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
- /* Free the route if we got one back */
- if (ro.ro_rt)
- RTFREE(ro.ro_rt);
- break;
}
-#endif /* INET6 */
- default:
- /* TSNH */
- break;
+ SCTP_IP6_OUTPUT(ret, o_pak, &ro, &ifp, stcb, vrf_id);
+
+ /* Free the route if we got one back */
+ if (ro.ro_rt)
+ RTFREE(ro.ro_rt);
}
+#endif
+ SCTP_STAT_INCR(sctps_sendpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_outpackets);
+ SCTP_STAT_INCR_COUNTER64(sctps_outcontrolchunks);
}
static struct mbuf *
diff --git a/sys/netinet/sctp_pcb.c b/sys/netinet/sctp_pcb.c
index 5f05dcd..291509e 100644
--- a/sys/netinet/sctp_pcb.c
+++ b/sys/netinet/sctp_pcb.c
@@ -2504,7 +2504,9 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
/* Pull the tcb from the old association */
LIST_REMOVE(stcb, sctp_tcbhash);
LIST_REMOVE(stcb, sctp_tcblist);
-
+ if (stcb->asoc.in_asocid_hash) {
+ LIST_REMOVE(stcb, sctp_tcbasocidhash);
+ }
/* Now insert the new_inp into the TCP connected hash */
head = &SCTP_BASE_INFO(sctp_tcpephash)[SCTP_PCBHASH_ALLADDR((lport),
SCTP_BASE_INFO(hashtcpmark))];
@@ -2520,7 +2522,13 @@ sctp_move_pcb_and_assoc(struct sctp_inpcb *old_inp, struct sctp_inpcb *new_inp,
* only have one connection? Probably not :> so lets get rid of it
* and not suck up any kernel memory in that.
*/
+ if (stcb->asoc.in_asocid_hash) {
+ struct sctpasochead *lhd;
+ lhd = &new_inp->sctp_asocidhash[SCTP_PCBHASH_ASOC(stcb->asoc.assoc_id,
+ new_inp->hashasocidmark)];
+ LIST_INSERT_HEAD(lhd, stcb, sctp_tcbasocidhash);
+ }
/* Ok. Let's restart timer. */
TAILQ_FOREACH(net, &stcb->asoc.nets, sctp_next) {
sctp_timer_start(SCTP_TIMER_TYPE_PATHMTURAISE, new_inp,
@@ -4652,7 +4660,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
/* pull from vtag hash */
LIST_REMOVE(stcb, sctp_asocs);
- sctp_add_vtag_to_timewait(asoc->my_vtag, inp->sctp_lport, stcb->rport, SCTP_TIME_WAIT);
+ sctp_add_vtag_to_timewait(asoc->my_vtag, SCTP_TIME_WAIT, inp->sctp_lport, stcb->rport);
/*
* Now restop the timers to be sure - this is paranoia at is finest!
@@ -4763,7 +4771,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/*
- if(ccnt) {
+ if (ccnt) {
printf("Freed %d from send_queue\n", ccnt);
ccnt = 0;
}
@@ -4788,7 +4796,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/*
- if(ccnt) {
+ if (ccnt) {
printf("Freed %d from sent_queue\n", ccnt);
ccnt = 0;
}
@@ -4813,7 +4821,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/*
- if(ccnt) {
+ if (ccnt) {
printf("Freed %d from ctrl_queue\n", ccnt);
ccnt = 0;
}
@@ -4839,7 +4847,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/*
- if(ccnt) {
+ if (ccnt) {
printf("Freed %d from asconf_queue\n", ccnt);
ccnt = 0;
}
@@ -4863,7 +4871,7 @@ sctp_free_assoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb, int from_inpcbfre
}
}
/*
- if(ccnt) {
+ if (ccnt) {
printf("Freed %d from reasm_queue\n", ccnt);
ccnt = 0;
}
@@ -5776,7 +5784,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
/* ok get the v4 address and check/add */
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&p4_buf, sizeof(p4_buf));
+ (struct sctp_paramhdr *)&p4_buf,
+ sizeof(p4_buf));
if (plen != sizeof(struct sctp_ipv4addr_param) ||
phdr == NULL) {
return (-5);
@@ -5858,7 +5867,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
struct sctp_ipv6addr_param *p6, p6_buf;
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&p6_buf, sizeof(p6_buf));
+ (struct sctp_paramhdr *)&p6_buf,
+ sizeof(p6_buf));
if (plen != sizeof(struct sctp_ipv6addr_param) ||
phdr == NULL) {
return (-14);
@@ -5883,8 +5893,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
stcb_tmp = sctp_findassociation_ep_addr(&inp, sa, &net,
local_sa, stcb);
atomic_add_int(&stcb->asoc.refcnt, -1);
- if (stcb_tmp == NULL && (inp == stcb->sctp_ep ||
- inp == NULL)) {
+ if (stcb_tmp == NULL &&
+ (inp == stcb->sctp_ep || inp == NULL)) {
/*
* we must validate the state again
* here
@@ -5965,7 +5975,8 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
return (-23);
}
phdr = sctp_get_next_param(m, offset,
- (struct sctp_paramhdr *)&lstore, min(plen, sizeof(lstore)));
+ (struct sctp_paramhdr *)&lstore,
+ min(plen, sizeof(lstore)));
if (phdr == NULL) {
return (-24);
}
@@ -6154,6 +6165,7 @@ sctp_load_addresses_from_init(struct sctp_tcb *stcb, struct mbuf *m,
break;
}
}
+
next_param:
offset += SCTP_SIZE32(plen);
if (offset >= limit) {
@@ -6206,8 +6218,10 @@ next_param:
bcopy(p_random->random_data, new_key->key, random_len);
}
#else
- keylen = sizeof(*p_random) + random_len + sizeof(*chunks) + num_chunks +
- sizeof(*hmacs) + hmacs_len;
+ keylen = sizeof(*p_random) + random_len + sizeof(*hmacs) + hmacs_len;
+ if (chunks != NULL) {
+ keylen += sizeof(*chunks) + num_chunks;
+ }
new_key = sctp_alloc_key(keylen);
if (new_key != NULL) {
/* copy in the RANDOM */
@@ -6343,6 +6357,8 @@ skip_vtag_check:
/* Audit expires this guy */
twait_block->vtag_block[i].tv_sec_at_expire = 0;
twait_block->vtag_block[i].v_tag = 0;
+ twait_block->vtag_block[i].lport = 0;
+ twait_block->vtag_block[i].rport = 0;
} else if ((twait_block->vtag_block[i].v_tag == tag) &&
(twait_block->vtag_block[i].lport == lport) &&
(twait_block->vtag_block[i].rport == rport)) {
diff --git a/sys/netinet/sctp_pcb.h b/sys/netinet/sctp_pcb.h
index 66c5f7b..684ed5a 100644
--- a/sys/netinet/sctp_pcb.h
+++ b/sys/netinet/sctp_pcb.h
@@ -144,6 +144,7 @@ struct sctp_tagblock {
struct sctp_epinfo {
+ struct socket *udp_tun_socket;
struct sctpasochead *sctp_asochash;
u_long hashasocmark;
diff --git a/sys/netinet/sctp_sysctl.c b/sys/netinet/sctp_sysctl.c
index 6703daf..bcba5b5 100644
--- a/sys/netinet/sctp_sysctl.c
+++ b/sys/netinet/sctp_sysctl.c
@@ -120,6 +120,7 @@ sctp_init_sysctls()
#endif
}
+
/* It returns an upper limit. No filtering is done here */
static unsigned int
number_of_addresses(struct sctp_inpcb *inp)
@@ -408,6 +409,8 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
xstcb.primary_addr = stcb->asoc.primary_destination->ro._l_addr;
xstcb.heartbeat_interval = stcb->asoc.heart_beat_delay;
xstcb.state = SCTP_GET_STATE(&stcb->asoc); /* FIXME */
+ /* 7.0 does not support this */
+ xstcb.assoc_id = sctp_get_associd(stcb);
xstcb.in_streams = stcb->asoc.streamincnt;
xstcb.out_streams = stcb->asoc.streamoutcnt;
xstcb.max_nr_retrans = stcb->asoc.overall_error_count;
@@ -506,7 +509,6 @@ sctp_assoclist(SYSCTL_HANDLER_ARGS)
}
-
#define RANGECHK(var, min, max) \
if ((var) < (min)) { (var) = (min); } \
else if ((var) > (max)) { (var) = (max); }
@@ -517,10 +519,17 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
int error;
uint32_t old_sctp_udp_tunneling_port;
+ SCTP_INP_INFO_RLOCK();
old_sctp_udp_tunneling_port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
+ SCTP_INP_INFO_RUNLOCK();
error = sysctl_handle_int(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
if (error == 0) {
RANGECHK(SCTP_BASE_SYSCTL(sctp_udp_tunneling_port), SCTPCTL_UDP_TUNNELING_PORT_MIN, SCTPCTL_UDP_TUNNELING_PORT_MAX);
+ if (old_sctp_udp_tunneling_port == SCTP_BASE_SYSCTL(sctp_udp_tunneling_port)) {
+ error = 0;
+ goto out;
+ }
+ SCTP_INP_INFO_WLOCK();
if (old_sctp_udp_tunneling_port) {
sctp_over_udp_stop();
}
@@ -529,7 +538,9 @@ sysctl_sctp_udp_tunneling_check(SYSCTL_HANDLER_ARGS)
SCTP_BASE_SYSCTL(sctp_udp_tunneling_port) = 0;
}
}
+ SCTP_INP_INFO_WUNLOCK();
}
+out:
return (error);
}
@@ -624,14 +635,15 @@ sysctl_sctp_check(SYSCTL_HANDLER_ARGS)
static int
sysctl_sctp_cleartrace(SYSCTL_HANDLER_ARGS)
{
+ int error = 0;
+
memset(&SCTP_BASE_SYSCTL(sctp_log), 0, sizeof(struct sctp_log));
- return (0);
+ return (error);
}
#endif
-
/*
* sysctl definitions
*/
diff --git a/sys/netinet/sctp_uio.h b/sys/netinet/sctp_uio.h
index 46e604f..27597ba 100644
--- a/sys/netinet/sctp_uio.h
+++ b/sys/netinet/sctp_uio.h
@@ -804,6 +804,10 @@ struct sctpstat {
uint32_t sctps_recvexpress; /* total fast path receives all one
* chunk */
uint32_t sctps_recvexpressm; /* total fast path multi-part data */
+ uint32_t sctps_recvnocrc;
+ uint32_t sctps_recvswcrc;
+ uint32_t sctps_recvhwcrc;
+
/* output statistics: */
uint32_t sctps_sendpackets; /* total output packets */
uint32_t sctps_sendsacks; /* total output SACKs */
@@ -820,6 +824,9 @@ struct sctpstat {
uint32_t sctps_sendecne;/* total output ECNE chunks */
uint32_t sctps_sendauth;/* total output AUTH chunks FIXME */
uint32_t sctps_senderrors; /* ip_output error counter */
+ uint32_t sctps_sendnocrc;
+ uint32_t sctps_sendswcrc;
+ uint32_t sctps_sendhwcrc;
/* PCKDROPREP statistics: */
uint32_t sctps_pdrpfmbox; /* Packet drop from middle box */
uint32_t sctps_pdrpfehos; /* P-drop from end host */
@@ -1009,6 +1016,7 @@ struct xsctp_tcb {
uint16_t remote_port; /* sctpAssocEntry 4 */
struct sctp_timeval start_time; /* sctpAssocEntry 16 */
struct sctp_timeval discontinuity_time; /* sctpAssocEntry 17 */
+ sctp_assoc_t assoc_id; /* sctpAssocEntry 1 */
};
struct xsctp_laddr {
diff --git a/sys/netinet/sctp_usrreq.c b/sys/netinet/sctp_usrreq.c
index c642762..9d04f56 100644
--- a/sys/netinet/sctp_usrreq.c
+++ b/sys/netinet/sctp_usrreq.c
@@ -908,6 +908,7 @@ sctp_disconnect(struct socket *so)
sctp_chunk_output(inp, stcb, SCTP_OUTPUT_FROM_CLOSING, SCTP_SO_LOCKED);
}
}
+ soisdisconnecting(so);
SCTP_TCB_UNLOCK(stcb);
SCTP_INP_RUNLOCK(inp);
return (0);
@@ -980,6 +981,11 @@ sctp_shutdown(struct socket *so)
struct sctp_tcb *stcb;
struct sctp_association *asoc;
+ if ((so->so_state &
+ (SS_ISCONNECTED | SS_ISCONNECTING | SS_ISDISCONNECTING)) == 0) {
+ SCTP_INP_RUNLOCK(inp);
+ return (ENOTCONN);
+ }
socantsendmore(so);
stcb = LIST_FIRST(&inp->sctp_asoc_list);
@@ -3515,6 +3521,22 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
if (events->sctp_sender_dry_event) {
sctp_feature_on(inp, SCTP_PCB_FLAGS_DRYEVNT);
+ if ((inp->sctp_flags & SCTP_PCB_FLAGS_TCPTYPE) ||
+ (inp->sctp_flags & SCTP_PCB_FLAGS_IN_TCPPOOL)) {
+ stcb = LIST_FIRST(&inp->sctp_asoc_list);
+ if (stcb) {
+ SCTP_TCB_LOCK(stcb);
+ }
+ if (stcb &&
+ TAILQ_EMPTY(&stcb->asoc.send_queue) &&
+ TAILQ_EMPTY(&stcb->asoc.sent_queue) &&
+ (stcb->asoc.stream_queue_cnt == 0)) {
+ sctp_ulp_notify(SCTP_NOTIFY_SENDER_DRY, stcb, 0, NULL, SCTP_SO_LOCKED);
+ }
+ if (stcb) {
+ SCTP_TCB_UNLOCK(stcb);
+ }
+ }
} else {
sctp_feature_off(inp, SCTP_PCB_FLAGS_DRYEVNT);
}
diff --git a/sys/netinet/sctputil.c b/sys/netinet/sctputil.c
index ce06853..ac13717 100644
--- a/sys/netinet/sctputil.c
+++ b/sys/netinet/sctputil.c
@@ -44,7 +44,6 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_output.h>
#include <netinet/sctp_uio.h>
#include <netinet/sctp_timer.h>
-#include <netinet/sctp_crc32.h>
#include <netinet/sctp_indata.h>/* for sctp_deliver_data() */
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
@@ -53,9 +52,15 @@ __FBSDID("$FreeBSD$");
#define NUMBER_OF_MTU_SIZES 18
+#if defined(__Windows__) && !defined(SCTP_LOCAL_TRACE_BUF)
+#include "eventrace_netinet.h"
+#include "sctputil.tmh" /* this is the file that will be auto
+ * generated */
+#else
#ifndef KTR_SCTP
#define KTR_SCTP KTR_SUBSYS
#endif
+#endif
void
sctp_sblog(struct sockbuf *sb,
@@ -2458,48 +2463,6 @@ sctp_timer_stop(int t_type, struct sctp_inpcb *inp, struct sctp_tcb *stcb,
return;
}
-#ifdef SCTP_USE_ADLER32
-static uint32_t
-update_adler32(uint32_t adler, uint8_t * buf, int32_t len)
-{
- uint32_t s1 = adler & 0xffff;
- uint32_t s2 = (adler >> 16) & 0xffff;
- int n;
-
- for (n = 0; n < len; n++, buf++) {
- /* s1 = (s1 + buf[n]) % BASE */
- /* first we add */
- s1 = (s1 + *buf);
- /*
- * now if we need to, we do a mod by subtracting. It seems a
- * bit faster since I really will only ever do one subtract
- * at the MOST, since buf[n] is a max of 255.
- */
- if (s1 >= SCTP_ADLER32_BASE) {
- s1 -= SCTP_ADLER32_BASE;
- }
- /* s2 = (s2 + s1) % BASE */
- /* first we add */
- s2 = (s2 + s1);
- /*
- * again, it is more efficent (it seems) to subtract since
- * the most s2 will ever be is (BASE-1 + BASE-1) in the
- * worse case. This would then be (2 * BASE) - 2, which will
- * still only do one subtract. On Intel this is much better
- * to do this way and avoid the divide. Have not -pg'd on
- * sparc.
- */
- if (s2 >= SCTP_ADLER32_BASE) {
- s2 -= SCTP_ADLER32_BASE;
- }
- }
- /* Return the adler32 of the bytes buf[0..len-1] */
- return ((s2 << 16) + s1);
-}
-
-#endif
-
-
uint32_t
sctp_calculate_len(struct mbuf *m)
{
@@ -2514,132 +2477,6 @@ sctp_calculate_len(struct mbuf *m)
return (tlen);
}
-#if defined(SCTP_WITH_NO_CSUM)
-
-uint32_t
-sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
-{
- /*
- * given a mbuf chain with a packetheader offset by 'offset'
- * pointing at a sctphdr (with csum set to 0) go through the chain
- * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
- * has a side bonus as it will calculate the total length of the
- * mbuf chain. Note: if offset is greater than the total mbuf
- * length, checksum=1, pktlen=0 is returned (ie. no real error code)
- */
- if (pktlen == NULL)
- return (0);
- *pktlen = sctp_calculate_len(m);
- return (0);
-}
-
-#elif defined(SCTP_USE_INCHKSUM)
-
-#include <machine/in_cksum.h>
-
-uint32_t
-sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
-{
- /*
- * given a mbuf chain with a packetheader offset by 'offset'
- * pointing at a sctphdr (with csum set to 0) go through the chain
- * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
- * has a side bonus as it will calculate the total length of the
- * mbuf chain. Note: if offset is greater than the total mbuf
- * length, checksum=1, pktlen=0 is returned (ie. no real error code)
- */
- int32_t tlen = 0;
- struct mbuf *at;
- uint32_t the_sum, retsum;
-
- at = m;
- while (at) {
- tlen += SCTP_BUF_LEN(at);
- at = SCTP_BUF_NEXT(at);
- }
- the_sum = (uint32_t) (in_cksum_skip(m, tlen, offset));
- if (pktlen != NULL)
- *pktlen = (tlen - offset);
- retsum = htons(the_sum);
- return (the_sum);
-}
-
-#else
-
-uint32_t
-sctp_calculate_sum(struct mbuf *m, int32_t * pktlen, uint32_t offset)
-{
- /*
- * given a mbuf chain with a packetheader offset by 'offset'
- * pointing at a sctphdr (with csum set to 0) go through the chain
- * of SCTP_BUF_NEXT()'s and calculate the SCTP checksum. This also
- * has a side bonus as it will calculate the total length of the
- * mbuf chain. Note: if offset is greater than the total mbuf
- * length, checksum=1, pktlen=0 is returned (ie. no real error code)
- */
- int32_t tlen = 0;
-
-#ifdef SCTP_USE_ADLER32
- uint32_t base = 1L;
-
-#else
- uint32_t base = 0xffffffff;
-
-#endif
- struct mbuf *at;
-
- at = m;
- /* find the correct mbuf and offset into mbuf */
- while ((at != NULL) && (offset > (uint32_t) SCTP_BUF_LEN(at))) {
- offset -= SCTP_BUF_LEN(at); /* update remaining offset
- * left */
- at = SCTP_BUF_NEXT(at);
- }
- while (at != NULL) {
- if ((SCTP_BUF_LEN(at) - offset) > 0) {
-#ifdef SCTP_USE_ADLER32
- base = update_adler32(base,
- (unsigned char *)(SCTP_BUF_AT(at, offset)),
- (unsigned int)(SCTP_BUF_LEN(at) - offset));
-#else
- if ((SCTP_BUF_LEN(at) - offset) < 4) {
- /* Use old method if less than 4 bytes */
- base = old_update_crc32(base,
- (unsigned char *)(SCTP_BUF_AT(at, offset)),
- (unsigned int)(SCTP_BUF_LEN(at) - offset));
- } else {
- base = update_crc32(base,
- (unsigned char *)(SCTP_BUF_AT(at, offset)),
- (unsigned int)(SCTP_BUF_LEN(at) - offset));
- }
-#endif
- tlen += SCTP_BUF_LEN(at) - offset;
- /* we only offset once into the first mbuf */
- }
- if (offset) {
- if (offset < (uint32_t) SCTP_BUF_LEN(at))
- offset = 0;
- else
- offset -= SCTP_BUF_LEN(at);
- }
- at = SCTP_BUF_NEXT(at);
- }
- if (pktlen != NULL) {
- *pktlen = tlen;
- }
-#ifdef SCTP_USE_ADLER32
- /* Adler32 */
- base = htonl(base);
-#else
- /* CRC-32c */
- base = sctp_csum_finalize(base);
-#endif
- return (base);
-}
-
-
-#endif
-
void
sctp_mtu_size_reset(struct sctp_inpcb *inp,
struct sctp_association *asoc, uint32_t mtu)
@@ -3428,7 +3265,6 @@ sctp_notify_shutdown_event(struct sctp_tcb *stcb)
}
#endif
socantsendmore(stcb->sctp_socket);
- socantrcvmore(stcb->sctp_socket);
#if defined (__APPLE__) || defined(SCTP_SO_LOCK_TESTING)
SCTP_SOCKET_UNLOCK(so, 1);
#endif
@@ -3596,6 +3432,9 @@ sctp_ulp_notify(uint32_t notification, struct sctp_tcb *stcb,
/* If the socket is gone we are out of here */
return;
}
+ if (stcb->sctp_socket->so_rcv.sb_state & SBS_CANTRCVMORE) {
+ return;
+ }
if (stcb && ((stcb->asoc.state & SCTP_STATE_COOKIE_WAIT) ||
(stcb->asoc.state & SCTP_STATE_COOKIE_ECHOED))) {
if ((notification == SCTP_NOTIFY_INTERFACE_DOWN) ||
@@ -6708,14 +6547,163 @@ sctp_log_trace(uint32_t subsys, const char *str SCTP_UNUSED, uint32_t a, uint32_
* so we can do UDP tunneling. In
* the mean-time, we return error
*/
+#include <netinet/udp.h>
+#include <netinet/udp_var.h>
+#include <sys/proc.h>
+#include <netinet6/sctp6_var.h>
+
+static void
+sctp_recv_udp_tunneled_packet(struct mbuf *m, int off, struct inpcb *ignored)
+{
+ struct ip *iph;
+ struct mbuf *sp, *last;
+ struct udphdr *uhdr;
+ uint16_t port = 0, len;
+ int header_size = sizeof(struct udphdr) + sizeof(struct sctphdr);
+
+ /*
+ * Split out the mbuf chain. Leave the IP header in m, place the
+ * rest in the sp.
+ */
+ if ((m->m_flags & M_PKTHDR) == 0) {
+ /* Can't handle one that is not a pkt hdr */
+ goto out;
+ }
+ /* pull the src port */
+ iph = mtod(m, struct ip *);
+ uhdr = (struct udphdr *)((caddr_t)iph + off);
+
+ port = uhdr->uh_sport;
+ sp = m_split(m, off, M_DONTWAIT);
+ if (sp == NULL) {
+ /* Gak, drop packet, we can't do a split */
+ goto out;
+ }
+ if (sp->m_pkthdr.len < header_size) {
+ /* Gak, packet can't have an SCTP header in it - to small */
+ m_freem(sp);
+ goto out;
+ }
+ /* ok now pull up the UDP header and SCTP header together */
+ sp = m_pullup(sp, header_size);
+ if (sp == NULL) {
+ /* Gak pullup failed */
+ goto out;
+ }
+ /* trim out the UDP header */
+ m_adj(sp, sizeof(struct udphdr));
+
+ /* Now reconstruct the mbuf chain */
+ /* 1) find last one */
+ last = m;
+ while (last->m_next != NULL) {
+ last = last->m_next;
+ }
+ last->m_next = sp;
+ m->m_pkthdr.len += sp->m_pkthdr.len;
+ last = m;
+ while (last != NULL) {
+ last = last->m_next;
+ }
+ /* Now its ready for sctp_input or sctp6_input */
+ iph = mtod(m, struct ip *);
+ switch (iph->ip_v) {
+ case IPVERSION:
+ {
+ /* its IPv4 */
+ len = SCTP_GET_IPV4_LENGTH(iph);
+ len -= sizeof(struct udphdr);
+ SCTP_GET_IPV4_LENGTH(iph) = len;
+ sctp_input_with_port(m, off, port);
+ break;
+ }
+#ifdef INET6
+ case IPV6_VERSION >> 4:
+ {
+ /* its IPv6 - NOT supported */
+ goto out;
+ break;
+
+ }
+#endif
+ default:
+ {
+ m_freem(m);
+ break;
+ }
+ }
+ return;
+out:
+ m_freem(m);
+}
void
sctp_over_udp_stop(void)
{
- return;
+ struct socket *sop;
+
+ /*
+ * This function assumes sysctl caller holds sctp_sysctl_info_lock()
+ * for writting!
+ */
+ if (SCTP_BASE_INFO(udp_tun_socket) == NULL) {
+ /* Nothing to do */
+ return;
+ }
+ sop = SCTP_BASE_INFO(udp_tun_socket);
+ soclose(sop);
+ SCTP_BASE_INFO(udp_tun_socket) = NULL;
}
int
sctp_over_udp_start(void)
{
- return (-1);
+ uint16_t port;
+ int ret;
+ struct sockaddr_in sin;
+ struct socket *sop = NULL;
+ struct thread *th;
+ struct ucred *cred;
+
+ /*
+ * This function assumes sysctl caller holds sctp_sysctl_info_lock()
+ * for writting!
+ */
+ port = SCTP_BASE_SYSCTL(sctp_udp_tunneling_port);
+ if (port == 0) {
+ /* Must have a port set */
+ return (EINVAL);
+ }
+ if (SCTP_BASE_INFO(udp_tun_socket) != NULL) {
+ /* Already running -- must stop first */
+ return (EALREADY);
+ }
+ th = curthread;
+ cred = th->td_ucred;
+ if ((ret = socreate(PF_INET, &sop,
+ SOCK_DGRAM, IPPROTO_UDP, cred, th))) {
+ return (ret);
+ }
+ SCTP_BASE_INFO(udp_tun_socket) = sop;
+ /* call the special UDP hook */
+ ret = udp_set_kernel_tunneling(sop, sctp_recv_udp_tunneled_packet);
+ if (ret) {
+ goto exit_stage_left;
+ }
+ /* Ok we have a socket, bind it to the port */
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_len = sizeof(sin);
+ sin.sin_family = AF_INET;
+ sin.sin_port = htons(port);
+ ret = sobind(sop, (struct sockaddr *)&sin, th);
+ if (ret) {
+ /* Close up we cant get the port */
+exit_stage_left:
+ sctp_over_udp_stop();
+ return (ret);
+ }
+ /*
+ * Ok we should now get UDP packets directly to our input routine
+ * sctp_recv_upd_tunneled_packet().
+ */
+ return (0);
}
diff --git a/sys/netinet/sctputil.h b/sys/netinet/sctputil.h
index cc940b3..56c6729 100644
--- a/sys/netinet/sctputil.h
+++ b/sys/netinet/sctputil.h
@@ -94,8 +94,6 @@ sctp_timer_stop(int, struct sctp_inpcb *, struct sctp_tcb *,
int
sctp_dynamic_set_primary(struct sockaddr *sa, uint32_t vrf_id);
-uint32_t sctp_calculate_sum(struct mbuf *, int32_t *, uint32_t);
-
void
sctp_mtu_size_reset(struct sctp_inpcb *, struct sctp_association *, uint32_t);
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 30b3fde..d3b91b6 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -117,6 +117,8 @@ int tcp_insecure_rst;
int tcp_do_autorcvbuf;
int tcp_autorcvbuf_inc;
int tcp_autorcvbuf_max;
+int tcp_do_rfc3465;
+int tcp_abc_l_var;
#endif
SYSCTL_V_STRUCT(V_NET, vnet_inet, _net_inet_tcp, TCPCTL_STATS, stats,
@@ -144,6 +146,13 @@ SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_tcp, OID_AUTO, rfc3390, CTLFLAG_RW,
tcp_do_rfc3390, 0,
"Enable RFC 3390 (Increasing TCP's Initial Congestion Window)");
+SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_tcp, OID_AUTO, rfc3465, CTLFLAG_RW,
+ tcp_do_rfc3465, 0,
+ "Enable RFC 3465 (Appropriate Byte Counting)");
+SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_tcp, OID_AUTO, abc_l_var, CTLFLAG_RW,
+ tcp_abc_l_var, 2,
+ "Cap the max cwnd increment during slow-start to this number of segments");
+
SYSCTL_NODE(_net_inet_tcp, OID_AUTO, ecn, CTLFLAG_RW, 0, "TCP ECN");
SYSCTL_V_INT(V_NET, vnet_inet, _net_inet_tcp_ecn, OID_AUTO, enable,
CTLFLAG_RW, tcp_do_ecn, 0, "TCP ECN support");
@@ -2293,20 +2302,59 @@ process_ACK:
/*
* When new data is acked, open the congestion window.
- * If the window gives us less than ssthresh packets
- * in flight, open exponentially (maxseg per packet).
- * Otherwise open linearly: maxseg per window
- * (maxseg^2 / cwnd per packet).
- * If cwnd > maxseg^2, fix the cwnd increment at 1 byte
- * to avoid capping cwnd (as suggested in RFC2581).
+ * Method depends on which congestion control state we're
+ * in (slow start or cong avoid) and if ABC (RFC 3465) is
+ * enabled.
+ *
+ * slow start: cwnd <= ssthresh
+ * cong avoid: cwnd > ssthresh
+ *
+ * slow start and ABC (RFC 3465):
+ * Grow cwnd exponentially by the amount of data
+ * ACKed capping the max increment per ACK to
+ * (abc_l_var * maxseg) bytes.
+ *
+ * slow start without ABC (RFC 2581):
+ * Grow cwnd exponentially by maxseg per ACK.
+ *
+ * cong avoid and ABC (RFC 3465):
+ * Grow cwnd linearly by maxseg per RTT for each
+ * cwnd worth of ACKed data.
+ *
+ * cong avoid without ABC (RFC 2581):
+ * Grow cwnd linearly by approximately maxseg per RTT using
+ * maxseg^2 / cwnd per ACK as the increment.
+ * If cwnd > maxseg^2, fix the cwnd increment at 1 byte to
+ * avoid capping cwnd.
*/
if ((!V_tcp_do_newreno && !(tp->t_flags & TF_SACK_PERMIT)) ||
!IN_FASTRECOVERY(tp)) {
u_int cw = tp->snd_cwnd;
u_int incr = tp->t_maxseg;
- if (cw > tp->snd_ssthresh)
- incr = max((incr * incr / cw), 1);
- tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale);
+ /* In congestion avoidance? */
+ if (cw > tp->snd_ssthresh) {
+ if (V_tcp_do_rfc3465) {
+ tp->t_bytes_acked += acked;
+ if (tp->t_bytes_acked >= tp->snd_cwnd)
+ tp->t_bytes_acked -= cw;
+ else
+ incr = 0;
+ }
+ else
+ incr = max((incr * incr / cw), 1);
+ /*
+ * In slow-start with ABC enabled and no RTO in sight?
+ * (Must not use abc_l_var > 1 if slow starting after an
+ * RTO. On RTO, snd_nxt = snd_una, so the snd_nxt ==
+ * snd_max check is sufficient to handle this).
+ */
+ } else if (V_tcp_do_rfc3465 &&
+ tp->snd_nxt == tp->snd_max)
+ incr = min(acked,
+ V_tcp_abc_l_var * tp->t_maxseg);
+ /* ABC is on by default, so (incr == 0) frequently. */
+ if (incr > 0)
+ tp->snd_cwnd = min(cw+incr, TCP_MAXWIN<<tp->snd_scale);
}
SOCKBUF_LOCK(&so->so_snd);
if (acked > so->so_snd.sb_cc) {
@@ -2328,8 +2376,10 @@ process_ACK:
tp->snd_recover = th->th_ack - 1;
if ((V_tcp_do_newreno || (tp->t_flags & TF_SACK_PERMIT)) &&
IN_FASTRECOVERY(tp) &&
- SEQ_GEQ(th->th_ack, tp->snd_recover))
+ SEQ_GEQ(th->th_ack, tp->snd_recover)) {
EXIT_FASTRECOVERY(tp);
+ tp->t_bytes_acked = 0;
+ }
tp->snd_una = th->th_ack;
if (tp->t_flags & TF_SACK_PERMIT) {
if (SEQ_GT(tp->snd_una, tp->snd_recover))
diff --git a/sys/netinet/tcp_subr.c b/sys/netinet/tcp_subr.c
index 9cb941a..53fc882 100644
--- a/sys/netinet/tcp_subr.c
+++ b/sys/netinet/tcp_subr.c
@@ -316,6 +316,8 @@ tcp_init(void)
V_tcp_do_autorcvbuf = 1;
V_tcp_autorcvbuf_inc = 16*1024;
V_tcp_autorcvbuf_max = 256*1024;
+ V_tcp_do_rfc3465 = 1;
+ V_tcp_abc_l_var = 2;
V_tcp_mssdflt = TCP_MSS;
#ifdef INET6
diff --git a/sys/netinet/tcp_syncache.c b/sys/netinet/tcp_syncache.c
index 18fab28..9faca96 100644
--- a/sys/netinet/tcp_syncache.c
+++ b/sys/netinet/tcp_syncache.c
@@ -1070,8 +1070,6 @@ _syncache_add(struct in_conninfo *inc, struct tcpopt *to, struct tcphdr *th,
* have an initialized label we can use.
*/
mac_syncache_destroy(&maclabel);
- KASSERT(sc->sc_label != NULL,
- ("%s: label not initialized", __func__));
#endif
/* Retransmit SYN|ACK and reset retransmit count. */
if ((s = tcp_log_addrs(&sc->sc_inc, th, NULL, NULL))) {
diff --git a/sys/netinet/tcp_timer.c b/sys/netinet/tcp_timer.c
index acce92f..6963d9c 100644
--- a/sys/netinet/tcp_timer.c
+++ b/sys/netinet/tcp_timer.c
@@ -587,6 +587,7 @@ tcp_timer_rexmt(void * xtp)
tp->t_dupacks = 0;
}
EXIT_FASTRECOVERY(tp);
+ tp->t_bytes_acked = 0;
(void) tcp_output(tp);
out:
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c
index f6dcae1..89987c4 100644
--- a/sys/netinet/tcp_usrreq.c
+++ b/sys/netinet/tcp_usrreq.c
@@ -441,8 +441,8 @@ tcp_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
if (sinp->sin_family == AF_INET
&& IN_MULTICAST(ntohl(sinp->sin_addr.s_addr)))
return (EAFNOSUPPORT);
- if (prison_remote_ip4(td->td_ucred, &sinp->sin_addr) != 0)
- return (EINVAL);
+ if ((error = prison_remote_ip4(td->td_ucred, &sinp->sin_addr)) != 0)
+ return (error);
TCPDEBUG0;
INP_INFO_WLOCK(&V_tcbinfo);
@@ -508,10 +508,9 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
in6_sin6_2_sin(&sin, sin6p);
inp->inp_vflag |= INP_IPV4;
inp->inp_vflag &= ~INP_IPV6;
- if (prison_remote_ip4(td->td_ucred, &sin.sin_addr) != 0) {
- error = EINVAL;
+ if ((error = prison_remote_ip4(td->td_ucred,
+ &sin.sin_addr)) != 0)
goto out;
- }
if ((error = tcp_connect(tp, (struct sockaddr *)&sin, td)) != 0)
goto out;
error = tcp_output_connect(so, nam);
@@ -520,10 +519,8 @@ tcp6_usr_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
inp->inp_vflag &= ~INP_IPV4;
inp->inp_vflag |= INP_IPV6;
inp->inp_inc.inc_flags |= INC_ISIPV6;
- if (prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr) != 0) {
- error = EINVAL;
+ if ((error = prison_remote_ip6(td->td_ucred, &sin6p->sin6_addr)) != 0)
goto out;
- }
if ((error = tcp6_connect(tp, nam, td)) != 0)
goto out;
error = tcp_output_connect(so, nam);
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index a4392cb..c52506e 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -189,6 +189,7 @@ struct tcpcb {
void *t_pspare[3]; /* toe usrreqs / toepcb * / congestion algo / vimage / 1 general use */
struct toe_usrreqs *t_tu; /* offload operations vector */
void *t_toe; /* TOE pcb pointer */
+ int t_bytes_acked; /* # bytes acked during current RTT */
};
/*
@@ -539,6 +540,8 @@ extern int tcp_insecure_rst;
extern int tcp_do_autorcvbuf;
extern int tcp_autorcvbuf_inc;
extern int tcp_autorcvbuf_max;
+extern int tcp_do_rfc3465;
+extern int tcp_abc_l_var;
extern int tcp_do_tso;
extern int tcp_do_autosndbuf;
diff --git a/sys/netinet/udp_usrreq.c b/sys/netinet/udp_usrreq.c
index e402297..804f5fe 100644
--- a/sys/netinet/udp_usrreq.c
+++ b/sys/netinet/udp_usrreq.c
@@ -488,10 +488,28 @@ udp_input(struct mbuf *m, int off)
struct mbuf *n;
n = m_copy(m, 0, M_COPYALL);
- if (n != NULL)
- udp_append(last, ip, n, iphlen +
- sizeof(struct udphdr), &udp_in);
- INP_RUNLOCK(last);
+ if (last->inp_ppcb == NULL) {
+ if (n != NULL)
+ udp_append(last,
+ ip, n,
+ iphlen +
+ sizeof(struct udphdr),
+ &udp_in);
+ INP_RUNLOCK(last);
+ } else {
+ /*
+ * Engage the tunneling protocol we
+ * will have to leave the info_lock
+ * up, since we are hunting through
+ * multiple UDP's.
+ *
+ */
+ udp_tun_func_t tunnel_func;
+
+ tunnel_func = (udp_tun_func_t)last->inp_ppcb;
+ tunnel_func(n, iphlen, last);
+ INP_RUNLOCK(last);
+ }
}
last = inp;
/*
@@ -516,10 +534,22 @@ udp_input(struct mbuf *m, int off)
V_udpstat.udps_noportbcast++;
goto badheadlocked;
}
- udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
- &udp_in);
- INP_RUNLOCK(last);
- INP_INFO_RUNLOCK(&V_udbinfo);
+ if (last->inp_ppcb == NULL) {
+ udp_append(last, ip, m, iphlen + sizeof(struct udphdr),
+ &udp_in);
+ INP_RUNLOCK(last);
+ INP_INFO_RUNLOCK(&V_udbinfo);
+ } else {
+ /*
+ * Engage the tunneling protocol.
+ */
+ udp_tun_func_t tunnel_func;
+
+ tunnel_func = (udp_tun_func_t)last->inp_ppcb;
+ tunnel_func(m, iphlen, last);
+ INP_RUNLOCK(last);
+ INP_INFO_RUNLOCK(&V_udbinfo);
+ }
return;
}
@@ -563,6 +593,17 @@ udp_input(struct mbuf *m, int off)
INP_RUNLOCK(inp);
goto badunlocked;
}
+ if (inp->inp_ppcb != NULL) {
+ /*
+ * Engage the tunneling protocol.
+ */
+ udp_tun_func_t tunnel_func;
+
+ tunnel_func = (udp_tun_func_t)inp->inp_ppcb;
+ tunnel_func(m, iphlen, inp);
+ INP_RUNLOCK(inp);
+ return;
+ }
udp_append(inp, ip, m, iphlen + sizeof(struct udphdr), &udp_in);
INP_RUNLOCK(inp);
return;
@@ -941,10 +982,9 @@ udp_output(struct inpcb *inp, struct mbuf *m, struct sockaddr *addr,
* Jail may rewrite the destination address, so let it do
* that before we use it.
*/
- if (prison_remote_ip4(td->td_ucred, &sin->sin_addr) != 0) {
- error = EINVAL;
+ error = prison_remote_ip4(td->td_ucred, &sin->sin_addr);
+ if (error)
goto release;
- }
/*
* If a local address or port hasn't yet been selected, or if
@@ -1138,6 +1178,40 @@ udp_attach(struct socket *so, int proto, struct thread *td)
INP_INFO_WUNLOCK(&V_udbinfo);
inp->inp_vflag |= INP_IPV4;
inp->inp_ip_ttl = V_ip_defttl;
+ /*
+ * UDP does not have a per-protocol pcb (inp->inp_ppcb).
+ * We use this pointer for kernel tunneling pointer.
+ * If we ever need to have a protocol block we will
+ * need to move this function pointer there. Null
+ * in this pointer means "do the normal thing".
+ */
+ inp->inp_ppcb = NULL;
+ INP_WUNLOCK(inp);
+ return (0);
+}
+
+int
+udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f)
+{
+ struct inpcb *inp;
+
+ inp = (struct inpcb *)so->so_pcb;
+ KASSERT(so->so_type == SOCK_DGRAM, ("udp_set_kernel_tunneling: !dgram"));
+ KASSERT(so->so_pcb != NULL, ("udp_set_kernel_tunneling: NULL inp"));
+ if (so->so_type != SOCK_DGRAM) {
+ /* Not UDP socket... sorry! */
+ return (ENOTSUP);
+ }
+ if (inp == NULL) {
+ /* NULL INP? */
+ return (EINVAL);
+ }
+ INP_WLOCK(inp);
+ if (inp->inp_ppcb != NULL) {
+ INP_WUNLOCK(inp);
+ return (EBUSY);
+ }
+ inp->inp_ppcb = f;
INP_WUNLOCK(inp);
return (0);
}
@@ -1196,10 +1270,11 @@ udp_connect(struct socket *so, struct sockaddr *nam, struct thread *td)
return (EISCONN);
}
sin = (struct sockaddr_in *)nam;
- if (prison_remote_ip4(td->td_ucred, &sin->sin_addr) != 0) {
+ error = prison_remote_ip4(td->td_ucred, &sin->sin_addr);
+ if (error != 0) {
INP_WUNLOCK(inp);
INP_INFO_WUNLOCK(&V_udbinfo);
- return (EAFNOSUPPORT);
+ return (error);
}
error = in_pcbconnect(inp, nam, td->td_ucred);
if (error == 0)
diff --git a/sys/netinet/udp_var.h b/sys/netinet/udp_var.h
index 39805ed..76a31b8 100644
--- a/sys/netinet/udp_var.h
+++ b/sys/netinet/udp_var.h
@@ -110,6 +110,10 @@ void udp_init(void);
void udp_input(struct mbuf *, int);
struct inpcb *udp_notify(struct inpcb *inp, int errno);
int udp_shutdown(struct socket *so);
+
+
+typedef void(*udp_tun_func_t)(struct mbuf *, int off, struct inpcb *);
+int udp_set_kernel_tunneling(struct socket *so, udp_tun_func_t f);
#endif
#endif
diff --git a/sys/netinet/vinet.h b/sys/netinet/vinet.h
index 449334e..618afaa 100644
--- a/sys/netinet/vinet.h
+++ b/sys/netinet/vinet.h
@@ -127,6 +127,8 @@ struct vnet_inet {
int _drop_synfin;
int _tcp_do_rfc3042;
int _tcp_do_rfc3390;
+ int _tcp_do_rfc3465;
+ int _tcp_abc_l_var;
int _tcp_do_ecn;
int _tcp_ecn_maxretries;
int _tcp_insecure_rst;
@@ -291,6 +293,7 @@ extern struct vnet_inet vnet_inet_0;
#define V_subnetsarelocal VNET_INET(subnetsarelocal)
#define V_tcb VNET_INET(tcb)
#define V_tcbinfo VNET_INET(tcbinfo)
+#define V_tcp_abc_l_var VNET_INET(tcp_abc_l_var)
#define V_tcp_autorcvbuf_inc VNET_INET(tcp_autorcvbuf_inc)
#define V_tcp_autorcvbuf_max VNET_INET(tcp_autorcvbuf_max)
#define V_tcp_autosndbuf_inc VNET_INET(tcp_autosndbuf_inc)
@@ -303,6 +306,7 @@ extern struct vnet_inet vnet_inet_0;
#define V_tcp_do_rfc1323 VNET_INET(tcp_do_rfc1323)
#define V_tcp_do_rfc3042 VNET_INET(tcp_do_rfc3042)
#define V_tcp_do_rfc3390 VNET_INET(tcp_do_rfc3390)
+#define V_tcp_do_rfc3465 VNET_INET(tcp_do_rfc3465)
#define V_tcp_do_sack VNET_INET(tcp_do_sack)
#define V_tcp_do_tso VNET_INET(tcp_do_tso)
#define V_tcp_ecn_maxretries VNET_INET(tcp_ecn_maxretries)
OpenPOWER on IntegriCloud