summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/netinet/tcp_input.c815
-rw-r--r--sys/netinet/tcp_var.h6
2 files changed, 275 insertions, 546 deletions
diff --git a/sys/netinet/tcp_input.c b/sys/netinet/tcp_input.c
index 6ad3623a7ee..4eb50c0a275 100644
--- a/sys/netinet/tcp_input.c
+++ b/sys/netinet/tcp_input.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_input.c,v 1.41 1999/07/13 21:57:42 deraadt Exp $ */
+/* $OpenBSD: tcp_input.c,v 1.42 1999/07/17 23:41:46 provos Exp $ */
/* $NetBSD: tcp_input.c,v 1.23 1996/02/13 23:43:44 christos Exp $ */
/*
@@ -48,12 +48,6 @@ You should have received a copy of the license with this software. If you
didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
*/
-/*
- * XXX - At this point, the TUBA support is likely to be hopelessly broken.
- * That's the bad news. The good news is that doing it again and doing it
- * right shouldn't be hard now that the IPv4 dependencies are isolated.
- */
-
#ifndef TUBA_INCLUDE
#include <sys/param.h>
#include <sys/systm.h>
@@ -94,19 +88,17 @@ didn't get a copy, you may request one from <license@ipv6.nrl.navy.mil>.
#include <netinet6/ipv6_var.h>
#include <netinet6/tcpipv6.h>
+struct tcpiphdr tcp_saveti;
+struct tcpipv6hdr tcp_saveti6;
+
/* for the packet header length in the mbuf */
#define M_PH_LEN(m) (((struct mbuf *)(m))->m_pkthdr.len)
#define M_V6_LEN(m) (M_PH_LEN(m) - sizeof(struct ipv6))
#define M_V4_LEN(m) (M_PH_LEN(m) - sizeof(struct ip))
#endif /* INET6 */
-#ifdef INET6
-char tcp_savebuf[sizeof(struct ipv6) + sizeof(struct tcphdr)];
-#else /* INET6 */
-char tcp_savebuf[sizeof(struct ip) + sizeof(struct tcphdr)];
-#endif /* INET6 */
-
int tcprexmtthresh = 3;
+struct tcpiphdr tcp_saveti;
int tcptv_keep_init = TCPTV_KEEP_INIT;
extern u_long sb_max;
@@ -313,9 +305,9 @@ tcp_input(struct mbuf *m, ...)
#else
tcp_input(m, va_alist)
register struct mbuf *m;
- va_dcl
#endif
{
+ register struct tcpiphdr *ti;
register struct inpcb *inp;
caddr_t optp = NULL;
int optlen = 0;
@@ -325,6 +317,7 @@ tcp_input(m, va_alist)
struct socket *so = NULL;
int todrop, acked, ourfinisacked, needoutput = 0;
short ostate = 0;
+ struct in_addr laddr;
int dropsocket = 0;
int iss = 0;
u_long tiwin;
@@ -333,19 +326,14 @@ tcp_input(m, va_alist)
int iphlen;
va_list ap;
register struct tcphdr *th;
- unsigned int pf;
#ifdef IPSEC
struct tdb *tdb = NULL;
#endif /* IPSEC */
- union {
- caddr_t p;
-#ifdef INET
- struct ip *ip;
-#endif /* INET */
#ifdef INET6
- struct ipv6 *ipv6;
-#endif /* INET */
- } nhu;
+ struct in6_addr laddr6;
+ unsigned short is_ipv6; /* Type of incoming datagram. */
+ struct ipv6 *ipv6 = NULL;
+#endif /* INET6 */
va_start(ap, m);
iphlen = va_arg(ap, int);
@@ -362,113 +350,87 @@ tcp_input(m, va_alist)
m->m_pkthdr.tdbi = NULL;
}
#endif /* IPSEC */
-
+#ifdef INET6
/*
- * Before we do ANYTHING, we have to figure out what network protocol
- * is underneath the TCP header in this packet.
- *
- * For IPv4 and IPv6, options don't really do anything at this layer
- * and therefore are stripped off.
+ * Before we do ANYTHING, we have to figure out if it's TCP/IPv6 or
+ * TCP/IPv4.
*/
-#if defined(INET) && defined(INET6)
- switch (mtod(m, struct ip *)->ip_v) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case 4:
- pf = PF_INET;
-
-#ifdef DIAGNOSTIC
- if (iphlen < sizeof(struct ip)) {
- m_freem(m);
- return;
- }
-#endif /* DIAGNOSTIC */
-
- if (iphlen > sizeof(struct ip)) {
- ip_stripoptions(m, (struct mbuf *)0);
- iphlen = sizeof(struct ip);
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case 6:
- pf = PF_INET6;
-
-#ifdef DIAGNOSTIC
- if (iphlen < sizeof(struct ipv6)) {
- m_freem(m);
- return;
- }
-#endif /* DIAGNOSTIC */
-
- if (iphlen > sizeof(struct ipv6)) {
- ipv6_stripoptions(m, iphlen);
- iphlen = sizeof(struct ipv6);
- }
- break;
+ is_ipv6 = mtod(m, struct ip *)->ip_v == 6;
#endif /* INET6 */
- default:
- m_freem(m);
- return;
- }
/*
* Get IP and TCP header together in first mbuf.
* Note: IP leaves IP header in first mbuf.
*/
+#ifndef INET6
+ ti = mtod(m, struct tcpiphdr *);
+#else /* INET6 */
+ if (!is_ipv6)
+#endif /* INET6 */
+ if (iphlen > sizeof (struct ip))
+ ip_stripoptions(m, (struct mbuf *)0);
if (m->m_len < iphlen + sizeof(struct tcphdr)) {
if ((m = m_pullup2(m, iphlen + sizeof(struct tcphdr))) == 0) {
tcpstat.tcps_rcvshort++;
return;
}
+#ifndef INET6
+ ti = mtod(m, struct tcpiphdr *);
+#endif /* INET6 */
}
tlen = m->m_pkthdr.len - iphlen;
+#ifdef INET6
/*
- * Checksum extended TCP header and data.
+ * After that, do initial segment processing which is still very
+ * dependent on what IP version you're using.
*/
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- {
- struct ipovly *ipovly;
- ipovly = mtod(m, struct ipovly *);
+ if (is_ipv6) {
+#ifdef DIAGNOSTIC
+ if (iphlen < sizeof(struct ipv6)) {
+ m_freem(m);
+ return;
+ }
+#endif /* DIAGNOSTIC */
- len = sizeof (struct ip) + tlen;
- bzero(ipovly->ih_x1, sizeof ipovly->ih_x1);
- ipovly->ih_len = (u_int16_t)tlen;
- HTONS(ipovly->ih_len);
+ /* strip off any options */
+ if (iphlen > sizeof(struct ipv6)) {
+ ipv6_stripoptions(m, iphlen);
+ iphlen = sizeof(struct ipv6);
+ }
- if (in_cksum(m, len)) {
- tcpstat.tcps_rcvbadsum++;
- goto drop;
- }
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case PF_INET6:
- if (in6_cksum(m, IPPROTO_TCP, tlen, sizeof(struct ipv6))) {
- tcpstat.tcps_rcvbadsum++;
- goto drop;
- } /* endif in6_cksum */
- break;
+ ti = NULL;
+ ipv6 = mtod(m, struct ipv6 *);
+
+ if (in6_cksum(m, IPPROTO_TCP, tlen, sizeof(struct ipv6))) {
+ tcpstat.tcps_rcvbadsum++;
+ goto drop;
+ } /* endif in6_cksum */
+ } else {
+ ti = mtod(m, struct tcpiphdr *);
#endif /* INET6 */
- }
+ /*
+ * Checksum extended TCP header and data.
+ */
+#ifndef INET6
+ tlen = ((struct ip *)ti)->ip_len;
+#endif /* INET6 */
+ len = sizeof (struct ip) + tlen;
+ bzero(ti->ti_x1, sizeof ti->ti_x1);
+ ti->ti_len = (u_int16_t)tlen;
+ HTONS(ti->ti_len);
+ if ((ti->ti_sum = in_cksum(m, len)) != 0) {
+ tcpstat.tcps_rcvbadsum++;
+ goto drop;
+ }
+#ifdef INET6
+ }
+#endif /* INET6 */
#endif /* TUBA_INCLUDE */
- nhu.p = mtod(m, caddr_t);
th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen);
/*
@@ -487,6 +449,12 @@ tcp_input(m, va_alist)
tcpstat.tcps_rcvshort++;
return;
}
+#ifdef INET6
+ if (is_ipv6)
+ ipv6 = mtod(m, struct ipv6 *);
+ else
+#endif /* INET6 */
+ ti = mtod(m, struct tcpiphdr *);
th = (struct tcphdr *)(mtod(m, caddr_t) + iphlen);
}
optlen = off - sizeof (struct tcphdr);
@@ -523,51 +491,25 @@ tcp_input(m, va_alist)
* Locate pcb for segment.
*/
findpcb:
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- inp = in_pcbhashlookup(&tcbtable, nhu.ip->ip_src,
- th->th_sport, nhu.ip->ip_dst, th->th_dport);
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
- inp = in6_pcbhashlookup(&tcbtable, &nhu.ipv6->ipv6_src,
- th->th_sport, &nhu.ipv6->ipv6_dst, th->th_dport);
- break;
+ if (is_ipv6) {
+ inp = in6_pcbhashlookup(&tcbtable, &ipv6->ipv6_src, th->th_sport,
+ &ipv6->ipv6_dst, th->th_dport);
+ } else
#endif /* INET6 */
- }
-
+ inp = in_pcbhashlookup(&tcbtable, ti->ti_src, ti->ti_sport,
+ ti->ti_dst, ti->ti_dport);
if (inp == 0) {
++tcpstat.tcps_pcbhashmiss;
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- inp = in_pcblookup(&tcbtable, &nhu.ip->ip_src,
- th->th_sport, &nhu.ip->ip_dst, th->th_dport,
- INPLOOKUP_WILDCARD);
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
- inp = in_pcblookup(&tcbtable, &nhu.ipv6->ipv6_src,
- th->th_sport, &nhu.ipv6->ipv6_dst,
- th->th_dport,
- INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
- break;
+ if (is_ipv6)
+ inp = in_pcblookup(&tcbtable, &ipv6->ipv6_src,
+ th->th_sport, &ipv6->ipv6_dst, th->th_dport,
+ INPLOOKUP_WILDCARD | INPLOOKUP_IPV6);
+ else
#endif /* INET6 */
- }
-
+ inp = in_pcblookup(&tcbtable, &ti->ti_src, ti->ti_sport,
+ &ti->ti_dst, ti->ti_dport, INPLOOKUP_WILDCARD);
/*
* If the state is CLOSED (i.e., TCB does not exist) then
* all data in the incoming segment is discarded.
@@ -596,8 +538,12 @@ findpcb:
if (so->so_options & (SO_DEBUG|SO_ACCEPTCONN)) {
if (so->so_options & SO_DEBUG) {
ostate = tp->t_state;
- bcopy(mtod(m, caddr_t), tcp_savebuf,
- iphlen + sizeof(struct tcphdr));
+#ifdef INET6
+ if (is_ipv6)
+ tcp_saveti6 = *(mtod(m, struct tcpipv6hdr *));
+ else
+#endif /* INET6 */
+ tcp_saveti = *ti;
}
if (so->so_options & SO_ACCEPTCONN) {
struct socket *so1;
@@ -645,57 +591,48 @@ findpcb:
* to the new one.
*/
{
- int flags = inp->inp_flags;
- struct inpcb *oldinpcb = inp;
+ int flags = inp->inp_flags;
+ struct inpcb *oldinpcb = inp;
- inp = (struct inpcb *)so->so_pcb;
- inp->inp_flags |=
- (flags & (INP_IPV6 | INP_IPV6_UNDEC
- | INP_IPV6_MAPPED));
- if ((inp->inp_flags & INP_IPV6) &&
- !(inp->inp_flags &
- INP_IPV6_MAPPED)) {
- inp->inp_ipv6.ipv6_hoplimit =
- oldinpcb->inp_ipv6.
- ipv6_hoplimit;
- inp->inp_ipv6.ipv6_versfl =
- oldinpcb->inp_ipv6.ipv6_versfl;
- }
+ inp = (struct inpcb *)so->so_pcb;
+ inp->inp_flags |= (flags & (INP_IPV6 | INP_IPV6_UNDEC
+ | INP_IPV6_MAPPED));
+ if ((inp->inp_flags & INP_IPV6) &&
+ !(inp->inp_flags & INP_IPV6_MAPPED)) {
+ inp->inp_ipv6.ipv6_hoplimit =
+ oldinpcb->inp_ipv6.ipv6_hoplimit;
+ inp->inp_ipv6.ipv6_versfl =
+ oldinpcb->inp_ipv6.ipv6_versfl;
+ }
}
#else /* INET6 */
inp = (struct inpcb *)so->so_pcb;
#endif /* INET6 */
inp->inp_lport = th->th_dport;
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
#ifdef INET6
- if (inp->inp_flags & INP_IPV6) {
- /* v4 to v6 socket */
- CREATE_IPV6_MAPPED(inp->inp_laddr6,
- nhu.ip->ip_dst.s_addr);
- } else
+ if (is_ipv6) {
+ inp->inp_laddr6 = ipv6->ipv6_dst;
+ inp->inp_fflowinfo = htonl(0x0fffffff) &
+ ipv6->ipv6_versfl;
+
+ /*inp->inp_options = ipv6_srcroute();*/ /* soon. */
+ /* still need to tweak outbound options
+ processing to include this mbuf in
+ the right place and put the correct
+ NextHdr values in the right places.
+ XXX rja */
+ } else {
+ if (inp->inp_flags & INP_IPV6) {/* v4 to v6 socket */
+ CREATE_IPV6_MAPPED(inp->inp_laddr6,
+ ti->ti_dst.s_addr);
+ } else {
#endif /* INET6 */
- {
- inp->inp_laddr = nhu.ip->ip_dst;
- inp->inp_options = ip_srcroute();
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case PF_INET6:
- inp->inp_laddr6 = nhu.ipv6->ipv6_dst;
- inp->inp_fflowinfo = htonl(0x0fffffff) &
- nhu.ipv6->ipv6_versfl;
- break;
+ inp->inp_laddr = ti->ti_dst;
+ inp->inp_options = ip_srcroute();
+#if INET6
+ }
+ };
#endif /* INET6 */
- }
-
in_pcbrehash(inp);
tp = intotcpcb(inp);
tp->t_state = TCPS_LISTEN;
@@ -703,8 +640,7 @@ findpcb:
/* Compute proper scaling value from buffer space
*/
while (tp->request_r_scale < TCP_MAX_WINSHIFT &&
- TCP_MAXWIN << tp->request_r_scale <
- so->so_rcv.sb_hiwat)
+ TCP_MAXWIN << tp->request_r_scale < so->so_rcv.sb_hiwat)
tp->request_r_scale++;
}
}
@@ -716,23 +652,12 @@ findpcb:
(inp->inp_seclevel[SL_ESP_TRANS] >= IPSEC_LEVEL_REQUIRE &&
!(m->m_flags & M_CONF))) {
#ifdef notyet
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
+ if (is_ipv6)
ipv6_icmp_error(m, ICMPV6_BLAH, ICMPV6_BLAH, 0);
- break;
+ else
#endif /* INET6 */
- }
+ icmp_error(m, ICMP_BLAH, ICMP_BLAH, 0, 0);
#endif /* notyet */
tcpstat.tcps_rcvnosec++;
goto drop;
@@ -759,15 +684,9 @@ findpcb:
* Process options if not in LISTEN state,
* else do it below (after getting remote address).
*/
- if (tp->t_state != TCPS_LISTEN)
-#ifdef TCP_SIGNATURE
- if (optp || (tp->t_flags & TF_SIGNATURE))
-#else /* TCP_SIGNATURE */
- if (optp)
-#endif /* TCP_SIGNATURE */
- if (tcp_dooptions(tp, optp, optlen, th, m, iphlen,
- &ts_present, &ts_val, &ts_ecr))
- goto drop;
+ if (optp && tp->t_state != TCPS_LISTEN)
+ tcp_dooptions(tp, optp, optlen, th,
+ &ts_present, &ts_val, &ts_ecr);
#ifdef TCP_SACK
if (!tp->sack_disable) {
@@ -930,6 +849,10 @@ findpcb:
*/
case TCPS_LISTEN: {
struct mbuf *am;
+ register struct sockaddr_in *sin;
+#ifdef INET6
+ register struct sockaddr_in6 *sin6;
+#endif /* INET6 */
if (tiflags & TH_RST)
goto drop;
@@ -938,27 +861,17 @@ findpcb:
if ((tiflags & TH_SYN) == 0)
goto drop;
if (th->th_dport == th->th_sport) {
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- if (nhu.ip->ip_src.s_addr ==
- nhu.ip->ip_dst.s_addr)
- goto drop;
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
- if (IN6_ARE_ADDR_EQUAL(&nhu.ipv6->ipv6_src,
- &nhu.ipv6->ipv6_dst))
- goto drop;
- break;
+ if (is_ipv6) {
+ if (IN6_ARE_ADDR_EQUAL(&ipv6->ipv6_src, &ipv6->ipv6_dst))
+ goto drop;
+ } else {
+#endif /* INET6 */
+ if (ti->ti_dst.s_addr == ti->ti_src.s_addr)
+ goto drop;
+#ifdef INET6
+ }
#endif /* INET6 */
- }
}
/*
@@ -968,172 +881,118 @@ findpcb:
*/
if (m->m_flags & (M_BCAST|M_MCAST))
goto drop;
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- if (nhu.ip->ip_dst.s_addr == INADDR_BROADCAST)
- goto drop;
- if (IN_MULTICAST(nhu.ip->ip_dst.s_addr))
- goto drop;
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
- if (IN6_IS_ADDR_MULTICAST(&nhu.ipv6->ipv6_dst))
+ if (is_ipv6) {
+ /* XXX What about IPv6 Anycasting ?? :-( rja */
+ if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst))
goto drop;
- break;
+ } else
#endif /* INET6 */
- }
-
+ if (IN_MULTICAST(ti->ti_dst.s_addr))
+ goto drop;
am = m_get(M_DONTWAIT, MT_SONAME); /* XXX */
if (am == NULL)
goto drop;
-
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
#ifdef INET6
- /*
- * Letting v4 incoming datagrams to reach valid
- * PF_INET6 sockets causes some overhead here.
- */
- if (inp->inp_flags & INP_IPV6) {
- struct sockaddr_in6 *sin6;
- struct in6_addr laddr6;
-
- if (!(inp->inp_flags & (INP_IPV6_UNDEC |
- INP_IPV6_MAPPED))) {
- m_freem(am);
- goto drop;
- }
-
- am->m_len = sizeof(struct sockaddr_in6);
- sin6 = mtod(am, struct sockaddr_in6 *);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- CREATE_IPV6_MAPPED(sin6->sin6_addr,
- nhu.ip->ip_src.s_addr);
- sin6->sin6_port = th->th_sport;
- sin6->sin6_flowinfo = 0;
-
- laddr6 = inp->inp_laddr6;
- if (inp->inp_laddr.s_addr == INADDR_ANY)
- break;
- CREATE_IPV6_MAPPED(inp->inp_laddr6,
- nhu.ip->ip_dst.s_addr);
-
- /*
- * The pcb initially has the v6 default hop
- * limit set. We're sending v4 packets, so we
- * need to set the v4 ttl and tos.
- */
- inp->inp_ip.ip_ttl = ip_defttl;
- inp->inp_ip.ip_tos = 0;
-
- if (in6_pcbconnect(inp, am)) {
- inp->inp_laddr6 = laddr6;
- m_freem(am);
- goto drop;
- }
- } else /* (inp->inp_flags & INP_IPV6) */
+ if (is_ipv6) {
+ /*
+ * This is probably the place to set the tp->pf value.
+ * (Don't forget to do it in the v4 code as well!)
+ *
+ * Also, remember to blank out things like flowlabel, or
+ * set flowlabel for accepted sockets in v6.
+ *
+ * FURTHERMORE, this is PROBABLY the place where the whole
+ * business of key munging is set up for passive
+ * connections.
+ */
+ am->m_len = sizeof(struct sockaddr_in6);
+ sin6 = mtod(am, struct sockaddr_in6 *);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ sin6->sin6_addr = ipv6->ipv6_src;
+ sin6->sin6_port = th->th_sport;
+ sin6->sin6_flowinfo = htonl(0x0fffffff) &
+ inp->inp_ipv6.ipv6_versfl;
+ laddr6 = inp->inp_laddr6;
+ if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
+ inp->inp_laddr6 = ipv6->ipv6_dst;
+ /* This is a good optimization. */
+ if (in6_pcbconnect(inp, am)) {
+ inp->inp_laddr6 = laddr6;
+ (void) m_free(am);
+ goto drop;
+ } /* endif in6_pcbconnect() */
+ tp->pf = PF_INET6;
+ } else {
+ /*
+ * Letting v4 incoming datagrams to reach valid
+ * PF_INET6 sockets causes some overhead here.
+ */
+ if (inp->inp_flags & INP_IPV6) {
+ if (!(inp->inp_flags & (INP_IPV6_UNDEC|INP_IPV6_MAPPED))) {
+ (void) m_free(am);
+ goto drop;
+ }
+
+ am->m_len = sizeof(struct sockaddr_in6);
+
+ sin6 = mtod(am, struct sockaddr_in6 *);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(*sin6);
+ CREATE_IPV6_MAPPED(sin6->sin6_addr, ti->ti_src.s_addr);
+ sin6->sin6_port = th->th_sport;
+ sin6->sin6_flowinfo = 0;
+
+ laddr6 = inp->inp_laddr6;
+ if (inp->inp_laddr.s_addr == INADDR_ANY)
+ CREATE_IPV6_MAPPED(inp->inp_laddr6, ti->ti_dst.s_addr);
+
+ /*
+ * The pcb initially has the v6 default hoplimit
+ * set. We're sending v4 packets so we need to set
+ * the v4 ttl and tos.
+ */
+ inp->inp_ip.ip_ttl = ip_defttl;
+ inp->inp_ip.ip_tos = 0;
+
+ if (in6_pcbconnect(inp, am)) {
+ inp->inp_laddr6 = laddr6;
+ (void) m_freem(am);
+ goto drop;
+ }
+ tp->pf = PF_INET;
+ } else {
#endif /* INET6 */
- {
- struct sockaddr_in *sin;
- struct in_addr laddr;
-
- am->m_len = sizeof(struct sockaddr_in);
- sin = mtod(am, struct sockaddr_in *);
- sin->sin_family = AF_INET;
- sin->sin_len = sizeof(struct sockaddr_in);
- sin->sin_addr = nhu.ip->ip_src;
- sin->sin_port = th->th_sport;
- bzero((caddr_t)sin->sin_zero,
- sizeof(sin->sin_zero));
- laddr = inp->inp_laddr;
- if (inp->inp_laddr.s_addr == INADDR_ANY)
- inp->inp_laddr = nhu.ip->ip_dst;
- if (in_pcbconnect(inp, am)) {
- inp->inp_laddr = laddr;
- m_free(am);
- goto drop;
- }
- } /* (inp->inp_flags & INP_IPV6) */
- tp->pf = PF_INET;
- break;
-#endif /* INET */
+ am->m_len = sizeof (struct sockaddr_in);
+ sin = mtod(am, struct sockaddr_in *);
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(*sin);
+ sin->sin_addr = ti->ti_src;
+ sin->sin_port = ti->ti_sport;
+ bzero((caddr_t)sin->sin_zero, sizeof(sin->sin_zero));
+ laddr = inp->inp_laddr;
+ if (inp->inp_laddr.s_addr == INADDR_ANY)
+ inp->inp_laddr = ti->ti_dst;
+ if (in_pcbconnect(inp, am)) {
+ inp->inp_laddr = laddr;
+ (void) m_free(am);
+ goto drop;
+ }
+ (void) m_free(am);
#ifdef INET6
- case PF_INET6:
- {
- struct sockaddr_in6 *sin6;
- struct in6_addr laddr6;
-
- /*
- * This is probably the place to set the tp->pf
- * value. (Don't forget to do it in the v4 code
- * as well!)
- *
- * Also, remember to blank out things like
- * flowlabel, or set flowlabel for accepted
- * sockets in v6.
- */
-
- am->m_len = sizeof(struct sockaddr_in6);
- sin6 = mtod(am, struct sockaddr_in6 *);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_len = sizeof(struct sockaddr_in6);
- sin6->sin6_addr = nhu.ipv6->ipv6_src;
- sin6->sin6_port = th->th_sport;
- sin6->sin6_flowinfo = htonl(0x0fffffff) &
- inp->inp_ipv6.ipv6_versfl;
- laddr6 = inp->inp_laddr6;
-
- if (IN6_IS_ADDR_UNSPECIFIED(&inp->inp_laddr6))
- inp->inp_laddr6 = nhu.ipv6->ipv6_dst;
- /* This is a good optimization. */
- if (in6_pcbconnect(inp, am)) {
- inp->inp_laddr6 = laddr6;
- m_free(am);
- goto drop;
- }
- }
-
- tp->pf = PF_INET6;
- break;
+ } /* if (inp->inp_flags & INP_IPV6) */
+ } /* if (is_ipv6) */
#endif /* INET6 */
- }
-
- m_free(am);
tp->t_template = tcp_template(tp);
if (tp->t_template == 0) {
tp = tcp_drop(tp, ENOBUFS);
dropsocket = 0; /* socket is already gone */
goto drop;
}
-
-#ifdef TCP_SIGNATURE
- if (optp || (tp->t_flags & TF_SIGNATURE)) {
-#else /* TCP_SIGNATURE */
- if (optp) {
-#endif /* TCP_SIGNATURE */
- m->m_data -= iphlen + off;
- m->m_len += iphlen + off;
- if (tcp_dooptions(tp, optp, optlen, th, m, iphlen,
- &ts_present, &ts_val, &ts_ecr))
- goto drop;
- m->m_data += iphlen + off;
- m->m_len -= iphlen + off;
- }
-
+ if (optp)
+ tcp_dooptions(tp, optp, optlen, th,
+ &ts_present, &ts_val, &ts_ecr);
#ifdef TCP_SACK
/*
* If peer did not send a SACK_PERMITTED option (i.e., if
@@ -1434,7 +1293,7 @@ trimthenstep6:
* Close the tcb.
*/
if (tiflags & TH_RST) {
- if (th->th_seq != tp->last_ack_sent)
+ if (ti->ti_seq != tp->last_ack_sent)
goto drop;
switch (tp->t_state) {
@@ -2060,9 +1919,14 @@ dodata: /* XXX */
break;
}
}
-
- if (so->so_options & SO_DEBUG)
- tcp_trace(TA_INPUT, ostate, tp, tcp_savebuf, 0, tlen);
+ if (so->so_options & SO_DEBUG) {
+#ifdef INET6
+ if (tp->pf == PF_INET6)
+ tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen);
+ else
+#endif /* INET6 */
+ tcp_trace(TA_INPUT, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen);
+ }
/*
* Return any desired output.
@@ -2103,36 +1967,26 @@ dropwithreset:
*/
if ((tiflags & TH_RST) || m->m_flags & (M_BCAST|M_MCAST))
goto drop;
-#if defined(INET) && defined(INET6)
- switch (pf) {
-#else /* defined(INET) && defined(INET6) */
- switch (-1) {
- case -1:
-#endif /* defined(INET) && defined(INET6) */
-#ifdef INET
- case PF_INET:
- if (mtod(m, struct ip *)->ip_dst.s_addr == INADDR_BROADCAST)
- goto drop;
- if (IN_MULTICAST(mtod(m, struct ip *)->ip_dst.s_addr))
- goto drop;
- break;
-#endif /* INET */
#ifdef INET6
- case PF_INET6:
- if (IN6_IS_ADDR_MULTICAST(&mtod(m, struct ipv6 *)->ipv6_dst))
- goto drop;
- break;
+ if (is_ipv6) {
+ /* For following calls to tcp_respond */
+ ti = mtod(m, struct tcpiphdr *);
+ if (IN6_IS_ADDR_MULTICAST(&ipv6->ipv6_dst))
+ goto drop;
+ } else {
#endif /* INET6 */
+ if (IN_MULTICAST(ti->ti_dst.s_addr))
+ goto drop;
+#ifdef INET6
}
-
+#endif /* INET6 */
if (tiflags & TH_ACK)
- tcp_respond(tp, mtod(m, caddr_t), m, (tcp_seq)0, th->th_ack,
- TH_RST);
+ tcp_respond(tp, (caddr_t) ti, m, (tcp_seq)0, th->th_ack, TH_RST);
else {
if (tiflags & TH_SYN)
tlen++;
- tcp_respond(tp, mtod(m, caddr_t), m, th->th_seq+tlen,
- (tcp_seq)0, TH_RST|TH_ACK);
+ tcp_respond(tp, (caddr_t) ti, m, th->th_seq+tlen, (tcp_seq)0,
+ TH_RST|TH_ACK);
}
/* destroy temporarily created socket */
if (dropsocket)
@@ -2143,8 +1997,14 @@ drop:
/*
* Drop space held by incoming segment and return.
*/
- if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG))
- tcp_trace(TA_DROP, ostate, tp, tcp_savebuf, 0, tlen);
+ if (tp && (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)) {
+#ifdef INET6
+ if (tp->pf == PF_INET6)
+ tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti6, 0, tlen);
+ else
+#endif /* INET6 */
+ tcp_trace(TA_DROP, ostate, tp, (caddr_t) &tcp_saveti, 0, tlen);
+ }
m_freem(m);
/* destroy temporarily created socket */
@@ -2154,22 +2014,17 @@ drop:
#ifndef TUBA_INCLUDE
}
-int
-tcp_dooptions(tp, cp, cnt, th, m, iphlen, ts_present, ts_val, ts_ecr)
+void
+tcp_dooptions(tp, cp, cnt, th, ts_present, ts_val, ts_ecr)
struct tcpcb *tp;
u_char *cp;
int cnt;
struct tcphdr *th;
- struct mbuf *m;
- int iphlen;
int *ts_present;
u_int32_t *ts_val, *ts_ecr;
{
u_int16_t mss = 0;
int opt, optlen;
-#ifdef TCP_SIGNATURE
- caddr_t sigp = NULL;
-#endif /* TCP_SIGNATURE */
for (; cnt > 0; cnt -= optlen, cp += optlen) {
opt = cp[0];
@@ -2238,137 +2093,11 @@ tcp_dooptions(tp, cp, cnt, th, m, iphlen, ts_present, ts_val, ts_ecr)
continue;
break;
#endif
-#ifdef TCP_SIGNATURE
- case TCPOPT_SIGNATURE:
- if (optlen != TCPOLEN_SIGNATURE)
- continue;
-
- if (sigp && bcmp(sigp, cp + 2, 16))
- return -1;
-
- sigp = cp + 2;
- break;
-#endif /* TCP_SIGNATURE */
}
}
-
-#ifdef TCP_SIGNATURE
- if ((sigp ? TF_SIGNATURE : 0) ^ (tp->t_flags & TF_SIGNATURE)) {
- tcpstat.tcps_rcvbadsig++;
- return -1;
- }
-
- if (sigp) {
- MD5_CTX ctx;
- union sockaddr_union sa;
- struct tdb *tdb;
- char sig[16];
-
- memset(&sa, 0, sizeof(union sockaddr_union));
-
- switch (tp->pf) {
- case 0:
- case AF_INET:
- sa.sa.sa_len = sizeof(struct sockaddr_in);
- sa.sa.sa_family = AF_INET;
- sa.sin.sin_addr = tp->t_inpcb->inp_laddr;
- break;
-#ifdef INET6
- case AF_INET6:
- sa.sa.sa_len = sizeof(struct sockaddr_in6);
- sa.sa.sa_family = AF_INET6;
- sa.sin6.sin6_addr = tp->t_inpcb->inp_laddr6;
- break;
-#endif /* INET6 */
- }
-
- tdb = gettdb(0, &sa, IPPROTO_TCP);
- if (tdb == NULL) {
- printf("tdb miss\n");
- tcpstat.tcps_rcvbadsig++;
- return -1;
- }
-
- MD5Init(&ctx);
-
- switch(tp->pf) {
- case 0:
-#ifdef INET
- case AF_INET:
- {
- struct ippseudo ippseudo;
-
- ippseudo.ippseudo_src =
- tp->t_inpcb->inp_faddr;
- ippseudo.ippseudo_dst =
- tp->t_inpcb->inp_laddr;
- ippseudo.ippseudo_pad = 0;
- ippseudo.ippseudo_p = IPPROTO_TCP;
- ippseudo.ippseudo_len = htons(
- m->m_pkthdr.len - iphlen);
-
- MD5Update(&ctx, (char *)&ippseudo,
- sizeof(struct ippseudo));
- }
- break;
-#endif /* INET */
-#ifdef INET6
- case AF_INET6:
- {
- static int printed = 0;
-
- if (!printed) {
- printf("error: TCP MD5 support"
- " for IPv6 not yet"
- " implemented.\n");
- printed = 1;
- }
- }
- break
-#endif /* INET6 */
- }
-
- {
- struct tcphdr tcphdr;
-
- tcphdr.th_sport = th->th_sport;
- tcphdr.th_dport = th->th_dport;
- tcphdr.th_seq = htonl(th->th_seq);
- tcphdr.th_ack = htonl(th->th_ack);
- tcphdr.th_off = th->th_off;
- tcphdr.th_x2 = th->th_x2;
- tcphdr.th_flags = th->th_flags;
- tcphdr.th_win = htons(th->th_win);
- tcphdr.th_sum = 0;
- tcphdr.th_urp = htons(th->th_urp);
-
- MD5Update(&ctx, (char *)&tcphdr,
- sizeof(struct tcphdr));
- }
-
- if (m_apply(m, iphlen + th->th_off * sizeof(uint32_t),
- m->m_pkthdr.len - (iphlen + th->th_off *
- sizeof(uint32_t)), tcp_signature_apply,
- (caddr_t)&ctx))
- return (-1);
-
- MD5Update(&ctx, tdb->tdb_amxkey, tdb->tdb_amxkeylen);
- MD5Final(sig, &ctx);
-
- if (bcmp(sig, sigp, 16)) {
- tcpstat.tcps_rcvbadsig++;
- return (-1);
- }
-
- tcpstat.tcps_rcvgoodsig++;
- };
-#endif /* TCP_SIGNATURE */
-
/* Update t_maxopd and t_maxseg after all options are processed */
if (th->th_flags & TH_SYN)
(void) tcp_mss(tp, mss); /* sets t_maxseg */
-
- return (0);
}
#if defined(TCP_SACK) || defined(TCP_NEWRENO)
diff --git a/sys/netinet/tcp_var.h b/sys/netinet/tcp_var.h
index 7b583c5fae5..9ac7ef96eed 100644
--- a/sys/netinet/tcp_var.h
+++ b/sys/netinet/tcp_var.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: tcp_var.h,v 1.21 1999/07/06 20:17:53 cmetz Exp $ */
+/* $OpenBSD: tcp_var.h,v 1.22 1999/07/17 23:41:46 provos Exp $ */
/* $NetBSD: tcp_var.h,v 1.17 1996/02/13 23:44:24 christos Exp $ */
/*
@@ -330,8 +330,8 @@ struct tcpcb *
tcp_disconnect __P((struct tcpcb *));
struct tcpcb *
tcp_drop __P((struct tcpcb *, int));
-int tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *,
- struct mbuf *, int, int *, u_int32_t *, u_int32_t *));
+void tcp_dooptions __P((struct tcpcb *, u_char *, int, struct tcphdr *,
+ int *, u_int32_t *, u_int32_t *));
void tcp_drain __P((void));
void tcp_fasttimo __P((void));
void tcp_init __P((void));