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

📄 ip.c

📁 ATmega103、ATmega128做的开发板web server源码
💻 C
字号:
/******************************************************************
* ip.c: Internet Protocol
* 
* Copyright (c) 2001 Atmel Corporation.
* All Rights Reserved.
*
* You are autorized to use, copy and distribute this software only at 
* a single site (the term "site" meaning a single company location). 
* This copyright notice must be included in any copy, modification 
* or portion of this software merged into another program.
* 
* This software is licenced solely for use with Atmel AVR micro 
* controller family. The software may not be modified to execute on 
* any other microcontroller architectures
*
* This software is provided "as is"; Without warranties either express
* or implied, including any warranty regarding merchantability, 
* fitness for a particular purpose or noninfringement. 
*
* In no event shall Atmel or its suppliers be liable for any special, 
* indirect,incidential or concequential damages resulting from the 
* use or inability to use this software.
*
* Revision history:
*
* January 17, 2001:   Version 1.0   Created by JB
* July 13, 2001		  Version 1.2     JB
* 					- Changed to IAR compiler V2.25
*					- Renamed flash file functions to avoid conflict with 
*					  standard file I/O names	
*					- Bug fixes in HTTP
*					- Speed optimization in TCP 
*
*
*******************************************************************/
#include "comp_a90.h"
#include "ip.h"  
#include "ethernet.h"
#include "main.h"
#include "icmp.h" 
#include "tcp.h"
#include "udp.h"
#include <iom103.h>
#include <string.h>

#ifdef IP_INCLUDE_FRAGMENT
  static unsigned int fragments[IP_FRAGMENT_BUFFER];
  static unsigned int fragID[IP_NUMBER_OF_FRAG];
#endif

unsigned int frame[FRAME_SIZE];
extern config_type ID;			//the IP and MAC-address of the EWS

/*used with DHCP, if dhcpConf is set, IP forwards all UDP-datagrams, 
  and ignores the destination IP-address field*/
unsigned char dhcpConf=0;                     

/*Add an IP header to the frame and send the IP fragment to ethernet layer.*/
void transmitIP(int length, unsigned int ip0, unsigned int ip1, char type)
{
  static unsigned int IDno= 10;
  unsigned int *pframe = frame;
  
  length += IP_HEADER_LENGTH;
  pframe[IP_VLT] 		= 0x4500;                     //VLT
  pframe[IP_LENGTH] 	= length;					  //LENGTH
  pframe[IP_ID] 		= IDno++;                     //ID
  pframe[IP_OFFSET] 	= 0;                          //OFFSET
  pframe[IP_TTL] 		= 0x4000 | type;              //TTL
  pframe[IP_CHECKSUM] 	= 0;                          //CHECKSUM
  pframe[IP_SENDER_IP0] = ID.IP0;                     //SENDER_IP0
  pframe[IP_SENDER_IP1] = ID.IP1;                     //SENDER_IP1
  pframe[IP_TARGET_IP0] = ip0;                        //TARGET_IP0
  pframe[IP_TARGET_IP1] = ip1;                        //TARGET_IP1
  frame[IP_CHECKSUM] = checksum(&frame[IP_VLT], IP_HEADER_LENGTH);
  sendFrame(length, 0x0800, ip0, ip1);
}

/*When a frame is received and it contain an IP fragment, this function is called. It calculate
  the checksum and forward the IP data to the either ICMP or TCP according to the protocol field.*/
