ip_reass(register struct ip *ip, register struct ipq *fp)

{

	register struct mbuf *m = dtom(ip);

	register struct ipasfrag *q;

	int hlen = ip->ip_hl << 2;

	int i, next;



	DEBUG_CALL("ip_reass");

	DEBUG_ARG("ip = %lx", (long)ip);

	DEBUG_ARG("fp = %lx", (long)fp);

	DEBUG_ARG("m = %lx", (long)m);



	/*

	 * Presence of header sizes in mbufs

	 * would confuse code below.

         * Fragment m_data is concatenated.

	 */

	m->m_data += hlen;

	m->m_len -= hlen;



	/*

	 * If first fragment to arrive, create a reassembly queue.

	 */

	if (fp == 0) {

	  struct mbuf *t;

	  if ((t = m_get()) == NULL) goto dropfrag;

	  fp = mtod(t, struct ipq *);

	  insque(&fp->ip_link, &ipq.ip_link);

	  fp->ipq_ttl = IPFRAGTTL;

	  fp->ipq_p = ip->ip_p;

	  fp->ipq_id = ip->ip_id;

	  fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;

	  fp->ipq_src = ip->ip_src;

	  fp->ipq_dst = ip->ip_dst;

	  q = (struct ipasfrag *)fp;

	  goto insert;

	}



	/*

	 * Find a segment which begins after this one does.

	 */

	for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;

            q = q->ipf_next)

		if (q->ipf_off > ip->ip_off)

			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 (q->ipf_prev != &fp->frag_link) {

        struct ipasfrag *pq = q->ipf_prev;

		i = pq->ipf_off + pq->ipf_len - ip->ip_off;

		if (i > 0) {

			if (i >= ip->ip_len)

				goto dropfrag;

			m_adj(dtom(ip), i);

			ip->ip_off += i;

			ip->ip_len -= i;

		}

	}



	/*

	 * While we overlap succeeding segments trim them or,

	 * if they are completely covered, dequeue them.

	 */

	while (q != (struct ipasfrag*)&fp->frag_link &&

            ip->ip_off + ip->ip_len > q->ipf_off) {

		i = (ip->ip_off + ip->ip_len) - q->ipf_off;

		if (i < q->ipf_len) {

			q->ipf_len -= i;

			q->ipf_off += i;

			m_adj(dtom(q), i);

			break;

		}

		q = q->ipf_next;

		m_freem(dtom(q->ipf_prev));

		ip_deq(q->ipf_prev);

	}



insert:

	/*

	 * Stick new segment in its place;

	 * check for complete reassembly.

	 */

	ip_enq(iptofrag(ip), q->ipf_prev);

	next = 0;

	for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;

            q = q->ipf_next) {

		if (q->ipf_off != next)

			return (0);

		next += q->ipf_len;

	}

	if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)

		return (0);



	/*

	 * Reassembly is complete; concatenate fragments.

	 */

    q = fp->frag_link.next;

	m = dtom(q);



	q = (struct ipasfrag *) q->ipf_next;

	while (q != (struct ipasfrag*)&fp->frag_link) {

	  struct mbuf *t = dtom(q);

	  q = (struct ipasfrag *) q->ipf_next;

	  m_cat(m, t);

	}



	/*

	 * Create header for new ip packet by

	 * modifying header of first packet;

	 * dequeue and discard fragment reassembly header.

	 * Make header visible.

	 */

	q = fp->frag_link.next;



	/*

	 * If the fragments concatenated to an mbuf that's

	 * bigger than the total size of the fragment, then and

	 * m_ext buffer was alloced. But fp->ipq_next points to

	 * the old buffer (in the mbuf), so we must point ip

	 * into the new buffer.

	 */

	if (m->m_flags & M_EXT) {

	  int delta;

	  delta = (char *)ip - m->m_dat;

	  q = (struct ipasfrag *)(m->m_ext + delta);

	}



	/* DEBUG_ARG("ip = %lx", (long)ip);

	 * ip=(struct ipasfrag *)m->m_data; */



    ip = fragtoip(q);

	ip->ip_len = next;

	ip->ip_tos &= ~1;

	ip->ip_src = fp->ipq_src;

	ip->ip_dst = fp->ipq_dst;

	remque(&fp->ip_link);

	(void) m_free(dtom(fp));

	m->m_len += (ip->ip_hl << 2);

	m->m_data -= (ip->ip_hl << 2);



	return ip;



dropfrag:

	STAT(ipstat.ips_fragdropped++);

	m_freem(m);

	return (0);

}

