?? ethernet.c
字號:
#define __ETHERNET
#include "ethernet.h"
#undef __ETHERNET
//********************** Global Variable **********************
volatile uchar *udppack = 0; // 接收的udp包的IP指針
volatile uchar PktBuf[(PKTBUFSRX+1) * PKTSIZE_ALIGN + PKTALIGN];
ushort ourport[10] = {10000,20000,30000,40000,50000,60000,808,300,800,801};
IPaddr_t NetOurIP; /* Our IP addr (0 = unknown) */
IPaddr_t NetOurSubnetMask=0; /* Our subnet mask (0=unknown) */
IPaddr_t NetOurGatewayIP=0; /* Our gateways IP address */
IPaddr_t NetServerIP; /* Server IP addr (0 = unknown) */
IPaddr_t NetArpWaitPacketIP;
IPaddr_t NetArpWaitReplyIP;
static rxhand_f *packetHandler; /* Current RX packet handler */
int NetArpWaitTxPacketSize;
uchar NetOurEther[6]; /* Our ethernet address */
uchar NetServerEther[6]; /* Boot server enet address */
volatile uchar * NetRxPkt; /* Current receive packet */
int NetRxPktLen; /* Current rx packet length */
uchar NetArpWaitPacketBuf[PKTSIZE_ALIGN + PKTALIGN];
uchar NetBcastAddr[6] = /* Ethernet bcast address */
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
uchar NetEtherNullAddr[6] = { 0, 0, 0, 0, 0, 0 };
int NetArpWaitTry;
ulong NetArpWaitTimerStart;
ulong NetIPID; /* IP packet ID */
int NetState; /* Network loop state */
static thand_f *timeHandler; /* Current timeout handler */
static ulong timeStart; /* Time base value */
static ulong timeDelta; /* Current timeout value */
uchar *NetArpWaitPacketMAC; /* MAC address of waiting packet's destination */
uchar *NetArpWaitTxPacket; /* THE transmit packet */
//*************************************************************
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 判斷是否16進制字符.
//
// [參數表]
// s: 待判斷的字符.
//
// 返回: 0-FALSE; 1-TRUE.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uchar IsXDigital (uchar s)
{
if(( s >= '0' && s <= '9') ||
(s >= 'A' && s <= 'F') ||
(s >= 'a' && s <= 'f'))
return 1;
else
return 0;
}//IsXDigital()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 判斷是否十進制字符.
//
// [參數表]
// s: 待判斷的字符.
//
// 返回: 0-FALSE; 1-TRUE.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uchar IsDigital (uchar s)
{
if( s >= '0' && s <= '9' )
return 1;
else
return 0;
}//IsDigital()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 判斷是否字符a~f.
//
// [參數表]
// s: 待判斷的字符.
//
// 返回: 0-FALSE; 1-TRUE.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 判斷是否是16進制字符中的'a'-'f' **************************
uchar IsLowerStr (uchar s)
{
if( s >= 'a' && s <= 'f' )
return 1;
else
return 0;
}//IsLowerStr()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 將小寫字符轉換為大寫字符.
//
// [參數表]
// s: 待轉換的字符.
//
// 返回: 轉換后的字符.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
uchar LowerToUp(uchar s)
{
return s-32;
}//LowerToUp()
ulong simple_strtoul (const char *cp, char **endp, uint base)
{
unsigned long result = 0,value;
if (*cp == '0')
{
cp++;
if ((*cp == 'x') && IsXDigital(cp[1]))
{
base = 16;
cp++;
}
if (!base)
{
base = 8;
}
}
if (!base)
{
base = 10;
}
while (IsXDigital(*cp) && (value = IsDigital(*cp) ? *cp-'0' : (IsLowerStr(*cp)
? LowerToUp(*cp) : *cp)-'A'+10) < base)
{
result = result*base + value;
cp++;
}
if (endp)
*endp = (char *)cp;
return result;
}//simple_strtoul()
void NetSetHandler(rxhand_f * f)
{
packetHandler = f;
}//NetSetHandler()
static startAgainTimeout(void)
{
NetState = NETLOOP_RESTART;
return NetState;
}//startAgainTimeout()
static IPaddr_t NetReadIP (void *from)
{
IPaddr_t ip;
memcpy((void*)&ip, from, sizeof(ip));
return ip;
}//NetReadIP()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 復制IP.
// 描述: Copy IP.
//
// [參數表]
// to: 目的地址.
// from: 源地址.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetCopyIP (void *to, void *from)
{
memcpy(to, from, sizeof(IPaddr_t));
}//NetCopyIP()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 將IP轉換為字符串.
// 描述: Convert an IP address to a string.
//
// [參數表]
// x: IP.
// s: 存儲字符串的數組.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void ip_to_string (IPaddr_t x, char *s)
{
x = ntohl(x);
sprintf (s,"%d.%d.%d.%d",
(int)((x >> 24) & 0xff),
(int)((x >> 16) & 0xff),
(int)((x >> 8) & 0xff),
(int)((x >> 0) & 0xff)
);
}//ip_to_string()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡校驗和檢查.
// 描述:
//
// [參數表]
// ptr: 數據指針.
// len: 數據包長度.
//
// 返回: 校驗和結果.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ushort NetCksum (uchar * ptr, int len)
{
ulong xsum;
xsum = 0;
while (len-- > 0)
xsum += *((ushort *)ptr)++;
xsum = (xsum & 0xffff) + (xsum >> 16);
xsum = (xsum & 0xffff) + (xsum >> 16);
return (xsum & 0xffff);
}//NetCksum()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡校驗和檢查是否成功.
//
// [參數表]
// ptr: 數據指針.
// len: 數據包長度.
//
// 返回: 0-FALSE; 1-TRUE.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int NetCksumOk (uchar * ptr, int len)
{
return !((NetCksum(ptr, len) + 1) & 0xfffe);
}//NetCksumOk()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡數據包接收.
// 描述: UDP包接收.
//
// [參數表]
// udpdata: 數據指針.
// srcipaddr: 源IP地址.
// srcport: 源端口號.
//
// 返回: 數據長度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ushort NetRxPack (uchar *udpdata, char *srcipaddr,ushort *srcport)
{
int i;
IP_t *ip ;
Ethernet_t *et;
IP_t *netarpip;
ushort udplen;
NetTRPackInit(); // 分配接收、發送緩沖區
( uchar *) udppack = NULL;
eth_rx();
if( !udppack ) // 若UDP包的IP地址為0, 則返回
return 0;
ip = (IP_t *)udppack;
for( i=0; i<10; i++ )
{
// 判定udp端口在不在我的端口范圍
if( ntohs(ip->udp_dst)==ourport[i] )
break;
}
if( i==10 )
{
// 判定udp端口不相等
return 0;
}
// 讀出發送端IP地址
ip_to_string(NetReadIP(&ip->ip_src), srcipaddr);
// 存貯ip地址和對應的MAC地址
et = (Ethernet_t *)((ulong)ip-ETHER_HDR_SIZE);
// 保存收包IP地址
memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest,(char *)et->et_src,6);
netarpip = (IP_t *)(NetArpWaitTxPacket+ETHER_HDR_SIZE);
NetCopyIP(&netarpip->ip_dst,&ip->ip_src); // 保存收包MAC地址
// 讀出源端口
*srcport = ntohs(ip->udp_dst);
// 讀出udp數據長度
udplen = ntohs(ip->udp_len) - 8;
// 讀出udp數據
memcpy (udpdata,(uchar *)ip + IP_HDR_SIZE, udplen);
return (udplen);
}//NetRxPack()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 設置網絡參數.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetSetEther (volatile uchar * xet, uchar * addr, uint prot)
{
Ethernet_t *et = (Ethernet_t *)xet;
memcpy (et->et_dest, addr, 6);
memcpy (et->et_src, NetOurEther, 6);
et->et_protlen = htons(prot);
}//NetSetEther()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 設置網絡參數.
//
// [參數表]
// x: IP.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void print_IPaddr (IPaddr_t x)
{
char tmp[16];
ip_to_string(x, tmp);
}//print_IPaddr()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡接收數據包處理.
//
// [參數表]
// ptr: 數據指針.
// len: 數據包長度.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetReceiveProcess (volatile uchar * pkt, int len)
{
Ethernet_t *et;
IP_t *ip;
ARP_t *arp;
IPaddr_t tmp;
int x;
NetRxPkt = pkt;
NetRxPktLen = len;
et = (Ethernet_t *)pkt;
x = ntohs(et->et_protlen);
if( x<1514 )
{
/*
* Got a 802 packet. Check the other protocol field.
*/
x = ntohs(et->et_prot);
ip = (IP_t *)(pkt + E802_HDR_SIZE);
len -= E802_HDR_SIZE;
}
else
{
ip = (IP_t *)(pkt + ETHER_HDR_SIZE);
len -= ETHER_HDR_SIZE;
}
switch (x) // 根據協議選擇處理
{
case PROT_ARP:
/*
* We have to deal with two types of ARP packets:
* - REQUEST packets will be answered by sending our
* IP address - if we know it.
* - REPLY packates are expected only after we asked
* for the TFTP server's or the gateway's ethernet
* address; so if we receive such a packet, we set
* the server ethernet address
*/
arp = (ARP_t *)ip;
if (NetReadIP(&arp->ar_data[16]) != NetOurIP) {
return;
}
if (len < ARP_HDR_SIZE) {
return;
}
if (ntohs(arp->ar_hrd) != ARP_ETHER) {
return;
}
if (ntohs(arp->ar_pro) != PROT_IP) {
return;
}
if (arp->ar_hln != 6) {
return;
}
if (arp->ar_pln != 4) {
return;
}
if (NetOurIP == 0) {
return;
}
switch (ntohs(arp->ar_op))
{
case ARPOP_REQUEST: /* reply with our IP address */
NetSetEther((uchar *)et, et->et_src, PROT_ARP);
arp->ar_op = htons(ARPOP_REPLY);
memcpy (&arp->ar_data[10], &arp->ar_data[0], 6);
NetCopyIP(&arp->ar_data[16], &arp->ar_data[6]);
memcpy (&arp->ar_data[ 0], NetOurEther, 6);
NetCopyIP(&arp->ar_data[ 6], &NetOurIP);
(void) eth_send((uchar *)et, ((uchar *)arp-pkt) + ARP_HDR_SIZE);
return;
case ARPOP_REPLY: /* arp reply */
/* are we waiting for a reply */
if (!NetArpWaitPacketIP || !NetArpWaitPacketMAC)
break;
tmp = NetReadIP(&arp->ar_data[6]);
/* matched waiting packet's address */
if (tmp == NetArpWaitReplyIP)
{
/* save address for later use */
memcpy(NetArpWaitPacketMAC, &arp->ar_data[0], 6);
/* modify header, and transmit it */
memcpy(((Ethernet_t *)NetArpWaitTxPacket)->et_dest, NetArpWaitPacketMAC, 6);
(void) eth_send(NetArpWaitTxPacket, NetArpWaitTxPacketSize);
/* no arp request pending now */
NetArpWaitPacketIP = 0;
NetArpWaitTxPacketSize = 0;
NetArpWaitPacketMAC = NULL;
}
return;
default:
return;
}
case PROT_RARP:
arp = (ARP_t *)ip;
if (len < ARP_HDR_SIZE)
{
//printf("bad length %d < %d\n", len, ARP_HDR_SIZE);
return;
}
if ((ntohs(arp->ar_op) != RARPOP_REPLY) ||
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -