Пример #1
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);
}
Пример #2
0
long
ipread(Chan *ch, void *a, long n, vlong offset)
{
	int r;
	Conv *c;
	Proto *x;
	uchar ip[4];
	char buf[128], *p;

/*print("ipread %s %lux\n", c2name(ch), (long)ch->qid.path);*/
	p = a;
	switch(TYPE(ch->qid)) {
	default:
		error(Eperm);
	case Qcs:
		return csread(ch, a, n, offset);
	case Qprotodir:
	case Qtopdir:
	case Qconvdir:
		return devdirread(ch, a, n, 0, 0, ipgen);
	case Qctl:
		sprint(buf, "%d", CONV(ch->qid));
		return readstr(offset, p, n, buf);
	case Qremote:
		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
		hnputl(ip, c->raddr);
		sprint(buf, "%I!%d\n", ip, c->rport);
		return readstr(offset, p, n, buf);
	case Qlocal:
		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
		hnputl(ip, c->laddr);
		sprint(buf, "%I!%d\n", ip, c->lport);
		return readstr(offset, p, n, buf);
	case Qstatus:
		x = &proto[PROTO(ch->qid)];
		c = x->conv[CONV(ch->qid)];
		sprint(buf, "%s/%d %d %s \n",
			c->p->name, c->x, c->r.ref, c->state);
		return readstr(offset, p, n, buf);
	case Qdata:
		c = proto[PROTO(ch->qid)].conv[CONV(ch->qid)];
		r = so_recv(c->sfd, a, n, 0);
		if(r < 0){
			oserrstr();
			nexterror();
		}
		return r;
	}
}
Пример #3
0
static int
hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd)
{
	int i;
	Devlink *l;

	l = pickdevlink(d);
	i = pickea(l);
	if(i == -1){
		downdev(d, "resend fails; no netlink/ea");
		return -1;
	}
	if(f->srb && sys->ticks - f->srb->ticksent > Srbtimeout){
		eventlog("%æ: srb timeout\n", d);
		frameerror(d, f, Etimedout);
		return -1;
	}
	memmove(h->dst, l->eatab[i], Eaddrlen);
	memmove(h->src, l->nl->ea, sizeof h->src);
	hnputs(h->type, Aoetype);
	h->verflag = Aoever << 4;
	h->error = 0;
	hnputs(h->major, d->major);
	h->minor = d->minor;
	h->cmd = cmd;

	hnputl(h->tag, f->tag = newtag(d));
	f->dl = l;
	f->nl = l->nl;
	f->eaidx = i;
	f->ticksent = sys->ticks;

	return f->tag;
}
Пример #4
0
SmbProcessResult
smbresponsesend(SmbSession *s)
{
	uchar cmd;
	SmbProcessResult pr;

	assert(smbbufferoffsetgetb(s->response, 4, &cmd));
smbloglock();
smblogprint(cmd, "sending:\n");
smblogdata(cmd, smblogprint, smbbufferreadpointer(s->response), smbbufferreadspace(s->response), 256);
smblogunlock();
	if (s->nbss) {
		NbScatterGather a[2];
		a[0].p = smbbufferreadpointer(s->response);
		a[0].l = smbbufferreadspace(s->response);
		a[1].p = nil;
		nbssgatherwrite(s->nbss, a);
		pr = SmbProcessResultOk;
	}
	else if (s->cifss) {
		ulong l = smbbufferreadspace(s->response);
		uchar nl[4];
		hnputl(nl, l);
		write(s->cifss->fd, nl, 4);
		write(s->cifss->fd, smbbufferreadpointer(s->response), l);
		pr = SmbProcessResultOk;
	}
	else
		pr = SmbProcessResultDie;
	smbbufferreset(s->response);
	return pr;
}
Пример #5
0
void hnputv(void *p, int64_t v)
{
	uint8_t *a;

	a = p;
	hnputl(a, v >> 32);
	hnputl(a + 4, v);
}
Пример #6
0
uint8_t*
optaddulong(uint8_t *p, int op, uint32_t x)
{
	p[0] = op;
	p[1] = 4;
	hnputl(p+2, x);
	return p+6;
}
Пример #7
0
void
igmpproc(void *a)
{
	IGMPrep *rp, **lrp;
	Multicast *mp, **lmp;
	uchar ip[IPaddrlen];

	USED(a);

	for(;;){
		sleep(&igmpalloc.r, isreport, 0);
		for(;;){
			lock(&igmpalloc);

			if(igmpalloc.reports == nil)
				break;

			/* look for a single report */
			lrp = &igmpalloc.reports;
			mp = nil;
			for(rp = *lrp; rp; rp = *lrp){
				rp->ticks++;
				lmp = &rp->multi;
				for(mp = *lmp; mp; mp = *lmp){
					if(rp->ticks >= mp->timeout){
						*lmp = mp->next;
						break;
					}
					lmp = &mp->next;
				}
				if(mp != nil)
					break;

				if(rp->multi != nil){
					lrp = &rp->next;
					continue;
				} else {
					*lrp = rp->next;
					free(rp);
				}
			}
			unlock(&igmpalloc);

			if(mp){
				/* do a single report and try again */
				hnputl(ip, mp->addr);
				igmpsendreport(rp->m, ip);
				free(mp);
				continue;
			}

			tsleep(&up->sleep, return0, 0, MSPTICK);
		}
		unlock(&igmpalloc);
	}

}
Пример #8
0
void
hnputv(void *p, uvlong v)
{
	uchar *a;

	a = p;
	hnputl(a, v>>32);
	hnputl(a+4, v);
}
Пример #9
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");
}
Пример #10
0
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 */
}
Пример #11
0
/* Write block to file descriptor */
void
B2fd(Block* blk, int fd)
{
	int sz;
	char size[4];
	
	sz = (int)(blk->wrp - blk->beg);
	hnputl((void*) size, sz);
	
	if (write(fd, size, 4) != 4)
		exits("could not write response size");
	
	if (write(fd, blk->beg, sz) != sz)
		exits("could not write response");
}
Пример #12
0
void
so_bind(int fd, int su, unsigned long addr, unsigned short port)
{
	int i, one;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	sin = (struct sockaddr_in*)&sa;

	one = 1;
//	if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof(one)) < 0) {
//		oserrstr(up->genbuf, sizeof(up->genbuf));
//		print("setsockopt: %s", err);
//	}

	if(su) {
		for(i = 600; i < 1024; i++) {
			memset(&sa, 0, sizeof(sa));
			sin->sin_family = AF_INET;
			hnputl(&sin->sin_addr.s_addr, addr);
			hnputs(&sin->sin_port, i);

			if(bind(fd, &sa, sizeof(sa)) >= 0)	
				return;
		}
		oserror();
	}

	memset(&sa, 0, sizeof(sa));
	sin->sin_family = AF_INET;
	hnputl(&sin->sin_addr.s_addr, addr);
	hnputs(&sin->sin_port, port);

	if(bind(fd, &sa, sizeof(sa)) < 0)
		oserror();
}
Пример #13
0
Файл: dhcp.c Проект: 8l/inferno
static int
rbootpread(char *bp, ulong offset, int len)
{
	int n, i;
	char *buf;
	uchar a[4];

	if(debug)
		print("dhcp: bootpread() \n");
	buf = smalloc(READSTR);
	if(waserror()){
		free(buf);
		nexterror();
	}

	hnputl(a, fsip);
	n = snprint(buf, READSTR, "fsip %15V\n", a);
	hnputl(a, auip);
	n += snprint(buf + n, READSTR-n, "auip %15V\n", a);
	hnputl(a, gwip);
	n += snprint(buf + n, READSTR-n, "gwip %15V\n", a);
	hnputl(a, ipmask);
	n += snprint(buf + n, READSTR-n, "ipmask %15V\n", a);
	hnputl(a, ipaddr);
	n += snprint(buf + n, READSTR-n, "ipaddr %15V\n", a);
	n += snprint(buf+n, READSTR-n, "expired %lud\n", iplease);

	n += snprint(buf + n, READSTR-n, "dns");
	if(dns2ip){
		hnputl(a, dns2ip);
		n+=snprint(buf + n, READSTR-n, " %15V", a);
	}
	if(dns1ip){
		hnputl(a, dns1ip);
		n += snprint(buf + n, READSTR-n, " %15V", a);
	}

	for(i=0; i<2; i++)
		if(ipcmp(pppdns[i], IPnoaddr) != 0 && ipcmp(pppdns[i], v4prefix) != 0)
			n += snprint(buf + n, READSTR-n, " %15I", pppdns[i]);

	snprint(buf + n, READSTR-n, "\n");
	len = readstr(offset, bp, len, buf);
	poperror();
	free(buf);
	return len;
}
Пример #14
0
void
so_connect(int fd, unsigned long raddr, unsigned short rport)
{
	int r;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	memset(&sa, 0, sizeof(sa));
	sin = (struct sockaddr_in*)&sa;
	sin->sin_family = AF_INET;
	hnputs(&sin->sin_port, rport);
	hnputl(&sin->sin_addr.s_addr, raddr);

	osenter();
	r = connect(fd, &sa, sizeof(sa));
	osleave();
	if(r < 0)
		oserror();
}
Пример #15
0
/*
 *  write out a packet trace
 */