ip_reass(register struct ip *ip, register struct ipq *fp)

{

	register struct mbuf *m = dtom(ip);

	register struct ipasfrag *q;

	int hlen = ip->ip_hl << 2;

	int i, next;



	DEBUG_CALL("ip_reass");

	DEBUG_ARG("ip = %lx", (long)ip);

	DEBUG_ARG("fp = %lx", (long)fp);

	DEBUG_ARG("m = %lx", (long)m);



	









	m->m_data += hlen;

	m->m_len -= hlen;



	





	if (fp == 0) {

	  struct mbuf *t;

	  if ((t = m_get()) == NULL) goto dropfrag;

	  fp = mtod(t, struct ipq *);

	  insque(&fp->ip_link, &ipq.ip_link);

	  fp->ipq_ttl = IPFRAGTTL;

	  fp->ipq_p = ip->ip_p;

	  fp->ipq_id = ip->ip_id;

	  fp->frag_link.next = fp->frag_link.prev = &fp->frag_link;

	  fp->ipq_src = ip->ip_src;

	  fp->ipq_dst = ip->ip_dst;

	  q = (struct ipasfrag *)fp;

	  goto insert;

	}



	





	for (q = fp->frag_link.next; q != (struct ipasfrag *)&fp->frag_link;

            q = q->ipf_next)

		if (q->ipf_off > ip->ip_off)

			break;



	









	if (q->ipf_prev != &fp->frag_link) {

        struct ipasfrag *pq = q->ipf_prev;

		i = pq->ipf_off + pq->ipf_len - ip->ip_off;

		if (i > 0) {

			if (i >= ip->ip_len)

				goto dropfrag;

			m_adj(dtom(ip), i);

			ip->ip_off += i;

			ip->ip_len -= i;

		}

	}



	







	while (q != (struct ipasfrag*)&fp->frag_link &&

            ip->ip_off + ip->ip_len > q->ipf_off) {

		i = (ip->ip_off + ip->ip_len) - q->ipf_off;

		if (i < q->ipf_len) {

			q->ipf_len -= i;

			q->ipf_off += i;

			m_adj(dtom(q), i);

			break;

		}

		q = q->ipf_next;

		m_freem(dtom(q->ipf_prev));

		ip_deq(q->ipf_prev);

	}



insert:

	







	ip_enq(iptofrag(ip), q->ipf_prev);

	next = 0;

	for (q = fp->frag_link.next; q != (struct ipasfrag*)&fp->frag_link;

            q = q->ipf_next) {

		if (q->ipf_off != next)

			return (0);

		next += q->ipf_len;

	}

	if (((struct ipasfrag *)(q->ipf_prev))->ipf_tos & 1)

		return (0);



	





    q = fp->frag_link.next;

	m = dtom(q);



	q = (struct ipasfrag *) q->ipf_next;

	while (q != (struct ipasfrag*)&fp->frag_link) {

	  struct mbuf *t = dtom(q);

	  q = (struct ipasfrag *) q->ipf_next;

	  m_cat(m, t);

	}



	











	q = fp->frag_link.next;



	













	if (m->m_flags & M_EXT) {

	  int delta;

	  delta = (char *)ip - m->m_dat;

	  q = (struct ipasfrag *)(m->m_ext + delta);

	}



	





    ip = fragtoip(q);

	ip->ip_len = next;

	ip->ip_tos &= ~1;

	ip->ip_src = fp->ipq_src;

	ip->ip_dst = fp->ipq_dst;

	remque(&fp->ip_link);

	(void) m_free(dtom(fp));

	m->m_len += (ip->ip_hl << 2);

	m->m_data -= (ip->ip_hl << 2);



	return ip;



dropfrag:

	STAT(ipstat.ips_fragdropped++);

	m_freem(m);

	return (0);

}

	  int delta; 	  delta = (char *)ip - m->m_dat;
FUNC_0(register struct VAR_0 *VAR_0, register struct ipq *VAR_1)

