📄 ethernet.c
字号:
* above the monRecvEnetPkt() function.
*/
if (AppPktPtr) {
memcpy(AppPktPtr,(char *)ehdr,size > AppPktLen ? AppPktLen : size);
AppPktPtr = 0;
AppPktLen = size;
return;
}
if (ehdr->ether_type == ecs(ETHERTYPE_ARP)) {
processARP(ehdr,size);
return;
}
else if (ehdr->ether_type == ecs(ETHERTYPE_REVARP)) {
processRARP(ehdr,size);
return;
}
else if (ehdr->ether_type != ecs(ETHERTYPE_IP)) {
return;
}
/* If source MAC address is this board, then assume we received our
* own outgoing broadcast message...
*/
if (!memcmp((char *)&(ehdr->ether_shost),BinEnetAddr,6)) {
return;
}
ihdr = (struct ip *) (ehdr + 1);
/* If not version # 4, return now... */
if (getIP_V(ihdr->ip_vhl) != 4) {
return;
}
/* IP address filtering:
* At this point, the only packets accepted are those destined for this
* board's IP address or broadcast to the subnet, plus DHCP, if active,
*/
if (memcmp((char *)&(ihdr->ip_dst),BinIpAddr,4)) {
long net_mask, sub_net_addr;
GetBinNetMask( (uchar *) &net_mask );
sub_net_addr = ihdr->ip_dst.s_addr & ~net_mask; /* x.x.x.255 */
uhdr = (struct Udphdr *)(ihdr+1);
if ( ihdr->ip_p != IP_UDP
|| ecs(uhdr->uh_dport) != MoncmdPort
|| sub_net_addr != ~net_mask ) {
#if INCLUDE_DHCPBOOT
if (DHCPState == DHCPSTATE_NOTUSED)
return;
if (ihdr->ip_p != IP_UDP)
return;
uhdr = (struct Udphdr *)(ihdr+1);
if (uhdr->uh_dport != ecs(DhcpClientPort)) {
return;
}
#else
return;
#endif
}
}
/* Verify incoming IP header checksum...
* Refer to section 3.2 of TCP/IP Illustrated, Vol 1 for details.
*/
csum = 0;
datap = (ushort *) ihdr;
for (i=0;i<(sizeof(struct ip)/sizeof(ushort));i++,datap++)
csum += *datap;
csum = (csum & 0xffff) + (csum >> 16);
if (csum != 0xffff) {
EtherIPERRCnt++;
if (EtherVerbose & SHOW_BADCSUM) {
printf("IP csum error: 0x%04x != 0xffff\n",(ushort)csum);
if (EtherVerbose & SHOW_BADCSUMV) {
int overbose = EtherVerbose;
EtherVerbose = SHOW_ALL;
printPkt(ehdr,size,ETHER_INCOMING);
EtherVerbose = overbose;
}
}
return;
}
if (ihdr->ip_p == IP_ICMP) {
processICMP(ehdr,size);
return;
}
else if (ihdr->ip_p == IP_TCP) {
processTCP(ehdr,size);
return;
}
else if (ihdr->ip_p != IP_UDP) {
int j;
SendICMPUnreachable(ehdr,ICMP_UNREACHABLE_PROTOCOL);
if (!(EtherVerbose & SHOW_INCOMING))
return;
for(j=0;protocols[j].pname;j++) {
if (ihdr->ip_p == protocols[j].pnum) {
printf("%s not supported\n",
protocols[j].pname);
return;
}
}
printf("<%02x> protocol unrecognized\n", ihdr->ip_p);
return;
}
uhdr = (struct Udphdr *)(ihdr+1);
/* If non-zero, verify incoming UDP packet checksum...
* Refer to section 11.3 of TCP/IP Illustrated, Vol 1 for details.
*/
if (uhdr->uh_sum) {
int len;
struct UdpPseudohdr pseudohdr;
memcpy((char *)&pseudohdr.ip_src.s_addr,(char *)&ihdr->ip_src.s_addr,4);
memcpy((char *)&pseudohdr.ip_dst.s_addr,(char *)&ihdr->ip_dst.s_addr,4);
pseudohdr.zero = 0;
pseudohdr.proto = ihdr->ip_p;
pseudohdr.ulen = uhdr->uh_ulen;
csum = 0;
datap = (ushort *) &pseudohdr;
for (i=0;i<(sizeof(struct UdpPseudohdr)/sizeof(ushort));i++)
csum += *datap++;
/* If length is odd, pad and add one. */
len = ecs(uhdr->uh_ulen);
if (len & 1) {
uchar *ucp;
ucp = (uchar *)uhdr;
ucp[len] = 0;
len++;
}
len >>= 1;
datap = (ushort *) uhdr;
for (i=0;i<len;i++)
csum += *datap++;
csum = (csum & 0xffff) + (csum >> 16);
if (csum != 0xffff) {
EtherUDPERRCnt++;
if (EtherVerbose & SHOW_BADCSUM) {
printf("UDP csum error: 0x%04x != 0xffff\n",(ushort)csum);
if (EtherVerbose & SHOW_BADCSUMV) {
int overbose = EtherVerbose;
EtherVerbose = SHOW_ALL;
printPkt(ehdr,size,ETHER_INCOMING);
printf("pseudohdr.ip_src: 0x%08lx\n",
pseudohdr.ip_src.s_addr);
printf("pseudohdr.ip_dst: 0x%08lx\n",
pseudohdr.ip_dst.s_addr);
printf("pseudohdr.zero: 0x%02x\n", pseudohdr.zero);
printf("pseudohdr.proto: 0x%02x\n", pseudohdr.proto);
printf("pseudohdr.ulen: 0x%04x\n", pseudohdr.ulen);
EtherVerbose = overbose;
}
}
return;
}
}
udpport = ecs(uhdr->uh_dport);
if (udpport == MoncmdPort)
processMONCMD(ehdr,size);
#if INCLUDE_DHCPBOOT
else if (udpport == DhcpClientPort)
processDHCP(ehdr,size);
#endif
#if INCLUDE_TFTP
else if ((udpport == TftpPort) || (udpport == TftpSrcPort))
processTFTP(ehdr,size);
#endif
#if INCLUDE_GDB
else if (udpport == GdbPort)
processGDB(ehdr,size);
#endif
else {
if (EtherVerbose & SHOW_INCOMING) {
uchar *cp;
cp = (uchar *)&(ihdr->ip_src);
printf(" Unexpected IP pkt from %d.%d.%d.%d ",
cp[0],cp[1],cp[2],cp[3]);
printf("(sport=0x%x,dport=0x%x)\n",
ecs(uhdr->uh_sport),ecs(uhdr->uh_dport));
}
SendICMPUnreachable(ehdr,ICMP_UNREACHABLE_PORT);
}
}
#define MONCMD_SRCIP_VARNAME "MONCMD_SRCIP"
#define MONCMD_SRCPORT_VARNAME "MONCMD_SRCPORT"
/* processMONCMD():
* This function is called as a result of receiving a packet on port
* 777. It will process the incoming packet as if it was an ASCII
* command destined for MicroMonitor's CLI.
*
* As of Aug 16, 2004, support for NETCAT is also in this function.
* Differentiating between netcat and moncmd is done by looking
* for the terminating newline character which is only present with
* netcat. For example:
* The following host command line: <netcat -u 135.222.140.72 777>
* puts the netcat user into an interactive mode with uMon so
* normal uMon commands can be issued through netcat (until interrupted).
*
* As of Aug 5, 2005, another change has been made to uMon's MONCMD
* server as a result of a bug reported by Leon Pollack. The change
* breaks up the processing of the incoming moncmd request into two
* parts processMONCMD() and executeMONCMD() (refer to CVS log for
* more details):
*
* 1. processMONCMD():
* Retrieve the incoming message from the ethernet interface and
* store the message in a local buffer to be processed later.
* 2. executeMONCMD():
* After the ethernet packet has been properly dequeued, then
* process the remote command appropriately.
*/
void
processMONCMD(struct ether_header *ehdr,ushort size)
{
int verbose = 0;
struct ip *ihdr;
struct Udphdr *uhdr;
char *moncmd;
uchar *src;
if (size > sizeof(IPMonCmdHdrBuf))
return;
ihdr = (struct ip *)(ehdr + 1);
uhdr = (struct Udphdr *)(ihdr + 1);
moncmd = (char *)(uhdr + 1);
memcpy((char *)IPMonCmdHdrBuf,(char *)ehdr,size);
IPMonCmdHdr = (struct ether_header *)&IPMonCmdHdrBuf;
src = (uchar *)&ihdr->ip_src;
/* Keep track of who sent the most recent moncmd request:
*/
shell_sprintf(MONCMD_SRCIP_VARNAME,"%d.%d.%d.%d",
src[0],src[1],src[2],src[3]);
shell_sprintf(MONCMD_SRCPORT_VARNAME,"%d",ecs(uhdr->uh_sport));
if (!MFLAGS_NOMONCMDPRN()) {
printf("MONCMD (from %s): ",getenv(MONCMD_SRCIP_VARNAME));
verbose = 1;
}
if (strlen(moncmd) >= (sizeof(IPMonCmdLine) - 2)) {
printf("MONCMD (from %s): too long\n",getenv(MONCMD_SRCIP_VARNAME));
return;
}
strcpy(IPMonCmdLine+1,moncmd);
IPMonCmdLine[0] = '+';
IPMonCmdVerbose = verbose;
}
void
executeMONCMD(void)
{
char *ncnl; /* netcat newline */
char *moncmd;
/* Clear the initial '+' character so that this function is
* never executed multiple times because of calls to
* polletherdev() during the MONCMD transaction.
*/
IPMonCmdLine[0] = 0;
/* If the first character of the incoming command is an '@', then
* the response is not sent back to the client...
*/
moncmd = IPMonCmdLine + 1;
if (*moncmd == '@') {
IPMonCmdActive = 0;
moncmd++;
}
else
IPMonCmdActive = 1;
/* Added to support netcat...
*/
ncnl = strchr(moncmd,0x0a);
if (ncnl)
*ncnl = 0;
docommand(moncmd,IPMonCmdVerbose);
if (ncnl)
writeprompt();
if (IPMonCmdActive) {
SendIPMonChar(0,1);
IPMonCmdActive = 0;
}
stkchk("Post-sendIPmonchar");
if (!ncnl)
writeprompt();
IPMonCmdLine[0] = 0;
}
int
SendIPMonChar(uchar c, int done)
{
static int idx;
static char linebuf[128];
int len, hdrlen;
struct ether_header *te;
struct ip *ti, *ri;
struct Udphdr *tu, *ru;
if (!IPMonCmdActive)
return(0);
/* Check for overflow and if detected, reset the buffer pointer...
*/
if (idx >= sizeof(linebuf))
idx = 0;
linebuf[idx++] = c;
if ((!done) && (c != '\n'))
return(0);
/* Once inside the meat of this function, clear the IPMonCmdActive flag
* to avoid recursion if an error message is to be printed by some
* called by this function...
*/
IPMonCmdActive = 0;
hdrlen = sizeof(struct ip) + sizeof(struct Udphdr);
len = idx + hdrlen ;
te = EtherCopy(IPMonCmdHdr);
ti = (struct ip *) (te + 1);
ri = (struct ip *) (IPMonCmdHdr + 1);
ti->ip_vhl = ri->ip_vhl;
ti->ip_tos = ri->ip_tos;
ti->ip_len = ecs(len);
ti->ip_id = ipId();
ti->ip_off = ri->ip_off;
ti->ip_ttl = UDP_TTL;
ti->ip_p = IP_UDP;
memcpy((char *)&(ti->ip_src.s_addr),(char *)BinIpAddr,
sizeof(struct in_addr));
memcpy((char *)&(ti->ip_dst.s_addr),(char *)&(ri->ip_src.s_addr),
sizeof(struct in_addr));
tu = (struct Udphdr *) (ti + 1);
ru = (struct Udphdr *) (ri + 1);
tu->uh_sport = ru->uh_dport;
tu->uh_dport = ru->uh_sport;
tu->uh_ulen = ecs((ushort)(sizeof(struct Udphdr) + idx));
memcpy((char *)(tu+1),linebuf,idx);
ipChksum(ti); /* Compute checksum of ip hdr */
udpChksum(ti); /* Compute UDP checksum */
sendBuffer(MONRESPSIZE);
idx = 0;
IPMonCmdActive = 1;
return(1);
}
/*
* printPkt(ehdr,len)
*/
void
printPkt(struct ether_header *ehdr, int len, int direction)
{
struct arphdr *arpp;
char *dir;
/* Filter based on verbosity level... */
switch(direction) {
case ETHER_INCOMING:
if (!(EtherVerbose & SHOW_INCOMING))
return;
dir = "INCOMING";
break;
case ETHER_OUTGOING:
if (!(EtherVerbose & SHOW_OUTGOING))
return;
dir = "OUTGOING";
break;
default:
printf("printPkt() direction error\n");
dir = "???";
break;
}
/* If direction is incoming and SHOW_BROADCAST is not set, then */
/* return here if the destination host is broadcast. */
if ((direction == ETHER_INCOMING) &&
(!(EtherVerbose & SHOW_BROADCAST)) &&
(!memcmp(ehdr->ether_dhost.ether_addr_octet,BroadcastAddr,6)))
return;
printf("\n%s PACKET (%d bytes):\n",dir,len);
if (EtherVerbose & SHOW_HEX)
printMem((char *)ehdr,len,EtherVerbose & SHOW_ASCII);
printf(" Destination Host = %02x:%02x:%02x:%02x:%02x:%02x\n",
ehdr->ether_dhost.ether_addr_octet[0],
ehdr->ether_dhost.ether_addr_octet[1],
ehdr->ether_dhost.ether_addr_octet[2],
ehdr->ether_dhost.ether_addr_octet[3],
ehdr->ether_dhost.ether_addr_octet[4],
ehdr->ether_dhost.ether_addr_octet[5]);
printf(" Source Host = %02x:%02x:%02x:%02x:%02x:%02x\n",
ehdr->ether_shost.ether_addr_octet[0],
ehdr->ether_shost.ether_addr_octet[1],
ehdr->ether_shost.ether_addr_octet[2],
ehdr->ether_shost.ether_addr_octet[3],
ehdr->ether_shost.ether_addr_octet[4],
ehdr->ether_shost.ether_addr_octet[5]);
switch (ehdr->ether_type) {
case ecs(ETHERTYPE_IP):
printIp((struct ip *)(ehdr+1));
break;
case ecs(ETHERTYPE_PUP):
printf(" Type = PUP\n");
break;
case ecs(ETHERTYPE_ARP):
arpp = (struct arphdr *)(ehdr+1);
printf(" Type = ARP %s from IP %d.%d.%d.%d)\n",
arpp->operation == ecs(ARP_RESPONSE) ? "RESPONSE" : "REQUEST",
arpp->senderia[0],arpp->senderia[1],
arpp->senderia[2],arpp->senderia[3]);
break;
case ecs(ETHERTYPE_REVARP):
printf(" Type = REVARP\n");
break;
default:
printf(" Type = 0x%04x ???\n", ehdr->ether_type);
break;
}
}
void
AppPrintPkt(char *buf, int size, int incoming)
{
int overbose, mode;
overbose = EtherVerbose;
if (incoming)
mode = ETHER_INCOMING;
else
mode = ETHER_OUTGOING;
printPkt((struct ether_header *)buf,size,mode);
EtherVerbose = overbose;
}
/*
* printIp(p)
*/
int
printIp(struct ip *ihdr)
{
int i, ipsize;
struct ip *icpy;
char buf[16], buf1[16], *payload;
ulong tmp[sizeof(struct ip)/2];
ipsize = ((ihdr->ip_vhl & 0x0f) << 2);
/* Copy data to aligned memory space so printf doesn't crash. */
memcpy((char *)tmp,(char *)ihdr,sizeof(struct ip));
icpy = (struct ip *)tmp;
printf(" IP: vhl/tos len id offset ttl/proto csum\n");
printf(" x%02x%02x x%04x x%04x x%04x x%02x%02x x%04x\n",
icpy->ip_vhl,icpy->ip_tos, ecs(icpy->ip_len),
ecs(icpy->ip_id), ecs(icpy->ip_off),
icpy->ip_ttl, icpy->ip_p, ecs(icpy->ip_sum));
printf(" src/dest: %s / %s\n",
IpToString(icpy->ip_src.s_addr,buf),
IpToString(icpy->ip_dst.s_addr,buf1));
/* Check for options...
*/
if (ipsize > sizeof(struct ip)) {
printf(" IP Options: x");
for(i=sizeof(struct ip);i<ipsize;i++)
printf("%02x",((char *)ihdr)[i]);
printf("\n");
}
payload = (char *)ihdr;
payload += ipsize;
if (icpy->ip_p == IP_UDP) {
printUdp((struct Udphdr *)payload);
return(0);
}
else if (icpy->ip_p == IP_IGMP) {
printIgmp((struct Igmphdr *)payload);
return(0);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -