Пример #1
0
struct tcpcb * 
tcp_drop(struct tcpcb * tp, int err)
{
   struct socket *   so =  tp->t_inpcb->inp_socket;

   if (TCPS_HAVERCVDSYN(tp->t_state)) 
   {
      tp->t_state = TCPS_CLOSED;
      (void) tcp_output(tp);
      tcpstat.tcps_drops++;
   }
   else
      tcpstat.tcps_conndrops++;
   so->so_error = err;
#ifdef TCP_ZEROCOPY
   if (so->rx_upcall)
      so->rx_upcall(so, NULL, err);
#endif   /* TCP_ZEROCOPY */
   return (tcp_close(tp));
}
Пример #2
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);
}