/* * called when a process writes to an interface's 'data' */ static void ipifckick(void *x) { Proc *up = externup(); Conv *c = x; Block *bp; Ipifc *ifc; bp = qget(c->wq); if(bp == nil) return; ifc = (Ipifc*)c->ptcl; if(!canrlock(ifc)){ freeb(bp); return; } if(waserror()){ runlock(ifc); nexterror(); } if(ifc->medium == nil || ifc->medium->pktin == nil) freeb(bp); else (*ifc->medium->pktin)(c->p->f, ifc, bp); runlock(ifc); poperror(); }
/* * called when a process writes to an interface's 'data' */ static void ipifckick(void *x) { ERRSTACK(1); struct conv *c = x; struct block *bp; struct Ipifc *ifc; bp = qget(c->wq); if (bp == NULL) return; ifc = (struct Ipifc *)c->ptcl; if (!canrlock(&ifc->rwlock)) { freeb(bp); return; } if (waserror()) { runlock(&ifc->rwlock); nexterror(); } if (ifc->m == NULL || ifc->m->pktin == NULL) freeb(bp); else (*ifc->m->pktin) (c->p->f, ifc, bp); runlock(&ifc->rwlock); poperror(); }
static void loopbackread(void *a) { Ipifc *ifc; Block *bp; LB *lb; ifc = a; lb = ifc->arg; lb->readp = up; /* hide identity under a rock for unbind */ if(waserror()){ lb->readp = 0; pexit("hangup", 1); } for(;;){ bp = qbread(lb->q, Maxtu); if(bp == nil) continue; ifc->in++; if(!canrlock(ifc)){ freeb(bp); continue; } if(waserror()){ runlock(ifc); nexterror(); } if(ifc->lifc == nil) freeb(bp); else ipiput4(lb->f, ifc, bp); runlock(ifc); poperror(); } }
void isrwlocked(Memblk *f, int iswr) { if(f->type != DBfile || f->mf == nil) fatal("isrwlocked: not a file at pc %#p", getcallerpc(&f)); if((iswr && canrlock(f->mf)) || (!iswr && canwlock(f->mf))) fatal("is%clocked at pc %#p", iswr?'w':'r', getcallerpc(&f)); }
static void pppreader(void *a) { Ipifc *ifc; Block *bp; PPP *ppp; ifc = a; ppp = ifc->arg; ppp->readp = up; /* hide identity under a rock for unbind */ setpri(PriHi); if (waserror()) { netlog(ppp->f, Logppp, "pppreader: %I: %s\n", ppp->local, up->env->errstr); ppp->readp = 0; deadremote(ifc); pexit("hangup", 1); } for (;;) { bp = pppread(ppp); if (bp == nil) error("hungup"); if (!canrlock(ifc)) { freeb(bp); continue; } if (waserror()) { runlock(ifc); nexterror(); } ifc->in++; if (ifc->lifc == nil) freeb(bp); else ipiput(ppp->f, ifc, bp); runlock(ifc); poperror(); } }
static void loopbackread(void *a) { ERRSTACK(2); struct Ipifc *ifc; struct block *bp; LB *lb; ifc = a; lb = ifc->arg; lb->readp = current; /* hide identity under a rock for unbind */ if (waserror()) { lb->readp = 0; warn("loopbackread exits unexpectedly"); return; poperror(); } for (;;) { bp = qbread(lb->q, Maxtu); if (bp == NULL) continue; ifc->in++; if (!canrlock(&ifc->rwlock)) { freeb(bp); continue; } if (waserror()) { runlock(&ifc->rwlock); nexterror(); } if (ifc->lifc == NULL) freeb(bp); else ipiput4(lb->f, ifc, bp); runlock(&ifc->rwlock); poperror(); } poperror(); }
/* * Print a string on the console. Convert \n to \r\n for serial * line consoles. Locking of the queues is left up to the screen * or uart code. Multi-line messages to serial consoles may get * interspersed with other messages. */ static void putstrn0(char *str, int n, int usewrite) { int m; char *t; char buf[PRINTSIZE + 2]; ERRSTACK(1); /* * if kprint is open, put the message there, otherwise * if there's an attached bit mapped display, * put the message there. */ m = consoleprint; if (canrlock(&(&kprintq)->rwlock)) { if (kprintq.q != NULL) { if (waserror()) { runlock(&(&kprintq)->rwlock); nexterror(); } if (usewrite) qwrite(kprintq.q, str, n); else qiwrite(kprintq.q, str, n); poperror(); m = 0; } runlock(&(&kprintq)->rwlock); } if (m && screenputs != NULL) screenputs(str, n); /* * if there's a serial line being used as a console, * put the message there. */ if (serwrite != NULL) { serwrite(str, n); return; } if (printq == 0) return; while (n > 0) { t = memchr(str, '\n', n); if (t && !kbd.raw) { m = t - str; if (m > sizeof(buf) - 2) m = sizeof(buf) - 2; memmove(buf, str, m); buf[m] = '\r'; buf[m + 1] = '\n'; if (usewrite) qwrite(printq, buf, m + 2); else qiwrite(printq, buf, m + 2); str = t + 1; n -= m + 1; } else { if (usewrite) qwrite(printq, str, n); else qiwrite(printq, str, n); break; } } }
static uint64_t rxmitsols(struct arp *arp) { unsigned int sflag; struct block *next, *xp; struct arpent *a, *b, **l; struct Fs *f; uint8_t ipsrc[IPaddrlen]; struct Ipifc *ifc = NULL; uint64_t nrxt; qlock(&arp->qlock); f = arp->f; a = arp->rxmt; if (a == NULL) { nrxt = 0; goto dodrops; /* return nrxt; */ } nrxt = a->rtime - NOW; if (nrxt > 3 * ReTransTimer / 4) goto dodrops; /* return nrxt; */ for (; a; a = a->nextrxt) { ifc = a->ifc; assert(ifc != NULL); if ((a->rxtsrem <= 0) || !(canrlock(&ifc->rwlock)) || (a->ifcid != ifc->ifcid)) { xp = a->hold; a->hold = NULL; if (xp) { if (arp->dropl == NULL) arp->dropf = xp; else arp->dropl->list = xp; } cleanarpent(arp, a); } else break; } if (a == NULL) goto dodrops; qunlock(&arp->qlock); /* for icmpns */ if ((sflag = ipv6anylocal(ifc, ipsrc)) != SRC_UNSPEC) icmpns(f, ipsrc, sflag, a->ip, TARG_MULTI, ifc->mac); runlock(&ifc->rwlock); qlock(&arp->qlock); /* put to the end of re-transmit chain */ l = &arp->rxmt; for (b = *l; b; b = b->nextrxt) { if (b == a) { *l = a->nextrxt; break; } l = &b->nextrxt; } for (b = *l; b; b = b->nextrxt) { l = &b->nextrxt; } *l = a; a->rxtsrem--; a->nextrxt = NULL; a->rtime = NOW + ReTransTimer; a = arp->rxmt; if (a == NULL) nrxt = 0; else nrxt = a->rtime - NOW; dodrops: xp = arp->dropf; arp->dropf = NULL; arp->dropl = NULL; qunlock(&arp->qlock); for (; xp; xp = next) { next = xp->list; icmphostunr(f, ifc, xp, icmp6_adr_unreach, 1); } return nrxt; }
static long conswrite(Chan *c, void *va, long n, vlong offset) { char buf[128], *a, ch; int x; if(c->qid.type & QTDIR) error(Eperm); switch((ulong)c->qid.path) { default: error(Egreg); case Qcons: if(canrlock(&kprintq.l)){ if(kprintq.q != nil){ if(waserror()){ runlock(&kprintq.l); nexterror(); } qwrite(kprintq.q, va, n); poperror(); runlock(&kprintq.l); return n; } runlock(&kprintq.l); } return write(1, va, n); case Qsysctl: return sysconwrite(va, n); case Qconsctl: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = 0; for(a = buf; a;){ if(strncmp(a, "rawon", 5) == 0){ kbd.raw = 1; /* clumsy hack - wake up reader */ ch = 0; qwrite(kbdq, &ch, 1); } else if(strncmp(buf, "rawoff", 6) == 0){ kbd.raw = 0; } if((a = strchr(a, ' ')) != nil) a++; } break; case Qkeyboard: for(x=0; x<n; ) { Rune r; x += chartorune(&r, &((char*)va)[x]); gkbdputc(gkbdq, r); } break; case Qnull: break; case Qtime: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = '\0'; timeoffset = strtoll(buf, 0, 0)-osusectime(); break; case Qhostowner: if(!iseve()) error(Eperm); if(offset != 0 || n >= sizeof(buf)) error(Ebadarg); memmove(buf, va, n); buf[n] = '\0'; if(n > 0 && buf[n-1] == '\n') buf[--n] = '\0'; if(n == 0) error(Ebadarg); /* renameuser(eve, buf); */ /* renameproguser(eve, buf); */ kstrdup(&eve, buf); kstrdup(&up->env->user, buf); break; case Quser: if(!iseve()) error(Eperm); if(offset != 0) error(Ebadarg); if(n <= 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, n); buf[n] = '\0'; if(n > 0 && buf[n-1] == '\n') buf[--n] = '\0'; if(n == 0) error(Ebadarg); setid(buf, 0); break; case Qhoststdout: return write(1, va, n); case Qhoststderr: return write(2, va, n); case Qjit: if(n >= sizeof(buf)) n = sizeof(buf)-1; strncpy(buf, va, n); buf[n] = '\0'; x = atoi(buf); if(x < 0 || x > 9) error(Ebadarg); cflag = x; break; case Qsysname: if(offset != 0) error(Ebadarg); if(n < 0 || n >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, n); buf[n] = '\0'; if(buf[n-1] == '\n') buf[n-1] = 0; kstrdup(&ossysname, buf); break; } return n; }
long conswrite(Chan *c, void *va, long count, vlong offset) { char buf[128], *p; int x, y; USED(offset); if(c->qid.type & QTDIR) error(Eperm); switch((ulong)c->qid.path) { default: error(Egreg); case Qcons: if(canrlock(&kprintq.l)){ if(kprintq.q != nil){ if(waserror()){ runlock(&kprintq.l); nexterror(); } qwrite(kprintq.q, va, count); poperror(); runlock(&kprintq.l); return count; } runlock(&kprintq.l); } return write(1, va, count); case Qsysctl: return sysconwrite(va, count); case Qconsctl: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = 0; if(strncmp(buf, "rawon", 5) == 0) { kbd.raw = 1; return count; } else if(strncmp(buf, "rawoff", 6) == 0) { kbd.raw = 0; return count; } error(Ebadctl); case Qkeyboard: for(x=0; x<count; ) { Rune r; x += chartorune(&r, &((char*)va)[x]); gkbdputc(gkbdq, r); } return count; case Qpointer: if(count > sizeof buf-1) count = sizeof buf -1; memmove(buf, va, count); buf[count] = 0; p = nil; x = strtoul(buf+1, &p, 0); if(p == nil || p == buf+1) error(Eshort); y = strtoul(p, 0, 0); setpointer(x, y); return count; case Qnull: return count; case Qpin: if(up->env->pgrp->pin != Nopin) error("pin already set"); if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; up->env->pgrp->pin = atoi(buf); return count; case Qtime: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; timeoffset = strtoll(buf, 0, 0)-osusectime(); return count; case Quser: if(count >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, count); buf[count] = '\0'; if(count > 0 && buf[count-1] == '\n') buf[--count] = '\0'; if(count == 0) error(Ebadarg); if(strcmp(up->env->user, eve) != 0) error(Eperm); setid(buf, 0); return count; case Qhostowner: if(count >= sizeof(buf)) error(Ebadarg); strncpy(buf, va, count); buf[count] = '\0'; if(count > 0 && buf[count-1] == '\n') buf[--count] = '\0'; if(count == 0) error(Ebadarg); if(strcmp(up->env->user, eve) != 0) error(Eperm); kstrdup(&eve, buf); return count; case Qhoststdout: return write(1, va, count); case Qhoststderr: return write(2, va, count); case Qjit: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; x = atoi(buf); if (x < 0 || x > 9) error(Ebadarg); cflag = x; return count; case Qsysname: if(count >= sizeof(buf)) count = sizeof(buf)-1; strncpy(buf, va, count); buf[count] = '\0'; kstrdup(&ossysname, buf); return count; case Qsnarf: if(offset+count >= SnarfSize) error(Etoobig); snarftab->qid.vers++; memmove((uchar*)(c->aux)+offset, va, count); return count; } return 0; }