void receiveIP(unsigned int length)
{
  unsigned int *pframe = frame;	
  unsigned int headerLength= ((frame[IP_VLT]>>8) & 0x0f)*2;
  unsigned int j = pframe[((IP_OFFSET & 0x1fff)*4)];
  
#ifdef IP_INCLUDE_FRAGMENT
  unsigned char x;
  unsigned int i;
  
      /*Timeout for fragmented segments*/
  for (x=0;x<2;x++)                     
  {
    if (fragID[4] > 0)                  //If counter is not zero, decrement
    {
      fragID[4]--;
    }
    else                                // If counter is zero (timeout) delete fragmented segments.
    {
      fragID[0] = 0;
      fragID[1] = 0;
      fragID[2] = 0;
      fragID[3] = 0;
    }
  }
#endif
  
  if ( (checksum(&frame[IP_VLT], headerLength*2) == 0) &&  //Check checksum and IP address.
     (((pframe[IP_TARGET_IP0] == ID.IP0) && (pframe[IP_TARGET_IP1] == ID.IP1)) ||
      ((pframe[IP_TARGET_IP0] == 0xffff) && (pframe[IP_TARGET_IP1] == 0xffff))) )
  {
    length = pframe[IP_LENGTH];
#ifdef IP_INCLUDE_FRAGMENT
    if ( (pframe[IP_OFFSET] & 0x3fff) )            // If this is a fragment.
    {
      if ( (pframe[IP_ID] == fragID[0]) || pframe[IP_ID] == 0) //Find other fragments if existing.
      {
        fragID[0] = pframe[IP_ID];
        fragID[1] = pframe[IP_SENDER_IP0];
        fragID[2] = pframe[IP_SENDER_IP1];
        fragID[3] = (pframe[IP_TTL] & 0xff);
        fragID[4] = 10;
        if ( (j+((length/2)-headerLength)) < MAX_SEGMENT_SIZE) //Copy fragment into fragment buffer
        {
          for (i=0; i<(length/2-headerLength); i++)
          {
            fragments[(j+i)] = pframe[IP_VLT+headerLength+i];
          }
        }
        if ( !(pframe[IP_OFFSET] & 0x2000) )       // If this is the last fragment
        {
          length = (pframe[IP_OFFSET] & 0x1fff)*8 + frame[IP_LENGTH];  
          pframe[IP_OFFSET] = 0;
          for (i=0; i<length/2;i++)               //Copy the fragments into the frame
          {
            pframe[IP_VLT+headerLength+i] = fragments[i];
          }
          fragID[0] = 0;
          fragID[1] = 0;
          fragID[2] = 0;
          fragID[3] = 0;
        }
        else
        {
          pframe[IP_TTL] = 0;
        }
      }
    }
#endif    
    if ( (pframe[IP_TTL] & 0xff) == 1)             //If protocol == ICMP
    {
      receiveICMP(frame, (length-(headerLength*2)), pframe[IP_SENDER_IP0], pframe[IP_SENDER_IP1]);
    }
    else if ( (pframe[IP_TTL] & 0xff) == 6)        //If protocol == TCP
    {
      receiveTCP((length-(headerLength*2)), pframe[IP_SENDER_IP0], pframe[IP_SENDER_IP1]);
    }
    else if ( (pframe[IP_TTL] & 0xff) == 17)       //If protocol == UDP
    {
      receiveUDP(IP_VLT+headerLength,(length-(headerLength*2)), pframe[IP_SENDER_IP0], pframe[IP_SENDER_IP1],
      pframe[IP_TARGET_IP0],pframe[IP_TARGET_IP1]);
    }
  
  }
  else if(dhcpConf && (pframe[IP_TTL] & 0xff) == 17) //If dhcp configuration is under progress, let the packet pass
  {
    receiveUDP(IP_VLT+headerLength,(length-(headerLength*2)), pframe[IP_SENDER_IP0], pframe[IP_SENDER_IP1],
      pframe[IP_TARGET_IP0],pframe[IP_TARGET_IP1]);
  }

}

/*Calculate the checksum of the header. Used by TCP, IP and ICMP*/
unsigned int checksum(unsigned int *pointer, unsigned int length) 
{
  unsigned long sum = 0;
  unsigned int x;
  
  for (x=0;x<(length)/2;x++)
  {
    sum+= *pointer++;
  }
  if (length & 0x01)
  {
    sum+= (((*pointer)) & 0xff00);
  }
  sum = (sum & 0xffff) + ((sum >> 16) & 0xffff);
  if (sum&0xffff0000)
  {
    sum++;
  }
  return ( (unsigned int)(~((sum) & 0xffff)) );
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -