📄 ethernet.c
字号:
/* ethernet.c: * This code supports most of the generic ethernet/IP/ARP/UDP stuff. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "endian.h"#include "stddefs.h"#include "genlib.h"#if INCLUDE_ETHERNET#include "cpuio.h"#include "ether.h"#include "monflags.h"#include "cli.h"void ShowEthernetStats(void);void processMONCMD(struct ether_header *,ushort);int SendIPMonChar(uchar,int);#if INCLUDE_DHCPBOOT#define dhcpStateCheck() dhcpStateCheck()#define dhcpDisable() dhcpDisable()#define ShowDhcpStats() ShowDhcpStats()#else#define dhcpStateCheck()#define dhcpDisable()#define ShowDhcpStats()#endif#if INCLUDE_TFTP#define tftpStateCheck() tftpStateCheck()#define tftpInit() tftpInit()#define ShowTftpStats() ShowTftpStats()#else#define tftpStateCheck()#define tftpInit()#define ShowTftpStats()#endifchar *Etheradd, *IPadd; /* Pointers to ascii addresses */uchar BinIpAddr[4]; /* Space for binary IP address */uchar BinEnetAddr[6]; /* Space for binary MAC address */int EtherVerbose; /* Verbosity flag (see ether.h). */int EtherIsActive; /* Non-zero if ethernet is up. */int EtherIPERRCnt; /* Number of IP errors detected. */int EtherUDPERRCnt; /* Number of UDP errors detected. */int EtherXFRAMECnt; /* Number of packets transmitted. */int EtherRFRAMECnt; /* Number of packets received. */int EtherPollNesting; /* Incremented when pollethernet() is called. */int MaxEtherPollNesting; /* High-warter mark of EtherPollNesting. */int IPMonCmdActive; /* Set if MONCMD is in progress. */ushort UniqueIpId;struct ether_header *IPMonCmdHdr;/* Ports used by the monitor have defaults, but can be redefined using * shell variables: */ushort MoncmdPort; /* shell var: MCMDPORT */ushort DhcpClientPort; /* shell var: DCLIPORT */ushort DhcpServerPort; /* shell var: DSRVPORT */ushort TftpPort; /* shell var: TFTPPORT */ushort TftpSrcPort; /* shell var: TFTPPORT */uchar BroadcastAddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };struct pinfo { int pnum; char *pname;} protocols[] = { { IP_IP, "IP" }, { IP_ICMP, "ICMP" }, { IP_IGMP, "IGMP" }, { IP_GGP, "GGP" }, { IP_TCP, "TCP" }, { IP_PUP, "PUP" }, { IP_UDP, "UDP" }, { 0,0 },};char *EtherHelp[] = { "Ethernet interface", "-[ps:v:V] {on | off | stat}", "Options...", " -p {1|0} promiscuous mode (1=on)",#ifdef SNOOP_ENABLED " -s {MAC} print all packets to/from MAC (snoop)",#endif " -t self-test ethernet interface", " -v {flgs} enable specific verbosity...", " a: enable ARP trace", " c: print csum errmsg", " C: dump csum errpkt", " d: enable DHCP trace", " i: incoming packets (minus broadcast)", " I: incoming packets (including broadcast)", " o: outgoing packets", " p: phy r/w accesses", " t: enable TFTP trace", " x: enable hex dump (requires i,I or o)", " X: same as 'x' plus ascii", " -V full verbosity (same as -v Iodtx)", 0};intEther(int argc,char *argv[]){ int i, len, opt; /* Set up some defaults: */ EtherVerbose = 0; while ((opt=getopt(argc,argv,"p:s:tv:V")) != -1) { switch(opt) { case 'p': /* Promiscuous mode: accept all packets */ if (*optarg == '1') enablePromiscuousReception(); else disablePromiscuousReception(); return(CMD_SUCCESS);#ifdef SNOOP_ENABLED case 's': if (EtherToBin(optarg,snoopInfo.mac) < 0) return(CMD_FAILURE); enablePromiscuousReception(); snoopInfo.on = 1; break;#endif case 't': enselftest(1); return(CMD_SUCCESS); case 'V': EtherVerbose = SHOW_ALL; break; case 'v': len = strlen(optarg); for(i=0;i<len;i++) { switch(optarg[i]) { case 'a': EtherVerbose |= SHOW_ARP; EtherVerbose |= SHOW_BROADCAST; break; case 'c': EtherVerbose |= SHOW_BADCSUM; break; case 'C': EtherVerbose |= SHOW_BADCSUM; EtherVerbose |= SHOW_BADCSUMV; break; case 'i': EtherVerbose |= SHOW_INCOMING; break; case 'I': EtherVerbose |= SHOW_INCOMING; EtherVerbose |= SHOW_BROADCAST; break; case 'o': EtherVerbose |= SHOW_OUTGOING; break; case 'p': EtherVerbose |= SHOW_PHY; break; case 'd': EtherVerbose |= SHOW_DHCP; break; case 't': EtherVerbose |= SHOW_TFTP; break; case 'x': EtherVerbose |= SHOW_HEX; break; case 'X': EtherVerbose |= SHOW_HEX; EtherVerbose |= SHOW_ASCII; break; default: printf("Bad 'v' arg\n"); return(CMD_PARAM_ERROR); } } break; default: return(CMD_PARAM_ERROR); } } if (argc != optind+1) { printf("Ethernet interface currently %sabled.\n", EtherIsActive ? "en" : "dis"); return(CMD_SUCCESS); } if (!strcmp(argv[optind],"off")) { enreset(); EtherIsActive = 0; return(CMD_SUCCESS); } else if (!strcmp(argv[optind],"stat")) { ShowEthernetStats(); ShowEtherdevStats(); ShowDhcpStats(); ShowTftpStats(); return(CMD_SUCCESS); } else if (strcmp(argv[optind],"on")) return(CMD_PARAM_ERROR); EthernetStartup(EtherVerbose,0); return(CMD_SUCCESS);}voidShowEthernetStats(void){ printf("Ethernet currently %s\n",EtherIsActive ? "active" : "off"); printf("Transmitted frames: %d\n",EtherXFRAMECnt); printf("Received frames: %d\n",EtherRFRAMECnt); printf("IP hdr cksum errors: %d\n",EtherIPERRCnt); printf("UDP pkt cksum errors: %d\n",EtherUDPERRCnt); printf("Max pollethernet nest: %d\n",MaxEtherPollNesting);}voidDisableEthernet(void){ EtherIsActive = 0; IPMonCmdActive = 0; DisableEtherdev();}intEthernetStartup(int verbose, int justreset){ char *ipa; /* Initialize the retransmission delay calculator: */ RetransmitDelay(DELAY_INIT_DHCP); EtherIPERRCnt = 0; EtherXFRAMECnt = 0; EtherRFRAMECnt = 0; EtherUDPERRCnt = 0; IPMonCmdActive = 0; EtherPollNesting = 0; EtherVerbose = verbose; MaxEtherPollNesting = 0; DHCPState = DHCPSTATE_NOTUSED; /* Setup all the IP addresses used by the monitor... */ if (getAddresses() == -1) return(-1); /* If, after having set up all addresses, the content of the IPADD * shell variable is 0.0.0.0, then don't startup ethernet, just return * here. */ ipa = getenv("IPADD"); if (ipa) { if (!strcmp(ipa,"0.0.0.0")) return(-1); } else return(-1); /* Call device specific startup code: */ EtherdevStartup(verbose); /* Initialize some TFTP state... */ tftpInit();#if INCLUDE_DHCPBOOT /* If EthernetStartup is called as a result of anything other than a * target reset, don't startup any DHCP/BOOTP transaction... */ if (!justreset) dhcpDisable();#endif EtherIsActive = 1; return(0);}/* pollethernet(): * Called at a few critical points in the monitor code to poll the * ethernet device and keep track of the state of DHCP and TFTP. */intpollethernet(void){ int pcnt; if ((!EtherIsActive) || (EtherPollNesting > 4)) return(0); EtherPollNesting++; if (EtherPollNesting > MaxEtherPollNesting) MaxEtherPollNesting = EtherPollNesting; pcnt = polletherdev(); dhcpStateCheck(); tftpStateCheck(); EtherPollNesting--; return(pcnt);}/* getAddresses(): * Try getting ether/ip addresses from environment. * If not there, try getting them from some target-specific interface. * If not there, then get them from raw flash. * If not there, just use the hard-coded default. * Also, load all port numbers from shell variables, else default. * * Discussion regarding etheraddr[] and ipaddr[]... * The purpose of these two arrays is to provide a point in flash that is * initialized to 0xff by the code (see reset.s). This then allows some * other mechanism (bed of nails, etc..) to program these locations to some * other non-0xff value. It is one of the alternatives provided by the * monitor code for storage of IP and MAC. */intgetAddresses(void){ char *mcmdPort, *dcliPort, *dsrvPort, *tftpPort; /* Set up port numbers: */ mcmdPort = getenv("MCMDPORT"); dcliPort = getenv("DCLIPORT"); dsrvPort = getenv("DSRVPORT"); tftpPort = getenv("TFTPPORT"); if (mcmdPort) MoncmdPort = (ushort)strtol(mcmdPort,0,0); else MoncmdPort = IPPORT_MONCMD; if (dcliPort) DhcpClientPort = (ushort)strtol(dcliPort,0,0); else DhcpClientPort = IPPORT_DHCP_CLIENT; if (dsrvPort) DhcpServerPort = (ushort)strtol(dsrvPort,0,0); else DhcpServerPort = IPPORT_DHCP_SERVER; if (tftpPort) TftpPort = (ushort)strtol(tftpPort,0,0); else TftpPort = IPPORT_TFTP; /* 69 */ TftpSrcPort = IPPORT_TFTPSRC; /* 8888 */ /* Retrieve MAC address and store in shell variable ETHERADD... * First see if the shell variable is already loaded. * If not see if some target-specific interface has it. * If not see if the the string is stored in raw flash (usually this * storage is initialized in reset.s of the target-specific code). * Finally, as a last resort, use the default set up in config.h. */ if (!(Etheradd = getenv("ETHERADD"))) { if (!(Etheradd = extGetEtherAdd())) { if (etheraddr[0] != 0xff) Etheradd = etheraddr; else { if (!strcmp(DEFAULT_ETHERADD,"ETHER_OFF")) { printf("Ethernet disabled, must set MAC address\n"); return(-1); } printf("WARNING: using default MAC address.\n"); Etheradd = DEFAULT_ETHERADD; } } setenv("ETHERADD",Etheradd); } /* Apply the same logic as above to the IP address... */ if (!(IPadd = getenv("IPADD"))) { if (!(IPadd = extGetIpAdd())) { if (ipaddr[0] != 0xff) IPadd = ipaddr; else IPadd = DEFAULT_IPADD; } setenv("IPADD",IPadd); } /* Convert addresses to binary: */#if INCLUDE_DHCPBOOT if (DhcpIPCheck(IPadd) == -1) return(-1);#else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -