📄 fragment.c
字号:
/* IpFragInit: Initialize IP fragment queue data structures *//* *//***********************************************************************/void IpFragInit(void){ IpFragQ *queue = &FragQ[0]; /*-------------------------------------------------------------------*/ /* Initialize fragment table entries. */ /*-------------------------------------------------------------------*/ for (queue = &FragQ[0]; queue < &FragQ[IP_FQSIZE]; ++queue) { queue->state = IPFF_FREE; queue->timer.action = frag_timeo; queue->timer.object = queue; INIT_TMR(queue->timer); } /*-------------------------------------------------------------------*/ /* Assign a random initial fragment identifier. */ /*-------------------------------------------------------------------*/ Net.IpAckId = rand();}/***********************************************************************//* IpOut: Send a packet to an interface's output queue *//* *//* Input: object = pointer to outbound packet buffer *//* *//***********************************************************************/void IpOut(void *object){ NetBuf *buf = object; Ip *ip = (Ip *)buf->ip_pkt; uint hlen, max, frag_dlen, tosend, offindg; Ni *ni = buf->ni; NetBuf *fbuf; Ip *ipfrag; /*-------------------------------------------------------------------*/ /* Copy IP length to buffer length field. */ /*-------------------------------------------------------------------*/ buf->length = ip->length; /*-------------------------------------------------------------------*/ /* Determine if no fragmentation is required. */ /*-------------------------------------------------------------------*/ if (ip->length <= ni->mtu) { /*-----------------------------------------------------------------*/ /* Change IP header to network byte order. */ /*-----------------------------------------------------------------*/ ip->length = htons(ip->length); ip->ip_id = htons(ip->ip_id); ip->frag_off = htons(ip->frag_off); /*-----------------------------------------------------------------*/ /* Calculate IP checksum and pass to network interface. */ /*-----------------------------------------------------------------*/ ip->checksum = 0; ip->checksum = IpChecksum(ip, IP_HLEN(ip)); NiWrite(buf); return; } /*-------------------------------------------------------------------*/ /* Fragmentation required, error if "do not fragment" bit is set. */ /*-------------------------------------------------------------------*/ if (ip->frag_off & IP_DF) { ++Stats.IpFragFails; IcmpDestUR(ICC_FRAGREQ, buf, ip->src_ip, ip->dst_ip); tcpRetBuf(&buf); return; } /*-------------------------------------------------------------------*/ /* The maximum data length must be a multiple of eight bytes. */ /*-------------------------------------------------------------------*/ frag_dlen = max = (ni->mtu - IP_HLEN(ip)) & ~7; /*-------------------------------------------------------------------*/ /* Calculate offset from original datagram and total amount to send. */ /*-------------------------------------------------------------------*/ offindg = (ip->frag_off & IP_FRAGOFF) << 3; tosend = ip->length - IP_HLEN(ip); /*-------------------------------------------------------------------*/ /* Convert buffer length to length of region starting at ip_data. */ /*-------------------------------------------------------------------*/ buf->length -= (buf->app_len + buf->app_len2); /*-------------------------------------------------------------------*/ /* Loop until all fragments have been sent. */ /*-------------------------------------------------------------------*/ do { /*-----------------------------------------------------------------*/ /* Get fragment buffer. */ /*-----------------------------------------------------------------*/ fbuf = tcpGetBuf(NIMHLEN + IPMHLEN + frag_dlen); if (fbuf == NULL) { ++Stats.IpFragFails; tcpRetBuf(&buf); return; } /*-----------------------------------------------------------------*/ /* Get pointer to fragment's IP datagram. */ /*-----------------------------------------------------------------*/ ipfrag = (Ip *)fbuf->ip_pkt; /*-----------------------------------------------------------------*/ /* Copy header from original datagram. */ /*-----------------------------------------------------------------*/ hlen = copy_frag_hdr(ipfrag, ip, offindg); /*-----------------------------------------------------------------*/ /* Prepare fragment offset and packet length fields. */ /*-----------------------------------------------------------------*/ if (tosend <= max) ipfrag->frag_off = (IP_MF & ip->frag_off); else ipfrag->frag_off = IP_MF; ipfrag->frag_off |= offindg >> 3; ipfrag->length = frag_dlen + hlen; /*-----------------------------------------------------------------*/ /* Assign buffer length. */ /*-----------------------------------------------------------------*/ fbuf->length = ipfrag->length; /*-----------------------------------------------------------------*/ /* Change IP header to network byte order. */ /*-----------------------------------------------------------------*/ ipfrag->length = htons(ipfrag->length); ipfrag->ip_id = htons(ipfrag->ip_id); ipfrag->frag_off = htons(ipfrag->frag_off); /*-----------------------------------------------------------------*/ /* Calculate IP checksum. */ /*-----------------------------------------------------------------*/ ipfrag->checksum = 0; ipfrag->checksum = IpChecksum(ipfrag, hlen); /*-----------------------------------------------------------------*/ /* Copy fragment data and next hop address. */ /*-----------------------------------------------------------------*/ copy_ip_data((ui8 *)ipfrag + hlen, buf, frag_dlen); fbuf->next_hop = buf->next_hop; /*-----------------------------------------------------------------*/ /* Set packet type and network interface and request transmission. */ /*-----------------------------------------------------------------*/ fbuf->type = htons(IP_TYPE); fbuf->ni = buf->ni; NiWrite(fbuf); /*-----------------------------------------------------------------*/ /* Update indices and adjust data length for last fragment. */ /*-----------------------------------------------------------------*/ offindg += frag_dlen; tosend -= frag_dlen; if (tosend < max) frag_dlen = tosend; /*-----------------------------------------------------------------*/ /* Update statistics. */ /*-----------------------------------------------------------------*/ ++Stats.IpFragCreates; } while (tosend > 0); /*-------------------------------------------------------------------*/ /* Free buffer containing original packet. */ /*-------------------------------------------------------------------*/ tcpRetBuf(&buf);}/***********************************************************************//* IpJoinFrag: Reassemble incoming IP datagram, if possible *//* *//* Returns: TRUE iff packet is re-assembled *//* *//***********************************************************************/int IpJoinFrag(void){ IpFragQ *frag; IpFragQ *firstfree = NULL; /*-------------------------------------------------------------------*/ /* Search for matching datagram ID in array of fragment queues. */ /*-------------------------------------------------------------------*/ for (frag = &FragQ[0]; frag < &FragQ[IP_FQSIZE]; ++frag) { /*-----------------------------------------------------------------*/ /* Skip if free. Also, remember first free entry found. */ /*-----------------------------------------------------------------*/ if (frag->state == IPFF_FREE) { if (firstfree == NULL) firstfree = frag; continue; } /*-----------------------------------------------------------------*/ /* Continue if datagram ID or source IP address don't match. */ /*-----------------------------------------------------------------*/ if ((frag->ip_id != Net.Ip->ip_id) || (frag->src_ip != Net.Ip->src_ip)) continue; /*-----------------------------------------------------------------*/ /* Free buffer and return FALSE if queue state is invalid. */ /*-----------------------------------------------------------------*/ if (frag->state != IPFF_VALID) goto add_fail; /*-----------------------------------------------------------------*/ /* Try to add fragment to queue. Free buffer if unable. */ /*-----------------------------------------------------------------*/ if (add_frag(frag) == FALSE) goto add_fail; /*-----------------------------------------------------------------*/ /* Successfully added fragment. Test for complete datagram. */ /*-----------------------------------------------------------------*/ return join_frag(frag); } /*-------------------------------------------------------------------*/ /* Free buffer if unable to make new fragment queue. */ /*-------------------------------------------------------------------*/ if (firstfree == NULL) goto add_fail; /*-------------------------------------------------------------------*/ /* Initialize new queue and add fragment. */ /*-------------------------------------------------------------------*/ RxBuf->next = NULL; firstfree->head = RxBuf; firstfree->src_ip = Net.Ip->src_ip; firstfree->ip_id = Net.Ip->ip_id; firstfree->state = IPFF_VALID; firstfree->count = 1; NetTimerStart(&firstfree->timer, IP_FTTL); return FALSE;add_fail: tcpRetBuf(&RxBuf); return FALSE;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -