Browse Source

Plan 9 from Bell Labs 2003-04-20

David du Colombier 21 years ago
parent
commit
ec1e487e0b
5 changed files with 674 additions and 18 deletions
  1. 5 4
      dist/replica/plan9.db
  2. 5 0
      dist/replica/plan9.log
  3. 643 0
      sys/src/9/ip/nudp.c
  4. 19 14
      sys/src/cmd/ip/rip.c
  5. 2 0
      sys/src/cmd/ndb/dnresolve.c

+ 5 - 4
dist/replica/plan9.db

@@ -268,7 +268,7 @@
 386/bin/ip/pptpd - 775 sys sys 1045538024 123603
 386/bin/ip/rarpd - 775 sys sys 1045538024 107221
 386/bin/ip/rexexec - 775 sys sys 1048799695 86880
-386/bin/ip/rip - 775 sys sys 1039758571 89757
+386/bin/ip/rip - 775 sys sys 1050760699 89819
 386/bin/ip/rlogind - 775 sys sys 1045538025 66387
 386/bin/ip/telnetd - 775 sys sys 1048799696 120198
 386/bin/ip/tftpd - 775 sys sys 1045538025 102539
@@ -297,7 +297,7 @@
 386/bin/ndb - 20000000775 sys sys 985743147 0
 386/bin/ndb/cs - 775 sys sys 1049377481 143599
 386/bin/ndb/csquery - 775 sys sys 1039758577 60136
-386/bin/ndb/dns - 775 sys sys 1050714846 211399
+386/bin/ndb/dns - 775 sys sys 1050757250 211475
 386/bin/ndb/dnsdebug - 775 sys sys 1050714853 186310
 386/bin/ndb/dnsquery - 775 sys sys 1039758578 62442
 386/bin/ndb/dnstcp - 775 sys sys 1049428258 185185
@@ -5062,6 +5062,7 @@ sys/src/9/ip/ipv6.h - 664 sys sys 1022588099 4304
 sys/src/9/ip/loopbackmedium.c - 664 sys sys 1045063513 1651
 sys/src/9/ip/netdevmedium.c - 664 sys sys 1045063517 2675
 sys/src/9/ip/netlog.c - 664 sys sys 1026847568 4003
+sys/src/9/ip/nudp.c - 664 sys sys 1050756592 13069
 sys/src/9/ip/nullmedium.c - 664 sys sys 1022588099 491
 sys/src/9/ip/pktmedium.c - 664 sys sys 1045063516 1355
 sys/src/9/ip/ptclbsum.c - 664 sys sys 1022588099 1243
@@ -9075,7 +9076,7 @@ sys/src/cmd/ip/pptp.c - 664 sys sys 1050360938 16575
 sys/src/cmd/ip/pptpd.c - 664 sys sys 1015701128 23548
 sys/src/cmd/ip/rarpd.c - 664 sys sys 1031510476 3347
 sys/src/cmd/ip/rexexec.c - 664 sys sys 1025393126 740
-sys/src/cmd/ip/rip.c - 664 sys sys 1015701126 12315
+sys/src/cmd/ip/rip.c - 664 sys sys 1050760698 12424
 sys/src/cmd/ip/rlogind.c - 664 sys sys 1015013113 755
 sys/src/cmd/ip/snoopy - 20000000775 sys sys 1015090062 0
 sys/src/cmd/ip/snoopy/arp.c - 664 sys sys 1032059928 1902
@@ -9313,7 +9314,7 @@ sys/src/cmd/ndb/csgetval.c - 664 sys sys 957402051 1051
 sys/src/cmd/ndb/csquery.c - 664 sys sys 1014926159 1062
 sys/src/cmd/ndb/dblookup.c - 664 sys sys 1049249333 18409
 sys/src/cmd/ndb/dn.c - 664 sys sys 1049408473 25198
-sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1050714836 15288
+sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1050757241 15358
 sys/src/cmd/ndb/dns.c - 664 sys sys 1049249331 15051
 sys/src/cmd/ndb/dns.h - 664 sys sys 1032060499 8082
 sys/src/cmd/ndb/dnsdebug.c - 664 sys sys 1049249332 8333