void
tracepkt(uint8_t *ps, int len)
{
	struct pcap_pkthdr *goo;

	if(Mflag && len > Mflag)
		len = Mflag;
	if(pcap){
		goo = (struct pcap_pkthdr*)(ps-16);
		goo->ts = pkttime;
		goo->caplen = len;
		goo->len = len;
		write(1, goo, len+16);
	} else {
		hnputs(ps-10, len);
		hnputl(ps-8, pkttime>>32);
		hnputl(ps-4, pkttime);
		write(1, ps-10, len+10);
	}
}
Пример #16
0
int
nbssgatherwrite(NbSession *s, NbScatterGather *a)
{
	uchar hdr[4];
	NbScatterGather *ap;
	long l = 0;
	for (ap = a; ap->p; ap++)
		l += ap->l;
//print("nbssgatherwrite %ld bytes\n", l);
	hnputl(hdr, l);
//nbdumpdata(hdr, sizeof(hdr));
	if (write(s->fd, hdr, sizeof(hdr)) != sizeof(hdr))
		return -1;
	for (ap = a; ap->p; ap++) {
//nbdumpdata(ap->p, ap->l);
		if (write(s->fd, ap->p, ap->l) != ap->l)
			return -1;
	}
	return 0;
}
Пример #17
0
static int
hset(Aoedev *d, Frame *f, Aoehdr *h, int cmd)
{
	int i;
	Devlink *l;

	if(f->srb && MACHP(0)->ticks - f->srb->ticksent > Maxreqticks){
		eventlog("%æ: srb timeout\n", d);
		if(cmd == ACata && f->srb && Nofail(d, s))
			f->srb->ticksent = MACHP(0)->ticks;
		else
			frameerror(d, f, Etimedout);
		return -1;
	}
	l = pickdevlink(d);
	i = pickea(l);
	if(i == -1){
		if(cmd != ACata || f->srb == nil || !Nofail(d, s))
			downdev(d, "resend fails; no netlink/ea");
		return -1;
	}
	memmove(h->dst, l->eatab[i], Eaddrlen);
	memmove(h->src, l->nl->ea, sizeof h->src);
	hnputs(h->type, Aoetype);
	h->verflag = Aoever << 4;
	h->error = 0;
	hnputs(h->major, d->major);
	h->minor = d->minor;
	h->cmd = cmd;

	hnputl(h->tag, f->tag = newtag(d));
	f->dl = l;
	f->nl = l->nl;
	f->eaidx = i;
	f->ticksent = MACHP(0)->ticks;

	return f->tag;
}
Пример #18
0
int
eipfmt(Fmt *f)
{
	char buf[5*8];
	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
	static char *ifmt = "%d.%d.%d.%d";
	uchar *p, ip[16];
	ulong ul;

	switch(f->r) {
	case 'E':		/* Ethernet address */
		p = va_arg(f->args, uchar*);
		snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
		return fmtstrcpy(f, buf);

	case 'I':
		ul = va_arg(f->args, ulong);
		hnputl(ip, ul);
		snprint(buf, sizeof buf, ifmt, ip[0], ip[1], ip[2], ip[3]);
		return fmtstrcpy(f, buf);
	}
	return fmtstrcpy(f, "(eipfmt)");
}
Пример #19
0
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);

}
Пример #20
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++;
}
Пример #21
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);
}
Пример #22
0
Файл: esp.c Проект: 8l/inferno
static int
rc4cipher(Espcb *ecb, uchar *p, int n)
{
	Esprc4 *esprc4;
	RC4state tmpstate;
	ulong seq;
	long d, dd;

	if(n < 4)
		return 0;

	esprc4 = ecb->espstate;
	if(ecb->incoming) {
		seq = nhgetl(p);
		p += 4;
		n -= 4;
		d = seq-esprc4->cseq;
		if(d == 0) {
			rc4(&esprc4->current, p, n);
			esprc4->cseq += n;
			if(esprc4->ovalid) {
				dd = esprc4->cseq - esprc4->lgseq;
				if(dd > RC4back)
					esprc4->ovalid = 0;
			}
		} else if(d > 0) {
print("missing packet: %uld %ld\n", seq, d);
			// this link is hosed
			if(d > RC4forward) {
				strcpy(up->errstr, "rc4cipher: skipped too much");
				return 0;
			}
			esprc4->lgseq = seq;
			if(!esprc4->ovalid) {
				esprc4->ovalid = 1;
				esprc4->oseq = esprc4->cseq;
				memmove(&esprc4->old, &esprc4->current, sizeof(RC4state));
			}
			rc4skip(&esprc4->current, d);
			rc4(&esprc4->current, p, n);
			esprc4->cseq = seq+n;
		} else {
print("reordered packet: %uld %ld\n", seq, d);
			dd = seq - esprc4->oseq;
			if(!esprc4->ovalid || -d > RC4back || dd < 0) {
				strcpy(up->errstr, "rc4cipher: too far back");
				return 0;
			}
			memmove(&tmpstate, &esprc4->old, sizeof(RC4state));
			rc4skip(&tmpstate, dd);
			rc4(&tmpstate, p, n);
			return 1;
		}

		// move old state up
		if(esprc4->ovalid) {
			dd = esprc4->cseq - RC4back - esprc4->oseq;
			if(dd > 0) {
				rc4skip(&esprc4->old, dd);
				esprc4->oseq += dd;
			}
		}
	} else {
		hnputl(p, esprc4->cseq);
		p += 4;
		n -= 4;
		rc4(&esprc4->current, p, n);
		esprc4->cseq += n;
	}
	return 1;
}
Пример #23
0
int
eipconv(va_list *arg, Fconv *f)
{
	char buf[8*5];
	static char *efmt = "%.2lux%.2lux%.2lux%.2lux%.2lux%.2lux";
	static char *ifmt = "%d.%d.%d.%d";
	uint8_t *p, ip[16];
	uint32_t *lp;
	uint16_t s;
	int i, j, n, eln, eli;

	switch(f->chr) {
	case 'E':		/* Ethernet address */
		p = va_arg(*arg, uint8_t*);
		sprint(buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
		break;
	case 'I':		/* Ip address */
		p = va_arg(*arg, uint8_t*);
common:
		if(memcmp(p, v4prefix, 12) == 0)
			sprint(buf, ifmt, p[12], p[13], p[14], p[15]);
		else {
			/* find longest elision */
			eln = eli = -1;
			for(i = 0; i < 16; i += 2){
				for(j = i; j < 16; j += 2)
					if(p[j] != 0 || p[j+1] != 0)
						break;
				if(j > i && j - i > eln){
					eli = i;
					eln = j - i;
				}
			}

			/* print with possible elision */
			n = 0;
			for(i = 0; i < 16; i += 2){
				if(i == eli){
					n += sprint(buf+n, "::");
					i += eln;
					if(i >= 16)
						break;
				} else if(i != 0)
					n += sprint(buf+n, ":");
				s = (p[i]<<8) + p[i+1];
				n += sprint(buf+n, "%x", s);
			}
		}
		break;
	case 'i':		/* v6 address as 4 longs */
		lp = va_arg(*arg, uint32_t*);
		for(i = 0; i < 4; i++)
			hnputl(ip+4*i, *lp++);
		p = ip;
		goto common;
	case 'V':		/* v4 ip address */
		p = va_arg(*arg, uint8_t*);
		sprint(buf, ifmt, p[0], p[1], p[2], p[3]);
		break;
	case 'M':		/* ip mask */
		p = va_arg(*arg, uint8_t*);

		/* look for a prefix mask */
		for(i = 0; i < 16; i++)
			if(p[i] != 0xff)
				break;
		if(i < 16){
			if((prefixvals[p[i]] & Isprefix) == 0)
				goto common;
			for(j = i+1; j < 16; j++)
				if(p[j] != 0)
					goto common;
			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
		} else
			n = 8*16;

		/* got one, use /xx format */
		sprint(buf, "/%d", n);
		break;
	default:
		strcpy(buf, "(eipconv)");
	}
	strconv(buf, f);
	return sizeof(uint8_t*);
}
Пример #24
0
int
main(int argc, char **argv)
{
    char *addr, *p, *q, to[4];
    char buf[2048];
    int port, fd, nfd, one, len, n, tot;
    ulong ip;
    struct sockaddr_in sin;
    WSADATA wasdat;

    if(argc != 1 && argc != 2) {
usage:
        fprintf(stderr, "usage: winplumb [tcp!ipaddr!port]\n");
        ExitThread(1);
    }

    if(argc == 1)
        addr = "tcp!*!17890";
    else
        addr = argv[1];

    strcpy(buf, addr);
    p = strchr(buf, '!');
    if(p == 0)
        goto usage;
    q = strchr(p+1, '!');
    if(q == 0)
        goto usage;
    *p++ = 0;
    *q++ = 0;

    if(strcmp(buf, "tcp") != 0)
        goto usage;

    port = atoi(q);
    if(strcmp(p, "*") == 0)
        ip = 0;
    else
        ip = parseip(to, p);

    WSAStartup(MAKEWORD(1, 1), &wasdat);


    fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd < 0) {
        oserror();
        fprintf(stderr, "socket: %s\n", errbuf);
        ExitThread(1);
    }

    one = 1;
    if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char*)&one, sizeof one) != 0) {
        oserror();
        fprintf(stderr, "setsockopt nodelay: %s\n", errbuf);
    }

    if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&one, sizeof one) != 0) {
        oserror();
        fprintf(stderr, "setsockopt reuse: %s\n", errbuf);
    }
    memset(&sin, 0, sizeof sin);
    sin.sin_family = AF_INET;
    hnputs(&sin.sin_port, port);
    hnputl(&sin.sin_addr, ip);
    if(bind(fd, (struct sockaddr*)&sin, sizeof sin) < 0) {
        oserror();
        fprintf(stderr, "bind: %s\n", errbuf);
        ExitThread(1);
    }

    if(listen(fd, 5) < 0) {
        oserror();
        fprintf(stderr, "listen: %s\n", errbuf);
        ExitThread(1);
    }

    for(;;) {
        len = sizeof sin;
        nfd = accept(fd, (struct sockaddr*)&sin, &len);
        if(nfd < 0) {
            oserror();
            fprintf(stderr, "accept: %s\n", errbuf);
            continue;
        }
        tot = 0;
        while(tot == 0 || buf[tot-1] != '\n') {
            n = recv(nfd, buf+tot, sizeof buf-tot, 0);
            if(n < 0)
                break;
            tot += n;
        }
        if(buf[tot-1] == '\n') {
            buf[tot-1] = 0;
            p = strchr(buf, ' ');
            if(p)
                *p++ = 0;
            ShellExecute(0, 0, buf, p, 0, SW_SHOWNORMAL);
        }
        closesocket(nfd);
    }
}
Пример #25
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();
}
Пример #26
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);
}
Пример #27
0
Файл: rip.c Проект: aahud/harvey
/*
 *  broadcast routes onto all networks
 */
void
sendto(Ifc *ip)
{
	int h, n;
	uint8_t raddr[Pasize], mbuf[Udphdrsize+512];
	Ripmsg *m;
	Route *r;
	Udphdr *u;

	u = (Udphdr*)mbuf;
	for(n = 0; n < Pasize; n++)
		raddr[n] = ip->net[n] | ~(ip->mask[n]);
	v4tov6(u->raddr, raddr);
	hnputs(u->rport, 520);
	m = (Ripmsg*)(mbuf+Udphdrsize);
	m->type = Response;
	m->vers = Version;
	if(debug)
		fprint(2, "to %V\n", u->raddr);

	n = 0;
	for(h = 0; h < Nhash; h++){
		for(r = ralloc.hash[h]; r; r = r->next){
			/*
			 *  don't send any route back to the net
			 *  it came from
			 */
			if(onnet(r->gate, ip->net, ip->mask))
				continue;

			/*
			 *  don't tell a network about itself
			 */
			if(equivip(r->dest, ip->net))
				continue;

			/*
			 *  don't tell nets about other net's subnets
			 */
			if(!equivip(r->mask, v4defmask(r->dest))
			&& !equivip(ip->cmask, v4defmask(r->dest)))
				continue;

			memset(&m->rip[n], 0, sizeof(m->rip[n]));
			memmove(m->rip[n].addr, r->dest, Pasize);
			if(r->metric < 1)
				hnputl(m->rip[n].metric, 1);
			else
				hnputl(m->rip[n].metric, r->metric);
			hnputs(m->rip[n].family, AF_INET);

			if(debug)
				fprint(2, " %16V & %16V -> %16V %2d\n",
					r->dest, r->mask, r->gate, r->metric);

			if(++n == Maxroutes && !readonly){
				write(ripfd, mbuf, Udphdrsize + 4 + n*20);
				n = 0;
			}
		}
	}

	if(n && !readonly)
		write(ripfd, mbuf, Udphdrsize+4+n*20);
}
Пример #28
0
int
eipfmt(Fmt *f)
{
	char buf[5*8];
	static char *efmt = "%.2ux%.2ux%.2ux%.2ux%.2ux%.2ux";
	static char *ifmt = "%d.%d.%d.%d";
	uchar *p, ip[16];
	ulong *lp;
	ushort s;
	int i, j, n, eln, eli;

	switch(f->r) {
	case 'E':		/* Ethernet address */
		p = va_arg(f->args, uchar*);
		snprint(buf, sizeof buf, efmt, p[0], p[1], p[2], p[3], p[4], p[5]);
		return fmtstrcpy(f, buf);

	case 'I':		/* Ip address */
		p = va_arg(f->args, uchar*);
common:
		if(memcmp(p, v4prefix, 12) == 0){
			snprint(buf, sizeof buf, ifmt, p[12], p[13], p[14], p[15]);
			return fmtstrcpy(f, buf);
		}

		/* find longest elision */
		eln = eli = -1;
		for(i = 0; i < 16; i += 2){
			for(j = i; j < 16; j += 2)
				if(p[j] != 0 || p[j+1] != 0)
					break;
			if(j > i && j - i > eln){
				eli = i;
				eln = j - i;
			}
		}

		/* print with possible elision */
		n = 0;
		for(i = 0; i < 16; i += 2){
			if(i == eli){
				n += sprint(buf+n, "::");
				i += eln;
				if(i >= 16)
					break;
			} else if(i != 0)
				n += sprint(buf+n, ":");
			s = (p[i]<<8) + p[i+1];
			n += sprint(buf+n, "%ux", s);
		}
		return fmtstrcpy(f, buf);

	case 'i':		/* v6 address as 4 longs */
		lp = va_arg(f->args, ulong*);
		for(i = 0; i < 4; i++)
			hnputl(ip+4*i, *lp++);
		p = ip;
		goto common;

	case 'V':		/* v4 ip address */
		p = va_arg(f->args, uchar*);
		snprint(buf, sizeof buf, ifmt, p[0], p[1], p[2], p[3]);
		return fmtstrcpy(f, buf);

	case 'M':		/* ip mask */
		p = va_arg(f->args, uchar*);

		/* look for a prefix mask */
		for(i = 0; i < 16; i++)
			if(p[i] != 0xff)
				break;
		if(i < 16){
			if((prefixvals[p[i]] & Isprefix) == 0)
				goto common;
			for(j = i+1; j < 16; j++)
				if(p[j] != 0)
					goto common;
			n = 8*i + (prefixvals[p[i]] & ~Isprefix);
		} else
			n = 8*16;

		/* got one, use /xx format */
		snprint(buf, sizeof buf, "/%d", n);
		return fmtstrcpy(f, buf);
	}
	return fmtstrcpy(f, "(eipfmt)");
}
Пример #29
0
Файл: dhcp.c Проект: 8l/inferno
static char*
rbootp(Ipifc *ifc)
{
	int cfd, dfd, tries, n;
	char ia[5+3*16], im[16], *av[3];
	uchar nipaddr[4], ngwip[4], nipmask[4];
	char dir[Maxpath];
	static uchar vend_rfc1048[] = { 99, 130, 83, 99 };
	uchar *vend;

	/*
	 * broadcast bootp's till we get a reply,
	 * or fixed number of tries
	 */
	if(debug)
	    print("dhcp: bootp() called\n");
	tries = 0;
	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcadd(ifc, av, 3, 0, nil);

	cfd = kannounce("udp!*!68", dir);
	if(cfd < 0)
		return "dhcp announce failed";
	strcat(dir, "/data");
	if(kwrite(cfd, "headers", 7) < 0){
		kclose(cfd);
		return "dhcp ctl headers failed";
	}
	kwrite(cfd, "oldheaders", 10);
	dfd = kopen(dir, ORDWR);
	if(dfd < 0){
		kclose(cfd);
		return "dhcp open data failed";
	}
	kclose(cfd);
	
	while(tries<1){
		tries++;
		memset(sid, 0, 4);
		iplease=0;
		dhcpmsgtype=-2;
/* DHCPDISCOVER*/
		done = 0;
		recv = 0;
		kproc("rcvbootp", rcvbootp, (void*)dfd, KPDUPFDG);
		/* Prepare DHCPDISCOVER */	
		memset(&req, 0, sizeof(req));
		ipmove(req.raddr, IPv4bcast);
		hnputs(req.rport, 67);
		req.op = Bootrequest;
		req.htype = 1;			/* ethernet (all we know) */
		req.hlen = 6;			/* ethernet (all we know) */
		
		memmove(req.chaddr, ifc->mac, 6);	/* Hardware MAC address */
		//ipv4local(ifc, req.ciaddr);				/* Fill in the local IP address if we know it */
		memset(req.file, 0, sizeof(req.file));
		vend=req.vend;
		memmove(vend, vend_rfc1048, 4); vend+=4;
		*vend++=53; *vend++=1;*vend++=1;		/* dhcp msg type==3, dhcprequest */
		
		*vend++=61;*vend++=7;*vend++=1;
		memmove(vend, ifc->mac, 6);vend+=6;
		*vend=0xff;

		if(debug)
			dispvend(req.vend); 
		for(n=0;n<4;n++){
			if(kwrite(dfd, &req, sizeof(req))<0)	/* SEND DHCPDISCOVER */
				print("DHCPDISCOVER: %r");
		
			tsleep(&bootpr, return0, 0, 1000);	/* wait DHCPOFFER */
			if(debug)
				print("[DHCP] DISCOVER: msgtype = %d\n", dhcpmsgtype);

			if(dhcpmsgtype==2)		/* DHCPOFFER */
				break;
			else if(dhcpmsgtype==0)	/* bootp */
				return nil;
			else if(dhcpmsgtype== -2)	/* time out */
				continue;
			else
				break;
			
		}
		if(dhcpmsgtype!=2)
			continue;

/* DHCPREQUEST */	
		memset(req.vend, 0, sizeof(req.vend));
		vend=req.vend;
		memmove(vend, vend_rfc1048, 4);vend+=4;	

		*vend++=53; *vend++=1;*vend++=3;		/* dhcp msg type==3, dhcprequest */

		*vend++=50;	*vend++=4;				/* requested ip address */
		*vend++=(ipaddr >> 24)&0xff;
		*vend++=(ipaddr >> 16)&0xff;
		*vend++=(ipaddr >> 8) & 0xff;
		*vend++=ipaddr & 0xff;

		*vend++=51;*vend++=4;					/* lease time */
		*vend++=(iplease>>24)&0xff; *vend++=(iplease>>16)&0xff; *vend++=(iplease>>8)&0xff; *vend++=iplease&0xff;

		*vend++=54; *vend++=4;					/* server identifier */
		memmove(vend, sid, 4);	vend+=4;
	
		*vend++=61;*vend++=07;*vend++=01;		/* client identifier */
		memmove(vend, ifc->mac, 6);vend+=6;
		*vend=0xff;
		if(debug) 
			dispvend(req.vend); 
		if(kwrite(dfd, &req, sizeof(req))<0){
			print("DHCPREQUEST: %r");
			continue;
		}
		tsleep(&bootpr, return0, 0, 2000);
		if(dhcpmsgtype==5)		/* wait for DHCPACK */
			break;
		else
			continue;
		/* CHECK ARP */
		/* DHCPDECLINE */
	}
	kclose(dfd);
	done = 1;
	if(rcvprocp != nil){
		postnote(rcvprocp, 1, "timeout", 0);
		rcvprocp = nil;
	}

	av[1] = "0.0.0.0";
	av[2] = "0.0.0.0";
	ipifcrem(ifc, av, 3);

	hnputl(nipaddr, ipaddr);
	sprint(ia, "%V", nipaddr);
	hnputl(nipmask, ipmask);
	sprint(im, "%V", nipmask);
	av[1] = ia;
	av[2] = im;
	ipifcadd(ifc, av, 3, 0, nil);

	if(gwip != 0) {
		hnputl(ngwip, gwip);
		n = sprint(ia, "add 0.0.0.0 0.0.0.0 %V", ngwip);
		routewrite(ifc->conv->p->f, nil, ia, n);
	}
	return nil;
}