projects
/
unix-history
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
tags
|
clone url
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
nasty little bug in packet reassembly
[unix-history]
/
usr
/
src
/
sys
/
netinet
/
tcp_input.c
diff --git
a/usr/src/sys/netinet/tcp_input.c
b/usr/src/sys/netinet/tcp_input.c
index
9f5275c
..
d00ead0
100644
(file)
--- a/
usr/src/sys/netinet/tcp_input.c
+++ b/
usr/src/sys/netinet/tcp_input.c
@@
-1,4
+1,4
@@
-/* tcp_input.c 1.
54 82/02/25
*/
+/* tcp_input.c 1.
71 82/06/30
*/
#include "../h/param.h"
#include "../h/systm.h"
#include "../h/param.h"
#include "../h/systm.h"
@@
-7,6
+7,7
@@
#include "../h/socket.h"
#include "../h/socketvar.h"
#include "../net/in.h"
#include "../h/socket.h"
#include "../h/socketvar.h"
#include "../net/in.h"
+#include "../net/route.h"
#include "../net/in_pcb.h"
#include "../net/in_systm.h"
#include "../net/if.h"
#include "../net/in_pcb.h"
#include "../net/in_systm.h"
#include "../net/if.h"
@@
-19,7
+20,7
@@
#include "../net/tcp_var.h"
#include "../net/tcpip.h"
#include "../net/tcp_debug.h"
#include "../net/tcp_var.h"
#include "../net/tcpip.h"
#include "../net/tcp_debug.h"
-#include
"../errno.h"
+#include
<errno.h>
int tcpprintfs = 0;
int tcpcksum = 1;
int tcpprintfs = 0;
int tcpcksum = 1;
@@
-45,8
+46,8
@@
tcp_input(m0)
struct socket *so;
int todrop, acked;
short ostate;
struct socket *so;
int todrop, acked;
short ostate;
+ struct in_addr laddr;
-COUNT(TCP_INPUT);
/*
* Get IP and TCP header together in first mbuf.
* Note: IP leaves IP header in first mbuf.
/*
* Get IP and TCP header together in first mbuf.
* Note: IP leaves IP header in first mbuf.
@@
-72,12
+73,13
@@
COUNT(TCP_INPUT);
ti->ti_next = ti->ti_prev = 0;
ti->ti_x1 = 0;
ti->ti_len = (u_short)tlen;
ti->ti_next = ti->ti_prev = 0;
ti->ti_x1 = 0;
ti->ti_len = (u_short)tlen;
-#if vax
- ti->ti_len = htons(ti->ti_len);
+#if vax
|| pdp11
+ ti->ti_len = htons(
(u_short)
ti->ti_len);
#endif
if (ti->ti_sum = in_cksum(m, len)) {
tcpstat.tcps_badsum++;
#endif
if (ti->ti_sum = in_cksum(m, len)) {
tcpstat.tcps_badsum++;
- printf("tcp cksum %x\n", ti->ti_sum);
+ if (tcpprintfs)
+ printf("tcp cksum %x\n", ti->ti_sum);
goto drop;
}
}
goto drop;
}
}
@@
-91,7
+93,8
@@
COUNT(TCP_INPUT);
tcpstat.tcps_badoff++;
goto drop;
}
tcpstat.tcps_badoff++;
goto drop;
}
- ti->ti_len = tlen - off;
+ tlen -= off;
+ ti->ti_len = tlen;
if (off > sizeof (struct tcphdr)) {
if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
tcpstat.tcps_hdrops++;
if (off > sizeof (struct tcphdr)) {
if ((m = m_pullup(m, sizeof (struct ip) + off)) == 0) {
tcpstat.tcps_hdrops++;
@@
-104,14
+107,22
@@
COUNT(TCP_INPUT);
om->m_off = MMINOFF;
om->m_len = off - sizeof (struct tcphdr);
{ caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
om->m_off = MMINOFF;
om->m_len = off - sizeof (struct tcphdr);
{ caddr_t op = mtod(m, caddr_t) + sizeof (struct tcpiphdr);
- bcopy(op, mtod(om, caddr_t), om->m_len);
+ bcopy(op, mtod(om, caddr_t),
(unsigned)
om->m_len);
m->m_len -= om->m_len;
m->m_len -= om->m_len;
- bcopy(op+om->m_len, op, m->m_len-sizeof (struct tcpiphdr));
+ bcopy(op+om->m_len, op,
+ (unsigned)(m->m_len-sizeof (struct tcpiphdr)));
}
}
tiflags = ti->ti_flags;
}
}
tiflags = ti->ti_flags;
-#if vax
+ /*
+ * Drop TCP and IP headers.
+ */
+ off += sizeof (struct ip);
+ m->m_off += off;
+ m->m_len -= off;
+
+#if vax || pdp11
/*
* Convert TCP protocol specific fields to host format.
*/
/*
* Convert TCP protocol specific fields to host format.
*/
@@
-122,10
+133,12
@@
COUNT(TCP_INPUT);
#endif
/*
#endif
/*
- * Locate pcb for segment.
+ * Locate pcb for segment. On match, update the local
+ * address stored in the block to reflect anchoring.
*/
inp = in_pcblookup
*/
inp = in_pcblookup
- (&tcb, ti->ti_src, ti->ti_sport, ti->ti_dst, ti->ti_dport);
+ (&tcb, 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
/*
* If the state is CLOSED (i.e., TCB does not exist) then
@@
-188,11
+201,18
@@
COUNT(TCP_INPUT);
goto drop;
tcp_in.sin_addr = ti->ti_src;
tcp_in.sin_port = ti->ti_sport;
goto drop;
tcp_in.sin_addr = ti->ti_src;
tcp_in.sin_port = ti->ti_sport;
- if (in_pcbconnect(inp, (struct sockaddr *)&tcp_in))
+ laddr = inp->inp_laddr;
+ if (inp->inp_laddr.s_addr == 0)
+ inp->inp_laddr = ti->ti_dst;
+ if (in_pcbconnect(inp, (struct sockaddr_in *)&tcp_in)) {
+ inp->inp_laddr = laddr;
goto drop;
goto drop;
+ }
tp->t_template = tcp_template(tp);
if (tp->t_template == 0) {
in_pcbdisconnect(inp);
tp->t_template = tcp_template(tp);
if (tp->t_template == 0) {
in_pcbdisconnect(inp);
+ inp->inp_laddr = laddr;
+ tp = 0;
goto drop;
}
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
goto drop;
}
tp->iss = tcp_iss; tcp_iss += TCP_ISSINCR/2;
@@
-222,8
+242,10
@@
COUNT(TCP_INPUT);
SEQ_GT(ti->ti_ack, tp->snd_max)))
goto dropwithreset;
if (tiflags & TH_RST) {
SEQ_GT(ti->ti_ack, tp->snd_max)))
goto dropwithreset;
if (tiflags & TH_RST) {
- if (tiflags & TH_ACK)
+ if (tiflags & TH_ACK)
{
tcp_drop(tp, ECONNREFUSED);
tcp_drop(tp, ECONNREFUSED);
+ tp = 0;
+ }
goto drop;
}
if ((tiflags & TH_SYN) == 0)
goto drop;
}
if ((tiflags & TH_SYN) == 0)
@@
-297,7
+319,8
@@
trimthenstep6:
tiflags &= ~TH_URG;
todrop--;
}
tiflags &= ~TH_URG;
todrop--;
}
- if (todrop > ti->ti_len)
+ if (todrop > ti->ti_len ||
+ todrop == ti->ti_len && (tiflags&TH_FIN) == 0)
goto dropafterack;
m_adj(m, todrop);
ti->ti_seq += todrop;
goto dropafterack;
m_adj(m, todrop);
ti->ti_seq += todrop;
@@
-316,7
+339,7
@@
trimthenstep6:
*/
todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
if (todrop > 0) {
*/
todrop = (ti->ti_seq+ti->ti_len) - (tp->rcv_nxt+tp->rcv_wnd);
if (todrop > 0) {
- if (todrop > ti->ti_len)
+ if (todrop >
=
ti->ti_len)
goto dropafterack;
m_adj(m, -todrop);
ti->ti_len -= todrop;
goto dropafterack;
m_adj(m, -todrop);
ti->ti_len -= todrop;
@@
-330,6
+353,7
@@
trimthenstep6:
*/
if (so->so_state & SS_USERGONE) {
tcp_close(tp);
*/
if (so->so_state & SS_USERGONE) {
tcp_close(tp);
+ tp = 0;
goto dropwithreset;
}
goto dropwithreset;
}
@@
-353,9
+377,14
@@
trimthenstep6:
inp->inp_ppcb = 0;
tp = tcp_newtcpcb(inp);
tp->t_state = TCPS_LISTEN;
inp->inp_ppcb = 0;
tp = tcp_newtcpcb(inp);
tp->t_state = TCPS_LISTEN;
+ inp->inp_faddr.s_addr = 0;
+ inp->inp_fport = 0;
+ inp->inp_laddr.s_addr = 0; /* not quite right */
+ tp = 0;
goto drop;
}
tcp_drop(tp, ECONNREFUSED);
goto drop;
}
tcp_drop(tp, ECONNREFUSED);
+ tp = 0;
goto drop;
case TCPS_ESTABLISHED:
goto drop;
case TCPS_ESTABLISHED:
@@
-363,12
+392,14
@@
trimthenstep6:
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
tcp_drop(tp, ECONNRESET);
case TCPS_FIN_WAIT_2:
case TCPS_CLOSE_WAIT:
tcp_drop(tp, ECONNRESET);
+ tp = 0;
goto drop;
case TCPS_CLOSING:
case TCPS_LAST_ACK:
case TCPS_TIME_WAIT:
tcp_close(tp);
goto drop;
case TCPS_CLOSING:
case TCPS_LAST_ACK:
case TCPS_TIME_WAIT:
tcp_close(tp);
+ tp = 0;
goto drop;
}
goto drop;
}
@@
-378,6
+409,7
@@
trimthenstep6:
*/
if (tiflags & TH_SYN) {
tcp_drop(tp, ECONNRESET);
*/
if (tiflags & TH_SYN) {
tcp_drop(tp, ECONNRESET);
+ tp = 0;
goto dropwithreset;
}
goto dropwithreset;
}
@@
-463,11
+495,11
@@
trimthenstep6:
sbdrop(&so->so_snd, so->so_snd.sb_cc);
tp->snd_wnd -= so->so_snd.sb_cc;
} else {
sbdrop(&so->so_snd, so->so_snd.sb_cc);
tp->snd_wnd -= so->so_snd.sb_cc;
} else {
- sbdrop(&so->so_snd
.sb_cc
, acked);
+ sbdrop(&so->so_snd, acked);
tp->snd_wnd -= acked;
acked = 0;
}
tp->snd_wnd -= acked;
acked = 0;
}
- if (
so->so_snd.sb_flags & SB_WAIT
)
+ if (
(so->so_snd.sb_flags & SB_WAIT) || so->so_snd.sb_sel
)
sowwakeup(so);
tp->snd_una = ti->ti_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
sowwakeup(so);
tp->snd_una = ti->ti_ack;
if (SEQ_LT(tp->snd_nxt, tp->snd_una))
@@
-514,8
+546,10
@@
trimthenstep6:
* and return.
*/
case TCPS_LAST_ACK:
* and return.
*/
case TCPS_LAST_ACK:
- if (ourfinisacked)
+ if (ourfinisacked)
{
tcp_close(tp);
tcp_close(tp);
+ tp = 0;
+ }
goto drop;
/*
goto drop;
/*
@@
-547,7
+581,8
@@
step6:
/*
* Process segments with URG.
*/
/*
* Process segments with URG.
*/
- if ((tiflags & TH_URG) && TCPS_HAVERCVDFIN(tp->t_state) == 0) {
+ if ((tiflags & TH_URG) && ti->ti_urp &&
+ TCPS_HAVERCVDFIN(tp->t_state) == 0) {
/*
* If this segment advances the known urgent pointer,
* then mark the data stream. This should not happen
/*
* If this segment advances the known urgent pointer,
* then mark the data stream. This should not happen
@@
-588,9
+623,6
@@
step6:
*/
if ((ti->ti_len || (tiflags&TH_FIN)) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
*/
if ((ti->ti_len || (tiflags&TH_FIN)) &&
TCPS_HAVERCVDFIN(tp->t_state) == 0) {
- off += sizeof (struct ip); /* drop IP header */
- m->m_off += off;
- m->m_len -= off;
tiflags = tcp_reass(tp, ti);
if (tcpnodelack == 0)
tp->t_flags |= TF_DELACK;
tiflags = tcp_reass(tp, ti);
if (tcpnodelack == 0)
tp->t_flags |= TF_DELACK;
@@
-656,22
+688,25
@@
step6:
/*
* Return any desired output.
*/
/*
* Return any desired output.
*/
- tcp_output(tp);
+
(void)
tcp_output(tp);
return;
dropafterack:
/*
return;
dropafterack:
/*
- * Generate an ACK dropping incoming segment
.
- *
Make ACK reflect
our state.
+ * Generate an ACK dropping incoming segment
if it occupies
+ *
sequence space, where the ACK reflects
our state.
*/
*/
- if (tiflags & TH_RST)
+ if ((tiflags&TH_RST) ||
+ tlen == 0 && (tiflags&(TH_SYN|TH_FIN)) == 0)
goto drop;
goto drop;
+ if (tp->t_inpcb->inp_socket->so_options & SO_DEBUG)
+ tcp_trace(TA_RESPOND, ostate, tp, &tcp_saveti, 0);
tcp_respond(tp, ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
return;
dropwithreset:
if (om)
tcp_respond(tp, ti, tp->rcv_nxt, tp->snd_nxt, TH_ACK);
return;
dropwithreset:
if (om)
- m_free(om);
+
(void)
m_free(om);
/*
* Generate a RST, dropping incoming segment.
* Make ACK acceptable to originator of segment.
/*
* Generate a RST, dropping incoming segment.
* Make ACK acceptable to originator of segment.
@@
-683,7
+718,8
@@
dropwithreset:
else {
if (tiflags & TH_SYN)
ti->ti_len++;
else {
if (tiflags & TH_SYN)
ti->ti_len++;
- tcp_respond(tp, ti, ti->ti_seq+ti->ti_len, (tcp_seq)0, TH_RST|TH_ACK);
+ tcp_respond(tp, ti, ti->ti_seq+ti->ti_len, (tcp_seq)0,
+ TH_RST|TH_ACK);
}
return;
}
return;
@@
-691,6
+727,8
@@
drop:
/*
* Drop space held by incoming segment and return.
*/
/*
* 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_saveti, 0);
m_freem(m);
return;
}
m_freem(m);
return;
}
@@
-721,8
+759,8
@@
tcp_dooptions(tp, om)
if (optlen != 4)
continue;
tp->t_maxseg = *(u_short *)(cp + 2);
if (optlen != 4)
continue;
tp->t_maxseg = *(u_short *)(cp + 2);
-#if vax
- tp->t_maxseg = ntohs(tp->t_maxseg);
+#if vax
|| pdp11
+ tp->t_maxseg = ntohs(
(u_short)
tp->t_maxseg);
#endif
break;
#endif
break;
@@
-751,7
+789,7
@@
printf("bad seq\n");
tp->t_iobseq = cp[2];
tp->t_iobc = cp[3];
mark = *(tcp_seq *)(cp + 4);
tp->t_iobseq = cp[2];
tp->t_iobc = cp[3];
mark = *(tcp_seq *)(cp + 4);
-#if vax
+#if vax
|| pdp11
mark = ntohl(mark);
#endif
so->so_oobmark = so->so_rcv.sb_cc + (mark-tp->rcv_nxt);
mark = ntohl(mark);
#endif
so->so_oobmark = so->so_rcv.sb_cc + (mark-tp->rcv_nxt);
@@
-779,7
+817,7
@@
printf("take oob ack %x and cancel rexmt\n", cp[2]);
#endif TCPTRUEOOB
}
}
#endif TCPTRUEOOB
}
}
- m_free(om);
+
(void)
m_free(om);
}
/*
}
/*
@@
-793,7
+831,7
@@
tcp_pulloutofband(so, ti)
struct tcpiphdr *ti;
{
register struct mbuf *m;
struct tcpiphdr *ti;
{
register struct mbuf *m;
- int cnt =
sizeof (struct tcpiphdr) +
ti->ti_urp - 1;
+ int cnt = ti->ti_urp - 1;
m = dtom(ti);
while (cnt >= 0) {
m = dtom(ti);
while (cnt >= 0) {
@@
-803,7
+841,7
@@
tcp_pulloutofband(so, ti)
tp->t_iobc = *cp;
tp->t_oobflags |= TCPOOB_HAVEDATA;
tp->t_iobc = *cp;
tp->t_oobflags |= TCPOOB_HAVEDATA;
- bcopy(cp+1, cp,
m->m_len - cnt - 1
);
+ bcopy(cp+1, cp,
(unsigned)(m->m_len - cnt - 1)
);
m->m_len--;
return;
}
m->m_len--;
return;
}
@@
-828,7
+866,6
@@
tcp_reass(tp, ti)
struct socket *so = tp->t_inpcb->inp_socket;
struct mbuf *m;
int flags;
struct socket *so = tp->t_inpcb->inp_socket;
struct mbuf *m;
int flags;
-COUNT(TCP_REASS);
/*
* Call with ti==0 after become established to
/*
* Call with ti==0 after become established to
@@
-858,7
+895,7
@@
COUNT(TCP_REASS);
if (i > 0) {
if (i >= ti->ti_len)
goto drop;
if (i > 0) {
if (i >= ti->ti_len)
goto drop;
- m_adj(dtom(t
p
), i);
+ m_adj(dtom(t
i
), i);
ti->ti_len -= i;
ti->ti_seq += i;
}
ti->ti_len -= i;
ti->ti_seq += i;
}
@@
-909,7
+946,7
@@
present:
m = dtom(ti);
ti = (struct tcpiphdr *)ti->ti_next;
if (so->so_state & SS_CANTRCVMORE)
m = dtom(ti);
ti = (struct tcpiphdr *)ti->ti_next;
if (so->so_state & SS_CANTRCVMORE)
-
(void)
m_freem(m);
+ m_freem(m);
else
sbappend(&so->so_rcv, m);
} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
else
sbappend(&so->so_rcv, m);
} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);