Beispiel #1
0
int
so_accept(int fd, unsigned char *raddr, unsigned short *rport)
{
	int nfd;
	socklen_t len;
	struct sockaddr_storage ss;

	len = sizeof(ss);
	nfd = accept(fd, (struct sockaddr*)&ss, &len);
	if(nfd < 0)
		oserror();

	switch(ss.ss_family){
	case AF_INET:
		v4tov6(raddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
		*rport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
		break;
	case AF_INET6:
		memcpy(raddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
		*rport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
		break;
	default:
		error("not AF_INET or AF_INET6");
	}
	return nfd;
}
Beispiel #2
0
void
rudpadvise(Proto *rudp, Block *bp, char *msg)
{
	Udphdr *h;
	uint8_t source[IPaddrlen], dest[IPaddrlen];
	uint16_t psource, pdest;
	Conv *s, **p;

	h = (Udphdr*)(bp->rp);

	v4tov6(dest, h->udpdst);
	v4tov6(source, h->udpsrc);
	psource = nhgets(h->udpsport);
	pdest = nhgets(h->udpdport);

	/* Look for a connection */
	for(p = rudp->conv; *p; p++) {
		s = *p;
		if(s->rport == pdest)
		if(s->lport == psource)
		if(ipcmp(s->raddr, dest) == 0)
		if(ipcmp(s->laddr, source) == 0){
			qhangup(s->rq, msg);
			qhangup(s->wq, msg);
			break;
		}
	}
	freeblist(bp);
}
Beispiel #3
0
int
wantsession(uint8_t *pkt)
{
	int len;
	uint8_t *s;
	Pppoehdr *ph;

	ph = (Pppoehdr*)(pkt+EtherHdrSz);

	if(ph->code != CodeDiscSess)
		return bad("not a session confirmation");
	if(nhgets(ph->sessid) == 0x0000)
		return bad("bad session id");
	if(findtag(pkt, TagSrvName, &len, 0) == nil)
		return bad("no service name");
	if(findtag(pkt, TagSrvNameErr, &len, 0))
		return bad("service name error");
	if(findtag(pkt, TagAcSysErr, &len, 0))
		return bad("ac system error");

	/*
	 * rsc said: ``if there is no -S option given, the current code
	 * waits for an offer with service name == "".
	 * that's silly.  it should take the first one it gets.''
	 */
	if(srvname[0] != '\0') {
		if((s = findtag(pkt, TagSrvName, &len, 0)) == nil)
			return bad("no matching service name");
		if(len != strlen(srvname) || memcmp(s, srvname, len) != 0)
			return bad("no matching service name");
	}
	sessid = nhgets(ph->sessid);
	return 1;
}
Beispiel #4
0
uint8_t*
findtag(uint8_t *pkt, int tagtype, int *plen, int skip)
{
	int len, sz, totlen;
	uint8_t *tagdat, *v;
	Etherhdr *eh;
	Pppoehdr *ph;
	Taghdr *t;

	eh = (Etherhdr*)pkt;
	ph = (Pppoehdr*)(pkt+EtherHdrSz);
	tagdat = pkt+Hdr;

	if(nhgets(eh->type) != EtherPppoeDiscovery)
		return nil;
	totlen = nhgets(ph->length);

	sz = 0;
	while(sz+4 <= totlen){
		t = (Taghdr*)(tagdat+sz);
		v = tagdat+sz+4;
		len = nhgets(t->length);
		if(sz+4+len > totlen)
			break;
		if(nhgets(t->type) == tagtype && skip-- == 0){
			*plen = len;
			return v;
		}
		sz += 2+2+len;
	}
	return nil;	
}
Beispiel #5
0
void
udpadvise(Proto *udp, Block *bp, char *msg)
{
	Udp4hdr *h4;
	Udp6hdr *h6;
	uchar source[IPaddrlen], dest[IPaddrlen];
	ushort psource, pdest;
	Conv *s, **p;
	int version;

	h4 = (Udp4hdr*)(bp->rp);
	version = ((h4->vihl&0xF0)==IP_VER6) ? 6 : 4;

	switch(version) {
	case V4:
		v4tov6(dest, h4->udpdst);
		v4tov6(source, h4->udpsrc);
		psource = nhgets(h4->udpsport);
		pdest = nhgets(h4->udpdport);
		break;
	case V6:
		h6 = (Udp6hdr*)(bp->rp);
		ipmove(dest, h6->udpdst);
		ipmove(source, h6->udpsrc);
		psource = nhgets(h6->udpsport);
		pdest = nhgets(h6->udpdport);
		break;
	default:
		panic("udpadvise: version %d", version);
		return;	/* to avoid a warning */
	}

	/* Look for a connection */
	qlock(udp);
	for(p = udp->conv; *p; p++) {
		s = *p;
		if(s->rport == pdest)
		if(s->lport == psource)
		if(ipcmp(s->raddr, dest) == 0)
		if(ipcmp(s->laddr, source) == 0){
			if(s->ignoreadvice)
				break;
			qlock(s);
			qunlock(udp);
			qhangup(s->rq, msg);
			qhangup(s->wq, msg);
			qunlock(s);
			freeblist(bp);
			return;
		}
	}
	qunlock(udp);
	freeblist(bp);
}
Beispiel #6
0
static void
sunudpread(void *v)
{
	int n, paraport, port;
	uchar *buf;
	Arg arg = *(Arg*)v;
	SunMsgUdp *msg;
	SunSrv *srv;
	Udphdr udp;
	uchar localip[IPaddrlen];

	sendp(arg.csync, 0);
	srv = arg.srv;
	paraport = -1;

	/* 127.1 */
	memmove(localip, v4prefix, IPaddrlen);
	localip[12] = 127;
	localip[15] = 1;

	buf = emalloc(UdpMaxRead);
	while((n = udpread(arg.fd, &udp, buf, UdpMaxRead)) > 0){
		if(arg.srv->chatty)
			fprint(2, "udpread got %d (%d) from %I\n", n, Udphdrsize, udp.raddr);
		msg = emalloc(sizeof(SunMsgUdp));
		msg->udp = udp;
		msg->msg.data = emalloc(n);
		msg->msg.count = n;
		memmove(msg->msg.data, buf, n);
		msg->msg.creply = arg.creply;
		msg->msg.srv = arg.srv;
		if(arg.srv->chatty)
			fprint(2, "message %p count %d\n", msg, msg->msg.count);
		if((srv->localonly || srv->localparanoia) && ipcmp(udp.raddr, localip) != 0){
			fprint(2, "dropping message from %I: not local\n", udp.raddr);
			sunmsgreplyerror(&msg->msg, SunAuthTooWeak);
			continue;
		}
		if(srv->localparanoia){
			port = nhgets(udp.rport);
			if(paraport == -1){
				fprint(2, "paranoid mode: only %I/%d allowed\n", localip, port);
				paraport = port;
			}else if(paraport != port){
				fprint(2, "dropping message from %I: not port %d\n", udp.raddr, port);
				sunmsgreplyerror(&msg->msg, SunAuthTooWeak);
				continue;
			}
		}
		if(srv->ipokay && !srv->ipokay(udp.raddr, nhgets(udp.rport)))
			msg->msg.rpc.status = SunProgUnavail;
		sendp(arg.srv->crequest, msg);
	}
}
Beispiel #7
0
void
dumptags(uint8_t *tagdat, int ntagdat)
{
	int i,len, sz;
	uint8_t *v;
	Taghdr *t;

	sz = 0;
	while(sz+4 <= ntagdat){
		t = (Taghdr*)(tagdat+sz);
		v = tagdat+sz+2+2;
		len = nhgets(t->length);
		if(sz+4+len > ntagdat)
			break;
		fprint(2, "\t0x%x %d: ", nhgets(t->type), len);
		switch(nhgets(t->type)){
		case TagEnd:
			fprint(2, "end of tag list\n");
			break;
		case TagSrvName:
			fprint(2, "service '%.*s'\n", len, (char*)v);
			break;
		case TagAcName:
			fprint(2, "ac '%.*s'\n", len, (char*)v);
			break;
		case TagHostUniq:
			fprint(2, "nonce ");
		Hex:
			for(i=0; i<len; i++)
				fprint(2, "%.2x", v[i]);
			fprint(2, "\n");
			break;
		case TagAcCookie:
			fprint(2, "ac cookie ");
			goto Hex;
		case TagVendSpec:
			fprint(2, "vend spec ");
			goto Hex;
		case TagRelaySessId:
			fprint(2, "relay ");
			goto Hex;
		case TagSrvNameErr:
			fprint(2, "srverr '%.*s'\n", len, (char*)v);
			break;
		case TagAcSysErr:
			fprint(2, "syserr '%.*s'\n", len, (char*)v);
			break;
		}
		sz += 2+2+len;
	}
	if(sz != ntagdat)
		fprint(2, "warning: only dumped %d of %d bytes\n", sz, ntagdat);
}
Beispiel #8
0
Datei: ipif.c Projekt: 8l/inferno
int
so_accept(int fd, uchar *raddr, ushort *rport)
{
	int nfd;
	socklen_t len;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	sin = (struct sockaddr_in*)&sa;

	len = sizeof(sa);
	osenter();
	if(doselect(fd) < 0) {
		osleave();
		return -1;
	}
	nfd = accept(fd, &sa, &len);
	osleave();
	if(nfd < 0)
		oserror();

	if(sin->sin_family != AF_INET || len != sizeof(*sin))
		error(Enotv4);

	ipw6(raddr, sin->sin_addr.s_addr);
	*rport = nhgets(&sin->sin_port);
	return nfd;
}
Beispiel #9
0
int
so_accept(int fd, unsigned long *raddr, unsigned short *rport)
{
	int nfd, len;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	sin = (struct sockaddr_in*)&sa;

	len = sizeof(sa);
	osenter();
	if(doselect(fd) < 0) {
		osleave();
		return -1;
	}
	nfd = accept(fd, &sa, &len);
	osleave();
	if(nfd < 0)
		oserror();

	if(sin->sin_family != AF_INET || len != sizeof(*sin))
		error("not AF_INET");

	*raddr = nhgetl(&sin->sin_addr.s_addr);
	*rport = nhgets(&sin->sin_port);
	return nfd;
}
Beispiel #10
0
/* notify a slave that an area has changed. */
static void
send_notify(char *slave, RR *soa, Request *req)
{
	int i, len, n, reqno, status, fd;
	char *err;
	uchar ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize];
	RR *rp;
	Udphdr *up = (Udphdr*)obuf;
	DNSmsg repmsg;

	/* create the request */
	reqno = rand();
	n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno);

	/* get an address */
	if(strcmp(ipattr(slave), "ip") == 0) {
		if (parseip(up->raddr, slave) == -1)
			dnslog("bad address %s to notify", slave);
	} else {
		rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status);
		if(rp == nil)
			rp = dnresolve(slave, Cin, Taaaa, req, nil, 0, 1, 1, &status);
		if(rp == nil)
			return;
		parseip(up->raddr, rp->ip->name);
		rrfreelist(rp);		/* was rrfree */
	}

	fd = udpport(nil);
	if(fd < 0)
		return;

	/* send 3 times or until we get anything back */
	n += Udphdrsize;
	for(i = 0; i < 3; i++, freeanswers(&repmsg)){
		dnslog("sending %d byte notify to %s/%I.%d about %s", n, slave,
			up->raddr, nhgets(up->rport), soa->owner->name);
		memset(&repmsg, 0, sizeof repmsg);
		if(write(fd, obuf, n) != n)
			break;
		alarm(2*1000);
		len = read(fd, ibuf, sizeof ibuf);
		alarm(0);
		if(len <= Udphdrsize)
			continue;
		err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg, nil);
		if(err != nil) {
			free(err);
			continue;
		}
		if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify)
			break;
	}
	if (i < 3)
		freeanswers(&repmsg);
	close(fd);
}
Beispiel #11
0
static int
_nameextract(uchar *base, uchar *p, uchar *ep, int k, uchar *outbuf, int outbufmaxlen, int *outbuflenp)
{
	uchar *op, *oep, *savep;
	savep = p;
	op = outbuf;
	oep = outbuf + outbufmaxlen;
	for (;;) {
		uchar b;
		int n;
		if (p >= ep)
			return 0;
		b = *p++;
		if (b == 0)
			break;
		if (k) {
			if (op >= oep)
				return 0;
			*op++ = '.';
		}
		if ((b & 0xc0) == 0xc0) {
			ushort off;
			if (ep - p < 2)
				return 0;
			off = nhgets(p - 1) & 0x3fff; p++;
			if (_nameextract(base, base + off, p, k, op, oep - ep, &n) == 0)
				return 0;
			op += n;
		}
		else if ((b & 0xc0) != 0x00)
			return 0;
		else if (b != 0x20)
			return 0;
		else {
			int x;
			if (p + b > ep)
				return 0;
			if (op + b / 2 > oep)
				return 0;
			for (x = 0; x < b; x += 2) {
				uchar hn, ln;
				if (*p < 'A' || *p >= 'A' + 16)
					return 0;
				hn = *p++ - 'A';
				if (*p < 'A' || *p >= 'A' + 16)
					return 0;
				ln = *p++ - 'A';
				*op++ = (hn << 4) | ln;
			}
		}
		k++;
	}
	*outbuflenp = op - outbuf;
	return p - savep;
}
Beispiel #12
0
long
nbssscatterread(NbSession *nbs, NbScatterGather *a)
{
	uchar hdr[4];
	uchar flags;
	long length, total;
	NbScatterGather *ap;
	Session *s = (Session *)nbs;

	long l = 0;
	for (ap = a; ap->p; ap++)
		l += ap->l;
//print("nbssscatterread %ld bytes\n", l);
again:
	if (readn(s->fd, hdr, 4) != 4) {
	dead:
		s->state = Dead;
		return -1;
	}
	flags = hdr[1];
	length = nhgets(hdr + 2) | ((flags & 1) << 16);
//print("%.2ux: %d\n", hdr[0], length);
	switch (hdr[0]) {
	case 0x85:
		if (length != 0) {
			werrstr("length in keepalive not 0");
			goto dead;
		}
		goto again;
	case 0x00:
		break;
	default:
		werrstr("unexpected session message code 0x%.2ux", hdr[0]);
		goto dead;
	}
	if (length > l) {
		werrstr("message too big (%ld)", length);
		goto dead;
	}
	total = length;
	for (ap = a; length && ap->p; ap++) {
		long thistime;
		long n;
		thistime = length;
		if (thistime > ap->l)
			thistime = ap->l;
//print("reading %d\n", length);
		n = readn(s->fd, ap->p, thistime);
		if (n != thistime)
			goto dead;
		length -= thistime;
	}
	return total;
}
Beispiel #13
0
int
so_getservbyname(char *service, char *net, char *port)
{
	struct servent *s;

	s = getservbyname(service, net);
	if(s == 0)
		return -1;

	sprint(port, "%d", nhgets(&s->s_port));
	return 0;
}
Beispiel #14
0
char*
addr2str(char *proto, uchar *a){
	static char s[128];
	uchar ip[16];
	int n, port;

	if(socksver == 4){
		a += 2;
		port = nhgets(a);
		a += 2;
		if((a[0] | a[1] | a[2]) == 0 && a[3]){
			a += 4;
			a += strlen((char*)a)+1;
			snprint(s, sizeof(s), "%s!%s!%d", proto, (char*)a, port);
			return s;
		}
		v4tov6(ip, a);
	} else {
		a += 3;
		switch(*a++){
		default:
			return nil;
		case 0x01:
			v4tov6(ip, a);
			port = nhgets(a+4);
			break;
		case 0x04:
			memmove(ip, a, 16);
			port = nhgets(a+16);
			break;
		case 0x03:
			n = *a++;
			port = nhgets(a+n);
			snprint(s, sizeof(s), "%s!%.*s!%d", proto, n, (char*)a, port);
			return s;
		}
	}
	snprint(s, sizeof(s), "%s!%I!%d", proto, ip, port);
	return s;
}
Beispiel #15
0
int recv_tcp(char *p, int len, nw_skt_t fd)
{
    int recv_len, pkt_size, total_recv_len = 0, num_attempts = 0;

    if (fd < 0) {
        //TODO XXX Fix this..
        I3_PRINT_DEBUG1 (I3_DEBUG_LEVEL_VERBOSE, "invalid fd = %d\n",fd);
        return -1;
    }

    /* recv header */
    recv_len = recv(fd, p, TCP_I3_HEADER_SIZE, 0);
    if (recv_len < 0) {
	    perror("TCP header recv");
        fprintf (stderr, " on fd %d\n\n", fd);
        nw_close (fd);
	    return recv_len;
    }
    
    /* recv rest of the packet */
    if (recv_len > 0) {
      if( (TCP_I3_HEADER_MAGIC != p[0]) ||	// Invalid packet; Not i3?
	  (recv_len < TCP_I3_HEADER_SIZE) ) {
	I3_PRINT_INFO1 (I3_INFO_LEVEL_WARNING,
		    "Invalid i3 tcp header on fd %d\n", fd);
	return -1;
      }
      pkt_size = nhgets(p + 1);
      if (len < pkt_size) {	// Invalid size
	I3_PRINT_INFO2 (I3_INFO_LEVEL_WARNING,
		    "Invalid i3 tcp packet size %d (on fd %d)\n",
		    pkt_size, fd);
	return -1;
      }      

	    while (pkt_size > 0 && num_attempts++ < MAX_ATTEMPTS) {
	        recv_len = recv(fd, p, pkt_size, 0);
	        total_recv_len += recv_len;
	        pkt_size -= recv_len;
	        p += recv_len;
	    }
    }
    
    /* Hack! */
    if (pkt_size > 0) {
	    I3_PRINT_DEBUG0(I3_DEBUG_LEVEL_MINIMAL, "Still some more bytes to be received, quitting!\n");
	    return -1;
    } else {
	    return total_recv_len;
    }
}
Beispiel #16
0
void
so_getsockname(int fd, unsigned char *laddr, unsigned short *lport)
{
	socklen_t len;
	struct sockaddr_storage ss;

	len = sizeof(ss);
	if(getsockname(fd, (struct sockaddr*)&ss, &len) < 0)
		oserror();

	switch(ss.ss_family){
	case AF_INET:
		v4tov6(laddr, (unsigned char*)&((struct sockaddr_in*)&ss)->sin_addr.s_addr);
		*lport = nhgets(&((struct sockaddr_in*)&ss)->sin_port);
		break;
	case AF_INET6:
		memcpy(laddr, &((struct sockaddr_in6*)&ss)->sin6_addr.s6_addr, sizeof(struct in6_addr));
		*lport = nhgets(&((struct sockaddr_in6*)&ss)->sin6_port);
		break;
	default:
		error("not AF_INET or AF_INET6");
	}
}
Beispiel #17
0
int
malformed(uint8_t *pkt, int n, int wantet)
{
	int et;
	Etherhdr *eh;
	Pppoehdr *ph;

	eh = (Etherhdr*)pkt;
	ph = (Pppoehdr*)(pkt+EtherHdrSz);

	if(n < Hdr || n < Hdr+nhgets(ph->length)){
		werrstr("packet too short %d != %d", n, Hdr+nhgets(ph->length));
		return 1;
	}

	et = nhgets(eh->type);
	if(et != wantet){
		werrstr("wrong ethernet packet type 0x%x != 0x%x", et, wantet);
		return 1;
	}

	return 0;
}
Beispiel #18
0
void
dumppkt(uint8_t *pkt)
{
	int et;
	Etherhdr *eh;
	Pppoehdr *ph;

	eh = (Etherhdr*)pkt;
	ph = (Pppoehdr*)(pkt+EtherHdrSz);
	et = nhgets(eh->type);

	fprint(2, "%E -> %E type 0x%x\n", 
		eh->src, eh->dst, et);
	switch(et){
	case EtherPppoeDiscovery:
	case EtherPppoeSession:
		fprint(2, "\tvers %d type %d code 0x%x sessid 0x%x length %d\n",
			ph->verstype>>4, ph->verstype&15,
			ph->code, nhgets(ph->sessid), nhgets(ph->length));
		if(et == EtherPppoeDiscovery)
			dumptags(pkt+Hdr, nhgets(ph->length));
	}
}
Beispiel #19
0
Datei: ipif.c Projekt: 8l/inferno
void
so_getsockname(int fd, uchar *laddr, ushort *lport)
{
	socklen_t len;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	len = sizeof(sa);
	if(getsockname(fd, &sa, &len) < 0)
		oserror();

	sin = (struct sockaddr_in*)&sa;
	if(sin->sin_family != AF_INET || len != sizeof(*sin))
		error(Enotv4);

	ipw6(laddr, sin->sin_addr.s_addr);
	*lport = nhgets(&sin->sin_port);
}
Beispiel #20
0
void
so_getsockname(int fd, uchar *laddr, ushort *lport)
{
	int len;
	struct sockaddr_storage sa;
	struct sockaddr_in6 *sin6;

	len = sizeof(*sin6);
	if(getsockname(fd, (struct sockaddr*)&sa, &len) < 0)
		oserror();

	sin6 = (struct sockaddr_in6*)&sa;
	if(sin6->sin6_family != AF_INET6 || len != sizeof(*sin6))
		error("not AF_INET6");

	memmove(laddr, &sin6->sin6_addr, IPaddrlen);
	*lport = nhgets(&sin6->sin6_port);
}
Beispiel #21
0
Datei: esp.c Projekt: 8l/inferno
void
espadvise(Proto *esp, Block *bp, char *msg)
{
	Esphdr *h;
	Conv *c;
	ulong spi;

	h = (Esphdr*)(bp->rp);

	spi = nhgets(h->espspi);
	qlock(esp);
	c = convlookup(esp, spi);
	if(c != nil) {
		qhangup(c->rq, msg);
		qhangup(c->wq, msg);
	}
	qunlock(esp);
	freeblist(bp);
}
Beispiel #22
0
void
so_getsockname(int fd, unsigned long *laddr, unsigned short *lport)
{
	int len;
	struct sockaddr sa;
	struct sockaddr_in *sin;

	sin = (struct sockaddr_in*)&sa;

	len = sizeof(sa);
	if(getsockname(fd, &sa, &len) < 0)
		oserror();

	if(sin->sin_family != AF_INET || len != sizeof(*sin))
		error("not AF_INET");

	*laddr = nhgetl(&sin->sin_addr.s_addr);
	*lport = nhgets(&sin->sin_port);
}
Beispiel #23
0
static void
tcpreader(void *a)
{
	Session *s = a;
	uint8_t *buf;
	int buflen = smbglobals.maxreceive + 4;
	buf = nbemalloc(buflen);
	for (;;) {
		int n;
		uint8_t flags;
		uint16_t length;

		n = readn(s->fd, buf, 4);
		if (n != 4) {
		die:
			free(buf);
			if (s->state == Connected)
				(*s->write)(s, nil, -1);
			deletesession(s);
			return;
		}
		flags = buf[1];
		length = nhgets(buf + 2) | ((flags & 1) << 16);
		if (length > buflen - 4) {
			print("nbss: too much data (%ud)\n", length);
			goto die;
		}
		n = readn(s->fd, buf + 4, length);
		if (n != length)
			goto die;
		if (s->state == Connected) {
			if ((*s->write)(s, buf + 4, length) != 0) {
				s->state = Dead;
				goto die;
			}
		}
	}
}
Beispiel #24
0
int
wantoffer(uint8_t *pkt)
{
	int i, len;
	uint8_t *s;
	Etherhdr *eh;
	Pppoehdr *ph;

	eh = (Etherhdr*)pkt;
	ph = (Pppoehdr*)(pkt+EtherHdrSz);

	if(ph->code != CodeDiscOffer)
		return bad("not an offer");
	if(nhgets(ph->sessid) != 0x0000)
		return bad("bad session id");

	for(i=0;; i++){
		if((s = findtag(pkt, TagSrvName, &len, i)) == nil)
			return bad("no matching service name");
		if(len == strlen(srvname) && memcmp(s, srvname, len) == 0)
			break;
	}

	if((s = findtag(pkt, TagAcName, &len, 0)) == nil)
		return bad("no ac name");
	acname = copy(s, len);
	if(wantac && strcmp(acname, wantac) != 0){
		free(acname);
		return bad("wrong ac name");
	}

	if(s = findtag(pkt, TagAcCookie, &len, 0)){
		cookie = copy(s, len);
		cookielen = len;
	}
	memmove(etherdst, eh->src, sizeof etherdst);
	return 1;
}
Beispiel #25
0
int
so_accept(int fd, uchar *raddr, ushort *rport)
{
	int nfd, len;
	struct sockaddr_storage sa;
	struct sockaddr_in6 *sin6;

	sin6 = (struct sockaddr_in6*)&sa;

	len = sizeof(*sin6);
	osenter();
	nfd = accept(fd, (struct sockaddr*)&sa, &len);
	osleave();
	if(nfd < 0)
		oserror();

	if(sin6->sin6_family != AF_INET6 || len != sizeof(*sin6))
		error("not AF_INET6");

	memmove(raddr, &sin6->sin6_addr, IPaddrlen);
	*rport = nhgets(&sin6->sin6_port);
	return nfd;
}
Beispiel #26
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);

}
Beispiel #27
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++;
}
Beispiel #28
0
void
bootpdump(uint8_t *p, int n)
{
	int len, i, code;
	Bootp *bp;
	Udphdr *up;

	bp = (Bootp*)p;
	up = (Udphdr*)bp->udphdr;

	if(n < bp->optmagic - p) {
		fprint(2, "dhcpclient: short bootp packet");
		return;
	}

	fprint(2, "laddr=%I lport=%d raddr=%I rport=%d\n", up->laddr,
		nhgets(up->lport), up->raddr, nhgets(up->rport));
	fprint(2, "op=%d htype=%d hlen=%d hops=%d\n", bp->op, bp->htype,
		bp->hlen, bp->hops);
	fprint(2, "xid=%ux secs=%d flags=%ux\n", nhgetl(bp->xid),
		nhgets(bp->secs), nhgets(bp->flags));
	fprint(2, "ciaddr=%V yiaddr=%V siaddr=%V giaddr=%V\n",
		bp->ciaddr, bp->yiaddr, bp->siaddr, bp->giaddr);
	fprint(2, "chaddr=");
	for(i=0; i<16; i++)
		fprint(2, "%ux ", bp->chaddr[i]);
	fprint(2, "\n");
	fprint(2, "sname=%s\n", bp->sname);
	fprint(2, "file = %s\n", bp->file);

	n -= bp->optmagic - p;
	p = bp->optmagic;

	if(n < 4)
		return;
	if(memcmp(optmagic, p, 4) != 0)
		fprint(2, "dhcpclient: bad opt magic %ux %ux %ux %ux\n",
			p[0], p[1], p[2], p[3]);
	p += 4;
	n -= 4;

	while(n>0) {
		code = *p++;
		n--;
		if(code == OBpad)
			continue;
		if(code == OBend)
			break;
		if(n == 0) {
			fprint(2, " bad option: %d", code);
			return;
		}
		len = *p++;
		n--;
		if(len > n) {
			fprint(2, " bad option: %d", code);
			return;
		}
		switch(code) {
		default:
			fprint(2, "unknown option %d\n", code);
			for(i = 0; i<len; i++)
				fprint(2, "%ux ", p[i]);
		case ODtype:
			fprint(2, "DHCP type %d\n", p[0]);
			break;
		case ODclientid:
			fprint(2, "client id=");
			for(i = 0; i<len; i++)
				fprint(2, "%ux ", p[i]);
			fprint(2, "\n");
			break;
		case ODlease:
			fprint(2, "lease=%d\n", nhgetl(p));
			break;
		case ODserverid:
			fprint(2, "server id=%V\n", p);
			break;
		case OBmask:
			fprint(2, "mask=%V\n", p);
			break;
		case OBrouter:
			fprint(2, "router=%V\n", p);
			break;
		}
		p += len;
		n -= len;
	}
}
Beispiel #29
0
Datei: gre.c Projekt: 8l/inferno
static void
greiput(Proto *gre, Ipifc*, Block *bp)
{
	int len;
	GREhdr *ghp;
	Conv *c, **p;
	ushort eproto;
	uchar raddr[IPaddrlen];
	GREpriv *gpriv;

	gpriv = gre->priv;
	ghp = (GREhdr*)(bp->rp);

	v4tov6(raddr, ghp->src);
	eproto = nhgets(ghp->eproto);
	qlock(gre);

	/* Look for a conversation structure for this port and address */
	c = nil;
	for(p = gre->conv; *p; p++) {
		c = *p;
		if(c->inuse == 0)
			continue;
		if(c->rport == eproto && 
			(gpriv->raw || ipcmp(c->raddr, raddr) == 0))
			break;
	}

	if(*p == nil) {
		qunlock(gre);
		freeblist(bp);
		return;
	}

	qunlock(gre);

	/*
	 * Trim the packet down to data size
	 */
	len = nhgets(ghp->len) - GRE_IPONLY;
	if(len < GRE_IPPLUSGRE){
		freeblist(bp);
		return;
	}
	bp = trimblock(bp, GRE_IPONLY, len);
	if(bp == nil){
		gpriv->lenerr++;
		return;
	}

	/*
	 *  Can't delimit packet so pull it all into one block.
	 */
	if(qlen(c->rq) > 64*1024)
		freeblist(bp);
	else{
		bp = concatblock(bp);
		if(bp == 0)
			panic("greiput");
		qpass(c->rq, bp);
	}
}
Beispiel #30
0
int
pppoe(char *ether)
{
	char buf[64];
	uint8_t pkt[1520];
	int dfd, p[2], n, sfd, sz, timeout;
	Pppoehdr *ph;

	ph = (Pppoehdr*)(pkt+EtherHdrSz);
	snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeDiscovery);
	if((dfd = dial(buf, nil, nil, nil)) < 0)
		sysfatal("dial %s: %r", buf);

	snprint(buf, sizeof buf, "%s!%d", ether, EtherPppoeSession);
	if((sfd = dial(buf, nil, nil, nil)) < 0)
		sysfatal("dial %s: %r", buf);

	for(timeout=250; timeout<16000; timeout*=2){
		clearstate();
		memset(pkt, 0, sizeof pkt);
		sz = padi(pkt);
		if(debug)
			dumppkt(pkt);
		if(sz < EtherMintu)
			sz = EtherMintu;
		ewrite(dfd, pkt, sz);

		if(pktread(timeout, dfd, pkt, sizeof pkt, wantoffer) < 0)
			continue;

		memset(pkt, 0, sizeof pkt);
		sz = padr(pkt);
		if(debug)
			dumppkt(pkt);
		if(sz < EtherMintu)
			sz = EtherMintu;
		ewrite(dfd, pkt, sz);

		if(pktread(timeout, dfd, pkt, sizeof pkt, wantsession) < 0)
			continue;

		break;
	}
	if(sessid < 0)
		sysfatal("could not establish session");

	rfork(RFNOTEG);
	if(pipe(p) < 0)
		sysfatal("pipe: %r");

	switch(fork()){
	case -1:
		sysfatal("fork: %r");
	default:
		break;
	case 0:
		close(p[1]);
		while((n = read(p[0], pkt+Hdr, sizeof pkt-Hdr)) > 0){
			etherhdr(pkt, etherdst, EtherPppoeSession);
			pppoehdr(pkt+EtherHdrSz, 0x00, sessid);
			hnputs(pkt+Hdr-2, n);
			sz = Hdr+n;
			if(debug > 1){
				dumppkt(pkt);
				hexdump(pkt, sz);
			}
			if(sz < EtherMintu)
				sz = EtherMintu;
			if(write(sfd, pkt, sz) < 0){
				if(debug)
					fprint(2, "write to ether failed: %r");
				_exits(nil);
			}
		}
		_exits(nil);
	}

	switch(fork()){
	case -1:
		sysfatal("fork: %r");
	default:
		break;
	case 0:
		close(p[1]);
		while((n = read(sfd, pkt, sizeof pkt)) > 0){
			if(malformed(pkt, n, EtherPppoeSession)
			|| ph->code != 0x00 || nhgets(ph->sessid) != sessid){
				if(debug)
					fprint(2, "malformed session pkt: %r\n");
				if(debug)
					dumppkt(pkt);
				continue;
			}
			if(write(p[0], pkt+Hdr, nhgets(ph->length)) < 0){
				if(debug)
					fprint(2, "write to ppp failed: %r\n");
				_exits(nil);
			}
		}
		_exits(nil);
	}
	close(p[0]);
	return p[1];
}