/** * Read into a buffer from the UART. * @param devptr UART device table entry * @param buf buffer to read bytes into * @param len size of the buffer * @return count of bytes read */ devcall uartRead(device *devptr, void *buf, uint len) { int i; uchar * buffer = buf; for(i = 0; i < len; i++){ buffer[i] = getc(SERIAL1); } return OK; #if 0 irqmask im; int count = 0; char c; struct uart *uartptr; uchar *buffer = buf; uartptr = &uarttab[devptr->minor]; im = disable(); /* If in non-blocking mode, ensure there is */ /* enough input for the entire read request */ if ((uartptr->iflags & UART_IFLAG_NOBLOCK) && (semcount(uartptr->isema) < len)) { restore(im); return SYSERR; } /* Put each character into the buffer from the input buffer */ while (count < len) { /* If in non-blocking mode, ensure there is another byte of input */ if ((uartptr->iflags & UART_IFLAG_NOBLOCK) && (semcount(uartptr->isema) < 1)) { break; } /* Wait for input and read character from the */ /* input buffer; Preserve the circular buffer */ wait(uartptr->isema); c = uartptr->in[uartptr->istart]; *buffer++ = c; uartptr->icount--; uartptr->istart = (uartptr->istart + 1) % UART_IBLEN; count++; /* If echo is enabled, echo the character */ if (uartptr->iflags & UART_IFLAG_ECHO) { uartPutc(uartptr->dev, c); } } restore(im); return count; #endif // if 0 }
bool8 test_checkSemCount(sid32 s, short c, bool8 verbose) { char msg[50]; if (!isbadsem(s) && c != semcount(s)) { sprintf(msg, "count = %d, not %d", semcount(s), c); testFail(verbose, msg); return FALSE; } return TRUE; }
/*------------------------------------------------------------------------ * nbgetbuf - a non-blocking version of getbuf *------------------------------------------------------------------------ */ char *nbgetbuf( bpid32 poolid /* index of pool in buftab */ ) { intmask mask; char *buf; mask = disable(); /* Check arguments */ if ( (poolid < 0 || poolid >= nbpools) ) { restore(mask); return (char *)SYSERR; } /* If the call will block, return an error */ if (semcount(buftab[poolid].bpsem) <= 0) { restore(mask); return (char *)SYSERR; } buf = getbuf(poolid); restore(mask); return buf; }
/*------------------------------------------------------------------------ * pipread -- Read from a pipe, blocking if empty *------------------------------------------------------------------------ */ syscall pipread( pipid32 pip, /* ID of pipe to read from */ char *buf, /* pointer to buffer to read to */ uint32 len /* number of bytes to read */ ) { intmask mask; /* saved interrupt mask */ mask = disable(); if (isbadpip(pip)) { restore(mask); return SYSERR; } struct pentry *pipptr; /* ptr to pipe table entry */ pipptr = &piptab[pip]; if (pipptr->pstate != PIPE_CONNECTED || (pipptr->pend1 != getpid() && pipptr->pend2 != getpid())) { restore(mask); return SYSERR; } /* Ensure there is enough space for the entire read request */ if (semcount(pipptr->prdsem) < len) { restore(mask); return SYSERR; } char *buffer = buf; /* local copy of buffer */ int count = 0; /* character count for buffer */ char c; /* temporary space for characters */ /* Read characters from the circular buffer */ while (count < len) { wait(pipptr->prdsem); c = pipptr->pbuf[pipptr->pbufs]; *buffer++ = c; pipptr->pbufc--; pipptr->pbufs = (pipptr->pbufs + 1) % PIPE_SIZ; count++; signal(pipptr->pwrsem); } restore(mask); return count; }
/*------------------------------------------------------------------------ * pipwrite -- Write to a pipe, blocking if full *------------------------------------------------------------------------ */ syscall pipwrite( pipid32 pip, /* ID of pipe to write to */ char *buf, /* pointer to buffer to write from */ uint32 len /* number of bytes to write */ ) { intmask mask; /* saved interrupt mask */ mask = disable(); if (isbadpip(pip)) { restore(mask); return SYSERR; } struct pentry *pipptr; /* ptr to pipe table entry */ pipptr = &piptab[pip]; if (pipptr->pstate != PIPE_CONNECTED || (pipptr->pend1 != getpid() && pipptr->pend2 != getpid())) { restore(mask); return SYSERR; } /* Ensure there is enough space for the entire write request */ if (semcount(pipptr->pwrsem) < len) { restore(mask); return SYSERR; } char *buffer = buf; /* local copy of buffer */ int count = 0; /* character count for buffer */ /* Write characters to the circular buffer */ while (count < len) { wait(pipptr->pwrsem); pipptr->pbuf[(pipptr->pbufs + pipptr->pbufc) % PIPE_SIZ] = *buffer++; count++; pipptr->pbufc++; signal(pipptr->prdsem); } restore(mask); return count; }
/** * HTTP server thread * @param host IP address of interface on which to listen * @param gentcpdev the allocated tcp device for general listening * @return OK or SYSERR */ thread httpServer(int netDescrp, int gentcpdev) { tid_typ shelltid, killtid; int tcpdev, httpdev; char thrname[TNMLEN]; bool noGenHTTP; struct netaddr *host; struct netif *nif; enable(); noGenHTTP = FALSE; wait(maxhttp); /* Make sure max HTTP threads not reached */ /* Allocate HTTP device */ httpdev = httpAlloc(); /* Received bad http device, close out allocated resources */ if (isbadhttp(httpdev)) { printf("failed to allocate proper HTTP device\n"); signal(maxhttp); return SYSERR; } /* Back up the general tcpdev number */ tcpdev = gentcpdev; /* Look up the network descriptor */ nif = netLookup(netDescrp); if (SYSERR == (int)nif) { fprintf(stderr, "%s is not associated with an active network", devtab[netDescrp].name); fprintf(stderr, " interface.\n"); return SYSERR; } host = &(nif->ip); /* Open HTTP device */ if (SYSERR == (long)open(httpdev, tcpdev)) { fprintf(stderr, "httpOpen SYSERR\n"); close(tcpdev); close(httpdev); return SYSERR; } /* Create web shell */ sprintf(thrname, "XWebShell_%d\0", (devtab[tcpdev].minor)); shelltid = create((void *)shell, INITSTK, INITPRIO, thrname, 3, httpdev, httpdev, DEVNULL); if (isbadtid(shelltid)) { fprintf(stderr, "shell creation bad tid\n"); close(httpdev); close(tcpdev); return SYSERR; } /* Spawn thread that will wait for kill httpserver thread signal */ sprintf(thrname, "XWebKillerD_%d\0", (devtab[tcpdev].minor)); killtid = create((void *)killHttpServer, INITSTK, INITPRIO, thrname, 3, httpdev, shelltid, tcpdev); /* Ready spawned threads */ ready(shelltid, RESCHED_NO); ready(killtid, RESCHED_NO); /* Open TCP device */ if (SYSERR == (long)open(tcpdev, host, NULL, HTTP_LOCAL_PORT, NULL, TCP_PASSIVE)) { int temp; sleep(TCP_TWOMSL + 500); if (SYSERR == (temp = (long)open(tcpdev, host, NULL, HTTP_LOCAL_PORT, NULL, TCP_PASSIVE))) { fprintf(CONSOLE, "open returns: %d\n", temp); fprintf(stderr, "tcpOpen SYSERR, devnum: %d\n", tcpdev); kill(shelltid); close(tcpdev); close(httpdev); return SYSERR; } fprintf(CONSOLE, "open returns: %d\n", temp); } /* Allocate TCP device */ gentcpdev = tcpAlloc(); if (isbadtcp(gentcpdev)) { /* Wait for a free http device */ wait(maxhttp); /* Acquire a TCP device through allocation */ while ((ushort)SYSERR == (gentcpdev = tcpAlloc())) { /* Do nothing, yield processor */ yield(); } /* Everything acquired, spawn general http device listener */ if (semcount(activeXWeb) <= 0) { sprintf(thrname, "XWeb_%d\0", (devtab[gentcpdev].minor)); ready(create((void *)httpServer, INITSTK, INITPRIO, thrname, 2, netDescrp, gentcpdev), RESCHED_NO); } /* Did not consume http device, just waited for availability */ signal(maxhttp); } else { sprintf(thrname, "XWeb_%d\0", (devtab[gentcpdev].minor)); ready(create((void *)httpServer, INITSTK, INITPRIO, thrname, 2, netDescrp, gentcpdev), RESCHED_NO); } return OK; }
/** * Read into a buffer from TCP. * @param devptr TCP device table entry * @param buf buffer to read octets into * @param len size of the buffer * @return count of octets read */ devcall tcpRead(device *devptr, void *buf, uint len) { int count = 0; struct tcb *tcbptr; int check; char *buffer = buf; tcbptr = &tcptab[devptr->minor]; wait(tcbptr->mutex); /* Handle states for which no data will ever be received */ check = stateCheck(tcbptr); if (check != OK) { return SYSERR; // return check; } signal(tcbptr->mutex); /* Put each octet into the buffer from the input buffer */ while (count < len) { /* Wait for input or FIN */ wait(tcbptr->readers); wait(tcbptr->mutex); /* Return if changed to a state where no data will ever be recvd */ check = stateCheck(tcbptr); if (check != OK) { return SYSERR; // return check; } /* Read as much as possible from the input buffer * Preserve the circular buffer */ while ((tcbptr->icount > 0) && (count < len)) { *buffer++ = tcbptr->in[tcbptr->istart]; tcbptr->imark[tcbptr->istart] = FALSE; tcbptr->istart = (tcbptr->istart + 1) % TCP_IBLEN; tcbptr->icount--; count++; } #ifdef TCP_GRACIOUSACK /* Send gracious acknowledgement if window has increaed */ if (seqlte(tcbptr->rcvwnd, tcbptr->rcvnxt)) { if (tcpSendWindow(tcbptr) > 0) { tcpSendAck(tcbptr); } } #endif /* If data remains, another reader can read */ if ((tcbptr->icount > 0) && (semcount(tcbptr->readers) < 1)) { signal(tcbptr->readers); } signal(tcbptr->mutex); } return count; }
process rawin (void) { status retval; /* return value from function */ struct netpacket *pkt; /* packet buffer being used now */ int32 nbufs; /* total number of buffers */ struct ifentry *ifptr; /* ptr to interface table entry */ int32 iface; /* index into interface table */ /* Global buffer pool shared by all interfaces */ nbufs = UDP_SLOTS * UDP_QSIZ + ICMP_SLOTS * ICMP_QSIZ + NIFACES * IF_QUEUESIZE + 1; netbufpool = mkbufpool(PACKLEN, nbufs); if (netbufpool == SYSERR) { kprintf("Cannot allocate network buffer pool\n"); kill(getpid()); } open(ETHER0, NULL, NULL); pkt = (struct netpacket *)getbuf(netbufpool); while(1) { retval = read(ETHER0, (char *)pkt, PACKLEN); if (retval == SYSERR) { panic("Ethernet read error"); } /* Demultiplex on MAC address */ for (iface=0; iface<=NIFACES; iface++) { ifptr = &if_tab[iface]; if (ifptr->if_state != IF_UP) { continue; } if ( (memcmp(ifptr->if_macucast, pkt->net_ethdst, ETH_ADDR_LEN) == 0) || (memcmp(ifptr->if_macbcast, pkt->net_ethdst, ETH_ADDR_LEN) == 0)) { /* packet goes to this interface */ /* Check interface queue; drop packet if full */ if (semcount(ifptr->if_sem) >= IF_QUEUESIZE) { kprintf("rawin: queue overflow on %d\n", iface); break; } /* Enqueue packet and signal semaphore */ ifptr->if_queue[ifptr->if_tail++] = pkt; if (ifptr->if_tail >= IF_QUEUESIZE) { ifptr->if_tail = 0; } signal(ifptr->if_sem); /* Obtain a buffer for the next packet */ pkt = (struct netpacket *)getbuf(netbufpool); break; } } } }
/*------------------------------------------------------------------------ * ttyInter_in -- handle one arriving char (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_in ( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { char ch; /* next char from device */ int32 avail; /* chars available in buffer */ ch = uptr->buffer; /* extract char. from device */ /* Compute chars available */ avail = semcount(typtr->tyisem); if (avail < 0) { /* one or more processes waiting*/ avail = 0; } /* Handle raw mode */ if (typtr->tyimode == TY_IMRAW) { if (avail >= TY_IBUFLEN) { /* no space => ignore input */ return; } /* Place char in buffer with no editing */ *typtr->tyitail++ = ch; /* Wrap buffer pointer */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Signal input semaphore and return */ signal(typtr->tyisem); return; } /* Handle cooked and cbreak modes (common part) */ if ( (ch == TY_RETURN) && typtr->tyicrlf ) { ch = TY_NEWLINE; } /* If flow control is in effect, handle ^S and ^Q */ if (typtr->tyoflow) { if (ch == typtr->tyostart) { /* ^Q starts output */ typtr->tyoheld = FALSE; ttyKickOut(typtr, uptr); return; } else if (ch == typtr->tyostop) { /* ^S stops output */ typtr->tyoheld = TRUE; return; } } typtr->tyoheld = FALSE; /* Any other char starts output */ if (typtr->tyimode == TY_IMCBREAK) { /* Just cbreak mode */ /* If input buffer is full, send bell to user */ if (avail >= TY_IBUFLEN) { eputc(typtr->tyifullc, typtr, uptr); } else { /* Input buffer has space for this char */ *typtr->tyitail++ = ch; /* Wrap around buffer */ if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } if (typtr->tyiecho) { /* are we echoing chars?*/ echoch(ch, typtr, uptr); } } return; } else { /* Just cooked mode (see common code above) */ /* Line kill character arrives - kill entire line */ if (ch == typtr->tyikillc && typtr->tyikill) { typtr->tyitail -= typtr->tyicursor; if (typtr->tyitail < typtr->tyibuff) { typtr->tyihead += TY_IBUFLEN; } typtr->tyicursor = 0; eputc(TY_RETURN, typtr, uptr); eputc(TY_NEWLINE, typtr, uptr); return; } /* Erase (backspace) character */ if ( (ch == typtr->tyierasec) && typtr->tyierase) { if (typtr->tyicursor > 0) { typtr->tyicursor--; erase1(typtr, uptr); } return; } /* End of line */ if ( (ch == TY_NEWLINE) || (ch == TY_RETURN) ) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } *typtr->tyitail++ = ch; if (typtr->tyitail>=&typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } /* Make entire line (plus \n or \r) available */ signaln(typtr->tyisem, typtr->tyicursor + 1); typtr->tyicursor = 0; /* Reset for next line */ return; } /* Character to be placed in buffer - send bell if */ /* buffer has overflowed */ avail = semcount(typtr->tyisem); if (avail < 0) { avail = 0; } if ((avail + typtr->tyicursor) >= TY_IBUFLEN-1) { eputc(typtr->tyifullc, typtr, uptr); return; } /* EOF character: recognize at beginning of line, but */ /* print and ignore otherwise. */ if (ch == typtr->tyeofch && typtr->tyeof) { if (typtr->tyiecho) { echoch(ch, typtr, uptr); } if (typtr->tyicursor != 0) { return; } *typtr->tyitail++ = ch; signal(typtr->tyisem); return; } /* Echo the character */ if (typtr->tyiecho) { echoch(ch, typtr, uptr); } /* Insert character in the input buffer */ typtr->tyicursor++; *typtr->tyitail++ = ch; /* Wrap around if needed */ if (typtr->tyitail >= &typtr->tyibuff[TY_IBUFLEN]) { typtr->tyitail = typtr->tyibuff; } return; } }
/*------------------------------------------------------------------------ * rdswrite - Write a block to a remote disk *------------------------------------------------------------------------ */ devcall rdswrite ( struct dentry *devptr, /* Entry in device switch table */ char *buff, /* Buffer that holds a disk blk */ int32 blk /* Block number to write */ ) { struct rdscblk *rdptr; /* Pointer to control block */ struct rdbuff *bptr; /* Pointer to buffer on a list */ struct rdbuff *pptr; /* Ptr to previous buff on list */ struct rdbuff *nptr; /* Ptr to next buffer on list */ bool8 found; /* Was buff found during search?*/ /* If device not currently in use, report an error */ rdptr = &rdstab[devptr->dvminor]; if (rdptr->rd_state != RD_OPEN) { return SYSERR; } /* Ensure rdsprocess is runnning */ if ( ! rdptr->rd_comruns ) { rdptr->rd_comruns = TRUE; resume(rdptr->rd_comproc); } /* If request queue already contains a write request */ /* for the block, replace the contents */ bptr = rdptr->rd_rhnext; while (bptr != (struct rdbuff *)&rdptr->rd_rtnext) { if ( (bptr->rd_blknum == blk) && (bptr->rd_op == RD_OP_WRITE) ) { memcpy(bptr->rd_block, buff, RD_BLKSIZ); return OK; } bptr = bptr->rd_next; } /* Search cache for cached copy of block */ bptr = rdptr->rd_chnext; found = FALSE; while (bptr != (struct rdbuff *)&rdptr->rd_ctnext) { if (bptr->rd_blknum == blk) { if (bptr->rd_refcnt <= 0) { pptr = bptr->rd_prev; nptr = bptr->rd_next; /* Unlink node from cache list and reset*/ /* the available semaphore accordingly*/ pptr->rd_next = bptr->rd_next; nptr->rd_prev = bptr->rd_prev; semreset(rdptr->rd_availsem, semcount(rdptr->rd_availsem) - 1); found = TRUE; } break; } bptr = bptr->rd_next; } if ( !found ) { bptr = rdsbufalloc(rdptr); } /* Create a write request */ memcpy(bptr->rd_block, buff, RD_BLKSIZ); bptr->rd_op = RD_OP_WRITE; bptr->rd_refcnt = 0; bptr->rd_blknum = blk; bptr->rd_status = RD_VALID; 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; /* Signal semaphore to start communication process */ signal(rdptr->rd_reqsem); return OK; }
/** * Tests raw sockets. * @return OK when testing is complete */ thread test_raw(bool verbose) { #if RAW0 /* the failif macro depends on 'passed' and 'verbose' vars */ bool passed = TRUE; device *devptr; struct raw *rawptr; struct netif *netptr; struct netaddr lip; struct netaddr rip; struct netaddr mask; struct packet *pkt; struct packet *pktA; struct pcap_pkthdr phdr; struct pcap_file_header pcap; uchar *data; uchar buf[500]; int nproc; int wait; int i; lip.type = NETADDR_IPv4; lip.len = IPv4_ADDR_LEN; lip.addr[0] = 192; lip.addr[1] = 168; lip.addr[2] = 1; lip.addr[3] = 6; rip.type = NETADDR_IPv4; rip.len = IPv4_ADDR_LEN; rip.addr[0] = 192; rip.addr[1] = 168; rip.addr[2] = 1; rip.addr[3] = 1; 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; /* Initialization */ testPrint(verbose, "Test case initialization"); data = (uchar *)(&_binary_data_testraw_pcap_start); memcpy(&pcap, data, sizeof(pcap)); data += sizeof(pcap); if (SYSERR == open(ELOOP)) { failif(TRUE, ""); } else { if (SYSERR == netUp(ELOOP, &lip, &mask, NULL)) { close(ELOOP); failif(TRUE, ""); } else { netptr = NULL; for (i = 0; i < NNETIF; i++) { if (ELOOP == netiftab[i].dev) { netptr = &netiftab[i]; break; } } pkt = netGetbuf(); failif(((NULL == netptr) || (SYSERR == (int)pkt)), ""); } } if (!passed) { testFail(TRUE, ""); return OK; } /* Test Open */ testPrint(verbose, "Open RAW (Proto Only)"); rawptr = NULL; if (SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_ALLOC) || (rawptr->dev != devptr) || (rawptr->proto != IPv4_PROTO_ICMP) || (rawptr->localip.type != NULL) || (rawptr->remoteip.type != NULL) || (rawptr->icount != 0) || (rawptr->istart != 0) || (semcount(rawptr->isema) != 0) || (rawptr->flags != 0)), "Incorrect control block"); } testPrint(verbose, "Open RAW (Already Open)"); failif((SYSERR != open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)), "Double open() succeeded"); /* Test Control */ testPrint(verbose, "Control (Closed Socket)"); failif((control(RAW1, RAW_CTRL_SETFLAG, NULL, NULL) != SYSERR), ""); testPrint(verbose, "Control (Bad Params)"); failif((control(RAW0, -1, NULL, NULL) != SYSERR), ""); testPrint(verbose, "Control (Set Flag)"); failif(((NULL != control(RAW0, RAW_CTRL_SETFLAG, (RAW_IACCEPT | RAW_IHDR), NULL)) || (0 == (rawptr->flags & RAW_IACCEPT)) || (0 == (rawptr->flags & RAW_IHDR))), ""); testPrint(verbose, "Control (Clear Flag)"); failif(((RAW_IHDR != control(RAW0, RAW_CTRL_CLRFLAG, RAW_IHDR, NULL)) || (0 == (rawptr->flags & RAW_IACCEPT)) || (1 == (rawptr->flags & RAW_IHDR))), ""); /* Test Close */ testPrint(verbose, "Close RAW"); if (SYSERR == close(RAW0)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_FREE) || (rawptr->dev != NULL)), "Control block not clear"); } testPrint(verbose, "Close RAW (Already Closed)"); failif((SYSERR != close(RAW0)), "Did not SYSERR"); /* Test demux */ testPrint(verbose, "Demulitplexing (No sockets)"); failif((NULL != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)), ""); testPrint(verbose, "Demulitplexing (All Protos)"); if ((SYSERR == open(RAW0, &lip, &rip, IPv4_PROTO_IGMP)) || (SYSERR == open(RAW1, NULL, NULL, NULL))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Proto)"); if ((SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, NULL, NULL, IPv4_PROTO_IGMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Remote IP)"); if ((SYSERR == open(RAW0, NULL, NULL, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, NULL, &rip, IPv4_PROTO_ICMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } testPrint(verbose, "Demulitplexing (Local IP)"); if ((SYSERR == open(RAW0, NULL, &rip, IPv4_PROTO_ICMP)) || (SYSERR == open(RAW1, &lip, &rip, IPv4_PROTO_ICMP))) { failif(TRUE, "Open failed"); } else { devptr = (device *)&devtab[RAW1]; rawptr = &rawtab[devptr->minor]; if (rawptr != rawDemux(&rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Incorrect socket"); } else { failif(((SYSERR == close(RAW0)) || (SYSERR == close(RAW1))), "Close failed"); } } /* Test Open */ testPrint(verbose, "Open RAW (Full Spec)"); if (SYSERR == open(RAW0, &lip, &rip, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(((rawptr->state != RAW_ALLOC) || (rawptr->dev != devptr) || (rawptr->proto != IPv4_PROTO_ICMP) || (FALSE == netaddrequal(&lip, &rawptr->localip)) || (FALSE == netaddrequal(&rip, &rawptr->remoteip)) || (rawptr->icount != 0) || (rawptr->istart != 0) || (semcount(rawptr->isema) != 0) || (rawptr->flags != 0)), "Incorrect control block"); } /* Test receive */ testPrint(verbose, "Receive (Bad Params)"); /* Get 1st packet */ memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } pkt->len = phdr.caplen; memcpy(pkt->data, data, phdr.caplen); pkt->linkhdr = pkt->data; pkt->nethdr = pkt->linkhdr + ETH_HDR_LEN; pkt->curr = pkt->nethdr + IPv4_HDR_LEN; failif(((SYSERR != rawRecv(NULL, NULL, NULL, NULL)) || (SYSERR != rawRecv(pkt, &rip, NULL, NULL))), ""); testPrint(verbose, "Receive (No Match)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_IGMP)) { failif(TRUE, "Returned SYSERR"); } else { failif(((rawptr->icount != 0) || (semcount(rawptr->isema) != 0) || (TRUE == netaddrequal(&rawptr->src[0], &rip)) || (rawptr->in[0] == pktA)), "Packet enqueued"); } testPrint(verbose, "Receive (One Pkt)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { failif(((rawptr->istart != 0) || (rawptr->icount != 1) || (semcount(rawptr->isema) != 1) || (FALSE == netaddrequal(&rawptr->src[0], &rip)) || (rawptr->in[0] != pktA)), "Incorrectly enqueued"); } testPrint(verbose, "Read (Closed socket)"); failif((SYSERR != read(RAW1, buf, 500)), ""); testPrint(verbose, "Read (One Pkt)"); failif(((read(RAW0, buf, 500) != 8) || (memcmp(buf, (pkt->data + ETH_HDR_LEN + IPv4_HDR_LEN), 8) != 0) || (rawptr->icount != 0) || (rawptr->istart != 1) || (semcount(rawptr->isema) != 0) || (rawptr->in[0] != NULL)), ""); testPrint(verbose, "Read (Include header)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; rawptr->flags = RAW_IHDR; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 500) != (IPv4_HDR_LEN + 8)) || (memcmp(buf, (pkt->data + ETH_HDR_LEN), IPv4_HDR_LEN + 8) != 0) || (rawptr->icount != 0) || (rawptr->istart != 2) || (semcount(rawptr->isema) != 0) || (rawptr->in[0] != NULL)), ""); } testPrint(verbose, "Read (Accept)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; rawptr->flags = RAW_IACCEPT; rawptr->remoteip.type = NULL; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 500) != 8) || (FALSE == netaddrequal(&rawptr->remoteip, &rip))), ""); } testPrint(verbose, "Read (Small buf)"); pktA = netGetbuf(); memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { failif(TRUE, "Recv returned SYSERR"); } else { failif(((read(RAW0, buf, 2) != 2) || (memcmp(buf, (pkt->data + ETH_HDR_LEN + IPv4_HDR_LEN), 2) != 0)), ""); } testPrint(verbose, "Receive (Full buf)"); for (i = 0; i < RAW_IBLEN; i++) { memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; if (SYSERR == rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)) { break; } } if (i < RAW_IBLEN) { failif(TRUE, "Unable to fill buffer"); } else { memcpy(pktA, pkt, sizeof(struct packet) + pkt->len); pktA->linkhdr = pktA->data; pktA->nethdr = pktA->linkhdr + ETH_HDR_LEN; pktA->curr = pktA->nethdr + IPv4_HDR_LEN; failif((SYSERR != rawRecv(pktA, &rip, &lip, IPv4_PROTO_ICMP)), "Did not return SYSERR"); } testPrint(verbose, "Close RAW"); failif((SYSERR == close(RAW0)), ""); /* Test Write/Send */ testPrint(verbose, "Open RAW"); if (SYSERR == open(RAW0, &lip, NULL, IPv4_PROTO_ICMP)) { failif(TRUE, "Returned SYSERR"); } else { devptr = (device *)&devtab[RAW0]; rawptr = &rawtab[devptr->minor]; failif(FALSE, ""); } testPrint(verbose, "Send (Bad Params)"); failif((rawSend(NULL, NULL, 0) != SYSERR), ""); testPrint(verbose, "Send (Incomplete Spec)"); failif((rawSend(rawptr, pkt->curr, 8) != SYSERR), ""); testPrint(verbose, "Send (Incomplete Spec Hdr Inc)"); rawptr->flags = RAW_OHDR; failif((rawSend(rawptr, pkt->curr, 8) != SYSERR), ""); testPrint(verbose, "Send (Net Hdr Included)"); /* Add ARP entry */ /* Get 2nd 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); /* Get 3rd Packet */ data += phdr.caplen; memcpy(&phdr, data, sizeof(phdr)); data += sizeof(phdr); if (PCAP_MAGIC != pcap.magic) { phdr.caplen = endswap(phdr.caplen); } memcpy(pkt->data, data, phdr.caplen); pkt->len = phdr.caplen; pkt->linkhdr = pkt->data; pkt->nethdr = pkt->linkhdr + ETH_HDR_LEN; pkt->curr = pkt->nethdr + IPv4_HDR_LEN; /* Wait for ARP entry to be added */ wait = 0; while ((wait < MAX_WAIT) && (netptr->nproc == nproc)) { wait++; sleep(10); } if (MAX_WAIT == wait) { failif(MAX_WAIT, "ARP entry failed"); } else { netaddrcpy(&rawptr->remoteip, &rip); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == rawSend(rawptr, pkt->nethdr, IPv4_HDR_LEN + 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } } testPrint(verbose, "Send"); rawptr->flags = NULL; netaddrcpy(&rawptr->remoteip, &rip); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == rawSend(rawptr, pkt->curr, 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } testPrint(verbose, "Write"); control(ELOOP, ELOOP_CTRL_SETFLAG, ELOOP_FLAG_HOLDNXT, NULL); if (SYSERR == write(RAW0, pkt->curr, 8)) { failif(TRUE, "Returned SYSERR"); } else { control(ELOOP, ELOOP_CTRL_GETHOLD, (long)buf, 500); failif((memcmp(pkt->data, buf, pkt->len) != 0), "Incorrect Packet"); } close(RAW0); netDown(ELOOP); close(ELOOP); /* always print out the overall tests status */ if (passed) { testPass(TRUE, ""); } else { testFail(TRUE, ""); } #endif /* RAW0 */ return OK; }
/*------------------------------------------------------------------------ * ttyInter_out - handle an output on a tty device by sending more * characters to the device FIFO (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_out( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *csrptr /* address of UART's CSRs */ ) { int32 ochars; /* number of output chars sent */ /* to the UART */ int32 avail; /* available chars in output buf*/ int32 uspace; /* space left in onboard UART */ /* output FIFO */ byte ier = 0; /* If output is currently held, simply ignore the call */ if (typtr->tyoheld) { inb( (int)&csrptr->lsr ); /* Clear the interrupt */ return; } /* If echo and output queues empty, turn off interrupts */ if ( (typtr->tyehead == typtr->tyetail) && (semcount(typtr->tyosem) >= TY_OBUFLEN) ) { ier = inb((int)&csrptr->ier); outb((int)&csrptr->ier, ier & ~UART_IER_ETBEI); return; } /* Initialize uspace to the size of the transmit FIFO */ uspace = UART_FIFO_SIZE; /* While onboard FIFO is not full and the echo queue is */ /* nonempty, xmit chars from the echo queue */ while ( (uspace>0) && typtr->tyehead != typtr->tyetail) { outb( (int)&csrptr->buffer, *typtr->tyehead++); if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) { typtr->tyehead = typtr->tyebuff; } uspace--; } /* While onboard FIFO is not full and the output queue */ /* is nonempty, xmit chars from the output queue */ ochars = 0; avail = TY_OBUFLEN - semcount(typtr->tyosem); while ( (uspace>0) && (avail > 0) ) { outb( (int)&csrptr->buffer, *typtr->tyohead++ ); if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) { typtr->tyohead = typtr->tyobuff; } avail--; uspace--; ochars++; } if (ochars > 0) { signaln(typtr->tyosem, ochars); } return; }
/** * Write a buffer to the UART. * * @param devptr pointer to UART device * @param buf buffer of characters to write * @param len number of characters to write from the buffer */ devcall uartWrite(device *devptr, void *buf, uint len) { irqmask im; int count = 0; struct uart *uartptr; volatile struct uart_csreg *regptr; uchar *buffer = buf; uartptr = &uarttab[devptr->minor]; regptr = (struct uart_csreg *)uartptr->csr; if (NULL == regptr) { return SYSERR; } im = disable(); /* If in non-blocking mode, ensure there is enough space for the entire * write request */ if ((uartptr->oflags & UART_OFLAG_NOBLOCK) && (semcount(uartptr->osema) < len)) { restore(im); return SYSERR; } /* Put each character from the buffer into the output buffer for the * lower half */ while (count < len) { /* If in non-blocking mode, ensure there is another byte of space * for output */ if ((uartptr->oflags & UART_OFLAG_NOBLOCK) && (semcount(uartptr->osema) < 1)) { break; } /* If the UART transmitter hardware is idle, write directly to the * hardware */ if (uartptr->oidle) { uartptr->oidle = FALSE; regptr->thr = *buffer++; count++; uartptr->cout++; } /* Wait for space and place character in the output buffer for the * lower half; Preserve the circular buffer */ else { wait(uartptr->osema); uartptr->out[(uartptr->ostart + uartptr->ocount) % UART_OBLEN] = *buffer++; count++; uartptr->ocount++; } } restore(im); return count; }
/*------------------------------------------------------------------------ * ttyInter_out - handle an output on a tty device by sending more * characters to the device FIFO (interrupts disabled) *------------------------------------------------------------------------ */ void ttyInter_out( struct ttycblk *typtr, /* ptr to ttytab entry */ struct uart_csreg *uptr /* address of UART's CSRs */ ) { int32 ochars; /* number of output chars sent */ /* to the UART */ int32 avail; /* available chars in output buf*/ int32 uspace; /* space left in onboard UART */ /* output FIFO */ /* If output is currently held, turn off output interrupts */ if (typtr->tyoheld) { uptr->uart_int_en &= (~UART_TX_EMPTY_INT_EN); return; } /* If echo and output queues empty, turn off output interrupts */ if ( (typtr->tyehead == typtr->tyetail) && (semcount(typtr->tyosem) >= TY_OBUFLEN) ) { uptr->uart_int_en &= (~UART_TX_EMPTY_INT_EN); return; } /* Initialize uspace to the size of the transmit FIFO */ uspace = UART_FIFO_SIZE; /* While onboard FIFO is not full and the echo queue is */ /* nonempty, xmit chars from the echo queue */ while ( (uspace>0) && typtr->tyehead != typtr->tyetail) { uptr->uart_data = ((*typtr->tyehead++) | UART_TX_CSR); if (typtr->tyehead >= &typtr->tyebuff[TY_EBUFLEN]) { typtr->tyehead = typtr->tyebuff; } uspace--; } /* While onboard FIFO is not full and the output queue */ /* is nonempty, xmit chars from the output queue */ ochars = 0; avail = TY_OBUFLEN - semcount(typtr->tyosem); while ( (uspace>0) && (avail > 0) ) { uptr->uart_data = ((*typtr->tyohead++) | UART_TX_CSR); if (typtr->tyohead >= &typtr->tyobuff[TY_OBUFLEN]) { typtr->tyohead = typtr->tyobuff; } avail--; uspace--; ochars++; } if (ochars > 0) { signaln(typtr->tyosem, ochars); } return; }