⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fragment.c

📁 用于嵌入式系统的TCP/IP协议栈
💻 C
📖 第 1 页 / 共 3 页
字号:
/*  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 + -