- /***********************************************************
- * *
- * merge fragment into reass.q *
- * algorithm: match start and end bytes of new *
- * fragment with fragments on the queue. if no *
- * overlaps are found, add new frag. to the queue. *
- * otherwise, adjust start and end of new frag. so no *
- * overlap and add remainder to queue. if any *
- * fragments are completely covered by the new one, or *
- * if the new one is completely duplicated, free the *
- * fragments. *
- * *
- ***********************************************************/
-
- q = fp->iqx.ip_next; /* -> top of reass. chain */
- ip->ip_end = ip->ip_off + ip->ip_len - 1;
-
- /* skip frags which new doesn't overlap at end */
-
- while ((q != (struct ip *)fp) && (ip->ip_off > q->ip_end))
- q = q->ip_next;
-
- if (q == (struct ip *)fp) /* frag at end of chain */
- ip_enq(ip, fp->iqx.ip_prev);
-
- else {
- if (ip->ip_end < q->ip_off) /* frag doesn't overlap any on chain */
- ip_enq(ip, q->ip_prev);
-
- /* new overlaps beginning of next frag only */
-
- else if (ip->ip_end < q->ip_end) {
- if ((i = ip->ip_end - q->ip_off + 1) < ip->ip_len) {
- ip->ip_len -= i;
- ip->ip_end -= i;
- m_adj(mp, -i);
- ip_enq(ip, q->ip_prev);
- } else
- m_freem(mp);
-
- /* new overlaps end of previous frag */
-
- } else {
-
- savq = q;
- if (ip->ip_off <= q->ip_off) { /* complete cover */
- savq = q->ip_prev;
- ip_deq(q);
- m_freem(dtom(q));
-
- } else { /* overlap */
- if ((i = q->ip_end - ip->ip_off + 1) < ip->ip_len) {
- ip->ip_off += i;
- ip->ip_len -= i;
- m_adj(mp, i);
- } else
- ip->ip_len = 0;
- }
-
- /* new overlaps at beginning of successor frags */
-
- q = savq->ip_next;
- while ((q != (struct ip *)fp) && (ip->ip_len != 0) &&
- (q->ip_off < ip->ip_end))
-
- /* complete cover */
-
- if (q->ip_end <= ip->ip_end) {
- p = q->ip_next;
- ip_deq(q);
- m_freem(dtom(q));
- q = p;
-
- } else { /* overlap */
-
- if ((i = ip->ip_end - q->ip_off + 1) < ip->ip_len) {
- ip->ip_len -= i;
- ip->ip_end -= i;
- m_adj(mp, -i);
- } else
- ip->ip_len = 0;
- break;
- }