{

	register struct mbuf *VAR_2 = dtom(VAR_0);

	register struct ipasfrag *VAR_3;

	int VAR_4 = VAR_0->ip_hl << 2;

	int VAR_5, VAR_6;



	DEBUG_CALL("FUNC_0");

	DEBUG_ARG("VAR_0 = %lx", (long)VAR_0);

	DEBUG_ARG("VAR_1 = %lx", (long)VAR_1);

	DEBUG_ARG("VAR_2 = %lx", (long)VAR_2);



	









	VAR_2->m_data += VAR_4;

	VAR_2->m_len -= VAR_4;



	





	if (VAR_1 == 0) {

	  struct mbuf *VAR_9;

	  if ((VAR_9 = m_get()) == NULL) goto dropfrag;

	  VAR_1 = mtod(VAR_9, struct ipq *);

	  insque(&VAR_1->ip_link, &ipq.ip_link);

	  VAR_1->ipq_ttl = IPFRAGTTL;

	  VAR_1->ipq_p = VAR_0->ip_p;

	  VAR_1->ipq_id = VAR_0->ip_id;

	  VAR_1->frag_link.VAR_6 = VAR_1->frag_link.prev = &VAR_1->frag_link;

	  VAR_1->ipq_src = VAR_0->ip_src;

	  VAR_1->ipq_dst = VAR_0->ip_dst;

	  VAR_3 = (struct ipasfrag *)VAR_1;

	  goto insert;

	}



	





	for (VAR_3 = VAR_1->frag_link.VAR_6; VAR_3 != (struct ipasfrag *)&VAR_1->frag_link;

            VAR_3 = VAR_3->ipf_next)

		if (VAR_3->ipf_off > VAR_0->ip_off)

			break;



	









	if (VAR_3->ipf_prev != &VAR_1->frag_link) {

        struct ipasfrag *VAR_8 = VAR_3->ipf_prev;

		VAR_5 = VAR_8->ipf_off + VAR_8->ipf_len - VAR_0->ip_off;

		if (VAR_5 > 0) {

			if (VAR_5 >= VAR_0->ip_len)

				goto dropfrag;

			m_adj(dtom(VAR_0), VAR_5);

			VAR_0->ip_off += VAR_5;

			VAR_0->ip_len -= VAR_5;

		}

	}



	







	while (VAR_3 != (struct ipasfrag*)&VAR_1->frag_link &&

            VAR_0->ip_off + VAR_0->ip_len > VAR_3->ipf_off) {

		VAR_5 = (VAR_0->ip_off + VAR_0->ip_len) - VAR_3->ipf_off;

		if (VAR_5 < VAR_3->ipf_len) {

			VAR_3->ipf_len -= VAR_5;

			VAR_3->ipf_off += VAR_5;

			m_adj(dtom(VAR_3), VAR_5);

			break;

		}

		VAR_3 = VAR_3->ipf_next;

		m_freem(dtom(VAR_3->ipf_prev));

		ip_deq(VAR_3->ipf_prev);

	}



insert:

	







	ip_enq(iptofrag(VAR_0), VAR_3->ipf_prev);

	VAR_6 = 0;

	for (VAR_3 = VAR_1->frag_link.VAR_6; VAR_3 != (struct ipasfrag*)&VAR_1->frag_link;

            VAR_3 = VAR_3->ipf_next) {

		if (VAR_3->ipf_off != VAR_6)

			return (0);

		VAR_6 += VAR_3->ipf_len;

	}

	if (((struct ipasfrag *)(VAR_3->ipf_prev))->ipf_tos & 1)

		return (0);



	





    VAR_3 = VAR_1->frag_link.VAR_6;

	VAR_2 = dtom(VAR_3);



	VAR_3 = (struct ipasfrag *) VAR_3->ipf_next;

	while (VAR_3 != (struct ipasfrag*)&VAR_1->frag_link) {

	  struct mbuf *VAR_9 = dtom(VAR_3);

	  VAR_3 = (struct ipasfrag *) VAR_3->ipf_next;

	  m_cat(VAR_2, VAR_9);

	}



	











	VAR_3 = VAR_1->frag_link.VAR_6;



	













	if (VAR_2->m_flags & M_EXT) {

	  int VAR_9;

	  VAR_9 = (char *)VAR_0 - VAR_2->m_dat;

	  VAR_3 = (struct ipasfrag *)(VAR_2->m_ext + VAR_9);

	}



	





    VAR_0 = fragtoip(VAR_3);

	VAR_0->ip_len = VAR_6;

	VAR_0->ip_tos &= ~1;

	VAR_0->ip_src = VAR_1->ipq_src;

	VAR_0->ip_dst = VAR_1->ipq_dst;

	remque(&VAR_1->ip_link);

	(void) m_free(dtom(VAR_1));

	VAR_2->m_len += (VAR_0->ip_hl << 2);

	VAR_2->m_data -= (VAR_0->ip_hl << 2);



	return VAR_0;



dropfrag:

	STAT(ipstat.ips_fragdropped++);

	m_freem(VAR_2);

	return (0);

}

