📄 fragment.c
字号:
/***********************************************************************//* *//* Module: tcp_ip/ip/fragment.c *//* Release: 2001.3 *//* Version: 2000.0 *//* Purpose: IP Fragment Processing *//* *//*---------------------------------------------------------------------*//* *//* Copyright 2000, Blunk Microsystems *//* ALL RIGHTS RESERVED *//* *//* Licensees have the non-exclusive right to use, modify, or extract *//* this computer program for software development at a single site. *//* This program may be resold or disseminated in executable format *//* only. The source code may not be redistributed or resold. *//* *//***********************************************************************/#include "../tcp_ipp.h"#include <string.h>#include <stdlib.h>#include "ip.h"/***********************************************************************//* Configuration *//***********************************************************************/#define IP_FQSIZE 10 /* max number of frag queues */#define IP_MAXNF 10 /* max number of frags in packet */#define IP_FTTL (60 * TICKS_PER_SEC) /* fragment lifetime *//***********************************************************************//* Symbol Definitions *//***********************************************************************//*** Queue entry state flags*/#define IPFF_VALID 1 /* contents are valid */#define IPFF_BOGUS 2 /* drop frags that match */#define IPFF_FREE 3 /* this queue is free to be allocated *//***********************************************************************//* Type Definitions *//***********************************************************************/typedef struct{ TcpTmr timer; /* fragment timer */ ui32 src_ip; /* IP address of the source */ ui16 ip_id; /* datagram id */ int count; /* number of queued entries */ NetBuf *head; /* queue head */ char state; /* IPFF_VALID, IPFF_BOGUS, or IPFF_FREE */} IpFragQ;/***********************************************************************//* Global Variable Definitions *//***********************************************************************/static IpFragQ FragQ[IP_FQSIZE]; /* IP frag queue table *//***********************************************************************//* Local Function Definitions *//***********************************************************************//***********************************************************************//* free_queue: Add buffer to a sorted IP fragment queue *//* *//* Input: head = pointer to the head of a fragment queue *//* *//* Note: Assumes queue contains atleast one buffer *//* *//***********************************************************************/static void free_queue(NetBuf *head){ NetBuf *buf; do { buf = head; head = head->next; tcpRetBuf(&buf); ++Stats.IpReasmFails; } while (head);}/***********************************************************************//* add_frag: Add buffer to a sorted IP fragment queue *//* *//* Input: queue = pointer to a fragment queue *//* *//* Returns: FALSE iff unable to add fragment to queue *//* *//***********************************************************************/static int add_frag(IpFragQ *queue){ NetBuf *nextbuf = queue->head; /*-------------------------------------------------------------------*/ /* If queue is full, release all fragments and set state to bogus. */ /*-------------------------------------------------------------------*/ if (queue->count == IP_MAXNF) { free_queue(nextbuf); queue->state = IPFF_BOGUS; ++Stats.IpReasmFails; return FALSE; } /*-------------------------------------------------------------------*/ /* Else insert buffer according to fragment offset order. */ /*-------------------------------------------------------------------*/ else { int fragoff = Net.Ip->frag_off & IP_FRAGOFF; Ip *nextip = (Ip *)nextbuf->ip_pkt; int nextfragoff = nextip->frag_off & IP_FRAGOFF; /*-----------------------------------------------------------------*/ /* If offset is less than first entry, fragment is new queue head. */ /*-----------------------------------------------------------------*/ if (fragoff < nextfragoff) { RxBuf->next = queue->head; queue->head = RxBuf; } /*-----------------------------------------------------------------*/ /* Search queue for fragment offset greater than buffer's. */ /*-----------------------------------------------------------------*/ else { NetBuf *prevbuf; for (;;) { /*-------------------------------------------------------------*/ /* Save pointer to current buffer and advance to next. */ /*-------------------------------------------------------------*/ prevbuf = nextbuf; nextbuf = nextbuf->next; /*-------------------------------------------------------------*/ /* If queue end reached, append buffer. */ /*-------------------------------------------------------------*/ if (nextbuf == NULL) { RxBuf->next = NULL; prevbuf->next = RxBuf; break; } /*-------------------------------------------------------------*/ /* If buffer fragment offset is less than this entry, insert. */ /*-------------------------------------------------------------*/ nextip = (Ip *)nextbuf->ip_pkt; nextfragoff = nextip->frag_off & IP_FRAGOFF; if (fragoff < nextfragoff) { RxBuf->next = nextbuf; prevbuf->next = RxBuf; break; } } } ++queue->count; NetTimerStart(&queue->timer, IP_FTTL); return TRUE; }}/***********************************************************************//* copy_ip_data: Copy IP data from buffer *//* *//* Inputs: dst = pointer to IP data destination *//* buf = pointer to buffer to copy from *//* length = number of bytes to copy *//* *//***********************************************************************/static void copy_ip_data(ui8 *dst, NetBuf *buf, uint length){ /*-------------------------------------------------------------------*/ /* If request fits in first region, take from there and return. */ /*-------------------------------------------------------------------*/ if (length <= buf->length) { memcpy(dst, buf->ip_data, length); buf->length -= length; buf->ip_data = (ui8 *)buf->ip_data + length; return; } /*-------------------------------------------------------------------*/ /* Else, copy all of the first region if non-empty. */ /*-------------------------------------------------------------------*/ else if (buf->length) { memcpy(dst, buf->ip_data, buf->length); dst += buf->length; length -= buf->length; buf->length = 0; } /*-------------------------------------------------------------------*/ /* If remainder fits in second region, take from there and return. */ /*-------------------------------------------------------------------*/ if (length <= buf->app_len) { memcpy(dst, buf->app_data, length); buf->app_len -= length; buf->app_data += length; return; } /*-------------------------------------------------------------------*/ /* Else, copy all of the second region if non-empty. */ /*-------------------------------------------------------------------*/ else if (buf->app_len) { memcpy(dst, buf->app_data, buf->app_len); dst += buf->app_len; length -= buf->app_len; buf->app_len = 0; } /*-------------------------------------------------------------------*/ /* If remaining request, take from third region. */ /*-------------------------------------------------------------------*/ if (length) { memcpy(dst, buf->app_data2, length); buf->app_len2 -= length; buf->app_data2 += length; }}/***********************************************************************//* join_frag: Join fragments, if all collected *//* *//* Input: queue = pointer to a fragment queue *//* *//* Returns: TRUE iff packet is re-assembled *//* *//***********************************************************************/static int join_frag(IpFragQ *queue){ NetBuf *fbuf, *buf = queue->head; int packoff, offset = 0; uint hlen, dlen; Ip *ip; ui8 *dst; /*-------------------------------------------------------------------*/ /* Look for continuous pattern of fragment offsets starting at zero. */ /*-------------------------------------------------------------------*/ do {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -