?? ethernet.c
字號:
(ntohs(arp->ar_hrd) != ARP_ETHER) ||
(ntohs(arp->ar_pro) != PROT_IP) ||
(arp->ar_hln != 6) || (arp->ar_pln != 4))
{
//printf("invalid RARP header\n");
}
else
{
NetCopyIP(&NetOurIP, &arp->ar_data[16]);
NetCopyIP(&NetServerIP, &arp->ar_data[ 6]);
memcpy (NetServerEther, &arp->ar_data[ 0], 6);
(*packetHandler)(0,0,0,0);
}
break;
case PROT_IP:
tmp = NetReadIP(&ip->ip_dst);
if (NetOurIP && tmp != NetOurIP && tmp != 0xFFFFFFFF)
{
return;
}
if (len < IP_HDR_SIZE) {
//debug ("len bad %d < %d\n", len, IP_HDR_SIZE);
return;
}
if (len < ntohs(ip->ip_len)) {
//printf("len bad %d < %d\n", len, ntohs(ip->ip_len));
return;
}
len = ntohs(ip->ip_len);
if ((ip->ip_hl_v & 0xf0) != 0x40) {
return;
}
if (ip->ip_off & htons(0x1fff)) { /* Can't deal w/ fragments */
return;
}
if (!NetCksumOk((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2)) {
//printf("checksum bad\n");
return;
}
if (ip->ip_p == IPPROTO_ICMP)
{
//
ICMP_t *icmph = (ICMP_t *)&(ip->udp_src);
switch (icmph->type)
{
case ICMP_REDIRECT:
if (icmph->code != ICMP_REDIR_HOST)
return;
print_IPaddr(icmph->un.gateway);
break;
case ICMP_ECHO_REQUEST: //上位機發來ping請求,ARM目標板應答
PingAck ((uchar *)ip,(uchar *)et); //ping回應程序
return;
default:
return;
}
}
else if (ip->ip_p != IPPROTO_UDP)
{ /* Only UDP packets */
return;
}
/*
* IP header OK. Pass the packet to the current handler.
*/
/**********************llr note :add 2005.12.12**********************/
(uchar *) udppack = (uchar *)ip ;
/**********************llr note :add 2005.12.12**********************/
if((DWORD)packetHandler <= 0x30000000 || (DWORD)packetHandler > 0x34000000) return;
(*packetHandler)((uchar *)ip +IP_HDR_SIZE,
ntohs(ip->udp_dst),
ntohs(ip->udp_src),
ntohs(ip->udp_len) - 8);
break;
}
}//NetReceiveProcess()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: Ping響應.
// 描述: 上位機有Ping請求, 進行Ping響應.
//
// [參數表]
// ipaddr: ip包指針.
// etheraddr: 以太網頭指針.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void PingAck (uchar *ipaddr, uchar *etheraddr)
{
volatile ushort *s,*s1;
int i=0;
IP_t *ipack;
IP_t *ip = (IP_t *)ipaddr;
Ethernet_t *et = (Ethernet_t *)etheraddr;
int NetTxPacketsize;
NetSetEther (NetTxPacket,et->et_src, PROT_IP);
ipack = (IP_t *)(NetTxPacket + ETHER_HDR_SIZE);
ipack->ip_hl_v = 0x45;
ipack->ip_tos = 0;
ipack->ip_len = ip->ip_len;
ipack->ip_id = ip->ip_id; //上位機的ping ID
ipack->ip_off = htons(0x4000);
ipack->ip_ttl = 128;
ipack->ip_p = 0x01; // ICMP協議
ipack->ip_sum = 0; // 校驗和
NetCopyIP((void*)&ipack->ip_src,&ip->ip_dst); //設置目的ip地址
NetCopyIP((void*)&ipack->ip_dst,&ip->ip_src);
ipack->ip_sum = ~NetCksum((uchar *)ipack, IP_HDR_SIZE_NO_UDP / 2);
s = &ipack->udp_src;
s1 = (&ip->udp_xsum)+1;
s[0] = htons(0x0000); // ping回應類型
s[1] = 0; // checksum
s[2] = ip->udp_len; // identifier
s[3] = ip->udp_xsum;
// ping發來的數據送回
for (i=0;i<ntohs(ip->ip_len)-IP_HDR_SIZE_NO_UDP-8;i++)
{
s[i+4] = s1[i];
}
s[1] = ~NetCksum((uchar *)s, (ntohs(ip->ip_len)-IP_HDR_SIZE_NO_UDP)/2);
NetTxPacketsize = ETHER_HDR_SIZE + ntohs(ip->ip_len);
(void) eth_send(NetTxPacket, NetTxPacketsize);
}//PingAck()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡傳輸初始化.
// 描述: 分配接收、發送緩沖區, 在網絡接收、發送前執行初始化.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void NetTRPackInit(void)
{
int i;
NetArpWaitPacketMAC = NULL;
NetArpWaitTxPacket = NULL;
NetArpWaitPacketIP = 0;
NetArpWaitReplyIP = 0;
NetArpWaitTxPacket = NULL;
NetTxPacket = NULL;
if( !NetTxPacket )
{
// 開辟包緩沖區
NetTxPacket = &PktBuf[0] + (PKTALIGN - 1);
NetTxPacket -= (ulong)NetTxPacket % PKTALIGN;
for( i = 0; i < PKTBUFSRX; i++)
{
NetRxPackets[i] = NetTxPacket + (i+1)*PKTSIZE_ALIGN;
}
}
if (!NetArpWaitTxPacket)
{
NetArpWaitTxPacket = &NetArpWaitPacketBuf[0] + (PKTALIGN - 1);
NetArpWaitTxPacket -= (ulong)NetArpWaitTxPacket % PKTALIGN;
NetArpWaitTxPacketSize = 0;
}
memcpy (NetOurEther,MACAddr , 6);
NetCopyIP(&NetOurIP, &IPAddr);
NetOurIP = ntohl(NetOurIP);
}//NetTRPackInit()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 字符串轉為IP.
//
// [參數表]
// s: 待轉換的字符串.
//
// 返回: 轉換所得的IP.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
IPaddr_t string_to_ip (char *s)
{
IPaddr_t addr;
ulong val;
char *e;
int i;
if (s == NULL)
return(0);
for (addr=0, i=0; i<4; ++i)
{
val = s ? simple_strtoul(s, &e, 10) : 0;
addr <<= 8;
addr |= (val & 0xFF);
if (s)
{
s = (*e) ? e+1 : e;
}
}
return (htonl(addr));
}//string_to_ip()
void NetSetTimeout(int iv, thand_f * f)
{
if (iv == 0)
{
timeHandler = (thand_f *)0;
}
else
{
timeHandler = f;
timeStart = get_timer(0);
timeDelta = iv;
}
}//NetSetTimeout()
static startAgainHandler (uchar * pkt, unsigned dest, unsigned src, unsigned len)
{
//Totally ignore the packet
return 0;
}//startAgainHandler()
void NetWriteIP(void *to, IPaddr_t ip)
{
memcpy(to, (void*)&ip, sizeof(ip));
}
void NetStartAgain(void)
{
NetSetTimeout(10 * CFG_HZ, (thand_f *)startAgainTimeout);
NetSetHandler((rxhand_f *)startAgainHandler);
}
void ArpRequest (void)
{
int i;
volatile uchar *pkt;
ARP_t * arp;
pkt = NetTxPacket;
NetSetEther(pkt, NetBcastAddr, PROT_ARP);/* set ethernet header */
pkt += ETHER_HDR_SIZE;
arp = (ARP_t *)pkt;
arp->ar_hrd = htons(ARP_ETHER);
arp->ar_pro = htons(PROT_IP);
arp->ar_hln = 6;
arp->ar_pln = 4;
arp->ar_op = htons(ARPOP_REQUEST);
memcpy (&arp->ar_data[0], NetOurEther, 6); /* source ET addr */
NetWriteIP((uchar*)&arp->ar_data[6], NetOurIP); /* source IP addr */
for (i=10; i<16; ++i) {
arp->ar_data[i] = 0; /* dest ET addr = 0 */
}
if((NetArpWaitPacketIP & NetOurSubnetMask) != (NetOurIP & NetOurSubnetMask))
{
NetArpWaitReplyIP = NetOurGatewayIP;
} else
NetArpWaitReplyIP = NetArpWaitPacketIP;
NetWriteIP((uchar*)&arp->ar_data[16], NetArpWaitReplyIP);
(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + ARP_HDR_SIZE);
}//ArpRequest()
void NetSetIP (volatile uchar * xip, IPaddr_t dest, int dport, int sport, int len)
{
volatile IP_t *ip = (IP_t *)xip;
/*
* If the data is an odd number of bytes, zero the
* byte after the last byte so that the checksum
* will work.
*/
if (len & 1)
xip[IP_HDR_SIZE + len] = 0;
/*
* Construct an IP and UDP header.
(need to set no fragment bit - XXX)
*/
ip->ip_hl_v = 0x45; /* IP_HDR_SIZE / 4 (not including UDP) */
ip->ip_tos = 0;
ip->ip_len = htons(IP_HDR_SIZE + len);
ip->ip_id = htons(NetIPID++);
ip->ip_off = htons(0x4000); /* No fragmentation */
ip->ip_ttl = 255;
ip->ip_p = 17; /* UDP */
ip->ip_sum = 0;
NetCopyIP((void*)&ip->ip_src, &NetOurIP); /* already in network byte order */
NetCopyIP((void*)&ip->ip_dst, &dest); /* - "" - */
ip->udp_src = htons(sport);
ip->udp_dst = htons(dport);
ip->udp_len = htons(8 + len);
ip->udp_xsum = 0;
ip->ip_sum = ~NetCksum((uchar *)ip, IP_HDR_SIZE_NO_UDP / 2);
}//NetSetIP()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡發送UDP包.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int NetSendUDPPacket (uchar *ether, IPaddr_t dest, int dport, int sport, int len)
{
/* convert to new style broadcast */
if (dest == 0)
dest = 0xFFFFFFFF;
/* if broadcast, make the ether address a broadcast and don't do ARP */
if (dest == 0xFFFFFFFF)
ether = NetBcastAddr;
/* if MAC address was not discovered yet, save the packet and do an ARP request */
if (memcmp(ether, NetEtherNullAddr, 6) == 0)
{
#ifdef ET_DEBUG
// printf("sending ARP for %08lx\n", dest);
#endif
NetArpWaitPacketIP = dest;
NetArpWaitPacketMAC = ether;
NetSetEther (NetArpWaitTxPacket, NetArpWaitPacketMAC, PROT_IP);
NetSetIP (NetArpWaitTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
memcpy(NetArpWaitTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE,
(uchar *)NetTxPacket + ETHER_HDR_SIZE + IP_HDR_SIZE, len);
/* size of the waiting packet */
NetArpWaitTxPacketSize = ETHER_HDR_SIZE + IP_HDR_SIZE + len;
/* and do the ARP request */
NetArpWaitTry = 1;
NetArpWaitTimerStart = get_timer(0);
ArpRequest();
return 1; /* waiting */
}
#ifdef ET_DEBUG
// printf("sending UDP to %08lx/%02x:%02x:%02x:%02x:%02x:%02x\n",
dest, ether[0], ether[1], ether[2], ether[3], ether[4], ether[5]);
#endif
NetSetEther (NetTxPacket, ether, PROT_IP);
NetSetIP (NetTxPacket + ETHER_HDR_SIZE, dest, dport, sport, len);
(void) eth_send(NetTxPacket, ETHER_HDR_SIZE + IP_HDR_SIZE + len);
return 0; /* transmited */
}//NetSendUDPPacket()
void ArpTimeoutCheck (void)
{
ulong t;
if (!NetArpWaitPacketIP)
return;
t = get_timer(0);
/* check for arp timeout */
if ((t - NetArpWaitTimerStart) > ARP_TIMEOUT * CFG_HZ)
{
NetArpWaitTry++;
if (NetArpWaitTry >= ARP_TIMEOUT_COUNT)
{
NetArpWaitTry = 0;
NetStartAgain();
} else {
NetArpWaitTimerStart = t;
ArpRequest();
}
}
}//ArpTimeoutCheck()
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// 函數: 網絡數據包接收.
// 描述: UDP包接收.
//
// [參數表]
// udpdata: 數據指針.
// ipstring: 目標ip地址字符串, 如“10.10.10.118".
// srcport: 源端口號.
// len: 數據長度.
//
// 返回: 1-發送不成功; 0-發送成功.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int NetTrPack (uchar *udpdata, char *ipstring, int sport, int len)
{
int is_arp;
IPaddr_t dest, tmp;
uchar ether[6]; // ether只要傳送目標mac地址值,即ether->et_dst
IP_t *netarpip;
memset(ether,0,6);
dest = string_to_ip(ipstring);
//讀出原來在內存的ip地址
(DWORD)netarpip = (DWORD)NetArpWaitTxPacket+ETHER_HDR_SIZE;//1026
tmp = NetReadIP(&netarpip->ip_dst);
//eth_current
/****************************************************************************
比較目的ip地址與內存ip地址。
如相等,說明內存中有相應的MAC地址,不用發arp協議,內存mac地址->目的mac地址。
不相等,在NetSendUDPPacket()函數中發arp協議。
*****************************************************************************/
if (tmp == dest)
{
memcpy(ether,((Ethernet_t *)NetArpWaitTxPacket)->et_dest,6);
}
//復制包數據
memcpy((uchar *)((DWORD)NetTxPacket+ (ETHER_HDR_SIZE + IP_HDR_SIZE)),udpdata,len);//1026
is_arp = NetSendUDPPacket(ether, dest, sport, sport, len);
while (is_arp == 1)
{
//如果不知道對方mac地址,即(ether)={0,0,0,0,0,0}則發arp
eth_rx();
ArpTimeoutCheck(); //每5秒發一次arp請求,發5次
if (!NetArpWaitTry)
{
// 5次沒有arp應答,表示目的不可達
return 1;
}
if (NetArpWaitTxPacketSize == 0)
{
return 0;//發送數據成功
}
}
return 0; //發送數據成功
}//NetTrPack()
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -