void rudpadvise(Proto *rudp, Block *bp, char *msg) { Udphdr *h; uint8_t source[IPaddrlen], dest[IPaddrlen]; uint16_t psource, pdest; Conv *s, **p; h = (Udphdr*)(bp->rp); v4tov6(dest, h->udpdst); v4tov6(source, h->udpsrc); psource = nhgets(h->udpsport); pdest = nhgets(h->udpdport); /* Look for a connection */ for(p = rudp->conv; *p; p++) { s = *p; if(s->rport == pdest) if(s->lport == psource) if(ipcmp(s->raddr, dest) == 0) if(ipcmp(s->laddr, source) == 0){ qhangup(s->rq, msg); qhangup(s->wq, msg); break; } } freeblist(bp); }
/* * we save up input characters till clock time to reduce * per character interrupt overhead. */ static void uartclock(void) { Uart *p; ilock(&uartalloc); for(p = uartalloc.elist; p; p = p->elist){ /* this hopefully amortizes cost of qproduce to many chars */ if(p->iw != p->ir){ ilock(&p->rlock); uartstageinput(p); iunlock(&p->rlock); } /* hang up if requested */ if(p->dohup){ qhangup(p->iq, 0); qhangup(p->oq, 0); p->dohup = 0; } /* this adds hysteresis to hardware/software flow control */ if(p->ctsbackoff){ ilock(&p->tlock); if(p->ctsbackoff){ if(--(p->ctsbackoff) == 0) (*p->phys->kick)(p); } iunlock(&p->tlock); } uartkick(p); /* keep it moving */ } iunlock(&uartalloc); }
void udpadvise(Proto *udp, Block *bp, char *msg) { Udp4hdr *h4; Udp6hdr *h6; uchar source[IPaddrlen], dest[IPaddrlen]; ushort psource, pdest; Conv *s, **p; int version; h4 = (Udp4hdr*)(bp->rp); version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4; switch(version) { case V4: v4tov6(dest, h4->udpdst); v4tov6(source, h4->udpsrc); psource = nhgets(h4->udpsport); pdest = nhgets(h4->udpdport); break; case V6: h6 = (Udp6hdr*)(bp->rp); ipmove(dest, h6->udpdst); ipmove(source, h6->udpsrc); psource = nhgets(h6->udpsport); pdest = nhgets(h6->udpdport); break; default: panic("udpadvise: version %d", version); return; /* to avoid a warning */ } /* Look for a connection */ qlock(udp); for(p = udp->conv; *p; p++) { s = *p; if(s->rport == pdest) if(s->lport == psource) if(ipcmp(s->raddr, dest) == 0) if(ipcmp(s->laddr, source) == 0){ if(s->ignoreadvice) break; qlock(s); qunlock(udp); qhangup(s->rq, msg); qhangup(s->wq, msg); qunlock(s); freeblist(bp); return; } } qunlock(udp); freeblist(bp); }
static char* espconnect(Conv *c, char **argv, int argc) { char *p, *pp, *e = nil; uint32_t spi; Espcb *ecb = (Espcb*)c->ptcl; switch(argc) { default: e = "bad args to connect"; break; case 2: p = strchr(argv[1], '!'); if(p == nil){ e = "malformed address"; break; } *p++ = 0; if (parseip(c->raddr, argv[1]) == -1) { e = Ebadip; break; } findlocalip(c->p->f, c->laddr, c->raddr); ecb->incoming = 0; ecb->seq = 0; if(strcmp(p, "*") == 0) { qlock(c->p); for(;;) { spi = nrand(1<<16) + 256; if(convlookup(c->p, spi) == nil) break; } qunlock(c->p); ecb->spi = spi; ecb->incoming = 1; qhangup(c->wq, nil); } else { spi = strtoul(p, &pp, 10); if(pp == p) { e = "malformed address"; break; } ecb->spi = spi; qhangup(c->rq, nil); } nullespinit(ecb, "null", nil, 0); nullahinit(ecb, "null", nil, 0); } Fsconnected(c, e); return e; }
static void pipeclose(Chan *c) { Pipe *p; p = c->aux; qlock(p); if(c->flag & COPEN){ /* * closing either side hangs up the stream */ switch(NETTYPE(c->qid.path)){ case Qdata0: p->qref[0]--; if(p->qref[0] == 0){ qhangup(p->q[1], 0); qclose(p->q[0]); } break; case Qdata1: p->qref[1]--; if(p->qref[1] == 0){ qhangup(p->q[0], 0); qclose(p->q[1]); } break; } } /* * if both sides are closed, they are reusable */ if(p->qref[0] == 0 && p->qref[1] == 0){ qreopen(p->q[0]); qreopen(p->q[1]); } /* * free the structure on last close */ p->ref--; if(p->ref == 0){ qunlock(p); free(p->q[0]); free(p->q[1]); free(p); } else qunlock(p); }
static void uartclose(Chan *c) { Uart *p; if(c->qid.type & QTDIR) return; if((c->flag & COPEN) == 0) return; switch(NETTYPE(c->qid.path)){ case Ndataqid: case Nctlqid: p = uart[NETID(c->qid.path)]; qlock(p); if(--(p->opens) == 0){ qclose(p->iq); ilock(&p->rlock); p->ir = p->iw = p->istage; iunlock(&p->rlock); /* */ qhangup(p->oq, nil); if(!waserror()){ uartdrainoutput(p); poperror(); } qclose(p->oq); uartdisable(p); p->dcd = p->dsr = p->dohup = 0; } qunlock(p); break; } }
/* called from icmp(v6) for unreachable hosts, time exceeded, etc. */ void espadvise(Proto *esp, Block *bp, char *msg) { Conv *c; Versdep vers; getverslens(pktipvers(esp->f, &bp), &vers); getpktspiaddrs(bp->rp, &vers); qlock(esp); c = convlookup(esp, vers.spi); if(c != nil) { qhangup(c->rq, msg); qhangup(c->wq, msg); } qunlock(esp); freeblist(bp); }
void espadvise(Proto *esp, Block *bp, char *msg) { Esphdr *h; Conv *c; ulong spi; h = (Esphdr*)(bp->rp); spi = nhgets(h->espspi); qlock(esp); c = convlookup(esp, spi); if(c != nil) { qhangup(c->rq, msg); qhangup(c->wq, msg); } qunlock(esp); freeblist(bp); }
static void consclose(Chan *c) { switch((ulong)c->qid.path){ /* close of kprint allows other opens */ case Qkprint: if(c->flag & COPEN){ kprintinuse = 0; qhangup(kprintoq, nil); } break; } }
static void consclose(struct chan *c) { switch ((uint32_t) c->qid.path) { /* last close of control file turns off raw */ case Qconsctl: if (c->flag & COPEN) { if (kref_put(&kbd.ctl) == 0) kbd.raw = 0; } break; /* close of kprint allows other opens */ case Qkprint: if (c->flag & COPEN) { kprintinuse = 0; qhangup(kprintoq, NULL); } break; } }
static void consclose(Chan *c) { switch((ulong)c->qid.path){ /* last close of control file turns off raw */ case Qconsctl: if(c->flag&COPEN){ if(decref(&kbd.ctl) == 0) kbd.raw = 0; } break; /* close of kprint allows other opens */ case Qkprint: if(c->flag & COPEN){ kprintinuse = 0; qhangup(kprintoq, nil); } break; } }
static void loopbackclose(Chan *c) { Loop *lb; int ref, chan; lb = c->aux; qlock(lb); /* * closing either side hangs up the stream */ if((c->flag & COPEN) && TYPE(c->qid.path) == Qdata){ chan = ID(c->qid.path); if(--lb->link[chan].ref == 0){ qhangup(lb->link[chan ^ 1].oq, nil); looper(lb); } } /* * if both sides are closed, they are reusable */ if(lb->link[0].ref == 0 && lb->link[1].ref == 0){ for(chan = 0; chan < 2; chan++){ closelink(&lb->link[chan], 0); qreopen(lb->link[chan].iq); qreopen(lb->link[chan].oq); qsetlimit(lb->link[chan].oq, lb->link[chan].limit); qsetlimit(lb->link[chan].iq, lb->link[chan].limit); } } ref = --lb->ref; if(ref == 0) freelb(lb); qunlock(lb); }
/* * move blocks between queues if they are ready. * schedule an interrupt for the next interesting time. * * must be called with the link ilocked. */ static void pushlink(Link *link, vlong now) { Block *bp; vlong tout, tin; /* * put another block in the link queue */ ilock(link); if(link->iq == nil || link->oq == nil){ iunlock(link); return; } timerdel(&link->ci); /* * put more blocks into the xmit queue * use the time the last packet was supposed to go out * as the start time for the next packet, rather than * the current time. this more closely models a network * device which can queue multiple output packets. */ tout = link->tout; if(!tout) tout = now; while(tout <= now){ bp = qget(link->oq); if(bp == nil){ tout = 0; break; } /* * can't send the packet before it gets queued */ tin = gtime(bp->rp); if(tin > tout) tout = tin; tout = tout + (BLEN(bp) - Tmsize) * link->delayn; /* * drop packets */ if(link->droprate && nrand(link->droprate) == 0) link->drops++; else{ ptime(bp->rp, tout + link->delay0ns); if(link->tq == nil) link->tq = bp; else link->tqtail->next = bp; link->tqtail = bp; } } /* * record the next time a packet can be sent, * but don't schedule an interrupt if none is waiting */ link->tout = tout; if(!qcanread(link->oq)) tout = 0; /* * put more blocks into the receive queue */ tin = 0; while(bp = link->tq){ tin = gtime(bp->rp); if(tin > now) break; bp->rp += Tmsize; link->tq = bp->next; bp->next = nil; if(!link->indrop) qpassnolim(link->iq, bp); else if(qpass(link->iq, bp) < 0) link->soverflows++; tin = 0; } if(bp == nil && qisclosed(link->oq) && !qcanread(link->oq) && !qisclosed(link->iq)) qhangup(link->iq, nil); link->tin = tin; if(!tin || tin > tout && tout) tin = tout; link->ci.ns = tin - now; if(tin){ if(tin < now) panic("loopback unfinished business"); timeradd(&link->ci); } iunlock(link); }
int uartctl(Uart *p, char *cmd) { char *f[16]; int i, n, nf; nf = tokenize(cmd, f, nelem(f)); for(i = 0; i < nf; i++){ if(strncmp(f[i], "break", 5) == 0){ (*p->phys->dobreak)(p, 0); continue; } n = atoi(f[i]+1); switch(*f[i]){ case 'B': case 'b': uartdrainoutput(p); if((*p->phys->baud)(p, n) < 0) return -1; break; case 'C': case 'c': p->hup_dcd = n; break; case 'D': case 'd': uartdrainoutput(p); (*p->phys->dtr)(p, n); break; case 'E': case 'e': p->hup_dsr = n; break; case 'F': case 'f': if(p->oq != nil) qflush(p->oq); break; case 'H': case 'h': if(p->iq != nil) qhangup(p->iq, 0); if(p->oq != nil) qhangup(p->oq, 0); break; case 'I': case 'i': uartdrainoutput(p); (*p->phys->fifo)(p, n); break; case 'K': case 'k': uartdrainoutput(p); (*p->phys->dobreak)(p, n); break; case 'L': case 'l': uartdrainoutput(p); if((*p->phys->bits)(p, n) < 0) return -1; break; case 'M': case 'm': uartdrainoutput(p); (*p->phys->modemctl)(p, n); break; case 'N': case 'n': if(p->oq != nil) qnoblock(p->oq, n); break; case 'P': case 'p': uartdrainoutput(p); if((*p->phys->parity)(p, *(f[i]+1)) < 0) return -1; break; case 'Q': case 'q': if(p->iq != nil) qsetlimit(p->iq, n); if(p->oq != nil) qsetlimit(p->oq, n); break; case 'R': case 'r': uartdrainoutput(p); (*p->phys->rts)(p, n); break; case 'S': case 's': uartdrainoutput(p); if((*p->phys->stop)(p, n) < 0) return -1; break; case 'W': case 'w': if(uarttimer == nil || n < 1) return -1; uarttimer->tns = (int64_t)n * 100000LL; break; case 'X': case 'x': if(p->enabled){ ilock(&p->tlock); p->xonoff = n; iunlock(&p->tlock); } break; } } return 0; }
static void uartctl(Uart *p, char *cmd) { int i, n; /* let output drain for a while (up to 4 secs) */ for(i = 0; i < 200 && (qlen(p->oq) || (readstatus(p) & USTAT_TC) == 0); i++) tsleep(&up->sleep, return0, 0, 20); if(strncmp(cmd, "break", 5) == 0){ uartbreak(p, 0); return; } n = atoi(cmd+1); switch(*cmd){ case 'B': case 'b': if(n <= 0) error(Ebadarg); p->bps = n; uartset(p); break; case 'f': case 'F': qflush(p->oq); break; case 'H': case 'h': qhangup(p->iq, 0); qhangup(p->oq, 0); break; case 'L': case 'l': if(n < 7 || n > 8) error(Ebadarg); p->bits = n; uartset(p); break; case 'n': case 'N': qnoblock(p->oq, n); break; case 'P': case 'p': p->parity = *(cmd+1); uartset(p); break; case 'K': case 'k': uartbreak(p, n); break; case 'Q': case 'q': qsetlimit(p->iq, n); qsetlimit(p->oq, n); break; case 's': case 'S': if(n < 1 || n > 2) error(Ebadarg); p->stop = n; uartset(p); break; } }