📄 fragment.c
字号:
ip = (Ip *)buf->ip_pkt; packoff = (ip->frag_off & IP_FRAGOFF) << 3; /*-----------------------------------------------------------------*/ /* Fail if this fragment's offset is not expected. */ /*-----------------------------------------------------------------*/ if (offset != packoff) return FALSE; /*-----------------------------------------------------------------*/ /* Get fragment data length. If not last, trim to 8-byte multiple. */ /*-----------------------------------------------------------------*/ dlen = buf->length; if (buf->next) dlen &= ~7; /*-----------------------------------------------------------------*/ /* Add this fragment's IP data to total offset count. */ /*-----------------------------------------------------------------*/ offset += dlen; /*-----------------------------------------------------------------*/ /* Advance to next buffer and break if end of queue. */ /*-----------------------------------------------------------------*/ buf = buf->next; } while (buf); /*-------------------------------------------------------------------*/ /* Return FALSE if MF flag set in last fragment received. */ /*-------------------------------------------------------------------*/ if (ip->frag_off & IP_MF) return FALSE; /*-------------------------------------------------------------------*/ /* Get pointers to first fragment buffer and IP packet. */ /*-------------------------------------------------------------------*/ fbuf = queue->head; ip = (Ip *)fbuf->ip_pkt; /*-------------------------------------------------------------------*/ /* Get large buffer for fragment reassembly or free fragment queue. */ /*-------------------------------------------------------------------*/ hlen = IP_HLEN(ip); buf = tcpGetBuf(NIMHLEN + hlen + offset); if (buf == NULL) { free_queue(fbuf); NetTimerStop(&queue->timer); queue->state = IPFF_FREE; return FALSE; } /*-------------------------------------------------------------------*/ /* Copy entire IP header from first fragment. */ /*-------------------------------------------------------------------*/ memcpy(buf->ip_pkt, ip, hlen); /*-------------------------------------------------------------------*/ /* Initialize data length and pointer to recontructed IP packet. */ /*-------------------------------------------------------------------*/ dst = buf->ip_data = buf->ip_pkt + hlen; dlen = fbuf->length & ~7; /*-------------------------------------------------------------------*/ /* Convert buffer length to length of region starting at ip_data. */ /*-------------------------------------------------------------------*/ fbuf->length -= (fbuf->app_len + fbuf->app_len2); /*-------------------------------------------------------------------*/ /* Copy IP data from first fragment. */ /*-------------------------------------------------------------------*/ copy_ip_data(dst, fbuf, dlen); dst += dlen; /*-------------------------------------------------------------------*/ /* Copy data from remaining fragments. */ /*-------------------------------------------------------------------*/ for (;;) { NetBuf *tmp; /*-----------------------------------------------------------------*/ /* Free head of fragment queue and advance to next queued buffer. */ /*-----------------------------------------------------------------*/ tmp = fbuf; fbuf = fbuf->next; tcpRetBuf(&tmp); /*-----------------------------------------------------------------*/ /* Break on reaching end of queue. */ /*-----------------------------------------------------------------*/ if (fbuf == NULL) break; /*-----------------------------------------------------------------*/ /* Get fragment data length. If not last, trim to 8-byte multiple. */ /*-----------------------------------------------------------------*/ dlen = fbuf->length; if (fbuf->next) dlen &= ~7; /*-----------------------------------------------------------------*/ /* Convert length of first region and copy IP data. */ /*-----------------------------------------------------------------*/ hlen = IP_HLEN(fbuf->ip_pkt); fbuf->length -= (fbuf->app_len + fbuf->app_len2); copy_ip_data(dst, fbuf, dlen); dst += dlen; } /*-------------------------------------------------------------------*/ /* Fix the large packet header. */ /*-------------------------------------------------------------------*/ Net.Ip = (Ip *)buf->ip_pkt; Net.Ip->length = dst - buf->ip_pkt; Net.Ip->frag_off = 0; /*-------------------------------------------------------------------*/ /* Release fragment queue. */ /*-------------------------------------------------------------------*/ NetTimerStop(&queue->timer); queue->state = IPFF_FREE; /*-------------------------------------------------------------------*/ /* Initialize buffer length and use re-assembled buffer. */ /*-------------------------------------------------------------------*/ buf->length = dst - (ui8 *)buf->ip_data; RxBuf = buf; return TRUE;}/***********************************************************************//* copy_frag_hdr: copy IP header and options for a fragment *//* *//* Inputs: ipto = pointer to buffer containing fragment *//* ipfrom = pointer to original buffer *//* offindg = offset from original fragment *//* *//* Returns: header length in bytes *//* *//***********************************************************************/static int copy_frag_hdr(Ip *ipto, const Ip *ipfrom, int offindg){ int ito, ifrom; int opt_size; /*-------------------------------------------------------------------*/ /* If first fragment, copy all options and return header size. */ /*-------------------------------------------------------------------*/ if (offindg == 0) { memcpy(ipto, ipfrom, IP_HLEN(ipfrom)); return IP_HLEN(ipfrom); } /*-------------------------------------------------------------------*/ /* Else start with fixed header from first fragment (no options). */ /*-------------------------------------------------------------------*/ memcpy(ipto, ipfrom, IPMHLEN); /*-------------------------------------------------------------------*/ /* Only options with COPY bit set are copied to remaining fragments. */ /*-------------------------------------------------------------------*/ opt_size = IP_HLEN(ipfrom) - IPMHLEN; ifrom = ito = 0; while (ifrom < opt_size) { ui8 otype, olen; /*-----------------------------------------------------------------*/ /* Read option type and tentative length from source datagram. */ /*-----------------------------------------------------------------*/ otype = ipfrom->options[ifrom]; olen = ipfrom->options[ifrom + 1]; /*-----------------------------------------------------------------*/ /* If copy bit is set, copy using variable length field. */ /*-----------------------------------------------------------------*/ if (otype & IPO_COPY) { memcpy(&ipto->options[ito], &ipfrom->options[ifrom], olen); ito += olen; } /*-----------------------------------------------------------------*/ /* Nop and "end of option list" tokens are copied with length 1. */ /*-----------------------------------------------------------------*/ else if ((otype == IPO_NOP) || (otype == IPO_EOOP)) { ipto->options[ito++] = otype; olen = 1; } /*-----------------------------------------------------------------*/ /* Finished processing this option, advance to next. */ /*-----------------------------------------------------------------*/ ifrom += olen; /*-----------------------------------------------------------------*/ /* Exit loop if "end of list" token is found. */ /*-----------------------------------------------------------------*/ if (otype == IPO_EOOP) break; } /*-------------------------------------------------------------------*/ /* Pad to a multiple of 4 bytes using nop options. */ /*-------------------------------------------------------------------*/ while (ito & 3) ipto->options[ito++] = IPO_NOP; /*-------------------------------------------------------------------*/ /* Return header length (option list size plus fixed header size). */ /*-------------------------------------------------------------------*/ return ito + IPMHLEN;}/***********************************************************************//* frag_timeo: Process IP fragment timeout *//* *//* Input: timer = pointer to expired fragment timer *//* *//***********************************************************************/static void frag_timeo(void *object){ IpFragQ *queue = object; Ip *ip = (Ip *)queue->head->ip_pkt; /*-------------------------------------------------------------------*/ /* If fragment queue was valid, release the pending buffers. */ /*-------------------------------------------------------------------*/ if (queue->state == IPFF_VALID) { /*-----------------------------------------------------------------*/ /* Send ICMP time expired error message. */ /*-----------------------------------------------------------------*/ IcmpTimeEx(ICC_FTIMEX, queue->head, ip->src_ip, ip->dst_ip); /*-----------------------------------------------------------------*/ /* Free queued fragment buffers. */ /*-----------------------------------------------------------------*/ free_queue(queue->head); } /*-------------------------------------------------------------------*/ /* Declare expired entry to be free. */ /*-------------------------------------------------------------------*/ queue->state = IPFF_FREE;}/***********************************************************************//* Global Function Definitions *//***********************************************************************//***********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -