📄 clnp_frag.c
字号:
return(1);}/* * FUNCTION: clnp_insert_frag * * PURPOSE: Insert fragment into list headed by 'cf'. * * RETURNS: nothing * * SIDE EFFECTS: * * NOTES: This is the 'guts' of the reassembly algorithm. * Each fragment in this list contains a clnp_frag * structure followed by the data of the fragment. * The clnp_frag structure actually lies on top of * part of the old clnp header. */clnp_insert_frag(cfh, m, seg)struct clnp_fragl *cfh; /* header of list of packet fragments */struct mbuf *m; /* new fragment */struct clnp_segment *seg; /* segment part of fragment header */{ register struct clnp_fixed *clnp; /* clnp hdr of fragment */ register struct clnp_frag *cf; /* generic fragment ptr */ register struct clnp_frag *cf_sub = NULL; /* frag subsequent to new one */ register struct clnp_frag *cf_prev = NULL; /* frag previous to new one */ u_short first; /* offset of first byte of initial pdu*/ u_short last; /* offset of last byte of initial pdu */ u_short fraglen;/* length of fragment */ clnp = mtod(m, struct clnp_fixed *); first = seg->cng_off; CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, fraglen); fraglen -= clnp->cnf_hdr_len; last = (first + fraglen) - 1; IFDEBUG(D_REASS) printf("clnp_insert_frag: New fragment: [%d ... %d], len %d\n", first, last, fraglen); printf("clnp_insert_frag: current fragments:\n"); for (cf = cfh->cfl_frags; cf != NULL; cf = cf->cfr_next) { printf("\tcf x%x: [%d ... %d]\n", cf, cf->cfr_first, cf->cfr_last); } ENDDEBUG if (cfh->cfl_frags != NULL) { /* * Find fragment which begins after the new one */ for (cf = cfh->cfl_frags; cf != NULL; cf_prev = cf, cf = cf->cfr_next) { if (cf->cfr_first > first) { cf_sub = cf; break; } } IFDEBUG(D_REASS) printf("clnp_insert_frag: Previous frag is "); if (cf_prev == NULL) printf("NULL\n"); else printf("[%d ... %d]\n", cf_prev->cfr_first, cf_prev->cfr_last); printf("clnp_insert_frag: Subsequent frag is "); if (cf_sub == NULL) printf("NULL\n"); else printf("[%d ... %d]\n", cf_sub->cfr_first, cf_sub->cfr_last); ENDDEBUG /* * If there is a fragment before the new one, check if it * overlaps the new one. If so, then trim the end of the * previous one. */ if (cf_prev != NULL) { if (cf_prev->cfr_last > first) { u_short overlap = cf_prev->cfr_last - first; IFDEBUG(D_REASS) printf("clnp_insert_frag: previous overlaps by %d\n", overlap); ENDDEBUG if (overlap > fraglen) { /* * The new fragment is entirely contained in the * preceeding one. We can punt on the new frag * completely. */ m_freem(m); return; } else { /* Trim data off of end of previous fragment */ /* inc overlap to prevent duplication of last byte */ overlap++; m_adj(cf_prev->cfr_data, -(int)overlap); cf_prev->cfr_last -= overlap; } } } /* * For all fragments past the new one, check if any data on * the new one overlaps data on existing fragments. If so, * then trim the extra data off the end of the new one. */ for (cf = cf_sub; cf != NULL; cf = cf->cfr_next) { if (cf->cfr_first < last) { u_short overlap = last - cf->cfr_first; IFDEBUG(D_REASS) printf("clnp_insert_frag: subsequent overlaps by %d\n", overlap); ENDDEBUG if (overlap > fraglen) { /* * The new fragment is entirely contained in the * succeeding one. This should not happen, because * early on in this code we scanned for the fragment * which started after the new one! */ m_freem(m); printf("clnp_insert_frag: internal error!\n"); return; } else { /* Trim data off of end of new fragment */ /* inc overlap to prevent duplication of last byte */ overlap++; m_adj(m, -(int)overlap); last -= overlap; } } } } /* * Insert the new fragment beween cf_prev and cf_sub * * Note: the clnp hdr is still in the mbuf. * If the data of the mbuf is not word aligned, shave off enough * so that it is. Then, cast the clnp_frag structure on top * of the clnp header. * The clnp_hdr will not be used again (as we already have * saved a copy of it). * * Save in cfr_bytes the number of bytes to shave off to get to * the data of the packet. This is used when we coalesce fragments; * the clnp_frag structure must be removed before joining mbufs. */ { int pad; u_int bytes; /* determine if header is not word aligned */ pad = (int)clnp % 4; if (pad < 0) pad = -pad; /* bytes is number of bytes left in front of data */ bytes = clnp->cnf_hdr_len - pad; IFDEBUG(D_REASS) printf("clnp_insert_frag: clnp x%x requires %d alignment\n", clnp, pad); ENDDEBUG /* make it word aligned if necessary */ if (pad) m_adj(m, pad); cf = mtod(m, struct clnp_frag *); cf->cfr_bytes = bytes; IFDEBUG(D_REASS) printf("clnp_insert_frag: cf now x%x, cfr_bytes %d\n", cf, cf->cfr_bytes); ENDDEBUG } cf->cfr_first = first; cf->cfr_last = last; /* * The data is the mbuf itself, although we must remember that the * first few bytes are actually a clnp_frag structure */ cf->cfr_data = m; /* link into place */ cf->cfr_next = cf_sub; if (cf_prev == NULL) cfh->cfl_frags = cf; else cf_prev->cfr_next = cf;}/* * FUNCTION: clnp_comp_pdu * * PURPOSE: Scan the list of fragments headed by cfh. Merge * any contigious fragments into one. If, after * traversing all the fragments, it is determined that * the packet is complete, then return a pointer to * the packet (with header prepended). Otherwise, * return NULL. * * RETURNS: NULL, or a pointer to the assembled pdu in an mbuf chain. * * SIDE EFFECTS: Will colapse contigious fragments into one. * * NOTES: This code assumes that there are no overlaps of * fragment pdus. */struct mbuf *clnp_comp_pdu(cfh)struct clnp_fragl *cfh; /* fragment header */{ register struct clnp_frag *cf = cfh->cfl_frags; while (cf->cfr_next != NULL) { register struct clnp_frag *cf_next = cf->cfr_next; IFDEBUG(D_REASS) printf("clnp_comp_pdu: comparing: [%d ... %d] to [%d ... %d]\n", cf->cfr_first, cf->cfr_last, cf_next->cfr_first, cf_next->cfr_last); ENDDEBUG if (cf->cfr_last == (cf_next->cfr_first - 1)) { /* * Merge fragment cf and cf_next * * - update cf header * - trim clnp_frag structure off of cf_next * - append cf_next to cf */ struct clnp_frag cf_next_hdr; struct clnp_frag *next_frag; cf_next_hdr = *cf_next; next_frag = cf_next->cfr_next; IFDEBUG(D_REASS) struct mbuf *mdump; int l; printf("clnp_comp_pdu: merging fragments\n"); printf("clnp_comp_pdu: 1st: [%d ... %d] (bytes %d)\n", cf->cfr_first, cf->cfr_last, cf->cfr_bytes); mdump = cf->cfr_data; l = 0; while (mdump != NULL) { printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len); l += mdump->m_len; mdump = mdump->m_next; } printf("\ttotal len: %d\n", l); printf("clnp_comp_pdu: 2nd: [%d ... %d] (bytes %d)\n", cf_next->cfr_first, cf_next->cfr_last, cf_next->cfr_bytes); mdump = cf_next->cfr_data; l = 0; while (mdump != NULL) { printf("\tmbuf x%x, m_len %d\n", mdump, mdump->m_len); l += mdump->m_len; mdump = mdump->m_next; } printf("\ttotal len: %d\n", l); ENDDEBUG cf->cfr_last = cf_next->cfr_last; /* * After this m_adj, the cf_next ptr is useless because we * have adjusted the clnp_frag structure away... */ IFDEBUG(D_REASS) printf("clnp_comp_pdu: shaving off %d bytes\n", cf_next_hdr.cfr_bytes); ENDDEBUG m_adj(cf_next_hdr.cfr_data, (int)cf_next_hdr.cfr_bytes); m_cat(cf->cfr_data, cf_next_hdr.cfr_data); cf->cfr_next = next_frag; } else { cf = cf->cfr_next; } } cf = cfh->cfl_frags; IFDEBUG(D_REASS) struct mbuf *mdump = cf->cfr_data; printf("clnp_comp_pdu: first frag now: [%d ... %d]\n", cf->cfr_first, cf->cfr_last); printf("clnp_comp_pdu: data for frag:\n"); while (mdump != NULL) { printf("mbuf x%x, m_len %d\n", mdump, mdump->m_len);/* dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/ mdump = mdump->m_next; } ENDDEBUG /* Check if datagram is complete */ if ((cf->cfr_first == 0) && (cf->cfr_last == cfh->cfl_last)) { /* * We have a complete pdu! * - Remove the frag header from (only) remaining fragment * (which is not really a fragment anymore, as the datagram is * complete). * - Prepend a clnp header */ struct mbuf *data = cf->cfr_data; struct mbuf *hdr = cfh->cfl_orighdr; struct clnp_fragl *scan; IFDEBUG(D_REASS) printf("clnp_comp_pdu: complete pdu!\n"); ENDDEBUG m_adj(data, (int)cf->cfr_bytes); m_cat(hdr, data); IFDEBUG(D_DUMPIN) struct mbuf *mdump = hdr; printf("clnp_comp_pdu: pdu is:\n"); while (mdump != NULL) { printf("mbuf x%x, m_len %d\n", mdump, mdump->m_len);/* dump_buf(mtod(mdump, caddr_t), mdump->m_len);*/ mdump = mdump->m_next; } ENDDEBUG /* * Remove cfh from the list of fragmented pdus */ if (clnp_frags == cfh) { clnp_frags = cfh->cfl_next; } else { for (scan = clnp_frags; scan != NULL; scan = scan->cfl_next) { if (scan->cfl_next == cfh) { scan->cfl_next = cfh->cfl_next; break; } } } /* free cfh */ m_freem(dtom(cfh)); return(hdr); } return(NULL);}#ifdef TROLLstatic int troll_cnt;#include <sys/time.h>/* * FUNCTION: troll_random * * PURPOSE: generate a pseudo-random number between 0 and 1 * * RETURNS: the random number * * SIDE EFFECTS: * * NOTES: This is based on the clock. */float troll_random(){ extern struct timeval time; long t = time.tv_usec % 100; return((float)t / (float) 100);}/* * FUNCTION: troll_output * * PURPOSE: Do something sneaky with the datagram passed. Possible * operations are: * Duplicate the packet * Drop the packet * Trim some number of bytes from the packet * Munge some byte in the packet * * RETURNS: 0, or unix error code * * SIDE EFFECTS: * * NOTES: The operation of this procedure is regulated by the * troll control structure (Troll). */troll_output(ifp, m, dst, rt)struct ifnet *ifp;struct mbuf *m;struct sockaddr *dst;struct rtentry *rt;{ int err = 0; troll_cnt++; if (trollctl.tr_ops & TR_DUPPKT) { /* * Duplicate every Nth packet * TODO: random? */ float f_freq = troll_cnt * trollctl.tr_dup_freq; int i_freq = troll_cnt * trollctl.tr_dup_freq; if (i_freq == f_freq) { struct mbuf *dup = m_copy(m, 0, (int)M_COPYALL); if (dup != NULL) err = (*ifp->if_output)(ifp, dup, dst, rt); } if (!err) err = (*ifp->if_output)(ifp, m, dst, rt); return(err); } else if (trollctl.tr_ops & TR_DROPPKT) { } else if (trollctl.tr_ops & TR_CHANGE) { struct clnp_fixed *clnp = mtod(m, struct clnp_fixed *); clnp->cnf_cksum_msb = 0; err = (*ifp->if_output)(ifp, m, dst, rt); return(err); } else { err = (*ifp->if_output)(ifp, m, dst, rt); return(err); }}#endif /* TROLL */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -