コード例 #1
0
ファイル: iop_netrequest.c プロジェクト: SRI-CSL/iopc
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;
}
コード例 #2
0
ファイル: esp.c プロジェクト: npe9/harvey
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;
}
コード例 #3
0
ファイル: pppmedium.c プロジェクト: alfongj/akaros
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();
	}
}
コード例 #4
0
ファイル: igmp.c プロジェクト: 99years/plan9
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 */
}
コード例 #5
0
ファイル: iop_netrequest.c プロジェクト: SRI-CSL/iopc
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;
}
コード例 #6
0
ファイル: udp.c プロジェクト: dhootha/akaros
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);

}
コード例 #7
0
ファイル: udp.c プロジェクト: dhootha/akaros
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++;
}
コード例 #8
0
ファイル: igmp.c プロジェクト: 99years/plan9
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);
}
コード例 #9
0
ファイル: esp.c プロジェクト: npe9/harvey
/*
 * 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);
}
コード例 #10
0
ファイル: rudp.c プロジェクト: Shamar/harvey
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);
}
コード例 #11
0
ファイル: rudp.c プロジェクト: Shamar/harvey
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();
}
コード例 #12
0
ファイル: iop_netrequest.c プロジェクト: SRI-CSL/iopc
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);
  }
}
コード例 #13
0
ファイル: NetChannel.cpp プロジェクト: matt-attack/netlibrary
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;
}
コード例 #14
0
ファイル: NetChannel.cpp プロジェクト: matt-attack/netlibrary
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);
			}
		}
	}
};
コード例 #15
0
ファイル: ipv6.c プロジェクト: Shamar/harvey
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;
	}
コード例 #16
0
ファイル: esp.c プロジェクト: 8l/inferno
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);
}