+ 5 - 0
dist/replica/plan9.log

@@ -19171,3 +19171,8 @@
 1050715915 19 c sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1050714836 15288
 1050715915 20 c sys/src/cmd/ndb/dnudpserver.c - 664 sys sys 1050714835 5133
 1050717717 0 c sys/src/libsunrpc/udp.c - 664 sys sys 1050717777 2193
+1050757300 0 c 386/bin/ndb/dns - 775 sys sys 1050757250 211475
+1050757300 1 a sys/src/9/ip/nudp.c - 664 sys sys 1050756592 13069
+1050757300 2 c sys/src/cmd/ndb/dnresolve.c - 664 sys sys 1050757241 15358
+1050760903 0 c 386/bin/ip/rip - 775 sys sys 1050760699 89819
+1050760903 1 c sys/src/cmd/ip/rip.c - 664 sys sys 1050760698 12424

+ 643 - 0
sys/src/9/ip/nudp.c

@@ -0,0 +1,643 @@
+#include	"u.h"
+#include	"../port/lib.h"
+#include	"mem.h"
+#include	"dat.h"
+#include	"fns.h"
+#include	"../port/error.h"
+
+#include	"ip.h"
+#include	"ipv6.h"
+
+
+#define DPRINT if(0)print
+
+enum
+{
+	UDP_UDPHDR_SZ	= 8,
+
+	UDP4_PHDR_OFF = 8,
+	UDP4_PHDR_SZ = 12,
+	UDP4_IPHDR_SZ = 20,
+	UDP6_IPHDR_SZ = 40,
+	UDP6_PHDR_SZ = 40,
+	UDP6_PHDR_OFF = 0,
+
+	IP_UDPPROTO	= 17,
+	UDP_USEAD7	= 52,
+	UDP_USEAD6	= 36,
+
+	Udprxms		= 200,
+	Udptickms	= 100,
+	Udpmaxxmit	= 10,
+};
+
+typedef struct Udp4hdr Udp4hdr;
+struct Udp4hdr
+{
+	/* ip header */
+	uchar	vihl;		/* Version and header length */
+	uchar	tos;		/* Type of service */
+	uchar	length[2];	/* packet length */
+	uchar	id[2];		/* Identification */
+	uchar	frag[2];	/* Fragment information */
+	uchar	Unused;	
+	uchar	udpproto;	/* Protocol */
+	uchar	udpplen[2];	/* Header plus data length */
+	uchar	udpsrc[IPv4addrlen];	/* Ip source */
+	uchar	udpdst[IPv4addrlen];	/* Ip destination */
+
+	/* udp header */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+typedef struct Udp6hdr Udp6hdr;
+struct Udp6hdr {
+	uchar viclfl[4];
+	uchar len[2];
+	uchar nextheader;
+	uchar hoplimit;
+	uchar udpsrc[IPaddrlen];
+	uchar udpdst[IPaddrlen];
+
+	/* udp header */
+	uchar	udpsport[2];	/* Source port */
+	uchar	udpdport[2];	/* Destination port */
+	uchar	udplen[2];	/* data length */
+	uchar	udpcksum[2];	/* Checksum */
+};
+
+/* MIB II counters */
+typedef struct Udpstats Udpstats;
+struct Udpstats
+{
+	ulong	udpInDatagrams;
+	ulong	udpNoPorts;
+	ulong	udpInErrors;
+	ulong	udpOutDatagrams;
+};
+
+typedef struct Udppriv Udppriv;
+struct Udppriv
+{
+	Ipht		ht;
+
+	/* MIB counters */
+	Udpstats	ustats;
+
+	/* non-MIB stats */
+	ulong		csumerr;		/* checksum errors */
+	ulong		lenerr;			/* short packet */
+};
+
+void (*etherprofiler)(char *name, int qlen);
+void udpkick(void *x, Block *bp);
+
+/*
+ *  protocol specific part of Conv
+ */
+typedef struct Udpcb Udpcb;
+struct Udpcb
+{
+	QLock;
+	uchar	headers;
+};
+
+static char*
+udpconnect(Conv *c, char **argv, int argc)
+{
+	char *e;
+	Udppriv *upriv;
+
+	upriv = c->p->priv;
+	e = Fsstdconnect(c, argv, argc);
+	Fsconnected(c, e);
+	if(e != nil)
+		return e;
+
+	iphtadd(&upriv->ht, c);
+	return nil;
+}
+
+
+static int
+udpstate(Conv *c, char *state, int n)
+{
+	return snprint(state, n, "%s", c->inuse?"Open":"Closed");
+}
+
+static char*
+udpannounce(Conv *c, char** argv, int argc)
+{
+	char *e;
+	Udppriv *upriv;
+
+	upriv = c->p->priv;
+	e = Fsstdannounce(c, argv, argc);
+	if(e != nil)
+		return e;
+	Fsconnected(c, nil);
+	iphtadd(&upriv->ht, c);
+
+	return nil;
+}
+
+static void
+udpcreate(Conv *c)
+{
+	c->rq = qopen(128*1024, Qmsg, 0, 0);
+	c->wq = qbypass(udpkick, c);
+}
+
+static void
+udpclose(Conv *c)
+{
+	Udpcb *ucb;
+	Udppriv *upriv;
+
+	upriv = c->p->priv;
+	iphtrem(&upriv->ht, c);
+
+	c->state = 0;
+	qclose(c->rq);
+	qclose(c->wq);
+	qclose(c->eq);
+	ipmove(c->laddr, IPnoaddr);
+	ipmove(c->raddr, IPnoaddr);
+	c->lport = 0;
+	c->rport = 0;
+
+	ucb = (Udpcb*)c->ptcl;
+	ucb->headers = 0;
+
+	qunlock(c);
+}
+
+void
+udpkick(void *x, Block *bp)
+{
+	Conv *c = x;
+	Udp4hdr *uh4;
+	Udp6hdr *uh6;
+	ushort rport;
+	uchar laddr[IPaddrlen], raddr[IPaddrlen];
+	Udpcb *ucb;
+	int dlen, ptcllen;
+	Udppriv *upriv;
+	Fs *f;
+	int version;
+	Conv *rc;
+
+	upriv = c->p->priv;
+	f = c->p->f;
+
+	netlog(c->p->f, Logudp, "udp: kick\n");
+	if(bp == nil)
+		return;
+
+	ucb = (Udpcb*)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;
+	case 6:
+		/* get user specified addresses */
+		bp = pullupblock(bp, UDP_USEAD6);
+		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);
+		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 = 4;
+		else
+			version = 6;
+	} else {
+		if( (memcmp(c->raddr, v4prefix, IPv4off) == 0 &&
+			memcmp(c->laddr, v4prefix, IPv4off) == 0)
+			|| ipcmp(c->raddr, IPnoaddr) == 0)
+			version = 4;
+		else
+			version = 6;
+	}
+
+	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 == nil)
+			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 = nil;
+		} 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, dlen+UDP_UDPHDR_SZ+UDP4_PHDR_SZ));
+		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 == nil)
+			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 = nil;
+		} else {
+			ipmove(uh6->udpdst, c->raddr);
+			hnputs(uh6->udpdport, c->rport);
+			if(ipcmp(c->laddr, IPnoaddr) == 0)
+				findlocalip(f, c->laddr, c->raddr);
+			ipmove(uh6->udpsrc, c->laddr);
+			rc = c;
+		}
+		hnputs(uh6->udpsport, c->lport);
+		hnputs(uh6->udplen, ptcllen);
+		uh6->udpcksum[0] = 0;
+		uh6->udpcksum[1] = 0;
+		hnputs(uh6->udpcksum, 
+		       ptclcsum(bp, UDP6_PHDR_OFF, dlen+UDP_UDPHDR_SZ+UDP6_PHDR_SZ));
+		memset(uh6, 0, 8);
+		uh6->viclfl[0] = IP_VER6;
+		hnputs(uh6->len, ptcllen);
+		uh6->nextheader = IP_UDPPROTO;
+		ipoput6(f, bp, 0, c->ttl, c->tos, rc);
+		break;
+
+	default:
+		panic("udpkick: version %d", version);
+	}
+	upriv->ustats.udpOutDatagrams++;
+}
+
+void
+udpiput(Proto *udp, Ipifc *ifc, Block *bp)
+{
+	int len;
+	Udp4hdr *uh4;
+	Udp6hdr *uh6;
+	Conv *c;
+	Udpcb *ucb;
+	uchar raddr[IPaddrlen], laddr[IPaddrlen];
+	ushort rport, lport;
+	Udppriv *upriv;
+	Fs *f;
+	int version;
+	int ottl, oviclfl, olen;
+	uchar *p;
+
+	upriv = udp->priv;
+	f = udp->f;
+	upriv->ustats.udpInDatagrams++;
+
+	uh4 = (Udp4hdr*)(bp->rp);
+	version = ((uh4->vihl&0xF0)==IP_VER6) ? 6 : 4;
+
+	/* 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(nhgets(uh4->udpcksum)) {
+			if(ptclcsum(bp, UDP4_PHDR_OFF, len+UDP4_PHDR_SZ)) {
+				upriv->ustats.udpInErrors++;
+				netlog(f, Logudp, "udp: checksum error %I\n", raddr);
+				DPRINT("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);
+			DPRINT("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);
+
+	c = iphtlook(&upriv->ht, raddr, rport, laddr, lport);
+	if(c == nil){
+		/* no converstation found */
+		upriv->ustats.udpNoPorts++;
+		qunlock(udp);
+		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 == nil){
+				qunlock(udp);
+				freeblist(bp);
+				return;
+			}
+			iphtadd(&upriv->ht, c);
+			ucb = (Udpcb*)c->ptcl;
+		}
+	}
+
+	qlock(c);
+	qunlock(udp);
+
+	/*
+	 * 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 = nil;
+		panic("udpiput4: version %d", version);
+	}
+	if(bp == nil){
+		qunlock(c);
+		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);
+		netlog(f, Logudp, "udp: qfull %I.%d -> %I.%d\n", raddr, rport,
+		       laddr, lport);
+		freeblist(bp);
+		return;
+	}
+
+	qpass(c->rq, bp);
+	qunlock(c);
+
+}
+
+char*
+udpctl(Conv *c, char **f, int n)
+{
+	Udpcb *ucb;
+
+	ucb = (Udpcb*)c->ptcl;
+	if(n == 1){
+		if(strcmp(f[0], "oldheaders") == 0){
+			ucb->headers = 6;
+			return nil;
+		} else if(strcmp(f[0], "headers") == 0){
+			ucb->headers = 7;
+			return nil;
+		}
+	}
+	return "unknown control request";
+}
+
+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);
+}
+
+int
+udpstats(Proto *udp, char *buf, int len)
+{
+	Udppriv *upriv;
+
+	upriv = udp->priv;
+	return snprint(buf, len, "InDatagrams: %lud\nNoPorts: %lud\nInErrors: %lud\nOutDatagrams: %lud\n",
+		upriv->ustats.udpInDatagrams,
+		upriv->ustats.udpNoPorts,
+		upriv->ustats.udpInErrors,
+		upriv->ustats.udpOutDatagrams);
+}
+
+void
+udpinit(Fs *fs)
+{
+	Proto *udp;
+
+	udp = smalloc(sizeof(Proto));
+	udp->priv = smalloc(sizeof(Udppriv));
+	udp->name = "udp";
+	udp->connect = udpconnect;
+	udp->announce = udpannounce;
+	udp->ctl = udpctl;
+	udp->state = udpstate;
+	udp->create = udpcreate;
+	udp->close = udpclose;
+	udp->rcv = udpiput;
+	udp->advise = udpadvise;
+	udp->stats = udpstats;
+	udp->ipproto = IP_UDPPROTO;
+	udp->nc = Nchans;
+	udp->ptclsize = sizeof(Udpcb);
+
+	Fsproto(fs, udp);
+}

+ 19 - 14
sys/src/cmd/ip/rip.c

@@ -202,7 +202,7 @@ void
 main(int argc, char *argv[])
 {
 	int i, n;
-	Udphdr *up;
+	OUdphdr *up;
 	Ripmsg *m;
 	Rip *r;
 	Route route;
@@ -212,6 +212,7 @@ main(int argc, char *argv[])
 	long diff;
 	char *p;
 	static long btime;
+	uchar raddr[Pasize];
 
 
 	setnetmtpt(netdir, sizeof(netdir), nil);
@@ -291,23 +292,24 @@ main(int argc, char *argv[])
 		if(n <= 0)
 			continue;
 
-		n = (n-Udphdrsize-4)/sizeof(Rip);
+		n = (n-OUdphdrsize-4)/sizeof(Rip);
 		if(n <= 0)
 			continue;
 
-		up = (Udphdr*)buf;
-		m = (Ripmsg*)(buf+Udphdrsize);
+		up = (OUdphdr*)buf;
+		m = (Ripmsg*)(buf+OUdphdrsize);
 		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, up->raddr))
+			if(equivip(ialloc.ifc[i].addr, raddr))
 				continue;
 
 		now = time(0);
 		for(r = m->rip; r < &m->rip[n]; r++){
-			memmove(route.gate, up->raddr, Pasize);
+			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;
@@ -330,8 +332,9 @@ openport(void)
 	ripctl = announce(data, devdir);
 	if(ripctl < 0)
 		fatal(1, "can't announce");
-	if(write(ripctl, "headers4", sizeof("headers")) < 0)
+	if(fprint(ripctl, "headers") < 0)
 		fatal(1, "can't set header mode");
+	fprint(ripctl, "oldheaders");
 
 	sprint(data, "%s/data", devdir);
 
@@ -612,15 +615,17 @@ sendto(Ifc *ip)
 {
 	int h, n;
 	Route *r;
-	uchar mbuf[Udphdrsize+512];
+	uchar mbuf[OUdphdrsize+512];
 	Ripmsg *m;
-	Udphdr *u;
+	OUdphdr *u;
+	uchar raddr[Pasize];
 
-	u = (Udphdr*)mbuf;
+	u = (OUdphdr*)mbuf;
 	for(n = 0; n < Pasize; n++)
-		u->raddr[n] = ip->net[n] | ~(ip->mask[n]);
+		raddr[n] = ip->net[n] | ~(ip->mask[n]);
+	v4tov6(u->raddr, raddr);
 	hnputs(u->rport, 520);
-	m = (Ripmsg*)(mbuf+Udphdrsize);
+	m = (Ripmsg*)(mbuf+OUdphdrsize);
 	m->type = Response;
 	m->vers = Version;
 	if(debug)
@@ -661,14 +666,14 @@ sendto(Ifc *ip)
 				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);
+				write(ripfd, mbuf, OUdphdrsize+4+n*20);
 				n = 0;
 			}
 		}
 	}
 
 	if(n && !readonly)
-		write(ripfd, mbuf, Udphdrsize+4+n*20);
+		write(ripfd, mbuf, OUdphdrsize+4+n*20);
 }
 void
 broadcast(void)

+ 2 - 0
sys/src/cmd/ndb/dnresolve.c

@@ -243,6 +243,7 @@ walkup(char *name)
  *  into "headers" mode.
  */
 static char *hmsg = "headers";
+static char *ohmsg = "oldheaders";
 
 static int
 udpport(void)
@@ -265,6 +266,7 @@ udpport(void)
 		warning(hmsg);
 		return -1;
 	}
+	write(ctl, ohmsg, strlen(ohmsg));
 
 	/* grab the data file */
 	snprint(ds, sizeof(ds), "%s/data", adir);