targeter() { while (TRUE) { recvclr(); targetx = (rand() % (XMAXFIELD-6)) + 2; targety = (rand() % (YMAXFIELD-6)) + 2; targetvalue=(rand() % 9)+1; newsend(pidplotter,3,targetx,targety,targetvalue+48 ); resume(pidtimer = create(removetarget,200,13,"remover",0)); if (receive() != REMOVE) kill(pidtimer); else newsend(pidplotter,3,targetx,targety ,' '); } }
int main(int argc, char **argv) { umsg32 retval; /* Creating a shell process */ resume(create(shell, 4096, 1, "shell", 1, CONSOLE)); retval = recvclr(); while (TRUE) { retval = receive(); kprintf("\n\n\rMain process recreating shell\n\n\r"); resume(create(shell, 4096, 1, "shell", 1, CONSOLE)); } return OK; }
process main(void) { /* Start the network */ //ethinit(&devtab[ETHER0]); uint32 *macaddr = 0x44e10630; kprintf("mac addr: %x %x\n", *macaddr, *(macaddr+1)); int32 i; /* for(i = 0; i < 6; i++) { NetData.ethucast[i] = i; NetData.ethbcast[i] = 0xff; }*/ //kprintf("reading packet from ETHER0\n"); //struct netpacket pkt; //read(ETHER0, &pkt, 1518); //resume(create(counterproc, 8192, 19, "counter proc", 0, NULL)); //sleep(10); //kprintf("Counter value: %d\n", gcounter); //DELAY(5000000); // Commented by Bryce Himebaugh on 9/02/1015. Generating run time error messages. // netstart(); kprintf("\n...creating a shell\n"); recvclr(); resume(create(shell, 8192, 50, "shell", 1, CONSOLE)); /* Wait for shell to exit and recreate it */ while (TRUE) { receive(); sleepms(200); kprintf("\n\nMain process recreating shell\n\n"); resume(create(shell, 4096, 20, "shell", 1, CONSOLE)); } return OK; }
process main(void) { char bbb_ipaddr[] = "192.168.1.101"; char bbb_router[] = "192.168.1.255"; /* Start the network */ netstart(bbb_ipaddr,bbb_router); kprintf("\n...creating a shell\n"); recvclr(); resume(create(shell, 8192, 50, "shell", 1, CONSOLE)); /* Wait for shell to exit and recreate it */ while (TRUE) { receive(); sleepms(200); kprintf("\n\nMain process recreating shell\n\n"); resume(create(shell, 4096, 20, "shell", 1, CONSOLE)); } return OK; }
int main(int argc, char **argv) { uint32 retval; kprintf("main: calling getlocalip\n"); NetData.ipvalid = FALSE; retval = getlocalip(); if (retval == SYSERR) { kprintf("I'm here to stop!\n"); } else { kprintf("I'm here to continue!\n"); kprintf("\n\n###########################################################\n\n"); kprintf("IP address is %d.%d.%d.%d %08x\n\r", (retval>>24)&0xff, (retval>>16)&0xff, (retval>>8)&0xff, retval&0xff,retval); kprintf("Subnet mask is %d.%d.%d.%d and router is %d.%d.%d.%d\n\r", (NetData.addrmask>>24)&0xff, (NetData.addrmask>>16)&0xff, (NetData.addrmask>> 8)&0xff, NetData.addrmask&0xff, (NetData.routeraddr>>24)&0xff, (NetData.routeraddr>>16)&0xff, (NetData.routeraddr>> 8)&0xff, NetData.routeraddr&0xff); } //netin(); //while (1); resume(create(shell, 8192, 50, "shell", 1, CONSOLE)); /* Wait for shell to exit and recreate it */ recvclr(); while (TRUE) { retval = receive(); kprintf("\n\n\rMain process recreating shell\n\n\r"); resume(create(shell, 4096, 1, "shell", 1, CONSOLE)); } return OK; }
/*------------------------------------------------------------------------ * rarpsend - broadcast a RARP packet to obtain my IP address *------------------------------------------------------------------------ */ int rarpsend(int ifn) { STATWORD ps; struct netif *pni = &nif[ifn]; struct ep *pep; int i, mypid, resp; IPaddr junk = 0; /* arg to mkarp; never used */ mypid = getpid(); for (i=0; i<ARP_MAXRETRY; ++i) { pep = mkarp(ifn, EPT_RARP, RA_REQUEST, junk, junk); if ((int)pep == SYSERR) break; disable(ps); rarppid = mypid; restore(ps); recvclr(); write(pni->ni_dev, pep, EP_MINLEN); /* ARP_RESEND is in secs, recvtim uses 1/10's of secs */ resp = recvtim(10*ARP_RESEND<<i); if (resp != TIMEOUT) { /* host route */ rtadd(pni->ni_ip, ip_maskall, pni->ni_ip, 0, NI_LOCAL, RT_INF); /* non-subnetted route */ rtadd(pni->ni_net, ip_maskall, pni->ni_ip, 0, NI_LOCAL, RT_INF); return OK; } } panic("No response to RARP"); return SYSERR; }
/*------------------------------------------------------------------------ * udp_recvaddr - receive a UDP packet and record the sender's address *------------------------------------------------------------------------ */ int32 udp_recvaddr ( uint32 *remip, /* loc to record remote IP addr.*/ uint16 *remport, /* loc to record remote port */ uint16 locport, /* local UDP protocol port */ char *buff, /* buffer to hold UDP data */ int32 len, /* length of buffer */ uint32 timeout /* read timeout in msec */ ) { intmask mask; /* saved interrupt mask */ int32 i; /* index into udptab */ struct udpentry *udptr; /* pointer to udptab entry */ umsg32 msg; /* message from recvtime() */ struct eth_packet *pkt; /* ptr to packet being read */ struct ipv4_packet *ippkt = NULL; struct udp_packet * udppkt = NULL; int32 msglen; /* length of UDP data in packet */ char *udataptr; /* pointer to UDP data */ /* Insure only one process access UDP table at a time */ mask = disable(); for (i=0; i<UDP_SLOTS; i++) { udptr = &udptab[i]; if ( (udptr->udremip == 0 ) && (locport == udptr->udlocport) ) { /* Entry in table matches request */ break; } } if (i >= UDP_SLOTS) { restore(mask); return SYSERR; } if (udptr->udcount == 0) { /* no packet is waiting */ udptr->udstate = UDP_RECV; udptr->udpid = currpid; msg = recvclr(); msg = recvtime(timeout); /* wait for packet */ udptr->udstate = UDP_USED; if (msg == TIMEOUT) { restore(mask); return TIMEOUT; } else if (msg != OK) { restore(mask); return SYSERR; } } /* Packet has arrived -- dequeue it */ pkt = udptr->udqueue[udptr->udhead++]; ippkt = (struct ipv4_packet *)(pkt->net_ethdata); udppkt = (struct udp_packet *)(ippkt->net_ipdata); if (udptr->udhead >= UDP_SLOTS) { udptr->udhead = 0; } udptr->udcount--; /* Record sender's IP address and UDP port number */ *remip = ippkt->net_ipsrc; *remport = udppkt->net_udpsport; /* Copy UDP data from packet into caller's buffer */ msglen = udppkt->net_udplen - UDP_HDR_LEN; udataptr = (char *)udppkt->net_udpdata; for (i=0; i<msglen; i++) { if (i >= len) { break; } *buff++ = *udataptr++; } freebuf((char *)pkt); restore(mask); return i; }
/*------------------------------------------------------------------------ * udp_recvaddr - Receive a UDP packet and record the sender's address *------------------------------------------------------------------------ */ int32 udp_recvaddr ( uid32 slot, /* Slot in table to use */ uint32 *remip, /* Loc for remote IP address */ uint16 *remport, /* Loc for remote protocol port */ char *buff, /* Buffer to hold UDP data */ int32 len, /* Length of buffer */ uint32 timeout /* Read timeout in msec */ ) { intmask mask; /* Saved interrupt mask */ struct udpentry *udptr; /* Pointer to udptab entry */ umsg32 msg; /* Message from recvtime() */ struct netpacket *pkt; /* Pointer to packet being read */ int32 msglen; /* Length of UDP data in packet */ int32 i; /* Counts bytes copied */ char *udataptr; /* Pointer to UDP data */ /* Ensure only one process can access the UDP table at a time */ mask = disable(); /* Verify that the slot is valid */ if ((slot < 0) || (slot >= UDP_SLOTS)) { restore(mask); return SYSERR; } /* Get pointer to table entry */ udptr = &udptab[slot]; /* Verify that the slot has been registered and is valid */ if (udptr->udstate != UDP_USED) { restore(mask); return SYSERR; } /* Wait for a packet to arrive */ if (udptr->udcount == 0) { /* No packet is waiting */ udptr->udstate = UDP_RECV; udptr->udpid = currpid; msg = recvclr(); msg = recvtime(timeout); /* Wait for a packet */ udptr->udstate = UDP_USED; if (msg == TIMEOUT) { restore(mask); return TIMEOUT; } else if (msg != OK) { restore(mask); return SYSERR; } } /* Packet has arrived -- dequeue it */ pkt = udptr->udqueue[udptr->udhead++]; if (udptr->udhead >= UDP_QSIZ) { udptr->udhead = 0; } /* Record sender's IP address and UDP port number */ *remip = pkt->net_ipsrc; *remport = pkt->net_udpsport; udptr->udcount--; /* Copy UDP data from packet into caller's buffer */ msglen = pkt->net_udplen - UDP_HDR_LEN; udataptr = (char *)pkt->net_udpdata; if (len < msglen) { msglen = len; } for (i=0; i<msglen; i++) { *buff++ = *udataptr++; } freebuf((char *)pkt); restore(mask); return msglen; }
process main(void) { kprintf("\nHello World!\n"); kprintf("\nI'm the first XINU app and running function main() in system/main.c.\n"); kprintf("\nI was created by nulluser() in system/initialize.c using create().\n"); kprintf("\nMy creator will turn itself into the do-nothing null process.\n"); kprintf("\nI will create a second XINU app that runs shell() in shell/shell.c as an example.\n"); kprintf("\nYou can do something else, or do nothing; it's completely up to you.\n"); kprintf("\n...creating a shell\n"); recvclr(); // Homework 1 { //resume(create(shell, 8192, 50, "shell", 1, CONSOLE)); /* * Createschild process calling app1() resume ( create((void *)app1, 65536, 20, "app1 process", 0, NULL)); * Creates child process calling app2() resume ( create((void *)app2, 65536, 20, "app2 process", 0, NULL));*/ /* Wait for shell to exit and recreate it */ /* while (TRUE) { receive(); sleepms(200); kprintf("\n\nMain process recreating shell\n\n"); resume(create(shell, 4096, 20, "shell", 1, CONSOLE)); }*/ } // Homework 2 { /* uint32 a = 0xAABBCCDD; uint32 b = host2netla(a); kprintf("\n\nLil Endian to Big Endian\nBig Endian of 0x%x is 0x%x", a, b); a = 0xAABBCCDD; b = host2netlb(a); kprintf("\n\nLil Endian to Big Endian\nBig Endian of 0x%x is 0x%x", a, host2netlb(a)); a = 0xAABBCCDD; b = host2netlc(a); kprintf("\n\nLil Endian to Big Endian\nBig Endian of 0x%x is 0x%x", a, b); prntsegaddr(); //kprintf("\nStack Depth:%d\n", stackdepth(currpid)); resume ( create((void *)f1, 65536, 20, "f1 process", 0, NULL)); unsigned long * topsp; asm("movl %esp, esp"); topsp = esp; kprintf("\ncurrpid : %d\n", currpid); kprintf("\nBefore myappA is created\n"); kprintf("run-time stack top : address = 0x%x, content = 0x%x\n", topsp, (unsigned long *) *topsp); pid32 myappA_pid = create( (void *) myappA, 65536, 20, "myappA process", 2, 5, currpid); asm("movl %esp, esp"); topsp = esp; kprintf("\nAfter myappA is created but before resuming it\n"); kprintf("run-time stack top : address = 0x%x, content = 0x%x\n", topsp, (unsigned long *) *topsp); resume(myappA_pid); sleepms(500); pid32 victim_pid; resume ( create((void *)myvictim, 2048, 10, "myvictim process", 1, 5)); resume (victim_pid = create((void *)myvictim, 2048, 10, "myvictim process", 1, 5)); resume ( create((void *)myhacker, 2048, 10, "myhacker process", 1, victim_pid)); return OK; */ } // Homework 3 homework3(); return OK; }
process shell ( did32 dev /* ID of tty device from which */ ) /* to accept commands */ { char buf[SHELL_BUFLEN]; /* Input line (large enough for */ /* one line from a tty device */ int32 len; /* Length of line read */ char tokbuf[SHELL_BUFLEN + /* Buffer to hold a set of */ SHELL_MAXTOK]; /* Contiguous null-terminated */ /* Strings of tokens */ int32 tlen; /* Current length of all data */ /* in array tokbuf */ int32 tok[SHELL_MAXTOK]; /* Index of each token in */ /* array tokbuf */ int32 toktyp[SHELL_MAXTOK]; /* Type of each token in tokbuf */ int32 ntok; /* Number of tokens on line */ pid32 child; /* Process ID of spawned child */ bool8 backgnd; /* Run command in background? */ char *outname, *inname; /* Pointers to strings for file */ /* names that follow > and < */ did32 stdinput, stdoutput; /* Descriptors for redirected */ /* input and output */ int32 i; /* Index into array of tokens */ int32 j; /* Index into array of commands */ int32 msg; /* Message from receive() for */ /* child termination */ int32 tmparg; /* Address of this var is used */ /* when first creating child */ /* process, but is replaced */ char *src, *cmp; /* Pointers used during name */ /* comparison */ bool8 diff; /* Was difference found during */ /* comparison */ char *args[SHELL_MAXTOK]; /* Argument vector passed to */ /* builtin commands */ /* Print shell banner and startup message */ fprintf(dev, "\n\n%s%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n", SHELL_BAN0,SHELL_BAN1,SHELL_BAN2,SHELL_BAN3,SHELL_BAN4, SHELL_BAN5,SHELL_BAN6,SHELL_BAN7,SHELL_BAN8,SHELL_BAN9); fprintf(dev, "%s\n\n", SHELL_STRTMSG); /* Continually prompt the user, read input, and execute command */ while (TRUE) { /* Display prompt */ fprintf(dev, SHELL_PROMPT); /* Read a command */ len = read(dev, buf, sizeof(buf)); /* Exit gracefully on end-of-file */ if (len == EOF) { break; } /* If line contains only NEWLINE, go to next line */ if (len <= 1) { continue; } buf[len] = SH_NEWLINE; /* terminate line */ /* Parse input line and divide into tokens */ ntok = lexan(buf, len, tokbuf, &tlen, tok, toktyp); /* Handle parsing error */ if (ntok == SYSERR) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } /* If line is empty, go to next input line */ if (ntok == 0) { fprintf(dev, "\n"); continue; } /* If last token is '&', set background */ if (toktyp[ntok-1] == SH_TOK_AMPER) { ntok-- ; tlen-= 2; backgnd = TRUE; } else { backgnd = FALSE; } /* Check for input/output redirection (default is none) */ outname = inname = NULL; if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS) ||(toktyp[ntok-2] == SH_TOK_GREATER))){ if (toktyp[ntok-1] != SH_TOK_OTHER) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } if (toktyp[ntok-2] == SH_TOK_LESS) { inname = &tokbuf[tok[ntok-1]]; } else { outname = &tokbuf[tok[ntok-1]]; } ntok -= 2; tlen = tok[ntok]; } if ( (ntok >=3) && ( (toktyp[ntok-2] == SH_TOK_LESS) ||(toktyp[ntok-2] == SH_TOK_GREATER))){ if (toktyp[ntok-1] != SH_TOK_OTHER) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } if (toktyp[ntok-2] == SH_TOK_LESS) { if (inname != NULL) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } inname = &tokbuf[tok[ntok-1]]; } else { if (outname != NULL) { fprintf(dev,"%s\n", SHELL_SYNERRMSG); continue; } outname = &tokbuf[tok[ntok-1]]; } ntok -= 2; tlen = tok[ntok]; } /* Verify remaining tokens are type "other" */ for (i=0; i<ntok; i++) { if (toktyp[i] != SH_TOK_OTHER) { break; } } if ((ntok == 0) || (i < ntok)) { fprintf(dev, SHELL_SYNERRMSG); continue; } stdinput = stdoutput = dev; /* Lookup first token in the command table */ for (j = 0; j < ncmd; j++) { src = cmdtab[j].cname; cmp = tokbuf; diff = FALSE; while (*src != NULLCH) { if (*cmp != *src) { diff = TRUE; break; } src++; cmp++; } if (diff || (*cmp != NULLCH)) { continue; } else { break; } } /* Handle command not found */ if (j >= ncmd) { fprintf(dev, "command %s not found\n", tokbuf); continue; } /* Handle built-in command */ if (cmdtab[j].cbuiltin) { /* No background or redirect. */ if (inname != NULL || outname != NULL || backgnd){ fprintf(dev, SHELL_BGERRMSG); continue; } else { /* Set up arg vector for call */ for (i=0; i<ntok; i++) { args[i] = &tokbuf[tok[i]]; } /* Call builtin shell function */ if ((*cmdtab[j].cfunc)(ntok, args) == SHELL_EXIT) { break; } } continue; } /* Open files and redirect I/O if specified */ if (inname != NULL) { stdinput = open(NAMESPACE,inname,"ro"); if (stdinput == SYSERR) { fprintf(dev, SHELL_INERRMSG, inname); continue; } } if (outname != NULL) { stdoutput = open(NAMESPACE,outname,"w"); if (stdoutput == SYSERR) { fprintf(dev, SHELL_OUTERRMSG, outname); continue; } else { control(stdoutput, F_CTL_TRUNC, 0, 0); } } /* Spawn child thread for non-built-in commands */ child = create(cmdtab[j].cfunc, SHELL_CMDSTK, SHELL_CMDPRIO, cmdtab[j].cname, 2, ntok, &tmparg); /* If creation or argument copy fails, report error */ if ((child == SYSERR) || (addargs(child, ntok, tok, tlen, tokbuf, &tmparg) == SYSERR) ) { fprintf(dev, SHELL_CREATMSG); continue; } /* Set stdinput and stdoutput in child to redirect I/O */ proctab[child].prdesc[0] = stdinput; proctab[child].prdesc[1] = stdoutput; msg = recvclr(); resume(child); if (! backgnd) { msg = receive(); while (msg != child) { msg = receive(); } } } /* Terminate the shell process by returning from the top level */ fprintf(dev,SHELL_EXITMSG); return OK; }
/** * The Xinu shell. Provides an interface to execute commands. * @param descrp descriptor of device on which the shell is open * @return OK for successful exit, SYSERR for unrecoverable error */ thread shell(int indescrp, int outdescrp, int errdescrp) { char buf[SHELL_BUFLEN]; /* line input buffer */ short buflen; /* length of line input */ char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK]; /* token value buffer */ short ntok; /* number of tokens */ char *tok[SHELL_MAXTOK]; /* pointers to token values */ char *outname; /* name of output file */ char *inname; /* name of input file */ bool background; /* is background proccess? */ syscall child; /* pid of child thread */ ushort i, j; /* temp variables */ irqmask im; /* interrupt mask state */ /* hostname variables */ char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend */ char *hostptr; /* pointer to hostname */ int hostname_strsz; /* nvram hostname name size */ device *devptr; /* device pointer */ printf( "Welcome to the shell!\n" ); /* Enable interrupts */ enable(); hostptr = NULL; devptr = NULL; hostname_strsz = 0; bzero(hostnm, NET_HOSTNM_MAXLEN + 1); /* Setup buffer for string for nvramGet call for hostname */ #ifdef ETH0 if (!isbaddev(ETH0)) { /* Determine the hostname of the main network device */ devptr = (device *)&devtab[ETH0]; hostname_strsz = strnlen(NET_HOSTNAME, NVRAM_STRMAX) + 1; hostname_strsz += DEVMAXNAME; char nvramget_hostname_str[hostname_strsz]; sprintf(nvramget_hostname_str, "%s_%s", devptr->name, NET_HOSTNAME); /* Acquire the backend's hostname */ #if NVRAM hostptr = nvramGet(nvramget_hostname_str); #endif /* NVRAM */ if (hostptr != NULL) { memcpy(hostnm, hostptr, NET_HOSTNM_MAXLEN); hostptr = hostnm; } } #endif /* Set command devices for input, output, and error */ stdin = indescrp; stdout = outdescrp; stderr = errdescrp; /* Print shell banner */ printf(SHELL_BANNER); /* Print shell welcome message */ printf(SHELL_START); /* Continually receive and handle commands */ while (TRUE) { /* Display prompt */ printf(SHELL_PROMPT); if (NULL != hostptr) { printf("@%s$ ", hostptr); } else { printf("$ "); } /* Setup proper tty modes for input and output */ control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); /* Null out the buf and read command */ memset(buf, '\0', SHELL_BUFLEN); buflen = shellRead(stdin, buf, SHELL_BUFLEN); if(buf[0] != '!') { addHistoryItem(buf, buflen); } /* Check for EOF and exit gracefully if seen */ if (EOF == buflen) { break; } // Check for indicator of history command if (buf[0] == '!') { int index; // handler for !! (just execute most recent command) if(buf[1] == '!') { index = 0; } else { // extract the number string char indexString[buflen]; strncpy(indexString, &buf[1], buflen - 1); indexString[buflen] = '\0'; // convert number string into a valid index // calculation is done because the index numbers // are reverse of their numbers printed using 'history' index = numHistoryItems - atoi(indexString); } //replace buf and buflen with the last command strncpy(buf, history[index].command, SHELL_BUFLEN); buflen = history[index].commandLength + 1; } /* Parse line input into tokens */ if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0]))) { fprintf(stderr, SHELL_SYNTAXERR); continue; } /* Ensure parse generated tokens */ if (0 == ntok) { continue; } /* Initialize command options */ inname = NULL; outname = NULL; background = FALSE; /* Mark as background thread, if last token is '&' */ if ('&' == *tok[ntok - 1]) { ntok--; background = TRUE; } /* Check each token and perform special handling of '>' and '<' */ for (i = 0; i < ntok; i++) { /* Background '&' should have already been handled; Syntax error */ if ('&' == *tok[i]) { ntok = -1; break; } /* Setup for output redirection if token is '>' */ if ('>' == *tok[i]) { /* Syntax error */ if (outname != NULL || i >= ntok - 1) { ntok = -1; break; } outname = tok[i + 1]; ntok -= 2; /* shift tokens (not to be passed to command */ for (j = i; j < ntok; j++) { tok[j] = tok[j + 2]; } continue; } /* Setup for input redirection if token is '<' */ if ('<' == *tok[i]) { /* Syntax error */ if (inname != NULL || i >= ntok - 1) { ntok = -1; break; } inname = tok[i + 1]; ntok -= 2; /* shift tokens (not to be passed to command */ for (j = i; j < ntok; j++) { tok[j] = tok[j + 2]; } continue; } } /* Handle syntax error */ if (ntok <= 0) { fprintf(stderr, SHELL_SYNTAXERR); continue; } /* Lookup first token in the command table */ for (i = 0; i < ncommand; i++) { if (0 == strncmp(commandtab[i].name, tok[0], SHELL_BUFLEN)) { break; } } /* Handle command not found */ if (i >= ncommand) { fprintf(stderr, "%s: command not found\n", tok[0]); continue; } /* Handle command if it is built-in */ if (commandtab[i].builtin) { if (inname != NULL || outname != NULL || background) { fprintf(stderr, SHELL_SYNTAXERR); } else { (*commandtab[i].procedure) (ntok, tok); } continue; } /* Spawn child thread for non-built-in commands */ child = create(commandtab[i].procedure, SHELL_CMDSTK, SHELL_CMDPRIO, commandtab[i].name, 2, ntok, tok); /* Ensure child command thread was created successfully */ if (SYSERR == child) { fprintf(stderr, SHELL_CHILDERR); continue; } /* Set file descriptors for newly created thread */ if (NULL == inname) { thrtab[child].fdesc[0] = stdin; } else { thrtab[child].fdesc[0] = getdev(inname); } if (NULL == outname) { thrtab[child].fdesc[1] = stdout; } else { thrtab[child].fdesc[1] = getdev(outname); } thrtab[child].fdesc[2] = stderr; if (background) { /* Make background thread ready, but don't reschedule */ im = disable(); ready(child, RESCHED_NO); restore(im); } else { /* Clear waiting message; Reschedule; */ while (recvclr() != NOMSG); im = disable(); ready(child, RESCHED_YES); restore(im); /* Wait for command thread to finish */ while (receive() != child); sleep(10); } } /* Close shell */ fprintf(stdout, SHELL_EXIT); sleep(10); return OK; }
/** * @ingroup shell * * Shell command (ping). * @param nargs number of arguments in args array * @param args array of arguments * @return OK for success, SYSERR for syntax error */ shellcmd xsh_ping(int nargs, char *args[]) { int i = 0; int interval = 1000, count = 10, recv = 0, echoq = 0; ulong rtt = 0, min = 0, max = 0, total = 0; ulong startsec = 0, startms = 0; struct netaddr target; struct packet *pkt = NULL; char str[50]; /* Output help, if '--help' argument was supplied */ if (nargs == 2 && strncmp(args[1], "--help", 7) == 0) { printf("Usage: ping <IP>\n\n"); printf("Description:\n"); printf("\tSend ICMP echo requests to network hosts\n"); printf("Options:\n"); printf("\t<IP>\t\tIP address\n"); printf("\t-c count\tstop after sending count packets\n"); printf ("\t-i interval\tsleep interval milliseconds between pings\n"); printf("\t--help\t\tdisplay this help and exit\n"); return OK; } /* Check for correct number of arguments */ if (nargs < 2) { fprintf(stderr, "ping: too few arguments\n"); fprintf(stderr, "Try 'ping --help' for more information\n"); return SHELL_ERROR; } i = 1; while (i < nargs) { if (0 == strncmp(args[i], "-c", 3)) { i++; if (i < nargs) { count = atoi(args[i]); } else { fprintf(stderr, "ping: -c requires integer argument\n"); return SHELL_ERROR; } } else if (0 == strncmp(args[i], "-i", 3)) { i++; if (i < nargs) { interval = atoi(args[i]); } else { fprintf(stderr, "ping: -i requires integer argument\n"); return SHELL_ERROR; } } else if (SYSERR == dot2ipv4(args[i], &target)) { fprintf(stderr, "ping: %s is not a valid IPv4 address.\n", args[i]); return SHELL_ERROR; } i++; } netaddrsprintf(str, &target); if (0 == strncmp(str, "ERROR", 6)) { fprintf(stderr, "ping: destination IP address required.\n"); return SHELL_ERROR; } printf("PING %s\n", str); echoq = echoQueueAlloc(); if (SYSERR == echoq) { printf("...No free echo queues!\n"); return SHELL_ERROR; } startsec = clktime; startms = clkticks; for (i = 0; i < count; i++) { // Send ping packet if (SYSERR == icmpEchoRequest(&target, gettid(), i)) { printf("...Failed to reach %s\n", str); return SHELL_ERROR; } sleep(interval); if (NOMSG != recvclr()) { // pick reply packets off of the queue pkt = echoQueueGet(echoq); while ((NULL != (ulong)pkt) && (SYSERR != (ulong)pkt)) { rtt = echoTripTime(pkt); total += rtt; if ((rtt < min) || (0 == min)) { min = rtt; } if (rtt > max) { max = rtt; } echoPrintPkt(pkt, rtt); netFreebuf(pkt); recv++; pkt = echoQueueGet(echoq); } } } echoQueueDealloc(echoq); netaddrsprintf(str, &target); printf("--- %s ping statistics ---\n", str); printf("%d packets transmitted, %d received,", count, recv); printf(" %d%% packet loss,", (count - recv) * 100 / count); printf(" time %dms\n", (clktime - startsec) * 1000 + ((clkticks - startms) * 1000) / CLKTICKS_PER_SEC); printf("rtt min/avg/max = %d.%03d/", min / 1000, min % 1000); if (0 != recv) { printf("%d.%03d/", (total / recv) / 1000, (total / recv) % 1000); } else { printf("-/"); } printf("%d.%03d ms\n", max / 1000, max % 1000); return SHELL_OK; }
/** * @ingroup shell * * Shell command (telnet). * @param nargs number of arguments in args array * @param args array of arguments * @return 0 for success, 1 for error */ shellcmd xsh_telnet(int nargs, char *args[]) { int i; ushort port = 0; struct netaddr host; struct netaddr *localhost; struct netif *interface; tid_typ recvthr; tid_typ sendthr; int msg = 0; int dev; for (i = 1; i < nargs; i++) { /* Help */ if (0 == strcmp(args[i], "--help")) { usage(args[0]); return 0; } /* Host */ if (0 == host.len) { if (SYSERR == dot2ipv4(args[i], &host)) { fprintf(stderr, "Invalid hostname\n"); return 1; } continue; } /* Port */ if (0 == port) { port = atoi(args[i]); if (port == 0) { fprintf(stderr, "Port must be greater than 0\n"); return 1; } continue; } /* Otherwise */ fprintf(stderr, "Invalid number of arguments\n"); return 1; } /* Verify a valid number of arguments were processed */ if (0 == host.len) { fprintf(stderr, "Invalid number of arguments\n"); return 1; } /* Set default port if none is specified */ if (port == 0) { port = TELNET_PORT; } /* Print that the client is trying to connect to the server */ printf("Trying %s...\n", args[1]); interface = netLookup((ethertab[0].dev)->num); if (NULL == interface) { fprintf(stderr, "No network interface found\n"); return 1; } localhost = &(interface->ip); /* Open connection */ #if NTCP dev = tcpAlloc(); #else dev = SYSERR; #endif /* NTCP */ if (SYSERR == dev) { fprintf(stderr, "Failed to allocate TCP device\n"); return 1; } if (SYSERR == open(dev, localhost, &host, NULL, port, TCP_ACTIVE)) { fprintf(stderr, "Failed to establish connection\n"); return 1; } /* Display a connection prompt and tell the user how to quit */ printf("Connected to %s.\nQuit character is '^]'.\n", args[1]); recvthr = create(telnetRecv, SHELL_CMDSTK, SHELL_CMDPRIO, "telnet_recv", 1, dev); sendthr = create(telnetSend, SHELL_CMDSTK, SHELL_CMDPRIO, "telnet_send", 1, dev); if ((SYSERR == recvthr) || (SYSERR == sendthr)) { kill(recvthr); kill(sendthr); close(dev); return 1; } thrtab[recvthr].fdesc[0] = stdin; thrtab[recvthr].fdesc[1] = stdout; thrtab[recvthr].fdesc[2] = stderr; thrtab[sendthr].fdesc[0] = stdin; thrtab[sendthr].fdesc[1] = stdout; thrtab[sendthr].fdesc[2] = stderr; /* Start both threads */ while (recvclr() != NOMSG); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); ready(recvthr, RESCHED_YES); ready(sendthr, RESCHED_NO); /* Wait for one thread to die */ while ((msg != recvthr) && (msg != sendthr)) { msg = receive(); } sleep(10); /* Kill both threads */ kill(recvthr); kill(sendthr); close(dev); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); return 0; }
/*------------------------------------------------------------------------ * icmp_recv - Receive an icmp echo reply packet *------------------------------------------------------------------------ */ int32 icmp_recv ( int32 icmpid, /* ICMP slot identifier */ char *buff, /* Buffer to ICMP data */ int32 len, /* Length of buffer */ uint32 timeout /* Time to wait in msec */ ) { intmask mask; /* Saved interrupt mask */ struct icmpentry *icmptr; /* Pointer to icmptab entry */ umsg32 msg; /* Message from recvtime() */ struct netpacket *pkt; /* Pointer to packet being read */ int32 datalen; /* Length of ICMP data area */ char *icdataptr; /* Pointer to icmp data */ int32 i; /* Counter for data copy */ /* Verify that the ID is valid */ if ( (icmpid < 0) || (icmpid >= ICMP_SLOTS) ) { return SYSERR; } /* Insure only one process touches the table at a time */ mask = disable(); /* Verify that the ID has been registered and is idle */ icmptr = &icmptab[icmpid]; if (icmptr->icstate != ICMP_USED) { restore(mask); return SYSERR; } if (icmptr->iccount == 0) { /* No packet is waiting */ icmptr->icstate = ICMP_RECV; icmptr->icpid = currpid; msg = recvclr(); msg = recvtime(timeout); /* Wait for a reply */ icmptr->icstate = ICMP_USED; if (msg == TIMEOUT) { restore(mask); return TIMEOUT; } else if (msg != OK) { restore(mask); return SYSERR; } } /* Packet has arrived -- dequeue it */ pkt = icmptr->icqueue[icmptr->ichead++]; if (icmptr->ichead >= ICMP_SLOTS) { icmptr->ichead = 0; } icmptr->iccount--; /* Copy data from ICMP message into caller's buffer */ datalen = pkt->net_iplen - IP_HDR_LEN - ICMP_HDR_LEN; icdataptr = (char *) &pkt->net_icdata; for (i=0; i<datalen; i++) { if (i >= len) { break; } *buff++ = *icdataptr++; } freebuf((char *)pkt); restore(mask); return i; }
/** * @ingroup arp * * Obtains a hardware address from the ARP table given a protocol address. * @param netptr network interface * @param praddr protocol address * @param hwaddr buffer into which hardware address should be placed * @return OK if hardware address was obtained, otherwise TIMEOUT or SYSERR */ syscall arpLookup(struct netif *netptr, const struct netaddr *praddr, struct netaddr *hwaddr) { struct arpEntry *entry = NULL; /**< pointer to ARP table entry */ uint lookups = 0; /**< num of ARP lookups performed */ int ttl; /**< TTL for ARP table entry */ irqmask im; /**< interrupt state */ /* Error check pointers */ if ((NULL == netptr) || (NULL == praddr) || (NULL == hwaddr)) { ARP_TRACE("Invalid args"); return SYSERR; } ARP_TRACE("Looking up protocol address"); /* Attempt to obtain destination hardware address from ARP table until: * 1) lookup succeeds; 2) TIMEOUT occurs; 3) SYSERR occurs; or * 4) maximum number of lookup attempts occrus. */ while (lookups < ARP_MAX_LOOKUP) { lookups++; /* Obtain entry from ARP table */ im = disable(); entry = arpGetEntry(praddr); /* If ARP entry does not exist; create an unresolved entry */ if (NULL == entry) { ARP_TRACE("Entry does not exist"); entry = arpAlloc(); if (SYSERR == (int)entry) { restore(im); return SYSERR; } entry->state = ARP_UNRESOLVED; entry->nif = netptr; netaddrcpy(&entry->praddr, praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; entry->count = 0; } /* Place hardware address in buffer if entry is resolved */ if (ARP_RESOLVED == entry->state) { netaddrcpy(hwaddr, &entry->hwaddr); ARP_TRACE("Entry exists"); return OK; } /* Entry is unresolved; enqueue thread to wait for resolution */ if (entry->count >= ARP_NTHRWAIT) { restore(im); ARP_TRACE("Queue of waiting threads is full"); return SYSERR; } entry->waiting[entry->count] = gettid(); entry->count++; ttl = (entry->expires - clktime) * CLKTICKS_PER_SEC; restore(im); /* Send an ARP request and wait for response */ if (SYSERR == arpSendRqst(entry)) { ARP_TRACE("Failed to send request"); return SYSERR; } recvclr(); switch (recvtime(ttl)) { case TIMEOUT: case SYSERR: return SYSERR; case ARP_MSG_RESOLVED: default: /* Reply received, address resolved, re-attempt lookup */ continue; } } return SYSERR; }
int main(int argc, char **argv) { uint32 retval; /* kprintf("main: calling getlocalip\n"); retval = getlocalip(); if (retval == SYSERR) { kprintf("I'm here to stop!\n"); } else { kprintf("I'm here to continue!\n"); kprintf("\n\n###########################################################\n\n"); kprintf("IP address is %d.%d.%d.%d %08x\n\r", (retval>>24)&0xff, (retval>>16)&0xff, (retval>>8)&0xff, retval&0xff,retval); kprintf("Subnet mask is %d.%d.%d.%d and router is %d.%d.%d.%d\n\r", (NetData.addrmask>>24)&0xff, (NetData.addrmask>>16)&0xff, (NetData.addrmask>> 8)&0xff, NetData.addrmask&0xff, (NetData.routeraddr>>24)&0xff, (NetData.routeraddr>>16)&0xff, (NetData.routeraddr>> 8)&0xff, NetData.routeraddr&0xff); } */ //BEG Lab1_______________________________________________________ /*kprintf("%x\n",host2netl_asm (0x12345678)); //long test_asm_val; //long testa = 3; //test_asm_val = host2netl_asm(testa); //kprintf("host2netl_asm: %s \r\n\r\n", test_asm_val); printsegaddress(); printprocstks(); myprogA(); kprintf("\r\nSpawning Processes...\r\n"); resume(create(myprogA,1024,20,"Process A",0)); //resume(create(myprogA,1024,20,"Process 2",0)); printprocstks();*/ //END Lab1_______________________________________________________ //BEG Lab2_______________________________________________________ //1024, 20priority, nameProcess, 1 arg, char /* uint32 pidA, pidB,pidC; pidA = create(printloop,1024,10,"Process A",1,'A'); pidB = create(printloop,1024,10,"Process B",1,'B'); pidC = create(printloop,1024,10,"Process C",1,'C'); //pidA = create(printloop,1024,6,"Process A",1,'A'); //pidB = create(printloop,1024,8,"Process B",1,'B'); //pidC = create(printloop,1024,10,"Process C",1,'C'); kprintf("P\r\n"); resume(pidA); kprintf("P\r\n"); resume(pidB); kprintf("P\r\n"); resume(pidC); //sleep for 5 seconds //sleepms(5000); sleepms(5000); */ //END Lab2_______________________________________________________ //BEG Lab3_______________________________________________________ //1024, 20priority, nameProcess, 1 arg, char test1(); sleepms(5000); test2(); sleepms(5000); test4(); // resume(create(cpuintensive, 1024, 20, "cpuintensiveA", 0)); // resume(create(cpuintensive, 1024, 20, "cpuintensiveB", 0)); // resume(create(cpuintensive, 1024, 20, "cpuintensiveC", 0)); // resume(create(cpuintensive, 1024, 20, "cpuintensiveD", 0)); //resume(create(cpuintensive, 1024, 20, "cpuintensiveE", 0)); //resume(create(cpuintensive, 1024, 20, "cpuintensiveF", 0)); /* resume(create(iointensive, 1024, 20, "iointensiveA", 0)); resume(create(iointensive, 1024, 20, "iointensiveB", 0)); resume(create(iointensive, 1024, 20, "iointensiveC", 0)); resume(create(iointensive, 1024, 20, "iointensiveD", 0)); resume(create(iointensive, 1024, 20, "iointensiveE", 0)); resume(create(iointensive, 1024, 20, "iointensiveF", 0)); */ /* uint32 pidA, pidB,pidC; pidA = create(printloop,1024,10,"Process A",1,'A'); pidB = create(printloop,1024,10,"Process B",1,'B'); pidC = create(printloop,1024,10,"Process C",1,'C'); //pidA = create(printloop,1024,6,"Process A",1,'A'); //pidB = create(printloop,1024,8,"Process B",1,'B'); //pidC = create(printloop,1024,10,"Process C",1,'C'); kprintf("P\r\n"); resume(pidA); kprintf("P\r\n"); resume(pidB); kprintf("P\r\n"); resume(pidC); //sleep for 5 seconds //sleepms(5000); sleepms(5000); */ //END Lab3_______________________________________________________ //comment out following line before, uncommented out lab 3 while (1); //Kalena commented out following line for lab3 //resume(create(shell, 8192, 50, "shell", 1, CONSOLE)); /* Wait for shell to exit and recreate it */ recvclr(); while (TRUE) { retval = receive(); kprintf("\n\n\rMain process recreating shell\n\n\r"); resume(create(shell, 4096, 1, "shell", 1, CONSOLE)); } return OK; }
/*------------------------------------------------------------------------ * rdsRead - Read a block from a remote disk *------------------------------------------------------------------------ */ devcall rdsRead ( struct dentry *devptr, /* entry in device switch table */ char *buff, /* buffer to hold disk block */ int32 blk /* block number of block to read*/ ) { struct rdscblk *rdptr; /* pointer to control block */ struct rdbuff *bptr; /* ptr to buffer possibly on */ /* the request list */ struct rdbuff *nptr; /* ptr to "next" node on a */ /* list */ struct rdbuff *pptr; /* ptr to "previous" node on */ /* a list */ struct rdbuff *cptr; /* ptr used to walk the cache */ /* If device not currently in use, report an error */ rdptr = &rdstab[devptr->dvminor]; if (rdptr->rd_state != RD_OPEN) { return SYSERR; } /* Search the cache for specified block */ bptr = rdptr->rd_chnext; while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) { if (bptr->rd_blknum == blk) { if (bptr->rd_status == RD_INVALID) { break; } memcpy(buff, bptr->rd_block, RD_BLKSIZ); return OK; } bptr = bptr->rd_next; } /* Search the request list for most recent occurrence of block */ bptr = rdptr->rd_rtprev; /* start at tail of list */ while (bptr != (struct rdbuff *)&rdptr->rd_rhnext) { if (bptr->rd_blknum == blk) { /* If most recent request for block is write, copy data */ if (bptr->rd_op == RD_OP_WRITE) { memcpy(buff, bptr->rd_block, RD_BLKSIZ); return OK; } break; } bptr = bptr->rd_prev; } /* Allocate a buffer and add read request to tail of req. queue */ bptr = rdsbufalloc(rdptr); bptr->rd_op = RD_OP_READ; bptr->rd_refcnt = 1; bptr->rd_blknum = blk; bptr->rd_status = RD_INVALID; bptr->rd_pid = getpid(); /* Insert new request into list just before tail */ pptr = rdptr->rd_rtprev; rdptr->rd_rtprev = bptr; bptr->rd_next = pptr->rd_next; bptr->rd_prev = pptr; pptr->rd_next = bptr; /* Prepare to receive message when read completes */ recvclr(); /* Signal semaphore to start communication process */ signal(rdptr->rd_reqsem); /* Block to wait for message */ bptr = (struct rdbuff *)receive(); if (bptr == (struct rdbuff *)SYSERR) { return SYSERR; } memcpy(buff, bptr->rd_block, RD_BLKSIZ); bptr->rd_refcnt--; if (bptr->rd_refcnt <= 0) { /* Look for previous item in cache with the same block */ /* number to see if this item was only being kept */ /* until pending read completed */ cptr = rdptr->rd_chnext; while (cptr != bptr) { if (cptr->rd_blknum == blk) { /* Unlink from cache */ pptr = bptr->rd_prev; nptr = bptr->rd_next; pptr->rd_next = nptr; nptr->rd_prev = pptr; /* Add to the free list */ bptr->rd_next = rdptr->rd_free; rdptr->rd_free = bptr; } } } return OK; }
/** * @ingroup shell * * Shell command (nc). * @param nargs number of arguments in args array * @param args array of arguments * @return 0 for success, 1 for error */ shellcmd xsh_nc(int nargs, char *args[]) { int a; ushort port; bool listen = FALSE; struct netaddr dst; struct netaddr src; tid_typ recvthr; tid_typ sendthr; int msg = 0; int dev; /* Output help, if '--help' argument was supplied */ if (nargs == 2 && 0 == strncmp(args[1], "--help", 7)) { usage(args[0]); return 0; } port = 0; dst.type = NULL; src.type = NULL; /* Parse arguments */ for (a = 1; a < nargs; a++) { if (args[a][0] != '-') { if (!listen && NULL == dst.type) { if (!isdigit(args[a][0])) { return argError(args[a]); } dot2ipv4(args[a], &dst); } else if (listen && NULL == src.type) { if (!isdigit(args[a][0])) { return argError(args[a]); } dot2ipv4(args[a], &src); } else if (NULL == port) { if (!isdigit(args[a][0])) { return argError(args[a]); } port = atoi(args[a]); } } else { switch (args[a][1]) { /* Listen on port */ case 'l': listen = TRUE; break; /* Source IP */ case 's': a++; if (a >= nargs || !isdigit(args[a][0])) { return argError(args[a - 1]); } dot2ipv4(args[a], &src); break; default: return argError(args[a]); } } } /* Verify arguments */ if (NULL == src.type) { fprintf(stderr, "Source/listen IP address required\n"); return 1; } if (NULL == port) { fprintf(stderr, "Invalid port\n"); return 1; } if (!listen && NULL == dst.type) { fprintf(stderr, "Remote IP address required\n"); return 1; } /* Allocate a TCP device */ #ifdef NTCP dev = tcpAlloc(); #else dev = SYSERR; #endif /* NTCP */ if (SYSERR == dev) { return connError(); } if (listen) { if (SYSERR == open(dev, &src, NULL, port, NULL, TCP_PASSIVE)) { close(dev); return connError(); } } else { if (SYSERR == open(dev, &src, &dst, NULL, port, TCP_ACTIVE)) { close(dev); return connError(); } } recvthr = create(ncRecv, SHELL_CMDSTK, SHELL_CMDPRIO, "nc_recv", 1, dev); sendthr = create(ncSend, SHELL_CMDSTK, SHELL_CMDPRIO, "nc_send", 1, dev); if ((SYSERR == recvthr) || (SYSERR == sendthr)) { kill(recvthr); kill(sendthr); close(dev); fprintf(stderr, "Failed to spawn threads"); return 1; } thrtab[recvthr].fdesc[0] = stdin; thrtab[recvthr].fdesc[1] = stdout; thrtab[recvthr].fdesc[2] = stderr; thrtab[sendthr].fdesc[0] = stdin; thrtab[sendthr].fdesc[1] = stdout; thrtab[sendthr].fdesc[2] = stderr; /* Start both threads */ while (recvclr() != NOMSG); ready(recvthr, RESCHED_YES); ready(sendthr, RESCHED_NO); /* Wait for one thread to die */ while ((msg != recvthr) && (msg != sendthr)) { msg = receive(); } sleep(10); /* Kill both threads */ kill(recvthr); kill(sendthr); close(dev); return 0; }
process main(void) { //printf("S**T\n"); recvclr(); //printf("----------Timed blocking message send TEST for PART 1-------\n"); //TEST1 //printf("TEST1 started\n"); //bmstest1(); //TEST2 //printf("TEST2 started\n"); //bmstest2(); //TEST3 //printf("TEST3 started\n"); //bmstest3(); //TEST4 //printf("TEST4 started\n"); //bmstest4(); //printbsmtests(); // prints the result of the tests printf("---------------ASYNC MSG RECV TEST CASES FOR PART2------------\n"); //TEST 1 - printf("TEST1 started\n"); asmtest1(); printf("TEST1 finished\n"); //TEST2 - printf("TEST2 started\n"); asmtest2(); printf("TEST2 finished\n"); printf("TEST3 started\n"); //TEST3 - asmtest3(); printf("TEST3 finished\n"); /*pid32 ar1 = create(asyncrec,1024,20,"asyncreceiver",0,NULL); pid32 as1 = create(asyncsend,1024,20,"asyncsender1",2,ar1,'A'); pid32 as2 = create(asyncsend,1024,20,"asyncsender2",2,ar1,'B'); pid32 as3 = create(asyncsend,1024,20,"asyncsender3",2,ar1,'C'); pid32 as4 = create(asyncsend,1024,20,"asyncsender4",2,ar1,'D'); resume(ar1); sleepms(25); resume(as1); sleepms(25); resume(as2); sleepms(25); resume(as3); sleepms(25); resume(as4);*/ return OK; }
/** * Tests ARP. * @return OK when testing is complete */ thread test_arp(bool verbose) { bool passed = TRUE; int i = 0; struct netaddr ip; struct netaddr mask; struct netaddr praddr; struct netaddr hwaddr; struct netaddr addrbuf; struct pcap_file_header pcap; struct pcap_pkthdr phdr; struct packet *pkt; struct netif *netptr; struct ethloop *pelp; uchar *data; uchar *request; struct arpPkt *arp; struct arpEntry *entry; uchar buf[ELOOP_BUFSIZE]; int nproc; int nout; int wait; tid_typ tids[ARP_NTHRWAIT]; tid_typ tid; irqmask im; enable(); ip.type = NETADDR_IPv4; ip.len = IPv4_ADDR_LEN; ip.addr[0] = 192; ip.addr[1] = 168; ip.addr[2] = 1; ip.addr[3] = 6; mask.type = NETADDR_IPv4; mask.len = IPv4_ADDR_LEN; mask.addr[0] = 255; mask.addr[1] = 255; mask.addr[2] = 255; mask.addr[3] = 0; /* Initialize loopback ethernet and network interface */ testPrint(verbose, "Test case initialization"); data = (uchar *)(&_binary_data_testarp_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); if (SYSERR == open(ELOOP)) { failif(TRUE, ""); } else { failif((SYSERR == netUp(ELOOP, &ip, &mask, NULL)), ""); } if (!passed) { testFail(TRUE, ""); return OK; } /* Setup pointers to underlying structures */ #if NNETIF for (i = 0; i < NNETIF; i++) { if ((NET_ALLOC == netiftab[i].state) && (ELOOP == netiftab[i].dev)) { break; } } #endif netptr = &netiftab[i]; pelp = &elooptab[devtab[ELOOP].minor]; pkt = netGetbuf(); if ((int)pkt != SYSERR) { pkt->nif = netptr; } praddr.type = NETADDR_IPv4; praddr.len = IPv4_ADDR_LEN; praddr.addr[0] = 192; praddr.addr[1] = 168; praddr.addr[2] = 1; praddr.addr[3] = 3; hwaddr.type = NETADDR_ETHERNET; hwaddr.len = ETH_ADDR_LEN; hwaddr.addr[0] = 0xAA; hwaddr.addr[1] = 0xBB; hwaddr.addr[2] = 0xCC; hwaddr.addr[3] = 0xDD; hwaddr.addr[4] = 0xEE; hwaddr.addr[5] = 0xFF; /* Test arpPkt structure */ testPrint(verbose, "Header structure (Request)"); /* Get 1st packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt = netGetbuf(); pkt->len += ARP_CONST_HDR_LEN + (2 * IPv4_ADDR_LEN) + (2 * ETH_ADDR_LEN); pkt->curr -= pkt->len; arp = (struct arpPkt *)pkt->curr; arp->hwtype = hs2net(ARP_HWTYPE_ETHERNET); arp->prtype = hs2net(ARP_PRTYPE_IPv4); arp->hwalen = ETH_ADDR_LEN; arp->pralen = IPv4_ADDR_LEN; arp->op = hs2net(ARP_OP_RQST); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpPkt structure */ testPrint(verbose, "Header structure (Reply)"); /* Get 2nd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } arp->op = hs2net(ARP_OP_REPLY); memcpy(&arp->addrs[ARP_ADDR_DHA(arp)], &arp->addrs[ARP_ADDR_SHA(arp)], arp->hwalen); arp->addrs[ARP_ADDR_DHA(arp) + ETH_ADDR_LEN - 1] = 0xCC; memcpy(&arp->addrs[ARP_ADDR_DPA(arp)], praddr.addr, arp->pralen); memcpy(&arp->addrs[ARP_ADDR_SHA(arp)], netptr->hwaddr.addr, arp->hwalen); memcpy(&arp->addrs[ARP_ADDR_SPA(arp)], netptr->ip.addr, arp->pralen); failif((0 != memcmp(data + ELOOP_LINKHDRSIZE, arp, pkt->len)), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate free entry"); /* Make first entry used */ arptab[0].state = ARP_USED; arptab[0].expires = clktime + ARP_TTL_UNRESOLVED; entry = arpAlloc(); failif(((NULL == entry) || (entry == &arptab[0]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpAlloc, free entry exists */ testPrint(verbose, "Allocate used entry"); arptab[1].state = ARP_USED; arptab[1].expires = clktime + 1; /* Make all entries (except the first 2) have ARP_TTL_RESOLVED */ for (i = 2; i < ARP_NENTRY; i++) { arptab[i].state = ARP_USED; arptab[i].expires = clktime + ARP_TTL_RESOLVED; } entry = arpAlloc(); failif(((NULL == entry) || (entry != &arptab[1]) || (0 == (entry->state & ARP_USED))), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads (bad params)"); failif((SYSERR != arpNotify(NULL, TIMEOUT)), ""); /* Test arpNotify */ testPrint(verbose, "Notify waiting threads"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)notifyTest, INITSTK, INITPRIO, "notifyTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); arpNotify(entry, ARP_MSG_RESOLVED); nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); /* Test arpFree */ testPrint(verbose, "Free entry (bad params)"); failif((SYSERR != arpFree(NULL)), ""); /* Test arpFree */ testPrint(verbose, "Free resolved entry"); entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->expires = clktime; failif(((SYSERR == arpFree(entry)) || (entry->expires != 0)), ""); /* Test arpFree */ testPrint(verbose, "Free unresolved entry"); entry = &arptab[0]; entry->state = ARP_UNRESOLVED; for (i = 0; i < ARP_NTHRWAIT; i++) { tid = create((void *)freeTest, INITSTK, INITPRIO, "freeTest", 0); tids[i] = tid; entry->waiting[i] = tid; entry->count++; ready(tid, RESCHED_NO); } recvclr(); if (SYSERR == arpFree(entry)) { failif(TRUE, "Returned SYSERR"); } else { nout = FALSE; nproc = 0; tid = recvtime(100); while ((tid != TIMEOUT) && (nproc < ARP_NTHRWAIT)) { for (i = 0; i < ARP_NTHRWAIT; i++) { if (tid == tids[i]) { tids[i] = NULL; } } nproc++; tid = recvtime(100); } for (i = 0; i < ARP_NTHRWAIT; i++) { if (tids[i] != NULL) { kill(tids[i]); nout = TRUE; } } failif(nout || (entry->count != 0), ""); } /* Test arpGetEntry */ testPrint(verbose, "Get entry"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } nout = 4; if (ARP_NENTRY < nout) { nout = ARP_NENTRY; } for (i = 1; i < nout; i++) { entry = &arptab[i]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = i + 1; hwaddr.addr[5] = ((i + 0xA) << 4) + (i + 0xA); netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_RESOLVED; } for (i = 1; i < nout; i++) { praddr.addr[3] = i + 1; entry = arpGetEntry(&praddr); if (entry != &arptab[i]) { break; } } failif((i != nout), ""); /* Test arpGetEntry with timeout */ testPrint(verbose, "Get entry (timeout entries)"); arptab[i].expires = clktime - 1; praddr.addr[3] = 2; entry = arpGetEntry(&praddr); if (entry != &arptab[1]) { failif(TRUE, "Incorrect entry"); } else { failif((arptab[0].state != ARP_FREE), "Did not free expired entry"); } for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } /* Test receive reply for non-existing ARP table entry */ testPrint(verbose, "Receive ARP reply, new entry"); /* Get 3rd packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if (ARP_RESOLVED == arptab[i].state) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else if (pelp->nout > (nout + 1)) { failif(TRUE, "Reply sent to reply"); } else { failif(FALSE, ""); } } /* Test receive request for non-existing ARP table entry */ testPrint(verbose, "Receive ARP request, new entry"); /* Get 4th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; nout = pelp->nout; nproc = netptr->nproc; im = disable(); write(ELOOP, data, phdr.caplen); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); restore(im); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry and ensure reply was not sent */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } if (NULL == entry) { failif(TRUE, "No entry inserted"); } else if ((FALSE == netaddrequal(&praddr, &entry->praddr)) || (FALSE == netaddrequal(&hwaddr, &entry->hwaddr)) || (entry->nif != netptr) || (entry->count != 0)) { failif(TRUE, "Entry incorrect"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); /* Get 5th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } failif((memcmp(data, buf, phdr.caplen) != 0), "Invalid reply"); } } /* Test receive request for non-supported hardware type */ testPrint(verbose, "Receive ARP request, bad HW type"); /* Get 6th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for non-supported protocol type */ testPrint(verbose, "Receive ARP reply, bad protocol type"); /* Get 7th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test receive reply for existing resolved ARP table entry */ testPrint(verbose, "Receive ARP reply, resolved entry"); /* Get 8th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 3; hwaddr.addr[5] = 0x0C; nout = pelp->nout; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Check entry */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((FALSE == netaddrequal(&hwaddr, &entry->hwaddr)), "Entry incorrect"); } /* Test receive request not for me */ testPrint(verbose, "Receive ARP request, not mine"); /* Get 9th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; nproc = netptr->nproc; write(ELOOP, data, phdr.caplen); /* Wait until packet is processed */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(100); } if (MAX_WAIT == wait) { failif(TRUE, "Wait time expired"); } else { /* Ensure entry was not added */ entry = NULL; for (i = 0; i < ARP_NENTRY; i++) { if ((ARP_RESOLVED == arptab[i].state) && (netaddrequal(&praddr, &arptab[i].praddr))) { entry = &arptab[i]; break; } } failif((entry != NULL), "Entry inserted"); } /* Test arpSendRequest */ testPrint(verbose, "Send ARP request (bad params)"); failif((SYSERR != arpSendRqst(NULL)), ""); /* Test arpSendRequest */ testPrint(verbose, "Send ARP request"); /* Get 10th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } entry = &arptab[0]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == arpSendRqst(entry)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (int)buf, ELOOP_BUFSIZE); failif((memcmp(buf, data, phdr.caplen) != 0), ""); } /* Test arpLookup */ testPrint(verbose, "Lookup address (bad params)"); failif((SYSERR != arpLookup(NULL, NULL, NULL)), ""); /* Test arpLookup */ testPrint(verbose, "Lookup existing resolved address"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } entry = &arptab[0]; entry->state = ARP_RESOLVED; entry->nif = netptr; praddr.addr[3] = 1; hwaddr.addr[5] = 0xAA; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup existing unresolved address"); entry = &arptab[1]; entry->state = ARP_UNRESOLVED; entry->nif = netptr; praddr.addr[3] = 2; hwaddr.addr[5] = 0xBB; netaddrcpy(&entry->hwaddr, &hwaddr); netaddrcpy(&entry->praddr, &praddr); entry->expires = clktime + ARP_TTL_UNRESOLVED; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 11th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup max threads wait for resolve"); entry->state = ARP_UNRESOLVED; entry->count = ARP_NTHRWAIT; failif((arpLookup(netptr, &praddr, &addrbuf) != SYSERR), ""); /* Test arpLookup */ testPrint(verbose, "Lookup non-existing unresolved addr"); praddr.addr[3] = 3; hwaddr.addr[5] = 0xCC; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); request = data; wait = phdr.caplen; /* Get 12th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } request = data; wait = phdr.caplen; /* Get 13th packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } tid = ready(create ((void *)lookupTest, INITSTK, INITPRIO, "lookupTest", 4, request, wait, data, phdr.caplen), RESCHED_NO); i = arpLookup(netptr, &praddr, &addrbuf); if ((SYSERR == i) || (TIMEOUT == i)) { kill(tid); failif(TRUE, "Returned SYSERR or TIMEOUT"); } else { failif((FALSE == netaddrequal(&addrbuf, &hwaddr)), "Wrong address"); } /* Test arpLookup */ testPrint(verbose, "Lookup timeout"); praddr.addr[3] = 4; hwaddr.addr[5] = 0xDD; control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_DROPALL, NULL); failif((SYSERR != arpLookup(netptr, &praddr, &addrbuf)), ""); /* Stop loopback ethernet and network interface */ testPrint(verbose, "Test case cleanup"); for (i = 0; i < ARP_NENTRY; i++) { arpFree(&arptab[i]); } failif(((SYSERR == netFreebuf(pkt)) || (SYSERR == netDown(ELOOP)) || (SYSERR == close(ELOOP))), ""); if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } return OK; }
/** * @ingroup shell * * The Xinu shell. Provides an interface to execute commands. * @param descrp descriptor of device on which the shell is open * @return OK for successful exit, SYSERR for unrecoverable error */ thread shell(int indescrp, int outdescrp, int errdescrp) { char buf[SHELL_BUFLEN]; /* line input buffer */ short buflen; /* length of line input */ char tokbuf[SHELL_BUFLEN + SHELL_MAXTOK]; /* token value buffer */ short ntok; /* number of tokens */ char *tok[SHELL_MAXTOK]; /* pointers to token values */ char *outname; /* name of output file */ char *inname; /* name of input file */ bool background; /* is background proccess? */ syscall child; /* pid of child thread */ ushort i, j; /* temp variables */ irqmask im; /* interrupt mask state */ char *hostptr = NULL; /* pointer to hostname */ /* Setup buffer for string for nvramGet call for hostname */ #if defined(ETH0) && NVRAM char hostnm[NET_HOSTNM_MAXLEN + 1]; /* hostname of backend */ if (!isbaddev(ETH0)) { size_t hostname_strsz; /* nvram hostname name size */ bzero(hostnm, NET_HOSTNM_MAXLEN + 1); /* Determine the hostname of the main network device */ hostname_strsz = strlen(NET_HOSTNAME); hostname_strsz += 1; hostname_strsz += DEVMAXNAME; hostname_strsz += 1; char nvramget_hostname_str[hostname_strsz]; sprintf(nvramget_hostname_str, "%s_%s", devtab[ETH0].name, NET_HOSTNAME); /* Acquire the backend's hostname */ hostptr = nvramGet(nvramget_hostname_str); if (hostptr != NULL) { strncpy(hostnm, hostptr, NET_HOSTNM_MAXLEN); hostptr = hostnm; } } #endif /* Set command devices for input, output, and error */ stdin = indescrp; stdout = outdescrp; stderr = errdescrp; /* Print shell banner to framebuffer, if exists */ #if defined(FRAMEBUF) if (indescrp == FRAMEBUF) { foreground = RASPBERRY; printf(SHELL_BANNER_NONVT100); foreground = LEAFGREEN; printf(SHELL_START); foreground = GREEN; } else #endif { printf(SHELL_BANNER); printf(SHELL_START); } /* Continually receive and handle commands */ while (TRUE) { /* Display prompt */ printf(SHELL_PROMPT); if (NULL != hostptr) { printf("@%s$ ", hostptr); } else { printf("$ "); } /* Setup proper tty modes for input and output */ control(stdin, TTY_CTRL_CLR_IFLAG, TTY_IRAW, NULL); control(stdin, TTY_CTRL_SET_IFLAG, TTY_ECHO, NULL); /* Read command */ buflen = read(stdin, buf, SHELL_BUFLEN - 1); /* Check for EOF and exit gracefully if seen */ if (EOF == buflen) { break; } /* Parse line input into tokens */ if (SYSERR == (ntok = lexan(buf, buflen, &tokbuf[0], &tok[0]))) { fprintf(stderr, SHELL_SYNTAXERR); continue; } /* Ensure parse generated tokens */ if (0 == ntok) { continue; } /* Initialize command options */ inname = NULL; outname = NULL; background = FALSE; /* Mark as background thread, if last token is '&' */ if ('&' == *tok[ntok - 1]) { ntok--; background = TRUE; } /* Check each token and perform special handling of '>' and '<' */ for (i = 0; i < ntok; i++) { /* Background '&' should have already been handled; Syntax error */ if ('&' == *tok[i]) { ntok = -1; break; } /* Setup for output redirection if token is '>' */ if ('>' == *tok[i]) { /* Syntax error */ if (outname != NULL || i >= ntok - 1) { ntok = -1; break; } outname = tok[i + 1]; ntok -= 2; /* shift tokens (not to be passed to command */ for (j = i; j < ntok; j++) { tok[j] = tok[j + 2]; } continue; } /* Setup for input redirection if token is '<' */ if ('<' == *tok[i]) { /* Syntax error */ if (inname != NULL || i >= ntok - 1) { ntok = -1; break; } inname = tok[i + 1]; ntok -= 2; /* shift tokens (not to be passed to command */ for (j = i; j < ntok; j++) { tok[j] = tok[j + 2]; } continue; } } /* Handle syntax error */ if (ntok <= 0) { fprintf(stderr, SHELL_SYNTAXERR); continue; } /* Lookup first token in the command table */ for (i = 0; i < ncommand; i++) { if (0 == strcmp(commandtab[i].name, tok[0])) { break; } } /* Handle command not found */ if (i >= ncommand) { fprintf(stderr, "%s: command not found\n", tok[0]); continue; } /* Handle command if it is built-in */ if (commandtab[i].builtin) { if (inname != NULL || outname != NULL || background) { fprintf(stderr, SHELL_SYNTAXERR); } else { (*commandtab[i].procedure) (ntok, tok); } continue; } /* Spawn child thread for non-built-in commands */ child = create(commandtab[i].procedure, SHELL_CMDSTK, SHELL_CMDPRIO, commandtab[i].name, 2, ntok, tok); /* Ensure child command thread was created successfully */ if (SYSERR == child) { fprintf(stderr, SHELL_CHILDERR); continue; } /* Set file descriptors for newly created thread */ if (NULL == inname) { thrtab[child].fdesc[0] = stdin; } else { thrtab[child].fdesc[0] = getdev(inname); } if (NULL == outname) { thrtab[child].fdesc[1] = stdout; } else { thrtab[child].fdesc[1] = getdev(outname); } thrtab[child].fdesc[2] = stderr; if (background) { /* Make background thread ready, but don't reschedule */ im = disable(); ready(child, RESCHED_NO); restore(im); } else { /* Clear waiting message; Reschedule; */ while (recvclr() != NOMSG); im = disable(); ready(child, RESCHED_YES); restore(im); /* Wait for command thread to finish */ while (receive() != child); sleep(10); } } /* Close shell */ fprintf(stdout, SHELL_EXIT); sleep(10); return OK; }
/*------------------------------------------------------------------------ * arp_resolve - Use ARP to resolve an IP address to an Ethernet address *------------------------------------------------------------------------ */ status arp_resolve ( uint32 nxthop, /* Next-hop address to resolve */ byte mac[ETH_ADDR_LEN] /* Array into which Ethernet */ ) /* address should be placed */ { intmask mask; /* Saved interrupt mask */ struct arppacket apkt; /* Local packet buffer */ int32 i; /* Index into arpcache */ int32 slot; /* ARP table slot to use */ struct arpentry *arptr; /* Ptr to ARP cache entry */ int32 msg; /* Message returned by recvtime */ /* Use MAC broadcast address for IP limited broadcast */ if (nxthop == IP_BCAST) { memcpy(mac, NetData.ethbcast, ETH_ADDR_LEN); return OK; } /* Use MAC broadcast address for IP network broadcast */ if (nxthop == NetData.ipbcast) { memcpy(mac, NetData.ethbcast, ETH_ADDR_LEN); return OK; } /* Ensure only one process uses ARP at a time */ mask = disable(); /* See if next hop address is already present in ARP cache */ for (i=0; i<ARP_SIZ; i++) { arptr = &arpcache[i]; if (arptr->arstate == AR_FREE) { continue; } if (arptr->arpaddr == nxthop) { /* Adddress is in cache */ break; } } if (i < ARP_SIZ) { /* Entry was found */ /* If entry is resolved - handle and return */ if (arptr->arstate == AR_RESOLVED) { memcpy(mac, arptr->arhaddr, ARP_HALEN); restore(mask); return OK; } /* Entry is already pending - return error because */ /* only one process can be waiting at a time */ if (arptr->arstate == AR_PENDING) { restore(mask); return SYSERR; } } /* IP address not in cache - allocate a new cache entry and */ /* send an ARP request to obtain the answer */ slot = arp_alloc(); if (slot == SYSERR) { restore(mask); return SYSERR; } arptr = &arpcache[slot]; arptr->arstate = AR_PENDING; arptr->arpaddr = nxthop; arptr->arpid = currpid; /* Hand-craft an ARP Request packet */ memcpy(apkt.arp_ethdst, NetData.ethbcast, ETH_ADDR_LEN); memcpy(apkt.arp_ethsrc, NetData.ethucast, ETH_ADDR_LEN); apkt.arp_ethtype = ETH_ARP; /* Packet type is ARP */ apkt.arp_htype = ARP_HTYPE; /* Hardware type is Ethernet */ apkt.arp_ptype = ARP_PTYPE; /* Protocol type is IP */ apkt.arp_hlen = 0xff & ARP_HALEN; /* Ethernet MAC size in bytes */ apkt.arp_plen = 0xff & ARP_PALEN; /* IP address size in bytes */ apkt.arp_op = 0xffff & ARP_OP_REQ;/* ARP type is Request */ memcpy(apkt.arp_sndha, NetData.ethucast, ARP_HALEN); apkt.arp_sndpa = NetData.ipucast; /* IP address of interface */ memset(apkt.arp_tarha, '\0', ARP_HALEN); /* Target HA is unknown*/ apkt.arp_tarpa = nxthop; /* Target protocol address */ /* Convert ARP packet from host to net byte order */ arp_hton(&apkt); /* Convert Ethernet header from host to net byte order */ eth_hton((struct netpacket *)&apkt); /* Send the packet ARP_RETRY times and await response */ msg = recvclr(); for (i=0; i<ARP_RETRY; i++) { write(ETHER0, (char *)&apkt, sizeof(struct arppacket)); msg = recvtime(ARP_TIMEOUT); if (msg == TIMEOUT) { continue; } else if (msg == SYSERR) { restore(mask); return SYSERR; } else { /* entry is resolved */ break; } } /* If no response, return TIMEOUT */ if (msg == TIMEOUT) { arptr->arstate = AR_FREE; /* Invalidate cache entry */ restore(mask); return TIMEOUT; } /* Return hardware address */ memcpy(mac, arptr->arhaddr, ARP_HALEN); restore(mask); return OK; }