Esempio n. 1
0
int
tcp_reass(struct tcpcb *tp,struct tcpiphdr *ti, usn_mbuf_t *m)
{
	struct tcpiphdr *q;
	struct usn_socket *so = tp->t_inpcb->inp_socket;
	int flags;

	// Call with ti==0 after become established to
	// force pre-ESTABLISHED data up to user socket.
	if (ti == 0)
		goto present;

	// Find a segment which begins after this one does.
	for (q = tp->seg_next; q != (struct tcpiphdr *)tp;
	    q = (struct tcpiphdr *)q->ti_next)
		if (SEQ_GT(q->ti_seq, ti->ti_seq))
			break;

	// If there is a preceding segment, it may provide some of
	// our data already.  If so, drop the data from the incoming
	// segment.  If it provides all of our data, drop us.
	if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
		int i;
		q = (struct tcpiphdr *)q->ti_prev;
		// conversion to int (in i) handles seq wraparound
		i = q->ti_seq + q->ti_len - ti->ti_seq;
		if (i > 0) {
			if (i >= ti->ti_len) {
				g_tcpstat.tcps_rcvduppack++;
				g_tcpstat.tcps_rcvdupbyte += ti->ti_len;
				usn_free_mbuf(m);
				return (0);
			}
			m_adj(m, i);
			ti->ti_len -= i;
			ti->ti_seq += i;
		}
		q = (struct tcpiphdr *)(q->ti_next);
	}
	g_tcpstat.tcps_rcvoopack++;
	g_tcpstat.tcps_rcvoobyte += ti->ti_len;
	REASS_MBUF(ti) = m; // XXX: wrong assumtion dst and src port for mbuf pointer

	// While we overlap succeeding segments trim them or,
	// if they are completely covered, dequeue them.

	while (q != (struct tcpiphdr *)tp) {
		int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
		if (i <= 0)
			break;
		if (i < q->ti_len) {
			q->ti_seq += i;
			q->ti_len -= i;
			m_adj(REASS_MBUF(q), i);
			break;
		}
		q = (struct tcpiphdr *)q->ti_next;
		m = REASS_MBUF((struct tcpiphdr *)q->ti_prev);
      // FIXME
		//remque(q->ti_prev);
		usn_free_mbuf(m);
	}

	// FIXME:  Stick new segment in its place.
	//insque(ti, q->ti_prev);

present:
	// Present data to user, advancing rcv_nxt through
	// completed sequence space.
	if (TCPS_HAVERCVDSYN(tp->t_state) == 0)
		return (0);
	ti = tp->seg_next;
	if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
		return (0);
	if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
		return (0);
	do {
		tp->rcv_nxt += ti->ti_len;
		flags = ti->ti_flags & TH_FIN;
      // FIXME
		//remque(ti);
		m = REASS_MBUF(ti);
		ti = (struct tcpiphdr *)ti->ti_next;
		if (so->so_state & USN_CANTRCVMORE) {
			usn_free_mbuf(m);
      } else {
			sbappend(so->so_rcv, m);
      }
	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);

	sorwakeup(so);
   usnet_tcpin_rwakeup(so, USN_TCP_IN, USN_TCPEV_READ, m);
	return (flags);
}
Esempio n. 2
0
int tcp_reass(struct tcpcb *tp, struct tcpiphdr *ti, struct mbuf *m)
{
	register struct tcpiphdr *q;
	struct socket *so = tp->t_socket;
	int flags;
	
	/*
	 * Call with ti==0 after become established to
	 * force pre-ESTABLISHED data up to user socket.
	 */
	if (ti == 0)
		goto present;

	/*
	 * Find a segment which begins after this one does.
	 */
	for (q = (struct tcpiphdr *)tp->seg_next; q != (struct tcpiphdr *)tp;
	    q = (struct tcpiphdr *)q->ti_next)
		if (SEQ_GT(q->ti_seq, ti->ti_seq))
			break;

	/*
	 * If there is a preceding segment, it may provide some of
	 * our data already.  If so, drop the data from the incoming
	 * segment.  If it provides all of our data, drop us.
	 */
	if ((struct tcpiphdr *)q->ti_prev != (struct tcpiphdr *)tp) {
		register int i;
		q = (struct tcpiphdr *)q->ti_prev;
		/* conversion to int (in i) handles seq wraparound */
		i = q->ti_seq + q->ti_len - ti->ti_seq;
		if (i > 0) {
			if (i >= ti->ti_len) {
				tcpstat.tcps_rcvduppack++;
				tcpstat.tcps_rcvdupbyte += ti->ti_len;
				m_freem(m);
				/*
				 * Try to present any queued data
				 * at the left window edge to the user.
				 * This is needed after the 3-WHS
				 * completes.
				 */
				goto present;   /* ??? */
			}
			m_adj(m, i);
			ti->ti_len -= i;
			ti->ti_seq += i;
		}
		q = (struct tcpiphdr *)(q->ti_next);
	}
	tcpstat.tcps_rcvoopack++;
	tcpstat.tcps_rcvoobyte += ti->ti_len;
	REASS_MBUF(ti) = (mbufp_32) m;		/* XXX */

	/*
	 * While we overlap succeeding segments trim them or,
	 * if they are completely covered, dequeue them.
	 */
	while (q != (struct tcpiphdr *)tp) {
		register int i = (ti->ti_seq + ti->ti_len) - q->ti_seq;
		if (i <= 0)
			break;
		if (i < q->ti_len) {
			q->ti_seq += i;
			q->ti_len -= i;
			m_adj((struct mbuf *) REASS_MBUF(q), i);
			break;
		}
		q = (struct tcpiphdr *)q->ti_next;
		m = (struct mbuf *) REASS_MBUF((struct tcpiphdr *)q->ti_prev);
		slirp_remque((void *)(q->ti_prev));
		m_freem(m);
	}

	/*
	 * Stick new segment in its place.
	 */
	slirp_insque(ti, (void *)(q->ti_prev));

present:
	/*
	 * Present data to user, advancing rcv_nxt through
	 * completed sequence space.
	 */
	if (!TCPS_HAVEESTABLISHED(tp->t_state))
		return (0);
	ti = (struct tcpiphdr *) tp->seg_next;
	if (ti == (struct tcpiphdr *)tp || ti->ti_seq != tp->rcv_nxt)
		return (0);
	if (tp->t_state == TCPS_SYN_RECEIVED && ti->ti_len)
		return (0);
	do {
		tp->rcv_nxt += ti->ti_len;
		flags = ti->ti_flags & TH_FIN;
		slirp_remque(ti);
		m = (struct mbuf *) REASS_MBUF(ti); /* XXX */
		ti = (struct tcpiphdr *)ti->ti_next;
/*		if (so->so_state & SS_FCANTRCVMORE) */
		if (so->so_state & SS_FCANTSENDMORE)
			m_freem(m);
		else {
			if (so->so_emu) {
				if (tcp_emu(so,m)) sbappend(so, m);
			} else
				sbappend(so, m);
		}
	} while (ti != (struct tcpiphdr *)tp && ti->ti_seq == tp->rcv_nxt);
/*	sorwakeup(so); */
	return (flags);
}