static void *netrequest_cmd_thread(void *arg){ msg *message = NULL; char* me = "netrequest_cmd_thread"; while(1){ requestNo++; freeMsg(message); netlog("%s waiting to process request number %d\n", me, requestNo); message = acceptMsg(STDIN_FILENO); if(message == NULL){ netlog("%s readMsg failed; %p", me, arg); continue; } netlog("%s processing request:\n\"%s\"\n", me, message->data); } return NULL; }
static int pktipvers(Fs *f, Block **bpp) { if (*bpp == nil || BLEN(*bpp) == 0) { /* get enough to identify the IP version */ *bpp = pullupblock(*bpp, IP4HDR); if(*bpp == nil) { netlog(f, Logesp, "esp: short packet\n"); return 0; } } return (((Esp4hdr*)(*bpp)->rp)->vihl & 0xf0) == IP_VER4? V4: V6; }
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(); } }
void igmpsendreport(Medium *m, uchar *addr) { IGMPpkt *p; Block *bp; bp = allocb(sizeof(IGMPpkt)); if(bp == nil) return; p = (IGMPpkt*)bp->wp; p->vihl = IP_VER4; bp->wp += IGMPPKTSZ; memset(bp->rp, 0, IGMPPKTSZ); hnputl(p->src, Mediumgetaddr(m)); hnputl(p->dst, Ipallsys); p->vertype = (1<<4) | IGMPreport; p->proto = IP_IGMPPROTO; memmove(p->group, addr, IPaddrlen); hnputs(p->igmpcksum, ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE)); netlog(Logigmp, "igmpreport %I\n", p->group); stats.outreports++; ipoput4(bp, 0, 1, DFLTTOS, nil); /* TTL of 1 */ }
void* handleRequest(void* args){ int from = -1, to = -1; echofds* fds = (echofds*)args; if(fds == NULL) goto fail; from = fds->from; to = fds->to; while(1){ msg* message = acceptMsg(from); if(message != NULL){ msg2netlog(message); pthread_mutex_lock(&netrequest_output_mutex); sendMsg(to, message); pthread_mutex_unlock(&netrequest_output_mutex); freeMsg(message); } else { netlog("handleRequest exiting gracefully!\n"); break; } } fail: if(from != -1){ close(from); } return NULL; }
void udpiput(struct Proto *udp, struct Ipifc *ifc, struct block *bp) { int len; Udp4hdr *uh4; Udp6hdr *uh6; struct conv *c; Udpcb *ucb; uint8_t raddr[IPaddrlen], laddr[IPaddrlen]; uint16_t rport, lport; Udppriv *upriv; struct Fs *f; int version; int ottl, oviclfl, olen; uint8_t *p; upriv = udp->priv; f = udp->f; upriv->ustats.udpInDatagrams++; uh4 = (Udp4hdr *) (bp->rp); version = ((uh4->vihl & 0xF0) == IP_VER6) ? V6 : V4; /* * Put back pseudo header for checksum * (remember old values for icmpnoconv()) */ switch (version) { case V4: ottl = uh4->Unused; uh4->Unused = 0; len = nhgets(uh4->udplen); olen = nhgets(uh4->udpplen); hnputs(uh4->udpplen, len); v4tov6(raddr, uh4->udpsrc); v4tov6(laddr, uh4->udpdst); lport = nhgets(uh4->udpdport); rport = nhgets(uh4->udpsport); if (!(bp->flag & Budpck) && (uh4->udpcksum[0] || uh4->udpcksum[1]) && ptclcsum(bp, UDP4_PHDR_OFF, len + UDP4_PHDR_SZ)) { upriv->ustats.udpInErrors++; netlog(f, Logudp, "udp: checksum error %I\n", raddr); printd("udp: checksum error %I\n", raddr); freeblist(bp); return; } uh4->Unused = ottl; hnputs(uh4->udpplen, olen); break; case V6: uh6 = (Udp6hdr *) (bp->rp); len = nhgets(uh6->udplen); oviclfl = nhgetl(uh6->viclfl); olen = nhgets(uh6->len); ottl = uh6->hoplimit; ipmove(raddr, uh6->udpsrc); ipmove(laddr, uh6->udpdst); lport = nhgets(uh6->udpdport); rport = nhgets(uh6->udpsport); memset(uh6, 0, 8); hnputl(uh6->viclfl, len); uh6->hoplimit = IP_UDPPROTO; if (ptclcsum(bp, UDP6_PHDR_OFF, len + UDP6_PHDR_SZ)) { upriv->ustats.udpInErrors++; netlog(f, Logudp, "udp: checksum error %I\n", raddr); printd("udp: checksum error %I\n", raddr); freeblist(bp); return; } hnputl(uh6->viclfl, oviclfl); hnputs(uh6->len, olen); uh6->nextheader = IP_UDPPROTO; uh6->hoplimit = ottl; break; default: panic("udpiput: version %d", version); return; /* to avoid a warning */ } qlock(&udp->qlock); c = iphtlook(&upriv->ht, raddr, rport, laddr, lport); if (c == NULL) { /* no converstation found */ upriv->ustats.udpNoPorts++; qunlock(&udp->qlock); netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport); switch (version) { case V4: icmpnoconv(f, bp); break; case V6: icmphostunr(f, ifc, bp, icmp6_port_unreach, 0); break; default: panic("udpiput2: version %d", version); } freeblist(bp); return; } ucb = (Udpcb *) c->ptcl; if (c->state == Announced) { if (ucb->headers == 0) { /* create a new conversation */ if (ipforme(f, laddr) != Runi) { switch (version) { case V4: v4tov6(laddr, ifc->lifc->local); break; case V6: ipmove(laddr, ifc->lifc->local); break; default: panic("udpiput3: version %d", version); } } c = Fsnewcall(c, raddr, rport, laddr, lport, version); if (c == NULL) { qunlock(&udp->qlock); freeblist(bp); return; } iphtadd(&upriv->ht, c); ucb = (Udpcb *) c->ptcl; } } qlock(&c->qlock); qunlock(&udp->qlock); /* * Trim the packet down to data size */ len -= UDP_UDPHDR_SZ; switch (version) { case V4: bp = trimblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ, len); break; case V6: bp = trimblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ, len); break; default: bp = NULL; panic("udpiput4: version %d", version); } if (bp == NULL) { qunlock(&c->qlock); netlog(f, Logudp, "udp: len err %I.%d -> %I.%d\n", raddr, rport, laddr, lport); upriv->lenerr++; return; } netlog(f, Logudpmsg, "udp: %I.%d -> %I.%d l %d\n", raddr, rport, laddr, lport, len); switch (ucb->headers) { case 7: /* pass the src address */ bp = padblock(bp, UDP_USEAD7); p = bp->rp; ipmove(p, raddr); p += IPaddrlen; ipmove(p, laddr); p += IPaddrlen; ipmove(p, ifc->lifc->local); p += IPaddrlen; hnputs(p, rport); p += 2; hnputs(p, lport); break; case 6: /* pass the src address */ bp = padblock(bp, UDP_USEAD6); p = bp->rp; ipmove(p, raddr); p += IPaddrlen; ipmove(p, ipforme(f, laddr) == Runi ? laddr : ifc->lifc->local); p += IPaddrlen; hnputs(p, rport); p += 2; hnputs(p, lport); break; } if (bp->next) bp = concatblock(bp); if (qfull(c->rq)) { qunlock(&c->qlock); netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport, laddr, lport); freeblist(bp); return; } qpass(c->rq, bp); qunlock(&c->qlock); }
void udpkick(void *x, struct block *bp) { struct conv *c = x; Udp4hdr *uh4; Udp6hdr *uh6; uint16_t rport; uint8_t laddr[IPaddrlen], raddr[IPaddrlen]; Udpcb *ucb; int dlen, ptcllen; Udppriv *upriv; struct Fs *f; int version; struct conv *rc; upriv = c->p->priv; assert(upriv); f = c->p->f; netlog(c->p->f, Logudp, "udp: kick\n"); if (bp == NULL) return; ucb = (Udpcb *) c->ptcl; switch (ucb->headers) { case 7: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD7); if (bp == NULL) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if (ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); bp->rp += IPaddrlen; /* Ignore ifc address */ rport = nhgets(bp->rp); bp->rp += 2 + 2; /* Ignore local port */ break; case 6: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD6); if (bp == NULL) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if (ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); rport = nhgets(bp->rp); bp->rp += 2 + 2; /* Ignore local port */ break; default: rport = 0; break; } if (ucb->headers) { if (memcmp(laddr, v4prefix, IPv4off) == 0 || ipcmp(laddr, IPnoaddr) == 0) version = V4; else version = V6; } else { if ((memcmp(c->raddr, v4prefix, IPv4off) == 0 && memcmp(c->laddr, v4prefix, IPv4off) == 0) || ipcmp(c->raddr, IPnoaddr) == 0) version = V4; else version = V6; } dlen = blocklen(bp); /* fill in pseudo header and compute checksum */ switch (version) { case V4: bp = padblock(bp, UDP4_IPHDR_SZ + UDP_UDPHDR_SZ); if (bp == NULL) return; uh4 = (Udp4hdr *) (bp->rp); ptcllen = dlen + UDP_UDPHDR_SZ; uh4->Unused = 0; uh4->udpproto = IP_UDPPROTO; uh4->frag[0] = 0; uh4->frag[1] = 0; hnputs(uh4->udpplen, ptcllen); if (ucb->headers) { v6tov4(uh4->udpdst, raddr); hnputs(uh4->udpdport, rport); v6tov4(uh4->udpsrc, laddr); rc = NULL; } else { v6tov4(uh4->udpdst, c->raddr); hnputs(uh4->udpdport, c->rport); if (ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); v6tov4(uh4->udpsrc, c->laddr); rc = c; } hnputs(uh4->udpsport, c->lport); hnputs(uh4->udplen, ptcllen); uh4->udpcksum[0] = 0; uh4->udpcksum[1] = 0; hnputs(uh4->udpcksum, ~ptclcsum(bp, UDP4_PHDR_OFF, UDP4_PHDR_SZ)); bp->checksum_start = UDP4_IPHDR_SZ; bp->checksum_offset = uh4->udpcksum - uh4->udpsport; bp->flag |= Budpck; uh4->vihl = IP_VER4; ipoput4(f, bp, 0, c->ttl, c->tos, rc); break; case V6: bp = padblock(bp, UDP6_IPHDR_SZ + UDP_UDPHDR_SZ); if (bp == NULL) return; // using the v6 ip header to create pseudo header // first then reset it to the normal ip header uh6 = (Udp6hdr *) (bp->rp); memset(uh6, 0, 8); ptcllen = dlen + UDP_UDPHDR_SZ; hnputl(uh6->viclfl, ptcllen); uh6->hoplimit = IP_UDPPROTO; if (ucb->headers) { ipmove(uh6->udpdst, raddr); hnputs(uh6->udpdport, rport); ipmove(uh6->udpsrc, laddr); rc = NULL; } else { ipmove(uh6->udpdst, c->raddr); hnputs(uh6->udpdport, c->rport); if (ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); ipmove(uh6->udpsrc, c->laddr); rc = c; } hnputs(uh6->udpsport, c->lport); hnputs(uh6->udplen, ptcllen); uh6->udpcksum[0] = 0; uh6->udpcksum[1] = 0; hnputs(uh6->udpcksum, ptclcsum(bp, UDP6_PHDR_OFF, dlen + UDP_UDPHDR_SZ + UDP6_PHDR_SZ)); memset(uh6, 0, 8); uh6->viclfl[0] = IP_VER6; hnputs(uh6->len, ptcllen); uh6->nextheader = IP_UDPPROTO; ipoput6(f, bp, 0, c->ttl, c->tos, rc); break; default: panic("udpkick: version %d", version); } upriv->ustats.udpOutDatagrams++; }
void igmpiput(Medium *m, Ipifc *, Block *bp) { int n; IGMPpkt *ghp; Ipaddr group; IGMPrep *rp, **lrp; Multicast *mp, **lmp; ghp = (IGMPpkt*)(bp->rp); netlog(Logigmp, "igmpiput: %d %I\n", ghp->vertype, ghp->group); n = blocklen(bp); if(n < IGMP_IPHDRSIZE+IGMP_HDRSIZE){ netlog(Logigmp, "igmpiput: bad len\n"); goto error; } if((ghp->vertype>>4) != 1){ netlog(Logigmp, "igmpiput: bad igmp type\n"); goto error; } if(ptclcsum(bp, IGMP_IPHDRSIZE, IGMP_HDRSIZE)){ netlog(Logigmp, "igmpiput: checksum error %I\n", ghp->src); goto error; } group = nhgetl(ghp->group); lock(&igmpalloc); switch(ghp->vertype & 0xf){ case IGMPquery: /* * start reporting groups that we're a member of. */ stats.inqueries++; for(rp = igmpalloc.reports; rp; rp = rp->next) if(rp->m == m) break; if(rp != nil) break; /* already reporting */ mp = Mediumcopymulti(m); if(mp == nil) break; rp = malloc(sizeof(*rp)); if(rp == nil) break; rp->m = m; rp->multi = mp; rp->ticks = 0; for(; mp; mp = mp->next) mp->timeout = nrand(MAXTIMEOUT); rp->next = igmpalloc.reports; igmpalloc.reports = rp; wakeup(&igmpalloc.r); break; case IGMPreport: /* * find report list for this medium */ stats.inreports++; lrp = &igmpalloc.reports; for(rp = *lrp; rp; rp = *lrp){ if(rp->m == m) break; lrp = &rp->next; } if(rp == nil) break; /* * if someone else has reported a group, * we don't have to. */ lmp = &rp->multi; for(mp = *lmp; mp; mp = *lmp){ if(mp->addr == group){ *lmp = mp->next; free(mp); break; } lmp = &mp->next; } break; } unlock(&igmpalloc); error: freeb(bp); }
/* * decapsulate IP packet from IP/ESP packet in bp and * pass the result up the spi's Conv's read queue. */ void espiput(Proto *esp, Ipifc *ipifc, Block *bp) { Mach *m = machp(); int payload, nexthdr; uint8_t *auth, *espspi; Conv *c; Espcb *ecb; Esptail *et; Fs *f; Userhdr *uh; Versdep vers; f = esp->f; getverslens(pktipvers(f, &bp), &vers); bp = pullupblock(bp, vers.hdrlen + Esptaillen); if(bp == nil) { netlog(f, Logesp, "esp: short packet\n"); return; } getpktspiaddrs(bp->rp, &vers); qlock(esp); /* Look for a conversation structure for this port */ c = convlookup(esp, vers.spi); if(c == nil) { qunlock(esp); netlog(f, Logesp, "esp: no conv %I -> %I!%lud\n", vers.raddr, vers.laddr, vers.spi); icmpnoconv(f, bp); freeblist(bp); return; } qlock(c); qunlock(esp); ecb = c->ptcl; /* too hard to do decryption/authentication on block lists */ if(bp->next) bp = concatblock(bp); if(BLEN(bp) < vers.hdrlen + ecb->espivlen + Esptaillen + ecb->ahlen) { qunlock(c); netlog(f, Logesp, "esp: short block %I -> %I!%lud\n", vers.raddr, vers.laddr, vers.spi); freeb(bp); return; } auth = bp->wp - ecb->ahlen; espspi = vers.version == V4? ((Esp4hdr*)bp->rp)->espspi: ((Esp6hdr*)bp->rp)->espspi; /* compute secure hash and authenticate */ if(!ecb->auth(ecb, espspi, auth - espspi, auth)) { qunlock(c); print("esp: bad auth %I -> %I!%ld\n", vers.raddr, vers.laddr, vers.spi); netlog(f, Logesp, "esp: bad auth %I -> %I!%lud\n", vers.raddr, vers.laddr, vers.spi); freeb(bp); return; } payload = BLEN(bp) - vers.hdrlen - ecb->ahlen; if(payload <= 0 || payload % 4 != 0 || payload % ecb->espblklen != 0) { qunlock(c); netlog(f, Logesp, "esp: bad length %I -> %I!%lud payload=%d BLEN=%lud\n", vers.raddr, vers.laddr, vers.spi, payload, BLEN(bp)); freeb(bp); return; } /* decrypt payload */ if(!ecb->cipher(ecb, bp->rp + vers.hdrlen, payload)) { qunlock(c); print("esp: cipher failed %I -> %I!%ld: %s\n", vers.raddr, vers.laddr, vers.spi, m->externup->errstr); netlog(f, Logesp, "esp: cipher failed %I -> %I!%lud: %s\n", vers.raddr, vers.laddr, vers.spi, m->externup->errstr); freeb(bp); return; } payload -= Esptaillen; et = (Esptail*)(bp->rp + vers.hdrlen + payload); payload -= et->pad + ecb->espivlen; nexthdr = et->nexthdr; if(payload <= 0) { qunlock(c); netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%lud\n", vers.raddr, vers.laddr, vers.spi); freeb(bp); return; } /* trim packet */ bp->rp += vers.hdrlen + ecb->espivlen; /* toss original IP & ESP hdrs */ bp->wp = bp->rp + payload; if(ecb->header) { /* assume Userhdrlen < Esp4hdrlen < Esp6hdrlen */ bp->rp -= Userhdrlen; uh = (Userhdr*)bp->rp; memset(uh, 0, Userhdrlen); uh->nexthdr = nexthdr; } /* ingress filtering here? */ if(qfull(c->rq)){ netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", vers.raddr, vers.laddr, vers.spi); freeblist(bp); }else { // print("esp: pass up: %uld\n", BLEN(bp)); qpass(c->rq, bp); /* pass packet up the read queue */ } qunlock(c); }
void rudpiput(Proto *rudp, Ipifc *ifc, Block *bp) { int len, olen, ottl; Udphdr *uh; Conv *c; Rudpcb *ucb; uint8_t raddr[IPaddrlen], laddr[IPaddrlen]; uint16_t rport, lport; Rudppriv *upriv; Fs *f; uint8_t *p; upriv = rudp->priv; f = rudp->f; upriv->ustats.rudpInDatagrams++; uh = (Udphdr*)(bp->rp); /* Put back pseudo header for checksum * (remember old values for icmpnoconv()) */ ottl = uh->Unused; uh->Unused = 0; len = nhgets(uh->udplen); olen = nhgets(uh->udpplen); hnputs(uh->udpplen, len); v4tov6(raddr, uh->udpsrc); v4tov6(laddr, uh->udpdst); lport = nhgets(uh->udpdport); rport = nhgets(uh->udpsport); if(nhgets(uh->udpcksum)) { if(ptclcsum(bp, UDP_IPHDR, len+UDP_PHDRSIZE)) { upriv->ustats.rudpInErrors++; upriv->csumerr++; netlog(f, Logrudp, "rudp: checksum error %I\n", raddr); DPRINT("rudp: checksum error %I\n", raddr); freeblist(bp); return; } } qlock(&rudp->ql); c = iphtlook(&upriv->ht, raddr, rport, laddr, lport); if(c == nil){ /* no conversation found */ upriv->ustats.rudpNoPorts++; qunlock(&rudp->ql); netlog(f, Logudp, "udp: no conv %I!%d -> %I!%d\n", raddr, rport, laddr, lport); uh->Unused = ottl; hnputs(uh->udpplen, olen); icmpnoconv(f, bp); freeblist(bp); return; } ucb = (Rudpcb*)c->ptcl; qlock(&ucb->ql); qunlock(&rudp->ql); if(reliput(c, bp, raddr, rport) < 0){ qunlock(&ucb->ql); freeb(bp); return; } /* * Trim the packet down to data size */ len -= (UDP_RHDRSIZE-UDP_PHDRSIZE); bp = trimblock(bp, UDP_IPHDR+UDP_RHDRSIZE, len); if(bp == nil) { netlog(f, Logrudp, "rudp: len err %I.%d -> %I.%d\n", raddr, rport, laddr, lport); DPRINT("rudp: len err %I.%d -> %I.%d\n", raddr, rport, laddr, lport); upriv->lenerr++; return; } netlog(f, Logrudpmsg, "rudp: %I.%d -> %I.%d l %d\n", raddr, rport, laddr, lport, len); switch(ucb->headers){ case 7: /* pass the src address */ bp = padblock(bp, UDP_USEAD7); p = bp->rp; ipmove(p, raddr); p += IPaddrlen; ipmove(p, laddr); p += IPaddrlen; ipmove(p, ifc->lifc->local); p += IPaddrlen; hnputs(p, rport); p += 2; hnputs(p, lport); break; default: /* connection oriented rudp */ if(ipcmp(c->raddr, IPnoaddr) == 0){ /* save the src address in the conversation */ ipmove(c->raddr, raddr); c->rport = rport; /* reply with the same ip address (if not broadcast) */ if(ipforme(f, laddr) == Runi) ipmove(c->laddr, laddr); else v4tov6(c->laddr, ifc->lifc->local); } break; } if(bp->next) bp = concatblock(bp); if(qfull(c->rq)) { netlog(f, Logrudp, "rudp: qfull %I.%d -> %I.%d\n", raddr, rport, laddr, lport); freeblist(bp); } else qpass(c->rq, bp); qunlock(&ucb->ql); }
void rudpkick(void *x) { Proc *up = externup(); Conv *c = x; Udphdr *uh; uint16_t rport; uint8_t laddr[IPaddrlen], raddr[IPaddrlen]; Block *bp; Rudpcb *ucb; Rudphdr *rh; Reliable *r; int dlen, ptcllen; Rudppriv *upriv; Fs *f; upriv = c->p->priv; f = c->p->f; netlog(c->p->f, Logrudp, "rudp: kick\n"); bp = qget(c->wq); if(bp == nil) return; ucb = (Rudpcb*)c->ptcl; switch(ucb->headers) { case 7: /* get user specified addresses */ bp = pullupblock(bp, UDP_USEAD7); if(bp == nil) return; ipmove(raddr, bp->rp); bp->rp += IPaddrlen; ipmove(laddr, bp->rp); bp->rp += IPaddrlen; /* pick interface closest to dest */ if(ipforme(f, laddr) != Runi) findlocalip(f, laddr, raddr); bp->rp += IPaddrlen; /* Ignore ifc address */ rport = nhgets(bp->rp); bp->rp += 2+2; /* Ignore local port */ break; default: ipmove(raddr, c->raddr); ipmove(laddr, c->laddr); rport = c->rport; break; } dlen = blocklen(bp); /* Make space to fit rudp & ip header */ bp = padblock(bp, UDP_IPHDR+UDP_RHDRSIZE); if(bp == nil) return; uh = (Udphdr *)(bp->rp); uh->vihl = IP_VER4; rh = (Rudphdr*)uh; ptcllen = dlen + (UDP_RHDRSIZE-UDP_PHDRSIZE); uh->Unused = 0; uh->udpproto = IP_UDPPROTO; uh->frag[0] = 0; uh->frag[1] = 0; hnputs(uh->udpplen, ptcllen); switch(ucb->headers){ case 7: v6tov4(uh->udpdst, raddr); hnputs(uh->udpdport, rport); v6tov4(uh->udpsrc, laddr); break; default: v6tov4(uh->udpdst, c->raddr); hnputs(uh->udpdport, c->rport); if(ipcmp(c->laddr, IPnoaddr) == 0) findlocalip(f, c->laddr, c->raddr); v6tov4(uh->udpsrc, c->laddr); break; } hnputs(uh->udpsport, c->lport); hnputs(uh->udplen, ptcllen); uh->udpcksum[0] = 0; uh->udpcksum[1] = 0; qlock(&ucb->ql); r = relstate(ucb, raddr, rport, "kick"); r->sndseq = NEXTSEQ(r->sndseq); hnputl(rh->relseq, r->sndseq); hnputl(rh->relsgen, r->sndgen); hnputl(rh->relack, r->rcvseq); /* ACK last rcvd packet */ hnputl(rh->relagen, r->rcvgen); if(r->rcvseq != r->acksent) r->acksent = r->rcvseq; hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, dlen+UDP_RHDRSIZE)); relackq(r, bp); qunlock(&ucb->ql); upriv->ustats.rudpOutDatagrams++; DPRINT("sent: %lud/%lud, %lud/%lud\n", r->sndseq, r->sndgen, r->rcvseq, r->rcvgen); doipoput(c, f, bp, 0, c->ttl, c->tos); if(waserror()) { relput(r); qunlock(&r->lock); nexterror(); } /* flow control of sorts */ qlock(&r->lock); if(UNACKED(r) > Maxunacked){ r->blocked = 1; sleep(&r->vous, flow, r); r->blocked = 0; } qunlock(&r->lock); relput(r); poperror(); }
int main(int argc, char *argv[]){ unsigned short port; char *description = NULL; int connections = 0, listen_socket, *sockp; pthread_t commandThread; if (argc != 3) { fprintf(stderr, "Usage: %s <port> <self>\n", argv[0]); exit(EXIT_FAILURE); } port = atoi(argv[1]); self = argv[2]; if(iop_install_handler(SIGCHLD, 0, iop_netrequest_sigchild_handler) != 0){ netlog("iop_netrequest could not install signal handler"); exit(EXIT_FAILURE); } if(pthread_create(&commandThread, NULL, netrequest_cmd_thread, NULL)){ fprintf(stderr, "Could not spawn netrequest_cmd_thread thread\n"); return -1; } if(allocateListeningSocket(port, &listen_socket) != 1){ fprintf(stderr, "Couldn't listen on port %d\n", port); exit(EXIT_FAILURE); } netlog("Netrequest listening on port %d\n", port); while(1){ echofds net2Sys; pthread_t thrNet2Sys; description = NULL; netlog("Blocking on acceptSocket (connections = %d)\n", connections); sockp = acceptSocket(listen_socket, &description); connections++; netlog("Woken from acceptSocket: %s)\n", description); if (*sockp == INVALID_SOCKET) { netlog("%s", description); free(description); continue; } net2Sys.from = *sockp; net2Sys.to = STDOUT_FILENO; if(pthread_create(&thrNet2Sys, NULL, handleRequest, &net2Sys) != 0){ netlog("Couldn't create thrR2A thread\n"); } netlog("%s", description); free(sockp); free(description); } }
bool NetChannel::ProcessHeader(char* data, int size)//this processes the header of incoming packets { if (size < 4) { netlog("[NetChan] ERROR: Packet size too small!! Possible interference/corruption!\n"); return false;//bad packet } int rsequence = *(int*)&data[0]; int ack, ackbits; if (rsequence == -1) {//is OOB packet //do nothing with OOB packets return true; } else if (rsequence & (1 << ReliableFlagBit))//if reliable flag is set { if (size < 12) { netlog("[NetChan] ERROR: Packet size too small!! Possible interference/corruption!\n"); return false;//bad packet } //record that we got it rsequence &= ~(1 << ReliableFlagBit);//get rid of reliable flag rsequence &= ~(1 << FragmentFlagBit);//get rid of fragment flag rsequence &= ~(1 << OrderedFlagBit);//get rid of ordered flag int diff = sequence_difference(rsequence, this->recieved_sequence); if (diff > NumberWindows)//rsequence > this->recieved_sequence + NumberAcks + 1)//33) { netlog("[NetChan] ERROR: Incoming sequence number too high! Packet possibly corrupted!\n"); return false; } //lets fill acks if (diff > 0)//rsequence > this->recieved_sequence) { //int diff = rsequence - this->recieved_sequence; this->recieved_sequence = rsequence; //ok, roll down the bits for (int c = 0; c < diff; c++) { for (int i = 1; i < NumberAcks; i++) this->acks[i - 1] = this->acks[i]; if (c == 0) acks[NumberAcks - 1] = true; else acks[NumberAcks - 1] = false; } this->unsent_acks++; } else if (diff < 0)//rsequence < this->recieved_sequence) { //either old or recent int id = NumberAcks - sequence_difference(this->recieved_sequence, rsequence);// (this->recieved_sequence - rsequence); if (id >= 0) { if (this->acks[id]) return false;//we already acked this, dont do anything with it //netlogf("[NetCon] Got reliable resend packet %d\n", id); #ifdef NET_VERBOSE_DEBUG netlogf("[%s] Got reliable resend packet %d\n", this->server ? "Server" : "Client", rsequence); #endif this->unsent_acks++; this->acks[id] = true; } else { netlog("[NetCon] Got Superold Packet, dropping!\n"); return false;//we acked this long time ago, drop } } else return false;//we already acked it ack = *(int*)&data[4]; ackbits = *(int*)&data[8]; } else { if (size < 8) { netlog("[NetChan] ERROR: Packet size too small!! Possible interference/corruption!\n"); return false;//bad packet } ack = rsequence; ackbits = *(int*)&data[4]; //first 4, last received sequence //next 4 ack bits //next 4 size (can probably change to unsigned short) } this->ProcessAck(ack, ackbits); return true; }
void NetChannel::ProcessPacket(char* buffer, int recvsize, std::vector<Packet>& container) { NetMsg msg(2048, buffer); int rsequence = msg.ReadInt();//sequence int reliable = rsequence & (1 << ReliableFlagBit); bool shoulduse = this->ProcessHeader(buffer, recvsize); if (shoulduse == false) { netlog("[NetChan] Dropped packet, for any number of reasons!\n"); return; } if (rsequence == -1)//OOB { if (recvsize < 4) return;//bad packet #ifdef NET_VERBOSE_DEBUG netlogf("[%s] Got OOB packet\n", this->server ? "Server" : "Client"); #endif Packet p; p.size = recvsize - 4; p.data = new char[p.size]; memcpy(p.data, &buffer[4], p.size); container.push_back(p); } else if (reliable == false) { #ifdef NET_VERBOSE_DEBUG netlogf("[%s] Decoding Packet %d bytes\n", this->server ? "Server" : "Client", recvsize); #endif int ackbits = msg.ReadInt();//this is ackbits int ptr = 8;//points to size of sub-packet while (ptr < recvsize)//can have multiple packets { unsigned short packetsize = *(unsigned short*)&buffer[ptr]; //packetsize = msg.ReadInt(); if (packetsize & 1 << SplitFlagBit) { packetsize &= ~(1 << SplitFlagBit); //range check if (packetsize + 5 + ptr > recvsize) { netlog("[NetChan] ERROR: Got packetsize that is too large!! Malformed packet!!\n"); break; } NetMsg msg2 = NetMsg(2048, &buffer[ptr + 2]); unsigned char sequence = msg2.ReadByte(); unsigned char frag = msg2.ReadByte(); unsigned char numfrags = msg2.ReadByte(); #ifdef NET_VERBOSE_DEBUG netlogf(" Got unreliable split packet %d of %d\n", frag + 1, numfrags); #endif if (sequence == this->unreliable_fragment.sequence) { if (frag == this->unreliable_fragment.frags_recieved)//it is next packet in set { this->unreliable_fragment.frags_recieved++; //msg.ReadData(&this->unreliable_fragment.data[this->unreliable_fragment.curpos], packetsize); memcpy(&this->unreliable_fragment.data[this->unreliable_fragment.curpos], &buffer[ptr + 5], packetsize); this->unreliable_fragment.curpos += packetsize; } } else//make sure its newer { if (this->unreliable_fragment.data) delete[] this->unreliable_fragment.data; this->unreliable_fragment.data = new char[numfrags*NET_FRAGMENT_SIZE]; this->unreliable_fragment.sequence = sequence; this->unreliable_fragment.frags_recieved = 1; this->unreliable_fragment.curpos = packetsize; //msg.ReadData(this->unreliable_fragment.data, packetsize); memcpy(this->unreliable_fragment.data, &buffer[ptr + 5], packetsize); } ptr += 5 + packetsize; if (frag + 1 == numfrags) { //we should be done if (this->unreliable_fragment.frags_recieved == numfrags) { #ifdef NET_VERBOSE_DEBUG netlog(" Was final packet in split unreliable set.\n"); #endif //return this->unreliable_fragment.data; Packet p; p.reliable = false; p.size = this->unreliable_fragment.curpos; p.data = this->unreliable_fragment.data; this->unreliable_fragment.data = 0; container.push_back(p); } } } else { //range check if (packetsize + 2 + ptr > recvsize) { netlog("[NetChan] ERROR: Got packetsize that is too large!! Malformed packet!!\n"); break; } #ifdef NET_VERBOSE_DEBUG netlogf(" Got packet of %d bytes at %d\n", packetsize, ptr); #endif Packet p; p.reliable = false; p.size = packetsize; //msg.cursize += packetsize; p.data = new char[p.size]; memcpy(p.data, &buffer[ptr + 2], p.size); container.push_back(p); ptr += 2 + packetsize; } } } else//safe { //check if the packet is complete if fragmented rsequence &= ~(1 << ReliableFlagBit); if (rsequence & (1 << FragmentFlagBit)) { rsequence &= ~(1 << FragmentFlagBit);//remove the bit //check if we have whole packet, if not continue if (rsequence & 1 << OrderedFlagBit) { if (recvsize < 19) return;//bad packet rsequence &= ~(1 << OrderedFlagBit); unsigned char chan = *(unsigned char*)&buffer[12]; unsigned short seq = *(unsigned short*)&buffer[13]; int frag = *(unsigned short*)&buffer[15]; int numfrags = *(unsigned short*)&buffer[17]; if (frag + 1 > numfrags) { netlog("[NetChan] ERROR: Fragment number over maximum number of fragments for set!\n"); return; } else if (numfrags > NET_MAX_FRAGMENTS) { netlog("[NetChan] ERROR: Fragmented packet too large, over NET_MAX_FRAGMENTS!\n"); return; } #ifdef NET_VERBOSE_DEBUG netlogf("[Client] Got ordered reliable split packet %d of %d\n", frag + 1, numfrags); #endif //we need to copy data into a buffer int startseq = rsequence - frag; int frag_index = modulus(startseq, NumberReliableFragments); if (reliable_frags[frag_index].sequence == startseq) { reliable_frags[frag_index].frags_recieved += 1; } else { //delete the old one //if (reliable_frags[startseq%20].data) //delete[] reliable_frags[startseq%20].data; //first packet we got in the set reliable_frags[frag_index].num_frags = numfrags; reliable_frags[frag_index].frags_recieved = 1; reliable_frags[frag_index].data = new char[NET_FRAGMENT_SIZE*numfrags]; reliable_frags[frag_index].sequence = startseq; reliable_frags[frag_index].curpos = 0; } //ok, copy in the data memcpy(reliable_frags[frag_index].data + frag*NET_FRAGMENT_SIZE, &buffer[16 + 3], recvsize - 19); reliable_frags[frag_index].curpos += recvsize - 19; if (reliable_frags[frag_index].frags_recieved == numfrags) { #ifdef NET_VERBOSE_DEBUG netlog("[Client] We got the whole split reliable packet\n"); #endif Packet p; p.reliable = true; p.size = reliable_frags[frag_index].curpos;//frags_recieved*(FRAGMENT_SIZE-1) + (recvsize - 16);//reliable_frags[startseq%20].frags_recieved*FRAGMENT_SIZE;//approximate p.data = reliable_frags[frag_index].data; reliable_frags[frag_index].data = 0; if (this->incoming_ordered_sequence[chan] + 1 == seq) { this->incoming_ordered_sequence[chan]++; #ifdef NET_VERBOSE_DEBUG netlogf("Pushed ordered pack %d\n", incoming_ordered_sequence[chan]); #endif container.push_back(p); //check map to see if next packet is availible while (this->ordered_buffer[chan].find(this->incoming_ordered_sequence[chan] + 1) != this->ordered_buffer[chan].end()) { container.push_back(this->ordered_buffer[chan][this->incoming_ordered_sequence[chan] + 1]); this->ordered_buffer[chan].erase(this->ordered_buffer[chan].find(this->incoming_ordered_sequence[chan] + 1)); this->incoming_ordered_sequence[chan]++; #ifdef NET_VERBOSE_DEBUG netlogf("Pushed ordered pack %d\n", incoming_ordered_sequence[chan]); #endif } } else { //hold it for a while until we get packets before it this->ordered_buffer[chan][seq] = p; } } } else { if (recvsize < 16) return;//bad packet int frag = *(unsigned short*)&buffer[12]; int numfrags = *(unsigned short*)&buffer[14]; #ifdef NET_VERBOSE_DEBUG netlogf("[Client] Got reliable split packet %d of %d\n", frag + 1, numfrags); #endif //we need to copy data into a buffer int startseq = rsequence - frag; int frag_index = modulus(startseq, NumberReliableFragments); if (reliable_frags[frag_index].sequence == startseq) { reliable_frags[frag_index].frags_recieved += 1; } else { //delete the old one //if (reliable_frags[startseq%20].data) //delete[] reliable_frags[startseq%20].data; //first packet we got in the set reliable_frags[frag_index].frags_recieved = 1; reliable_frags[frag_index].data = new char[NET_FRAGMENT_SIZE*numfrags]; reliable_frags[frag_index].sequence = startseq; reliable_frags[frag_index].curpos = 0; } //ok, copy in the data memcpy(reliable_frags[frag_index].data + frag*NET_FRAGMENT_SIZE, &buffer[16], recvsize - 16); reliable_frags[frag_index].curpos += recvsize - 16; if (reliable_frags[frag_index].frags_recieved == numfrags) { #ifdef NET_VERBOSE_DEBUG netlog("[Client] We got the whole split reliable packet\n"); #endif Packet p; p.reliable = true; p.size = reliable_frags[frag_index].curpos;//frags_recieved*(FRAGMENT_SIZE-1) + (recvsize - 16);//reliable_frags[startseq%20].frags_recieved*FRAGMENT_SIZE;//approximate p.data = reliable_frags[frag_index].data; reliable_frags[frag_index].data = 0; container.push_back(p); } } } else//safe { if (rsequence & 1 << OrderedFlagBit) { if (recvsize < 15) return;//bad packet #ifdef NET_VERBOSE_DEBUG netlog("[NetChan] Got Ordered Reliable Packet\n"); #endif //size at 15 //chan at 12 //seq at 13 unsigned short seq = *(unsigned short*)&buffer[13]; unsigned char chan = *(unsigned char*)&buffer[12]; Packet p; p.reliable = true; p.size = recvsize - (14 + 1); //lets make copy p.data = new char[p.size]; memcpy(p.data, &buffer[14 + 1], p.size); if (this->incoming_ordered_sequence[chan] + 1 == seq) { this->incoming_ordered_sequence[chan]++; #ifdef NET_VERBOSE_DEBUG netlogf("Pushed ordered pack %d\n", incoming_ordered_sequence[chan]); #endif container.push_back(p); //check map to see if next packet is availible while (this->ordered_buffer[chan].find(this->incoming_ordered_sequence[chan] + 1) != this->ordered_buffer[chan].end()) { container.push_back(this->ordered_buffer[chan][this->incoming_ordered_sequence[chan] + 1]); this->ordered_buffer[chan].erase(this->ordered_buffer[chan].find(this->incoming_ordered_sequence[chan] + 1)); this->incoming_ordered_sequence[chan]++; #ifdef NET_VERBOSE_DEBUG netlogf("Pushed ordered pack %d\n", incoming_ordered_sequence[chan]); #endif } } else { #ifdef NET_VERBOSE_DEBUG netlogf("Got ordered pack %d\n", seq); #endif //hold it for a while until we get packets before it this->ordered_buffer[chan][seq] = p; } } else { if (recvsize < 12) return;//bad packet #ifdef NET_VERBOSE_DEBUG netlog("[Client] Got Reliable packet\n"); #endif //not split packet, or ordered Packet p; p.reliable = true; p.size = recvsize - 12; p.data = new char[p.size]; memcpy(p.data, &buffer[12], p.size); container.push_back(p); } } } };
int ipoput6(Fs *f, Block *bp, int gating, int ttl, int tos, Conv *c) { Proc *up = externup(); int medialen, len, chunk, uflen, flen, seglen, lid, offset, fragoff; int morefrags, blklen, rv = 0, tentative; uint8_t *gate, nexthdr; Block *xp, *nb; Fraghdr6 fraghdr; IP *ip; Ip6hdr *eh; Ipifc *ifc; Route *r, *sr; ip = f->ip; /* Fill out the ip header */ eh = (Ip6hdr*)(bp->rp); ip->stats[OutRequests]++; /* Number of uint8_ts in data and ip header to write */ len = blocklen(bp); tentative = iptentative(f, eh->src); if(tentative){ netlog(f, Logip, "reject tx of packet with tentative src address %I\n", eh->src); goto free; } if(gating){ chunk = nhgets(eh->ploadlen); if(chunk > len){ ip->stats[OutDiscards]++; netlog(f, Logip, "short gated packet\n"); goto free; } if(chunk + IP6HDR < len) len = chunk + IP6HDR; } if(len >= IP_MAX){ ip->stats[OutDiscards]++; netlog(f, Logip, "exceeded ip max size %I\n", eh->dst); goto free; } r = v6lookup(f, eh->dst, c); if(r == nil){ // print("no route for %I, src %I free\n", eh->dst, eh->src); ip->stats[OutNoRoutes]++; netlog(f, Logip, "no interface %I\n", eh->dst); rv = -1; goto free; } ifc = r->RouteTree.ifc; if(r->RouteTree.type & (Rifc|Runi)) gate = eh->dst; else if(r->RouteTree.type & (Rbcast|Rmulti)) { gate = eh->dst; sr = v6lookup(f, eh->src, nil); if(sr && (sr->RouteTree.type & Runi)) ifc = sr->RouteTree.ifc; } else gate = r->v6.gate; if(!gating) eh->vcf[0] = IP_VER6; eh->ttl = ttl; if(!gating) { eh->vcf[0] |= tos >> 4; eh->vcf[1] = tos << 4; }
void espiput(Proto *esp, Ipifc*, Block *bp) { Esphdr *eh; Esptail *et; Userhdr *uh; Conv *c; Espcb *ecb; uchar raddr[IPaddrlen], laddr[IPaddrlen]; Fs *f; uchar *auth; ulong spi; int payload, nexthdr; f = esp->f; bp = pullupblock(bp, EsphdrSize+EsptailSize); if(bp == nil) { netlog(f, Logesp, "esp: short packet\n"); return; } eh = (Esphdr*)(bp->rp); spi = nhgetl(eh->espspi); v4tov6(raddr, eh->espsrc); v4tov6(laddr, eh->espdst); qlock(esp); /* Look for a conversation structure for this port */ c = convlookup(esp, spi); if(c == nil) { qunlock(esp); netlog(f, Logesp, "esp: no conv %I -> %I!%d\n", raddr, laddr, spi); icmpnoconv(f, bp); freeblist(bp); return; } qlock(c); qunlock(esp); ecb = c->ptcl; // too hard to do decryption/authentication on block lists if(bp->next) bp = concatblock(bp); if(BLEN(bp) < EsphdrSize + ecb->espivlen + EsptailSize + ecb->ahlen) { qunlock(c); netlog(f, Logesp, "esp: short block %I -> %I!%d\n", raddr, laddr, spi); freeb(bp); return; } eh = (Esphdr*)(bp->rp); auth = bp->wp - ecb->ahlen; if(!ecb->auth(ecb, eh->espspi, auth-eh->espspi, auth)) { qunlock(c); print("esp: bad auth %I -> %I!%ld\n", raddr, laddr, spi); netlog(f, Logesp, "esp: bad auth %I -> %I!%d\n", raddr, laddr, spi); freeb(bp); return; } payload = BLEN(bp)-EsphdrSize-ecb->ahlen; if(payload<=0 || payload%4 != 0 || payload%ecb->espblklen!=0) { qunlock(c); netlog(f, Logesp, "esp: bad length %I -> %I!%d payload=%d BLEN=%d\n", raddr, laddr, spi, payload, BLEN(bp)); freeb(bp); return; } if(!ecb->cipher(ecb, bp->rp+EsphdrSize, payload)) { qunlock(c); print("esp: cipher failed %I -> %I!%ld: %r\n", raddr, laddr, spi); netlog(f, Logesp, "esp: cipher failed %I -> %I!%d: %r\n", raddr, laddr, spi); freeb(bp); return; } payload -= EsptailSize; et = (Esptail*)(bp->rp + EsphdrSize + payload); payload -= et->pad + ecb->espivlen; nexthdr = et->nexthdr; if(payload <= 0) { qunlock(c); netlog(f, Logesp, "esp: short packet after decrypt %I -> %I!%d\n", raddr, laddr, spi); freeb(bp); return; } // trim packet bp->rp += EsphdrSize + ecb->espivlen; bp->wp = bp->rp + payload; if(ecb->header) { // assume UserhdrSize < EsphdrSize bp->rp -= UserhdrSize; uh = (Userhdr*)bp->rp; memset(uh, 0, UserhdrSize); uh->nexthdr = nexthdr; } if(qfull(c->rq)){ netlog(f, Logesp, "esp: qfull %I -> %I.%uld\n", raddr, laddr, spi); freeblist(bp); }else { //print("esp: pass up: %uld\n", BLEN(bp)); qpass(c->rq, bp); } qunlock(c); }