Пример #1
0
Файл: ipif.c Проект: 8l/inferno
int
so_send(int sock, void *va, int len, void *hdr, int hdrlen)
{
	int r;
	struct sockaddr sa;
	struct sockaddr_in *sin;
	uchar *h = hdr;


	osenter();
	if(hdr == 0)
		r = send(sock, va, len, 0);
	else {
		memset(&sa, 0, sizeof(sa));
		sin = (struct sockaddr_in*)&sa;
		sin->sin_family = AF_INET;
		switch(hdrlen){
		case OUdphdrlenv4:
			memmove(&sin->sin_addr, h,  4);
			memmove(&sin->sin_port, h+8, 2);
			break;
		case OUdphdrlen:
			v6tov4((uchar*)&sin->sin_addr, h);
			memmove(&sin->sin_port, h+2*IPaddrlen, 2);	/* rport */
			break;
		default:
			v6tov4((uchar*)&sin->sin_addr, h);
			memmove(&sin->sin_port, h+3*IPaddrlen, 2);
			break;
		}
		r = sendto(sock, va, len, 0, &sa, sizeof(sa));
	}
	osleave();
	return r;
}
Пример #2
0
void
dhcpsend(int type)
{
	int n;
	uint8_t *p;
	Bootp bp;
	Udphdr *up;

	memset(&bp, 0, sizeof bp);
	up = (Udphdr*)bp.udphdr;

	hnputs(up->rport, 67);
	bp.op = Bootrequest;
	hnputl(bp.xid, dhcp.xid);
	hnputs(bp.secs, time(0) - dhcp.starttime);
	hnputs(bp.flags, Fbroadcast);		/* reply must be broadcast */
	memmove(bp.optmagic, optmagic, 4);
	p = bp.optdata;
	p = optaddbyte(p, ODtype, type);
	p = optadd(p, ODclientid, dhcp.cid, strlen(dhcp.cid));
	switch(type) {
	default:
		myfatal("dhcpsend: unknown message type: %d", type);
	case Discover:
		ipmove(up->raddr, IPv4bcast);	/* broadcast */
		break;
	case Request:
		if(dhcp.state == Sbound || dhcp.state == Srenewing)
			ipmove(up->raddr, dhcp.server);
		else
			ipmove(up->raddr, IPv4bcast);	/* broadcast */
		p = optaddulong(p, ODlease, dhcp.lease);
		if(dhcp.state == Sselecting || dhcp.state == Srequesting) {
			p = optaddaddr(p, ODipaddr, dhcp.client);	/* mistake?? */
			p = optaddaddr(p, ODserverid, dhcp.server);
		} else
			v6tov4(bp.ciaddr, dhcp.client);
		break;
	case Release:
		ipmove(up->raddr, dhcp.server);
		v6tov4(bp.ciaddr, dhcp.client);
		p = optaddaddr(p, ODipaddr, dhcp.client);
		p = optaddaddr(p, ODserverid, dhcp.server);
		break;
	}

	*p++ = OBend;

	n = p - (uint8_t*)&bp;

	if(write(dhcp.fd, &bp, n) != n)
		myfatal("dhcpsend: write failed: %r");
}
Пример #3
0
void
relsendack(Conv *c, Reliable *r, int hangup)
{
	Udphdr *uh;
	Block *bp;
	Rudphdr *rh;
	int ptcllen;
	Fs *f;

	bp = allocb(UDP_IPHDR + UDP_RHDRSIZE);
	if(bp == nil)
		return;
	bp->wp += UDP_IPHDR + UDP_RHDRSIZE;
	f = c->p->f;
	uh = (Udphdr *)(bp->rp);
	uh->vihl = IP_VER4;
	rh = (Rudphdr*)uh;

	ptcllen = (UDP_RHDRSIZE-UDP_PHDRSIZE);
	uh->Unused = 0;
	uh->udpproto = IP_UDPPROTO;
	uh->frag[0] = 0;
	uh->frag[1] = 0;
	hnputs(uh->udpplen, ptcllen);

	v6tov4(uh->udpdst, r->addr);
	hnputs(uh->udpdport, r->port);
	hnputs(uh->udpsport, c->lport);
	if(ipcmp(c->laddr, IPnoaddr) == 0)
		findlocalip(f, c->laddr, c->raddr);
	v6tov4(uh->udpsrc, c->laddr);
	hnputs(uh->udplen, ptcllen);

	if(hangup)
		hnputl(rh->relsgen, Hangupgen);
	else
		hnputl(rh->relsgen, r->sndgen);
	hnputl(rh->relseq, 0);
	hnputl(rh->relagen, r->rcvgen);
	hnputl(rh->relack, r->rcvseq);

	if(r->acksent < r->rcvseq)
		r->acksent = r->rcvseq;

	uh->udpcksum[0] = 0;
	uh->udpcksum[1] = 0;
	hnputs(uh->udpcksum, ptclcsum(bp, UDP_IPHDR, UDP_RHDRSIZE));

	DPRINT("sendack: %lud/%lud, %lud/%lud\n", 0L, r->sndgen, r->rcvseq, r->rcvgen);
	doipoput(c, f, bp, 0, c->ttl, c->tos);
}
Пример #4
0
uint8_t *
optaddaddr(uint8_t *p, int op, uint8_t *ip)
{
	p[0] = op;
	p[1] = 4;
	v6tov4(p+2, ip);
	return p+6;
}
Пример #5
0
Файл: rip.c Проект: aahud/harvey
void
readifcs(void)
{
	Ipifc *ifc;
	Iplifc *lifc;
	Ifc *ip;
	Bnet *bn;
	Route route;
	int i;

	ifcs = readipifc(netdir, ifcs, -1);
	i = 0;
	for(ifc = ifcs; ifc != nil; ifc = ifc->next){
		for(lifc = ifc->lifc; lifc != nil && i < Nifc; lifc = lifc->next){
			// ignore any interfaces that aren't v4
			if(memcmp(lifc->ip, v4prefix, IPaddrlen-IPv4addrlen) != 0)
				continue;
			ip = &ialloc.ifc[i++];
			v6tov4(ip->addr, lifc->ip);
			v6tov4mask(ip->mask, lifc->mask);
			v6tov4(ip->net, lifc->net);
			ip->cmask = v4defmask(ip->net);
			v4maskip(ip->net, ip->cmask, ip->cnet);
			ip->bcast = 0;

			/* add as a route */
			memmove(route.mask, ip->mask, Pasize);
			memmove(route.dest, ip->net, Pasize);
			memset(route.gate, 0, Pasize);
			route.metric = 0;
			considerroute(&route);

			/* mark as broadcast */
			if(bnets == 0)
				ip->bcast = 1;
			else for(bn = bnets; bn; bn = bn->next)
				if(memcmp(bn->addr, ip->net, Pasize) == 0){
					ip->bcast = 1;
					break;
				}
		}
	}
	ialloc.nifc = i;
}
Пример #6
0
int
str2addr(char *s, uchar *a)
{
	uchar *a0, ip[16];
	char *p;

	if((s = strchr(s, '!')) == nil)
		return 0;
	if((p = strchr(++s, '!')) == nil)
		return 0;
	if(strchr(++p, '!') != nil)
		return 0;
	if(parseip(ip, s) == -1)
		return 0;

	a0 = a;
	if(socksver == 4){
		a += 2;
		hnputs(a, atoi(p));
		a += 2;
		v6tov4(a, ip);
		a += 4;
	} else {
		a += 3;
		if(isv4(ip)){
			*a++ = 0x01;
			v6tov4(a, ip);
			a += 4;
		} else {
			*a++ = 0x04;
			memmove(a, ip, 16);
			a += 16;
		}
		hnputs(a, atoi(p));
		a += 2;
	}
	return a - a0;
}
Пример #7
0
void
so_connect(int fd, unsigned char *raddr, unsigned short rport)
{
	struct sockaddr_storage ss;

	memset(&ss, 0, sizeof(ss));

	ss.ss_family = family(raddr);

	switch(ss.ss_family){
	case AF_INET:
		hnputs(&((struct sockaddr_in*)&ss)->sin_port, rport);
		v6tov4((unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr, raddr);
		break;
	case AF_INET6:
		hnputs(&((struct sockaddr_in6*)&ss)->sin6_port, rport);
		memcpy(&((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, raddr, sizeof(struct in6_addr));
		break;
	}

	if(connect(fd, (struct sockaddr*)&ss, addrlen(&ss)) < 0)
		oserror();
}
Пример #8
0
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++;
}
Пример #9
0
Файл: esp.c Проект: npe9/harvey
/*
 * encapsulate next IP packet on x's write queue in IP/ESP packet
 * and initiate output of the result.
 */
static void
espkick(void *x)
{
	int nexthdr, payload, pad, align;
	uint8_t *auth;
	Block *bp;
	Conv *c = x;
	Esp4hdr *eh4;
	Esp6hdr *eh6;
	Espcb *ecb;
	Esptail *et;
	Userhdr *uh;
	Versdep vers;

	getverslens(convipvers(c), &vers);
	bp = qget(c->wq);
	if(bp == nil)
		return;

	qlock(c);
	ecb = c->ptcl;

	if(ecb->header) {
		/* make sure the message has a User header */
		bp = pullupblock(bp, Userhdrlen);
		if(bp == nil) {
			qunlock(c);
			return;
		}
		uh = (Userhdr*)bp->rp;
		nexthdr = uh->nexthdr;
		bp->rp += Userhdrlen;
	} else {
		nexthdr = 0;	/* what should this be? */
	}

	payload = BLEN(bp) + ecb->espivlen;

	/* Make space to fit ip header */
	bp = padblock(bp, vers.hdrlen + ecb->espivlen);
	getpktspiaddrs(bp->rp, &vers);

	align = 4;
	if(ecb->espblklen > align)
		align = ecb->espblklen;
	if(align % ecb->ahblklen != 0)
		panic("espkick: ahblklen is important after all");
	pad = (align-1) - (payload + Esptaillen-1)%align;

	/*
	 * Make space for tail
	 * this is done by calling padblock with a negative size
	 * Padblock does not change bp->wp!
	 */
	bp = padblock(bp, -(pad+Esptaillen+ecb->ahlen));
	bp->wp += pad+Esptaillen+ecb->ahlen;

	et = (Esptail*)(bp->rp + vers.hdrlen + payload + pad);

	/* fill in tail */
	et->pad = pad;
	et->nexthdr = nexthdr;

	/* encrypt the payload */
	ecb->cipher(ecb, bp->rp + vers.hdrlen, payload + pad + Esptaillen);
	auth = bp->rp + vers.hdrlen + payload + pad + Esptaillen;

	/* fill in head; construct a new IP header and an ESP header */
	if (vers.version == V4) {
		eh4 = (Esp4hdr *)bp->rp;
		eh4->vihl = IP_VER4;
		v6tov4(eh4->espsrc, c->laddr);
		v6tov4(eh4->espdst, c->raddr);
		eh4->espproto = IP_ESPPROTO;
		eh4->frag[0] = 0;
		eh4->frag[1] = 0;

		hnputl(eh4->espspi, ecb->spi);
		hnputl(eh4->espseq, ++ecb->seq);
	} else {
		eh6 = (Esp6hdr *)bp->rp;
		eh6->vcf[0] = IP_VER6;
		ipmove(eh6->src, c->laddr);
		ipmove(eh6->dst, c->raddr);
		eh6->proto = IP_ESPPROTO;

		hnputl(eh6->espspi, ecb->spi);
		hnputl(eh6->espseq, ++ecb->seq);
	}

	/* compute secure hash */
	ecb->auth(ecb, bp->rp + vers.iphdrlen, (vers.hdrlen - vers.iphdrlen) +
		payload + pad + Esptaillen, auth);

	qunlock(c);
	/* print("esp: pass down: %uld\n", BLEN(bp)); */
	if (vers.version == V4)
		ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
	else
		ipoput6(c->p->f, bp, 0, c->ttl, c->tos, c);
}
Пример #10
0
int
so_recv(int sock, void *va, int len, void *hdr, int hdrlen)
{
	int r, l;
	struct sockaddr_storage sa;
	struct sockaddr_in6 *sin6;
	char h[Udphdrlen];

	osenter();
	if(hdr == 0)
		r = read(sock, va, len);
	else {
		sin6 = (struct sockaddr_in6*)&sa;
		l = sizeof(sa);
		r = recvfrom(sock, va, len, 0, (struct sockaddr*)&sa, &l);
		if(r >= 0) {
			memset(h, 0, sizeof(h));
			switch(hdrlen){
			case OUdphdrlenv4:
				if(v6tov4(h, (uchar*)&sin6->sin6_addr) < 0) {
					osleave();
					error("OUdphdrlenv4 with IPv6 address");
				}
				memmove(h+2*IPv4addrlen, &sin6->sin6_port, 2);
				break;
			case OUdphdrlen:
				memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen);
				memmove(h+2*IPaddrlen, &sin6->sin6_port, 2);
				break;
			default:
				memmove(h, (uchar*)&sin6->sin6_addr, IPaddrlen);
				memmove(h+3*IPaddrlen, &sin6->sin6_port, 2);
				break;
			}

			/* alas there's no way to get the local addr/port correctly.  Pretend. */
			memset(&sa, 0, sizeof(sa));
			l = sizeof(sa);
			getsockname(sock, (struct sockaddr*)&sa, &l);
			switch(hdrlen){
			case OUdphdrlenv4:
				/*
				 * we get v6Unspecified/noaddr if local address cannot be determined.
				 * that's reasonable for ipv4 too.
				 */
				if(ipcmp(v6Unspecified, (uchar*)&sin6->sin6_addr) != 0
				&& v6tov4(h+IPv4addrlen, (uchar*)&sin6->sin6_addr) < 0) {
					osleave();
					error("OUdphdrlenv4 with IPv6 address");
				}
				memmove(h+2*IPv4addrlen+2, &sin6->sin6_port, 2);
				break;
			case OUdphdrlen:
				memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen);
				memmove(h+2*IPaddrlen+2, &sin6->sin6_port, 2);
				break;
			default:
				memmove(h+IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen);
				memmove(h+2*IPaddrlen, (uchar*)&sin6->sin6_addr, IPaddrlen);	/* ifcaddr */
				memmove(h+3*IPaddrlen+2, &sin6->sin6_port, 2);
				break;
			}
			memmove(hdr, h, hdrlen);
		}
	}
	osleave();
	return r;
}
Пример #11
0
void
sender(int fd, int msglen, int interval, int n)
{
	int i, extra;
	uint16_t seq;
	char *buf = malloc(BUFSIZE);
	uint8_t me[IPaddrlen], mev4[IPv4addrlen];
	struct icmphdr *icmp;
	Req *r;

	firstseq = seq = rand();

	icmp = geticmp(buf);
	memset(buf, 0, proto->iphdrsz + ICMP_HDRSIZE);
	for(i = proto->iphdrsz + ICMP_HDRSIZE; i < msglen; i++)
		buf[i] = i;
	icmp->type = proto->echocmd;
	icmp->code = 0;

	/* arguably the kernel should fill in the right src addr. */
	myipvnaddr(me, proto, network);
	if (proto->version == 4) {
		v6tov4(mev4, me);
		memmove(((struct ip4hdr *)buf)->src, mev4, IPv4addrlen);
	} else
		ipmove(((struct ip6hdr *)buf)->src, me);
	if (addresses)
		printf("\t%i -> %s\n", me, target);

	if(pingrint != 0 && interval <= 0)
		pingrint = 0;
	extra = 0;
	for(i = 0; i < n; i++){
		if(i != 0){
			if(pingrint != 0)
				extra = rand();
			/* uth_sleep takes seconds, interval is in ms */
			uthread_usleep((interval + extra) * 1000);
		}
		r = calloc(sizeof *r, 1);
		if (r == NULL){
			printf("out of memory? \n");
			break;
		}
		hnputs(icmp->seq, seq);
		r->seq = seq;
		r->next = NULL;
		r->replied = 0;
		r->tsctime = read_tsc();	/* avoid early free in reply! */
		spin_pdr_lock(&listlock);
		if(first == NULL)
			first = r;
		else
			last->next = r;
		last = r;
		spin_pdr_unlock(&listlock);
		r->tsctime = read_tsc();
		if(write(fd, buf, msglen) < msglen){
			fprintf(stderr, "%s: write failed: %r\n", argv0);
			return;
		}
		seq++;
	}
	done = 1;
}
Пример #12
0
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();
}
Пример #13
0
int
udprelay(int fd, char *dir)
{
	struct {
		Udphdr;
		uchar data[8*1024];
	} msg;
	char addr[128], ldir[40];
	int r, n, rfd, cfd;
	uchar *p;

	snprint(addr, sizeof(addr), "%s/udp!*!0", outside);
	if((cfd = announce(addr, ldir)) < 0)
		return -1;
	if(write(cfd, "headers", 7) != 7)
		return -1;
	strcat(ldir, "/data");
	if((rfd = open(ldir, ORDWR)) < 0)
		return -1;
	close(cfd);
	
	if((r = rfork(RFMEM|RFPROC|RFNOWAIT)) <= 0)
		return r;

	if((cfd = listen(dir, ldir)) < 0)
		return -1;
	close(fd);	/* close inside udp server */
	if((fd = accept(cfd, ldir)) < 0)
		return -1;

	switch(rfork(RFMEM|RFPROC|RFNOWAIT)){
	case -1:
		return -1;
	case 0:
		while((r = read(fd, msg.data, sizeof(msg.data))) > 0){
			if(r < 4)
				continue;
			p = msg.data;
			if(p[0] | p[1] | p[2])
				continue;
			p += 3;
			switch(*p++){
			default:
				continue;
			case 0x01:
				r -= 2+1+1+4+2;
				if(r < 0)
					continue;
				v4tov6(msg.raddr, p);
				p += 4;
				break;
			case 0x04:
				r -= 2+1+1+16+2;
				if(r < 0)
					continue;
				memmove(msg.raddr, p, 16);
				p += 16;
				break;
			}
			memmove(msg.rport, p, 2);
			p += 2;
			memmove(msg.data, p, r);
			write(rfd, &msg, sizeof(Udphdr)+r);
		}
		break;
	default:
		while((r = read(rfd, &msg, sizeof(msg))) > 0){
			r -= sizeof(Udphdr);
			if(r < 0)
				continue;
			p = msg.data;
			if(isv4(msg.raddr))
				n = 2+1+1+4+2;
			else
				n = 2+1+1+16+2;
			if(r+n > sizeof(msg.data))
				r = sizeof(msg.data)-n;
			memmove(p+n, p, r);
			*p++ = 0;
			*p++ = 0;
			*p++ = 0;
			if(isv4(msg.raddr)){
				*p++ = 0x01;
				v6tov4(p, msg.raddr);
				p += 4;
			} else {
				*p++ = 0x04;
				memmove(p, msg.raddr, 16);
				p += 16;
			}
			memmove(p, msg.rport, 2);
			r += n;
			write(fd, msg.data, r);
		}
	}
	return -1;
}
Пример #14
0
Файл: rip.c Проект: aahud/harvey
void
main(int argc, char *argv[])
{
	int dobroadcast, i, n;
	long diff;
	char *p;
	char buf[2*1024];
	uint8_t raddr[Pasize];
	Bnet *bn, **l;
	Udphdr *up;
	Rip *r;
	Ripmsg *m;
	Route route;
	static long btime;

	setnetmtpt(netdir, sizeof(netdir), nil);
	dobroadcast = 0;
	ARGBEGIN{
	case 'b':
		dobroadcast++;
		break;
	case 'd':
		debug++;
		break;
	case 'n':
		readonly++;
		break;
	case 'x':
		p = ARGF();
		if(p == nil)
			usage();
		setnetmtpt(netdir, sizeof(netdir), p);
		break;
	default:
		usage();
	}ARGEND

	/* specific broadcast nets */
	l = &bnets;
	while(argc > 0){
		bn = (Bnet*)malloc(sizeof(Bnet));
		if(bn == 0)
			fatal(1, "out of mem");
		v4parseip(bn->addr, *argv);
		*l = bn;
		l = &bn->next;
		argc--;
		argv++;
		dobroadcast++;
	}

	/* command returns */
	if(!debug)
		switch(rfork(RFNOTEG|RFPROC|RFFDG|RFNOWAIT)) {
		case -1:
			fatal(1, "fork");
		case 0:
			break;
		default:
			exits(0);
		}


	fmtinstall('E', eipfmt);
	fmtinstall('V', eipfmt);

	snprint(routefile, sizeof(routefile), "%s/iproute", netdir);
	snprint(buf, sizeof(buf), "%s/iproute", netdir);

	now = time(0);
	readifcs();
	readroutes();

	notify(ding);

	ripfd = openport();
	for(;;) {
		diff = btime - time(0);
		if(diff <= 0){
			if(dobroadcast)
				broadcast();
			timeoutroutes();

			btime = time(0) + 2*60;
			diff = 2*60;
		}
		alarm(diff*1000);
		n = read(ripfd, buf, sizeof(buf));
		alarm(0);
		if(n <= 0)
			continue;

		n = (n - Udphdrsize - 4) / sizeof(Rip);
		if(n <= 0)
			continue;

		up = (Udphdr*)buf;
		m = (Ripmsg*)(buf+Udphdrsize);
		if(m->type != Response || m->vers != Version)
			continue;
		v6tov4(raddr, up->raddr);

		/* ignore our own messages */
		for(i = 0; i < ialloc.nifc; i++)
			if(equivip(ialloc.ifc[i].addr, raddr))
				continue;

		now = time(0);
		for(r = m->rip; r < &m->rip[n]; r++){
			memmove(route.gate, raddr, Pasize);
			memmove(route.mask, getmask(r->addr), Pasize);
			v4maskip(r->addr, route.mask, route.dest);
			route.metric = nhgetl(r->metric) + 1;
			if(route.metric < 1)
				continue;
			considerroute(&route);
		}
	}
	/* not reached */
}
Пример #15
0
Файл: esp.c Проект: 8l/inferno
static void
espkick(void *x)
{
	Conv *c = x;
	Esphdr *eh;
	Esptail *et;
	Userhdr *uh;
	Espcb *ecb;
	Block *bp;
	int nexthdr;
	int payload;
	int pad;
	int align;
	uchar *auth;

	bp = qget(c->wq);
	if(bp == nil)
		return;

	qlock(c);
	ecb = c->ptcl;

	if(ecb->header) {
		/* make sure the message has a User header */
		bp = pullupblock(bp, UserhdrSize);
		if(bp == nil) {
			qunlock(c);
			return;
		}
		uh = (Userhdr*)bp->rp;
		nexthdr = uh->nexthdr;
		bp->rp += UserhdrSize;
	} else {
		nexthdr = 0;  // what should this be?
	}

	payload = BLEN(bp) + ecb->espivlen;

	/* Make space to fit ip header */
	bp = padblock(bp, EsphdrSize + ecb->espivlen);

	align = 4;
	if(ecb->espblklen > align)
		align = ecb->espblklen;
	if(align % ecb->ahblklen != 0)
		panic("espkick: ahblklen is important after all");
	pad = (align-1) - (payload + EsptailSize-1)%align;

	/*
	 * Make space for tail
	 * this is done by calling padblock with a negative size
	 * Padblock does not change bp->wp!
	 */
	bp = padblock(bp, -(pad+EsptailSize+ecb->ahlen));
	bp->wp += pad+EsptailSize+ecb->ahlen;

	eh = (Esphdr *)(bp->rp);
	et = (Esptail*)(bp->rp + EsphdrSize + payload + pad);

	// fill in tail
	et->pad = pad;
	et->nexthdr = nexthdr;

	ecb->cipher(ecb, bp->rp+EsphdrSize, payload+pad+EsptailSize);
	auth = bp->rp + EsphdrSize + payload + pad + EsptailSize;

	// fill in head
	eh->vihl = IP_VER4;
	hnputl(eh->espspi, ecb->spi);
	hnputl(eh->espseq, ++ecb->seq);
	v6tov4(eh->espsrc, c->laddr);
	v6tov4(eh->espdst, c->raddr);
	eh->espproto = IP_ESPPROTO;
	eh->frag[0] = 0;
	eh->frag[1] = 0;

	ecb->auth(ecb, bp->rp+IphdrSize, (EsphdrSize-IphdrSize)+payload+pad+EsptailSize, auth);

	qunlock(c);
	//print("esp: pass down: %uld\n", BLEN(bp));
	ipoput4(c->p->f, bp, 0, c->ttl, c->tos, c);
}