FUNC_0(register struct VAR_0 *VAR_0, register struct ipq *VAR_1)
{ register struct mbuf *VAR_2 = dtom(VAR_0); register struct ipasfrag *VAR_3; int VAR_4 = VAR_0->ip_hl << 2; int VAR_5, VAR_6; DEBUG_CALL("FUNC_0"); DEBUG_ARG("VAR_0 = %lx", (long)VAR_0); DEBUG_ARG("VAR_1 = %lx", (long)VAR_1); DEBUG_ARG("VAR_2 = %lx", (long)VAR_2); VAR_2->m_data += VAR_4; VAR_2->m_len -= VAR_4; if (VAR_1 == 0) { struct mbuf *VAR_9; if ((VAR_9 = m_get()) == NULL) goto dropfrag; VAR_1 = mtod(VAR_9, struct ipq *); insque(&VAR_1->ip_link, &ipq.ip_link); VAR_1->ipq_ttl = IPFRAGTTL; VAR_1->ipq_p = VAR_0->ip_p; VAR_1->ipq_id = VAR_0->ip_id; VAR_1->frag_link.VAR_6 = VAR_1->frag_link.prev = &VAR_1->frag_link; VAR_1->ipq_src = VAR_0->ip_src; VAR_1->ipq_dst = VAR_0->ip_dst; VAR_3 = (struct ipasfrag *)VAR_1; goto insert; } for (VAR_3 = VAR_1->frag_link.VAR_6; VAR_3 != (struct ipasfrag *)&VAR_1->frag_link; VAR_3 = VAR_3->ipf_next)
if (VAR_3->ipf_off > VAR_0->ip_off)
break; if (VAR_3->ipf_prev != &VAR_1->frag_link) { struct ipasfrag *VAR_8 = VAR_3->ipf_prev; VAR_5 = VAR_8->ipf_off + VAR_8->ipf_len - VAR_0->ip_off; if (VAR_5 > 0) { if (VAR_5 >= VAR_0->ip_len)
goto dropfrag; m_adj(dtom(VAR_0), VAR_5); VAR_0->ip_off += VAR_5; VAR_0->ip_len -= VAR_5; } } while (VAR_3 != (struct ipasfrag*)&VAR_1->frag_link &&
VAR_0->ip_off + VAR_0->ip_len > VAR_3->ipf_off) { VAR_5 = (VAR_0->ip_off + VAR_0->ip_len) - VAR_3->ipf_off; if (VAR_5 < VAR_3->ipf_len) { VAR_3->ipf_len -= VAR_5; VAR_3->ipf_off += VAR_5; m_adj(dtom(VAR_3), VAR_5); break; } VAR_3 = VAR_3->ipf_next; m_freem(dtom(VAR_3->ipf_prev)); ip_deq(VAR_3->ipf_prev); } insert:
ip_enq(iptofrag(VAR_0), VAR_3->ipf_prev); VAR_6 = 0; for (VAR_3 = VAR_1->frag_link.VAR_6; VAR_3 != (struct ipasfrag*)&VAR_1->frag_link; VAR_3 = VAR_3->ipf_next) { if (VAR_3->ipf_off != VAR_6)
return (0); VAR_6 += VAR_3->ipf_len; } if (((struct ipasfrag *)(VAR_3->ipf_prev))->ipf_tos & 1)
return (0); VAR_3 = VAR_1->frag_link.VAR_6; VAR_2 = dtom(VAR_3); VAR_3 = (struct ipasfrag *) VAR_3->ipf_next; while (VAR_3 != (struct ipasfrag*)&VAR_1->frag_link) { struct mbuf *VAR_9 = dtom(VAR_3); VAR_3 = (struct ipasfrag *) VAR_3->ipf_next; m_cat(VAR_2, VAR_9); } VAR_3 = VAR_1->frag_link.VAR_6; if (VAR_2->m_flags & M_EXT) { int VAR_9; VAR_9 = (char *)VAR_0 - VAR_2->m_dat; VAR_3 = (struct ipasfrag *)(VAR_2->m_ext + VAR_9); } VAR_0 = fragtoip(VAR_3); VAR_0->ip_len = VAR_6; VAR_0->ip_tos &= ~1; VAR_0->ip_src = VAR_1->ipq_src; VAR_0->ip_dst = VAR_1->ipq_dst; remque(&VAR_1->ip_link); (void) m_free(dtom(VAR_1)); VAR_2->m_len += (VAR_0->ip_hl << 2); VAR_2->m_data -= (VAR_0->ip_hl << 2); return VAR_0; dropfrag:
STAT(ipstat.ips_fragdropped++); m_freem(VAR_2); return (0); }