Coda File System

A Christmas Present: RPC2 over IPv6

From: Rod Van Meter <Rod.VanMeter_at_nokia.com>
Date: 20 Dec 2002 14:35:36 -0800
A patchfile for your pleasure, against rpc2-1.14-1.  Very rough so far,
and probably only about 10-15% of the total work in making Coda run over
IPv6 (updating the database format will be fun).  But, it's a start. 
See README.ipv6 for more.

It's unlikely that I'll be contributing significantly toward the next
stage of making the full Coda run over IPv6; it's not really my main
line of work, and that's piling up.  I'll be happy to test and help out
if someone wants to pick it up and run with it, though.

		--Rod

P.S. I'm gone for two weeks, away from email.  Happy New Year!

*** /dev/null	2002-08-30 16:31:37.000000000 -0700
--- README.ipv6	2002-12-20 07:31:12.000000000 -0800
***************
*** 0 ****
--- 1,91 ----
+ The RPC2 IPv6 code is copyright (c) 2002, Nokia.  The author is Rod
+ Van Meter (Rod.VanMeter_at_Nokia.com or rdv_at_alumni.caltech.edu).  As part
+ of the RPC2 suite, this code is licensed under the LGPL.
+ 
+ This code is a rewrite of the key networking code, following the
+ advice of Metz [1], to be protocol independent.  It replaces the IPv4
+ code with code intended to support both IPv4 and IPv6.  The code uses
+ the more modern getaddrinfo() to replace gethostbyname() [2].
+ 
+ The new code has been tested to work (using stest and ctest) both
+ within a node (using the loopback address) and between a pair of nodes
+ with globally routable IPv6 addresses, using DNS names.  Also tested
+ for IPv4.
+ 
+ This should, in theory, work over Mobile IPv6, which should enhance
+ its overall usability.  This is not yet tested.
+ 
+ COMPILING AND INSTALLING
+ 
+ To turn on this code, compile with
+ 
+ #define CODA_IPV6
+ 
+ To do this, at the moment, I run ./configure, then put the following
+ at the bottom of the generated config.h:
+ 
+ /* XXX hand-hacked by rdv */
+ #define CODA_IPV6
+ 
+ 
+ TODO
+ 
+ This is, so far, VERY incomplete code, and reflects my still-evolving
+ understanding of the best way to write protocol-independent code.
+ Some of these are marked with XXX in the source.
+ 
+ * This desperately needs a config flag.  I'm no autoconf guru, so I
+   just hack this into config.h when I want to turn it on.  Ideally,
+   autoconf itself needs a test for whether IPv6 and the new APIs are
+   supported.  I'm surprised no one has done this yet.
+ * One goal is to eliminate RPC2_PortIdent and rpc2_LocalPort and keep
+   it all in one structure, RPC2_HostIdent.  This is only partially
+   done.
+ * There are probably ways to reduce further the dependence on
+   sockaddr_in and sockaddr_in6.  Some of the existing use is probably
+   not type safe, too.
+ * This is only in the RPC2 code.  To be useful, it needs to be
+   incorporated into the full Coda code, including things like the
+   configuration files.
+ * I'm far from certain, at this point, that I'm not leaking memory
+   with the malloc()s I'm doing for addrinfo.
+ * I'm equally uncertain that what I have is thread safe, to the extent
+   that the code can handle concurrent requests.
+ * Multi-valued returns from getaddrinfo, which are the norm, are not
+   yet handled properly.  The code should look through the list to find
+   the best one for its purposes, perhaps by trying them all.  This is
+   especially important given that not all clients and servers will
+   support v6 right away.
+ * There are too many places with #ifdef CODA_IPV6...#else...This is
+   fragile code.
+ * I'm sure there are error conditions I'm not catching right yet.
+ * So far, this is only tested on Linux (Red Hat 8.0 with the stock
+   2.4.18-14 kernel).  I'll test it on FreeBSD 4.x and other Linux
+   kernels at some point, but someone else will have to test the
+   broader range of systems.  The APIs should be the same, but
+   differences in behavior (e.g., ordering of addresses returned) may
+   affect it.
+ * As mentioned above, not yet tested over Mobile IP.
+ * Testing so far consists of running stest and a single ctest.  There
+   are probably bugs lurking that aren't exercised with this simple
+   setup.
+ * Not yet tested with scoped (site or link local) addresses, other
+   than the loopback address.  This probably needs code (the advanced
+   sockets API [3]).
+ * Not yet tested on a system that supports v6 but doesn't have the
+   module loaded or IPv6 otherwise enabled.  I'll bet
+     if (error = getaddrinfo("::1", NULL, &req, &ai))
+       if (error = getaddrinfo("localhost", NULL, &req, &ai))
+   will do it.
+ 
+ References
+ 
+ [1] Metz, C., "Protocol Independence Using the Sockets API", FREENIX
+ 2000, June 2000.
+
http://www.usenix.org/publications/library/proceedings/usenix2000/freenix/metzprotocol.html
+ 
+ [2] R. Gilligan, S. Thomson, J. Bound, W. Stevens,  "Basic Socket
+ Interface Extensions for IPv6", RFC2553, March 1999.
+ 
+ [3] W. Stevens, M. Thomas, "Advanced Sockets API for IPv6",  RFC 2292,
+ February 1998.
*** rpc2-src/rpc2a.c.orig	2002-12-19 11:37:16.000000000 -0800
--- rpc2-src/rpc2a.c	2002-12-19 11:39:44.000000000 -0800
***************
*** 348,355 ****
--- 348,366 ----
      /* And now we are really done */
      if (ce->Flags & CE_OLDV)
      {
+ #ifdef CODA_IPV6
+ 	char addr[50];
+ 	struct addrinfo *aip = ce->PeerHost.Value.AddrInfo;
+ 	if (!inet_ntop(aip->ai_family,aip->ai_addr,addr,aip->ai_addrlen)) {
+ 	    say(-1, RPC2_DebugLevel, "Request from (untranslatable): Old rpc2
version\n");
+ 	} else {
+ 	    say(-1, RPC2_DebugLevel, "Request from %s: Old rpc2 version\n",
+ 		addr);
+ 	}
+ #else /* CODA_IPV6 */
  	say(-1, RPC2_DebugLevel, "Request from %s: Old rpc2 version\n",
  		inet_ntoa(ce->PeerHost.Value.InetAddress));
+ #endif /* CODA_IPV6 */
  
  	/* Get rid of allocated connection entry. */
  	DROPIT();
***************
*** 970,987 ****
--- 981,1027 ----
      */
      {
      struct servent *sentry;
+ #ifdef CODA_IPV6
+     struct addrinfo hint;
+     struct addrinfo *result;
+     int retval;
+ #else /* CODA_IPV6 */
      struct hostent *hentry;
+ #endif /* CODA_IPV6 */
  
      /* Resolve host */
      switch(whichHost->Tag)
  	{
  	case RPC2_HOSTBYINETADDR:	/* you passed it in in network order! */
  		whichConn->PeerHost.Tag = RPC2_HOSTBYINETADDR;
+ #ifdef CODA_IPV6
+ 		whichConn->PeerHost.Value.AddrInfo =
+ 		    whichHost->Value.AddrInfo; /* structure assignment */
+ #else /* CODA_IPV6 */
  		whichConn->PeerHost.Value.InetAddress.s_addr =
  		    whichHost->Value.InetAddress.s_addr;
+ #endif /* CODA_IPV6 */
  		break;
  
  	case RPC2_HOSTBYNAME:
+ #ifdef CODA_IPV6
+ 		bzero(&hint, sizeof(struct addrinfo));
+ 		hint.ai_family = PF_UNSPEC;
+ 		hint.ai_socktype = SOCK_DGRAM;
+ 		/* XXX need to know whether or not we're server, so
+ 		   we'll know whether or not to set AI_PASSIVE */
+ 		if ((retval = getaddrinfo(whichHost->Value.Name, NULL,
+ 					  &hint, &result))) {
+ 		    say(0, RPC2_DebugLevel, "ResolveBindParms: getaddrinfo
failed\n");
+ 		    return(RPC2_FAIL);
+ 		}
+ 		whichConn->PeerHost.Tag = RPC2_HOSTBYINETADDR;
+ 		/* XXX here -- just keep the addrinfo we were given */
+ 		whichConn->PeerHost.Value.AddrInfo = result;
+ 		/* memcpy(&whichConn->PeerHost.Value, result->ai_addr,
+ 		       result->ai_addrlen); */
+ 		/* XXX what do I do with multiple return values? */
+ #else /* CODA_IPV6 */
  		if ((hentry = gethostbyname (whichHost->Value.Name)) == NULL) {
  		    say(0, RPC2_DebugLevel, "ResolveBindParms: gethostbyname
failed\n");
  		    return(RPC2_FAIL);
***************
*** 989,994 ****
--- 1029,1035 ----
  		whichConn->PeerHost.Tag = RPC2_HOSTBYINETADDR;
  		memcpy(&whichConn->PeerHost.Value.InetAddress, hentry->h_addr,
  		       hentry->h_length); /* Already in network byte order */
+ #endif /* CODA_IPV6 */
  	    break;
  
  	default:  assert(FALSE);
*** rpc2-src/rpc2b.c.orig	2002-12-19 11:31:44.000000000 -0800
--- rpc2-src/rpc2b.c	2002-12-20 03:57:05.000000000 -0800
***************
*** 72,77 ****
--- 72,98 ----
  extern int errno;
  struct in_addr rpc2_bindaddr = { INADDR_ANY };
  
+ 
+ #ifdef CODA_IPV6
+ void rpc2_addrinfo_ntop(struct addrinfo *host, char *addr, int len)
+ {
+     switch (host->ai_family) {
+     case AF_INET:
+ 	inet_ntop(host->ai_family,
+ 		  (struct in_addr *)&(((struct sockaddr_in
*)host->ai_addr)->sin_addr),
+ 		  addr, len);
+ 	break;
+     case AF_INET6:
+ 	inet_ntop(host->ai_family,
+ 		  (struct in6_addr *)&(((struct sockaddr_in6
*)host->ai_addr)->sin6_addr),
+ 		  addr, len);
+ 	break;
+     default:
+ 	exit(-1);
+     }
+ }
+ #endif /* CODA_IPV6 */
+ 
  long RPC2_Init(char *VId,		/* magic version string */
  	       RPC2_Options *Options,
  	       RPC2_PortIdent *Port,	/* array of portal ids */
***************
*** 81,86 ****
--- 102,111 ----
  {
      char *c;
      long rc, i, ctpid;
+ #ifdef CODA_IPV6
+     int error;
+     struct addrinfo req, *ai;
+ #endif /* CODA_IPV6 */
  
      rpc2_logfile = stderr;
      rpc2_tracefile = stderr;
***************
*** 111,119 ****
--- 136,161 ----
       * requires an enormous amount of modifications all over rpc2.
--JH */
      
      rpc2_LocalHost.Tag = RPC2_HOSTBYINETADDR;
+ #ifdef CODA_IPV6
+     /* XXX this just uses the first one returned, for the moment */
+     memset(&req, 0, sizeof(struct addrinfo));
+     /* actually unnecessary, I think */
+     req.ai_family = PF_UNSPEC;
+     req.ai_socktype = SOCK_DGRAM;
+     if (error = getaddrinfo("::1", NULL, &req, &ai)) {
+ 	say(-1, RPC2_DebugLevel, "RPC2_Init(): Couldn't get addrinfo for
localhost!\n");
+ 	rpc2_Quit(rc);
+     }
+     rpc2_LocalHost.Value.AddrInfo = ai;
+ #else /* CODA_IPV6 */
      rpc2_LocalHost.Value.InetAddress.s_addr = htonl(INADDR_LOOPBACK);
+ #endif /* CODA_IPV6 */
      
+ #ifdef CODA_IPV6
+     rc = rpc2_CreateIPSocket(&rpc2_RequestSocket, &rpc2_LocalPort,
&rpc2_LocalHost);
+ #else /* CODA_IPV6 */
      rc = rpc2_CreateIPSocket(&rpc2_RequestSocket, &rpc2_LocalPort);
+ #endif /* CODA_IPV6 */
      if (Port) *Port = rpc2_LocalPort; 
  
      if (rc < RPC2_ELIMIT) {
***************
*** 803,816 ****
--- 845,874 ----
      }  
  
      
+ #ifdef CODA_IPV6
+ /* adding this arg in theory allows me to specify whether to
+    create a v4 or v6 socket.  Simpler way to do this? */
+ long rpc2_CreateIPSocket(long *svar, RPC2_PortIdent *pvar,
RPC2_HostIdent *hvar)
+ #else /* CODA_IPV6 */
  long rpc2_CreateIPSocket(long *svar, RPC2_PortIdent *pvar)
+ #endif /* CODA_IPV6 */
  {
+ #ifdef CODA_IPV6
+     struct sockaddr_storage bindaddr_storage;
+     struct sockaddr_in6 *bindaddr6 = (struct sockaddr_in6
*)&bindaddr_storage;
+     struct sockaddr_in *bindaddr = (struct sockaddr_in
*)&bindaddr_storage;
+ #else /* CODA_IPV6 */
  	struct sockaddr_in bindaddr;
+ #endif /* CODA_IPV6 */
  	struct servent *sentry;
  	int blen = 0x8000 ;
  
  	/* Allocate socket */
+ #ifdef CODA_IPV6
+ 	*svar = socket(hvar->Value.AddrInfo->ai_family, SOCK_DGRAM,
IPPROTO_UDP);
+ #else /* CODA_IPV6 */
  	*svar = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ #endif /* CODA_IPV6 */
  	if (*svar < 0) 
  		return(RPC2_FAIL);
  
***************
*** 844,849 ****
--- 902,987 ----
  		exit(1);
  	}
  #endif
+ #ifdef CODA_IPV6
+ 	memset(&bindaddr_storage, 0, sizeof(bindaddr_storage));
+ 	bindaddr_storage.ss_family = hvar->Value.AddrInfo->ai_family;
+         switch (bindaddr_storage.ss_family) {
+ 	case AF_INET:
+ 	    bindaddr->sin_addr = rpc2_bindaddr;
+ 	    blen = sizeof(struct sockaddr_in);	    
+ 	    /* set port address for bind() */
+ 	    switch (pvar->Tag) {
+ 	    case RPC2_PORTBYNAME:
+ 		sentry = getservbyname(pvar->Value.Name, "udp");
+ 		if (sentry == NULL) 
+ 		    return(RPC2_BADSERVER);
+ 		/* sentry has port in network order */
+ 		bindaddr->sin_port  = sentry->s_port;
+ 		break;
+ 	
+ 		/*  XXXX NO INETNUMBER , just ports */
+ 	    case RPC2_PORTBYINETNUMBER:
+ 		bindaddr->sin_port = pvar->Value.InetPortNumber;
+ 		break;
+ 
+ 	    case RPC2_DUMMYPORT:
+ 	    default:
+ 		bindaddr->sin_port = 0; /* kernel will assign */
+ 	    }
+ 	    break;
+ 	case AF_INET6:
+ 	    bindaddr6->sin6_addr = in6addr_any;	/* struct assignment */
+ 	    blen = sizeof(struct sockaddr_in6);
+ 	    /* set port address for bind() */
+ 	    switch (pvar->Tag) {
+ 	    case RPC2_PORTBYNAME:
+ 		sentry = getservbyname(pvar->Value.Name, "udp");
+ 		if (sentry == NULL) 
+ 		    return(RPC2_BADSERVER);
+ 		/* sentry has port in network order */
+ 		bindaddr6->sin6_port  = sentry->s_port;
+ 		break;
+ 	
+ 		/*  XXXX NO INETNUMBER , just ports */
+ 	    case RPC2_PORTBYINETNUMBER:
+ 		bindaddr6->sin6_port = pvar->Value.InetPortNumber;
+ 		break;
+ 
+ 	    case RPC2_DUMMYPORT:
+ 	    default:
+ 		bindaddr6->sin6_port = 0; /* kernel will assign */
+ 	    }
+ 	    break;
+ 	default:
+ 	    assert(FALSE);
+ 	} /* end switch af_family */
+ 
+ 	/* Now bind the socket */
+ 	if (bind (*svar, (struct sockaddr *)bindaddr, blen) < 0) {
+ 		if (errno == EADDRINUSE) 
+ 			return(RPC2_DUPLICATESERVER);
+ 		else 
+ 			return(RPC2_BADSERVER);
+ 	}
+ 
+ 	/* Retrieve fully resolved socket address */
+ 	assert(pvar->Tag != RPC2_DUMMYPORT);
+ 
+         blen = sizeof(bindaddr_storage);
+         if (getsockname(*svar, (struct sockaddr *)bindaddr, &blen) <
0) 
+             return(RPC2_FAIL);
+         pvar->Tag = RPC2_PORTBYINETNUMBER;
+         switch (bindaddr_storage.ss_family) {
+ 	case AF_INET:
+ 	    pvar->Value.InetPortNumber = bindaddr->sin_port; break;
+ 	case AF_INET6:
+         pvar->Value.InetPortNumber = bindaddr6->sin6_port; break;
+ 	default:
+ 	    assert(FALSE);
+ 	}
+ 
+ #else /* CODA_IPV6 */
+ 
  	/* set host address for bind() */
  	memset(&bindaddr, 0, sizeof(bindaddr));
  	bindaddr.sin_family = AF_INET;
***************
*** 885,890 ****
--- 1023,1029 ----
              return(RPC2_FAIL);
          pvar->Tag = RPC2_PORTBYINETNUMBER;
          pvar->Value.InetPortNumber = bindaddr.sin_port;
+ #endif /* CODA_IPV6 */
  
  #ifdef RPC2DEBUG
  	if (RPC2_DebugLevel > 9) {
*** rpc2-src/conn.c.orig	2002-12-19 11:42:41.000000000 -0800
--- rpc2-src/conn.c	2002-12-19 11:42:54.000000000 -0800
***************
*** 47,52 ****
--- 47,58 ----
  #include <sys/time.h>
  #include <time.h>
  #include <assert.h>
+ /* what's the right thing to do here? */
+ #include <config.h>
+ #ifdef CODA_IPV6
+ #include <rpc2/rpc2.h>
+ #include <netdb.h>
+ #endif /* CODA_IPV6 */
  #include "rpc2.private.h"
  
  /* HASHLENGTH should be a power of two, because we use modulo
HASHLENGTH-1 to
*** rpc2-src/ctest.c.orig	2002-12-19 11:43:41.000000000 -0800
--- rpc2-src/ctest.c	2002-12-19 11:44:19.000000000 -0800
***************
*** 52,57 ****
--- 52,60 ----
  #include <rpc2/se.h>
  #include "sftp.h"
  #include "test.h"
+ #ifdef CODA_IPV6
+ #include <netdb.h>
+ #endif /* CODA_IPV6 */
  
  #define SUBSYS_SRV 1001
  
***************
*** 568,574 ****
--- 571,582 ----
  	if (!qflag) printf("Host id? ");
  	(void) fscanf(ifd, "%s", buff);
  	if (!qflag && fflag) printf(" %s\n", buff);
+ #ifdef CODA_IPV6
+     } while (!inet_pton(h->Value.AddrInfo->ai_family, buff,
+ 			h->Value.AddrInfo->ai_addr));
+ #else /* CODA_IPV6 */
      } while (inet_aton(buff, &h->Value.InetAddress) != 0);
+ #endif /* CODA_IPV6 */
  }
  
  void GetPort(    RPC2_PortIdent *p)
*** rpc2-src/stest.c.orig	2002-12-19 11:47:11.000000000 -0800
--- rpc2-src/stest.c	2002-12-19 11:48:02.000000000 -0800
***************
*** 53,58 ****
--- 53,61 ----
  #include <rpc2/se.h>
  #include "sftp.h"
  #include "test.h"
+ #ifdef CODA_IPV6
+ #include <netdb.h>
+ #endif /* CODA_IPV6 */
  
  #define SUBSYS_SRV 1001
  #define STESTSTACK 0x25000
***************
*** 243,255 ****
--- 246,266 ----
      RPC2_HostIdent *hPtr;
      FILE *tFile;
      {
+ #ifdef CODA_IPV6
+ 	char addr[50];
+ #endif /* CODA_IPV6 */
      if (tFile == NULL) tFile = stdout;	/* it's ok, call-by-value */
      switch (hPtr->Tag)
  	{
  	case RPC2_HOSTBYINETADDR:
  		{
+ #ifdef CODA_IPV6
+ 		    rpc2_addrinfo_ntop(hPtr->Value.AddrInfo, addr, 50);
+ 		fprintf(tFile, "Host.AddrInfo = %s", addr);
+ #else /* CODA_IPV6 */
  		fprintf(tFile, "Host.InetAddress = %s",
  			inet_ntoa(hPtr->Value.InetAddress));
+ #endif /* CODA_IPV6 */
  		break;	
  		}
  	
*** rpc2-src/multi3.c.orig	2002-12-19 11:49:21.000000000 -0800
--- rpc2-src/multi3.c	2002-12-19 11:49:29.000000000 -0800
***************
*** 52,57 ****
--- 52,60 ----
  #include <netdb.h>
  #include <assert.h>
  #include "rpc2.private.h"
+ #ifdef CODA_IPV6
+ #include <sys/socket.h>
+ #endif /* CODA_IPV6 */
  #include <rpc2/se.h>
  #include "trace.h"
  #include "cbuf.h"
***************
*** 77,82 ****
--- 80,92 ----
  static RPC2_Handle	LastMgrpidAllocated;
  #define	LISTENERALLOCSIZE   8		    /* malloc/realloc granularity */
  
+ #ifdef CODA_IPV6
+ /* try to grab the low-order 8 bits, assuming all are stored big
endian */
+ #define HASHHOST(h)
(((h)->Value.AddrInfo->ai_addr->sa_data[(h)->Value.AddrInfo->ai_addrlen-1]) & (MGRPHASHLENGTH-1))
+ #else /* CODA_IPV6 */
+ #define HASHHOST(h) ((((h)->s_addr & 0xff000000) >> 24) &
(HOSTHASHBUCKETS-1))
+ #endif /* CODA_IPV6 */
+ 
  /* Initialize the multicast group data structures; all this requires
     is zeroing the hash table. */
  void rpc2_InitMgrp()
***************
*** 96,102 ****
--- 106,116 ----
      {
      int index;
  
+ #ifdef CODA_IPV6
+     index = HASHHOST(host);
+ #else /* CODA_IPV6 */
      index = (host->Value.InetAddress.s_addr ^ mgrpid) &
(MGRPHASHLENGTH - 1);
+ #endif /* CODA_IPV6 */
      say(9, RPC2_DebugLevel, "bucket = %d, count = %d\n", index,
MgrpHashTable[index].count);
      return(&MgrpHashTable[index]);
      }
***************
*** 113,118 ****
--- 127,135 ----
      struct MEntry  *me;
      RPC2_Handle    mgrpid;
      struct bucket  *bucket;
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
  
      rpc2_AllocMgrps++;
      if (rpc2_MgrpFreeCount == 0)
***************
*** 123,129 ****
--- 140,151 ----
         mgrpid in the rpc2_initmulticast message.  Thus, the unique
         identifier is <client_host, client_port, mgrpid, role>. */
      mgrpid = (handle == 0) ? ++LastMgrpidAllocated : handle;
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(host->Value.AddrInfo, addr, 50);
+     say(9, RPC2_DebugLevel, "Allocating Mgrp: host = %s\tport =
0x%x\tmgrpid = 0x%lx\t", addr, port->Value.InetPortNumber, mgrpid);
+ #else /* CODA_IPV6 */
      say(9, RPC2_DebugLevel, "Allocating Mgrp: host = %s\tport =
0x%x\tmgrpid = 0x%lx\t", inet_ntoa(host->Value.InetAddress),
port->Value.InetPortNumber, mgrpid);
+ #endif /* CODA_IPV6 */
      bucket = rpc2_GetBucket(host, port, mgrpid);
  
      me = (struct MEntry *)rpc2_MoveEntry(&rpc2_MgrpFreeList,
&bucket->chain, NULL, &rpc2_MgrpFreeCount, &bucket->count);
***************
*** 144,149 ****
--- 166,174 ----
      struct CEntry  *ce;
      int	    i;
      struct bucket  *bucket;
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
  
      assert(me != NULL && !TestRole(me, FREE));
      if (TestState(me, CLIENT, ~(C_THINK|C_HARDERROR)) ||
***************
*** 170,176 ****
--- 195,206 ----
  
      rpc2_FreeMgrps++;
      SetRole(me, FREE);
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(me->ClientHost.Value.AddrInfo, addr, 50);
+     say(9, RPC2_DebugLevel, "Freeing Mgrp: ClientHost = %s\tClientPort
= 0x%x\tMgroupID = 0x%lx\t", addr, me->ClientPort.Value.InetPortNumber,
me->MgroupID);
+ #else /* CODA_IPV6 */
      say(9, RPC2_DebugLevel, "Freeing Mgrp: ClientHost = %s\tClientPort
= 0x%x\tMgroupID = 0x%lx\t",
inet_ntoa(me->ClientHost.Value.InetAddress),
me->ClientPort.Value.InetPortNumber, me->MgroupID);
+ #endif /* CODA_IPV6 */
      bucket = rpc2_GetBucket(&me->ClientHost, &me->ClientPort,
me->MgroupID);
      rpc2_MoveEntry(&bucket->chain, &rpc2_MgrpFreeList, me,
&bucket->count, &rpc2_MgrpFreeCount);
  }
***************
*** 191,196 ****
--- 221,247 ----
      bucket = rpc2_GetBucket(host, port, handle);
  
      for (me = bucket->chain, i = 0; i < bucket->count; me = me->Next,
i++) {
+ #ifdef CODA_IPV6
+ 	char addr[50];
+ 
+ 	rpc2_addrinfo_ntop(me->ClientHost.Value.AddrInfo, addr, 50);
+ 	say(9, RPC2_DebugLevel, "GetMgrp: %s.%u.%ld\n", addr,
+ 	    (unsigned) me->ClientPort.Value.InetPortNumber, me->MgroupID);
+ 	/* XXX not convinced this is the right way to compare addresses */
+         if ((me->ClientHost.Value.AddrInfo->ai_family ==
+ 	     host->Value.AddrInfo->ai_family) &&
+ 	    (me->ClientHost.Value.AddrInfo->ai_addrlen ==
+ 	     host->Value.AddrInfo->ai_addrlen) &&
+ 	    (!memcmp(me->ClientHost.Value.AddrInfo->ai_addr,
+ 		     host->Value.AddrInfo->ai_addr,
+ 		     me->ClientHost.Value.AddrInfo->ai_addrlen)) &&
+            
(me->ClientPort.Value.InetPortNumber==port->Value.InetPortNumber) &&
+ 	    (me->MgroupID == handle) && TestRole(me, role))
+ 	    {
+ 	    assert(me->MagicNumber == OBJ_MENTRY);
+ 	    return(me);
+ 	    }
+ #else /* CODA_IPV6 */
  	say(9, RPC2_DebugLevel, "GetMgrp: %s.%u.%ld\n",
  	    inet_ntoa(me->ClientHost.Value.InetAddress),
  	    (unsigned) me->ClientPort.Value.InetPortNumber, me->MgroupID);
***************
*** 202,207 ****
--- 253,259 ----
  	    assert(me->MagicNumber == OBJ_MENTRY);
  	    return(me);
  	    }
+ #endif /* CODA_IPV6 */
      }
  
      return((struct MEntry *)NULL);
***************
*** 277,284 ****
--- 329,341 ----
  	{
  	case RPC2_MGRPBYINETADDR:	/* you passed it in network order */
  	    me->IPMHost.Tag = (HostTag) RPC2_MGRPBYINETADDR;
+ #ifdef CODA_IPV6
+ 	    /* struct assignment, with embedded pointers */
+ 	    me->IPMHost.Value.AddrInfo = MulticastHost->Value.AddrInfo;
+ #else /* CODA_IPV6 */
  	    me->IPMHost.Value.InetAddress.s_addr =
  		MulticastHost->Value.InetAddress.s_addr;
+ #endif /* CODA_IPV6 */
  	    break;
  
  	case RPC2_MGRPBYNAME:		/* NOT yet supported */
***************
*** 821,826 ****
--- 878,886 ----
  	    h_LocalHandle = ntohl(pb->Header.LocalHandle),
  	    h_Flags = ntohl(pb->Header.Flags),
  	    h_SeqNumber;				/* decrypt first */
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
  
      say(9, RPC2_DebugLevel, "In XlateMcastPacket()\n");
  
***************
*** 855,863 ****
--- 915,929 ----
          TestState(ce, SERVER, ~S_AWAITREQUEST) ||
          (h_Flags & RPC2_RETRY) != 0) {BOGUS(pb); return(FALSE);}
  
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(pb->Prefix.PeerHost.Value.AddrInfo, addr, 50);
+     say(9, RPC2_DebugLevel, "Host = 0x%s\tPort = 0x%x\tMgrp =
0x%lx\n",
+ 	addr, pb->Prefix.PeerPort.Value.InetPortNumber, h_RemoteHandle);
+ #else /* CODA_IPV6 */
      say(9, RPC2_DebugLevel, "Host = 0x%s\tPort = 0x%x\tMgrp =
0x%lx\n",
  	inet_ntoa(pb->Prefix.PeerHost.Value.InetAddress),
  	pb->Prefix.PeerPort.Value.InetPortNumber, h_RemoteHandle);
+ #endif /* CODA_IPV6 */
  
      /* Decrypt the packet with the MULTICAST session key. Clear the
encrypted 
         bit so that we don't decrypt again with the connection session
key. */
*** rpc2-src/packet.c.orig	2002-12-19 11:51:11.000000000 -0800
--- rpc2-src/packet.c	2002-12-20 03:38:04.000000000 -0800
***************
*** 81,90 ****
--- 81,96 ----
  
      if (predicate)
  	{
+ #ifdef CODA_IPV6
+ 	    say(10, RPC2_DebugLevel, "Error in DontFailPacket: predicate
set!");
+ 	    return(-1);
+ 	    
+ #else /* CODA_IPV6 */
  	ip1 = (ntohl(addr->sin_addr.s_addr) >> 24) & 0x000000ff;
  	ip2 = (ntohl(addr->sin_addr.s_addr) >> 16) & 0x000000ff;
  	ip3 = (ntohl(addr->sin_addr.s_addr) >> 8) & 0x000000ff;
  	ip4 = ntohl(addr->sin_addr.s_addr) & 0x000000ff;
+ #endif /* CODA_IPV6 */
  	ntohPktColor(pb);
  	color = GetPktColor(pb);
  	htonPktColor(pb);
***************
*** 124,135 ****
--- 130,150 ----
  	case RPC2_HOSTBYINETADDR:
  	case RPC2_MGRPBYINETADDR:
  	    {
+ #ifdef CODA_IPV6
+             struct sockaddr_in *sa;
+ 	    
+ 	    assert(whichPort->Tag == RPC2_PORTBYINETNUMBER);
+ 	    sa = (struct sockaddr_in *) whichHost->Value.AddrInfo->ai_addr;
+ 	    sa->sin_port = whichPort->Value.InetPortNumber; /* In network
order */
+ #else /* CODA_IPV6 */
  	    struct sockaddr_in sa;
  
  	    assert(whichPort->Tag == RPC2_PORTBYINETNUMBER);
+ 
  	    sa.sin_family = AF_INET;
  	    sa.sin_addr.s_addr = whichHost->Value.InetAddress.s_addr;	/* In
network order */
  	    sa.sin_port = whichPort->Value.InetPortNumber; /* In network
order */
+ #endif /* CODA_IPV6 */
  
  	    if (ntohl(whichPB->Header.Flags) & RPC2_MULTICAST)
  		{
***************
*** 144,152 ****
--- 159,174 ----
  
  	    if (DontFailPacket(Fail_SendPredicate, whichPB, &sa,
whichSocket))
  		{
+ #ifdef CODA_IPV6
+                 n = sendto(whichSocket, &whichPB->Header,
+                            whichPB->Prefix.LengthOfPacket, 0,
+                            whichHost->Value.AddrInfo->ai_addr,
+ 			   whichHost->Value.AddrInfo->ai_addrlen);
+ #else /* CODA_IPV6 */
                  n = sendto(whichSocket, &whichPB->Header,
                             whichPB->Prefix.LengthOfPacket, 0,
                             (struct sockaddr *)&sa, sizeof(struct
sockaddr_in));
+ #endif /* CODA_IPV6 */
  
  #ifdef __linux__
                  if ((n == -1) && (errno == ECONNREFUSED))
***************
*** 158,174 ****
  		     * We retry the send, because the failing host was possibly
  		     * not the one we tried to send to this time. --JH
                       */
                      n = sendto(whichSocket, &whichPB->Header,
                                 whichPB->Prefix.LengthOfPacket, 0,
                                 (struct sockaddr *)&sa,
                                 sizeof(struct sockaddr_in));
                  }
  #endif
  
  		if (n != whichPB->Prefix.LengthOfPacket)
  		    {
  		    char msg[100];
! 		    (void) sprintf(msg, "socket %ld", whichSocket);
  		    if (RPC2_Perror) perror(msg);
  		    }
  	        }
--- 180,203 ----
  		     * We retry the send, because the failing host was possibly
  		     * not the one we tried to send to this time. --JH
                       */
+ #ifdef CODA_IPV6
+                     n = sendto(whichSocket, &whichPB->Header,
+                                whichPB->Prefix.LengthOfPacket, 0,
+ 			       whichHost->Value.AddrInfo->ai_addr,
+                                whichHost->Value.AddrInfo->ai_addrlen);
+ #else /* CODA_IPV6 */
                      n = sendto(whichSocket, &whichPB->Header,
                                 whichPB->Prefix.LengthOfPacket, 0,
                                 (struct sockaddr *)&sa,
                                 sizeof(struct sockaddr_in));
+ #endif /* CODA_IPV6 */
                  }
  #endif
  
  		if (n != whichPB->Prefix.LengthOfPacket)
  		    {
  		    char msg[100];
! 		    (void) sprintf(msg, "Xmit_Packet socket %ld, errno %d",
whichSocket, errno);
  		    if (RPC2_Perror) perror(msg);
  		    }
  	        }
***************
*** 191,197 ****
--- 220,231 ----
  {
      long rc, len;
      int fromlen;
+ #ifdef CODA_IPV6
+     struct sockaddr_storage sa;
+     struct sockaddr_in *saip = (struct sockaddr_in *)&sa;
+ #else /* CODA_IPV6 */
      struct sockaddr_in sa;
+ #endif /* CODA_IPV6 */
  
      say(0, RPC2_DebugLevel, "rpc2_RecvPacket()\n");
      assert(whichBuff->Prefix.MagicNumber == OBJ_PACKETBUFFER);
***************
*** 209,214 ****
--- 243,279 ----
  	    return(-1);
      }
  
+ #ifdef CODA_IPV6
+     /* do we really need to zero these? */
+     memset(&whichBuff->Prefix.PeerHost, 0, sizeof(RPC2_HostIdent));
+     memset(&whichBuff->Prefix.PeerPort, 0, sizeof(RPC2_PortIdent));
+ 
+     whichBuff->Prefix.PeerHost.Tag = RPC2_HOSTBYINETADDR;
+     whichBuff->Prefix.PeerPort.Tag = RPC2_PORTBYINETNUMBER;
+     /* XXX this isn't the correct way to get this, I'm sure */
+     whichBuff->Prefix.PeerPort.Value.InetPortNumber = saip->sin_port;
+ 
+     if (!whichBuff->Prefix.PeerHost.Value.AddrInfo) {
+ 	whichBuff->Prefix.PeerHost.Value.AddrInfo = malloc(sizeof(struct
addrinfo));
+ 	if (!whichBuff->Prefix.PeerHost.Value.AddrInfo) {
+ 	    say(10, RPC2_DebugLevel, "Error in recvf from: errno = %d\n",
errno);
+ 	    return(-1);
+ 	}
+ 	memset(whichBuff->Prefix.PeerHost.Value.AddrInfo,0,sizeof(struct
addrinfo));
+     }
+     if (!whichBuff->Prefix.PeerHost.Value.AddrInfo->ai_addr) {
+ 	whichBuff->Prefix.PeerHost.Value.AddrInfo->ai_addr =
malloc(sizeof(sa));
+ 	if (!whichBuff->Prefix.PeerHost.Value.AddrInfo->ai_addr) {
+ 	    say(10, RPC2_DebugLevel, "Error in recvf from: errno = %d\n",
errno);
+ 	    return(-1);
+ 	}
+ 	memcpy(whichBuff->Prefix.PeerHost.Value.AddrInfo->ai_addr,
+ 	       &sa, fromlen);
+ 	whichBuff->Prefix.PeerHost.Value.AddrInfo->ai_addrlen = fromlen;
+     }
+     /* XXX I hope that this doesn't conflict with an addrinfo
allocation.
+        I'm not sure enough on how the operation works... */
+ #else /* CODA_IPV6 */
      /* do we really need to zero these? */
      memset(&whichBuff->Prefix.PeerHost, 0, sizeof(RPC2_HostIdent));
      memset(&whichBuff->Prefix.PeerPort, 0, sizeof(RPC2_PortIdent));
***************
*** 217,222 ****
--- 282,288 ----
      whichBuff->Prefix.PeerHost.Value.InetAddress.s_addr =
sa.sin_addr.s_addr;
      whichBuff->Prefix.PeerPort.Tag = RPC2_PORTBYINETNUMBER;
      whichBuff->Prefix.PeerPort.Value.InetPortNumber = sa.sin_port;
+ #endif /* CODA_IPV6 */
  
      TR_RECV();
  
***************
*** 569,574 ****
--- 635,646 ----
  /* For converting packet headers to/from network order */
  void rpc2_htonp(RPC2_PacketBuffer *p)
  {
+ #ifdef CODA_IPV6
+   /*
+    * Actually, the test for endianness shouldn't be necessary -- most
+    * implementations make these nops on the right machines.
+    */
+ #endif /* CODA_IPV6 */
  	p->Header.ProtoVersion = htonl(p->Header.ProtoVersion);
  	p->Header.RemoteHandle = htonl(p->Header.RemoteHandle);
  	p->Header.LocalHandle = htonl(p->Header.LocalHandle);
*** rpc2-src/debug.c.orig	2002-12-19 11:52:31.000000000 -0800
--- rpc2-src/debug.c	2002-12-19 11:53:12.000000000 -0800
***************
*** 37,43 ****
  
  */
  
- 
  #ifdef RPC2DEBUG
  #include <stdio.h>
  #include <sys/types.h>
--- 37,42 ----
***************
*** 179,190 ****
  
  void rpc2_PrintHEntry(struct HEntry *hPtr, FILE *tFile)
  {
      if (tFile == NULL) tFile = rpc2_logfile;	/* it's ok, call-by-value
*/
  
      fprintf(tFile, "\nHost 0x%lx state is...\n\tNextEntry = 0x%lx 
PrevEntry = 0x%lx  MagicNumber = %s\n",
  	(long)hPtr, (long)hPtr->Next, (long)hPtr->Prev,
WhichMagic(hPtr->MagicNumber));
  
!     fprintf(tFile, "\tHost.InetAddress = %s\n",
inet_ntoa(hPtr->Host));
      fprintf(tFile, "\tLastWord = %ld.%06ld\n", hPtr->LastWord.tv_sec,
hPtr->LastWord.tv_usec);
      fprintf(tFile, "\tRTT = %ld.%03ld, RTTvar = %ld.%03ld\n",
  	    hPtr->RTT >> RPC2_RTT_SHIFT,
--- 178,197 ----
  
  void rpc2_PrintHEntry(struct HEntry *hPtr, FILE *tFile)
  {
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
      if (tFile == NULL) tFile = rpc2_logfile;	/* it's ok, call-by-value
*/
  
      fprintf(tFile, "\nHost 0x%lx state is...\n\tNextEntry = 0x%lx 
PrevEntry = 0x%lx  MagicNumber = %s\n",
  	(long)hPtr, (long)hPtr->Next, (long)hPtr->Prev,
WhichMagic(hPtr->MagicNumber));
  
! #ifdef CODA_IPV6
!     rpc2_addrinfo_ntop(&hPtr->Host, addr, 50);
!     fprintf(tFile, "Host.AddrInfo = %s", addr);
! #else /* CODA_IPV6 */
!     fprintf(tFile, "\tHostInetAddress = %s\n", inet_ntoa(hPtr->Host));
! #endif /* CODA_IPV6 */
      fprintf(tFile, "\tLastWord = %ld.%06ld\n", hPtr->LastWord.tv_sec,
hPtr->LastWord.tv_usec);
      fprintf(tFile, "\tRTT = %ld.%03ld, RTTvar = %ld.%03ld\n",
  	    hPtr->RTT >> RPC2_RTT_SHIFT,
***************
*** 345,352 ****
--- 352,365 ----
          case RPC2_HOSTBYINETADDR:
          case RPC2_MGRPBYINETADDR:
              {
+ #ifdef CODA_IPV6
+ 		char addr[50];
+ 		rpc2_addrinfo_ntop(hPtr->Value.AddrInfo, addr, 50);
+ 		fprintf(tFile, "Host.AddrInfo = %s", addr);
+ #else /* CODA_IPV6 */
                  fprintf(tFile, "Host.InetAddress = %s",
                          inet_ntoa(hPtr->Value.InetAddress));
+ #endif /* CODA_IPV6 */
                  break;	
              }
  
***************
*** 653,661 ****
--- 666,684 ----
  			break;
  		    
  		    case RPC2_HOSTBYINETADDR:
+ #ifdef CODA_IPV6
+ 		    {
+ 			char addr[50];
+ 			rpc2_addrinfo_ntop(tea->Host.Value.AddrInfo, addr, 50);
+ 			fprintf(outFile, "Host:     Tag = RPC2_HOSTBYINETADDR	AddrInfo =
%s\n",
+ 				addr);
+ 			break;
+ 		    }
+ #else /* CODA_IPV6 */
  			fprintf(outFile, "Host:     Tag = RPC2_HOSTBYINETADDR	InetAddress =
%s\n",
  				inet_ntoa(tea->Host.Value.InetAddress));
  			break;
+ #endif /* CODA_IPV6 */
  
  		    default:
  			fprintf(outFile, "Host:   ?????????\n");
*** rpc2-src/host.c.orig	2002-12-20 08:17:08.000000000 -0800
--- rpc2-src/host.c	2002-12-20 08:20:19.000000000 -0800
***************
*** 80,86 ****
--- 80,91 ----
     We hash on the low bytes of the host address (in network order) */
   
  #define HOSTHASHBUCKETS 64
+ #ifdef CODA_IPV6
+ /* try to grab the low-order 8 bits, assuming all are stored big
endian */
+ #define HASHHOST(h) (((h)->ai_addr->sa_data[(h)->ai_addrlen-1]) &
(HOSTHASHBUCKETS-1))
+ #else /* CODA_IPV6 */
  #define HASHHOST(h) ((((h)->s_addr & 0xff000000) >> 24) &
(HOSTHASHBUCKETS-1))
+ #endif /* CODA_IPV6 */
                                          /* mod HOSTHASHBUCKETS */
  static struct HEntry **HostHashTable;	/* malloc'ed hash table static
size */
  
***************
*** 93,99 ****
--- 98,108 ----
  
  /* Returns pointer to the host entry corresponding to hostid
     Returns NULL if host does not exist.  */
+ #ifdef CODA_IPV6
+ struct HEntry *rpc2_FindHEAddr(IN struct addrinfo *whichHost)
+ #else /* CODA_IPV6 */
  struct HEntry *rpc2_FindHEAddr(IN struct in_addr *whichHost)
+ #endif /* CODA_IPV6 */
  {
  	long bucket;
  	struct HEntry *headdr;
***************
*** 104,110 ****
--- 113,126 ----
  	bucket = HASHHOST(whichHost);
  	headdr = HostHashTable[bucket];
  	while (headdr)  {
+ #ifdef CODA_IPV6
+ 		if (headdr->Host.ai_family == whichHost->ai_family &&
+ 		    headdr->Host.ai_addrlen == whichHost->ai_addrlen &&
+ 		    (!memcmp(headdr->Host.ai_addr,whichHost->ai_addr,
+ 			     headdr->Host.ai_addrlen)))
+ #else /* CODA_IPV6 */
  		if (headdr->Host.s_addr == whichHost->s_addr)
+ #endif /* CODA_IPV6 */
  			return(headdr);
  		headdr = headdr->HLink;
  	}
***************
*** 116,122 ****
--- 132,142 ----
  struct HEntry *rpc2_GetHost(RPC2_HostIdent *host)
  {
  	struct HEntry *he;
+ #ifdef CODA_IPV6
+ 	he = rpc2_FindHEAddr(host->Value.AddrInfo);
+ #else /* CODA_IPV6 */
  	he = rpc2_FindHEAddr(&host->Value.InetAddress);
+ #endif /* CODA_IPV6 */
  	assert(!he || he->MagicNumber == OBJ_HENTRY);
  	return(he);
  }
***************
*** 140,146 ****
--- 160,170 ----
  	assert (he->MagicNumber == OBJ_HENTRY);
  
  	/* Initialize */
+ #ifdef CODA_IPV6
+ 	he->Host = *host->Value.AddrInfo; /* struct assignment */
+ #else /* CODA_IPV6 */
  	he->Host.s_addr = host->Value.InetAddress.s_addr;
+ #endif /* CODA_IPV6 */
  	he->LastWord.tv_sec = he->LastWord.tv_usec = 0;
  
  	/* clear the network measurement logs */
***************
*** 304,309 ****
--- 328,336 ----
      long	   eBR;      /* estimated byterate (ns/B) */
      unsigned long  eU;       /* temporary unsigned variable */
      long	   eL;       /* temporary signed variable */
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
  
      if (!host) return;
  
***************
*** 364,375 ****
--- 391,411 ----
      eL -= (host->RTTVar >> RPC2_RTTVAR_SHIFT);
      host->RTTVar += eL;
  
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(&host->Host, addr, 50);
+     say(0, RPC2_DebugLevel,
+ 	"Est: %s %4ld.%06lu/%-5lu<%-5lu RTT:%lu/%lu us BR:%lu/%lu ns/B\n",
+ 	    addr, elapsed_us / 1000000, elapsed_us % 1000000,
+ 	    InBytes, OutBytes, host->RTT>>RPC2_RTT_SHIFT,
host->RTTVar>>RPC2_RTTVAR_SHIFT,
+ 	    (host->BR>>RPC2_BR_SHIFT), host->BRVar>>RPC2_BRVAR_SHIFT);
+ #else /* CODA_IPV6 */
      say(0, RPC2_DebugLevel,
  	"Est: %s %4ld.%06lu/%-5lu<%-5lu RTT:%lu/%lu us BR:%lu/%lu ns/B\n",
  	    inet_ntoa(host->Host), elapsed_us / 1000000, elapsed_us %
1000000,
  	    InBytes, OutBytes, host->RTT>>RPC2_RTT_SHIFT,
  	    host->RTTVar>>RPC2_RTTVAR_SHIFT, (host->BR>>RPC2_BR_SHIFT),
  	    host->BRVar>>RPC2_BRVAR_SHIFT);
+ #endif /* CODA_IPV6 */
  
      return;
  }
*** rpc2-src/sftp1.c.orig	2002-12-19 11:55:03.000000000 -0800
--- rpc2-src/sftp1.c	2002-12-19 11:55:24.000000000 -0800
***************
*** 100,105 ****
--- 100,109 ----
  long SFTP_Init()
  {
      char *sname;
+ #ifdef CODA_IPV6
+     static RPC2_HostIdent sftp_Host;
+     static struct addrinfo sftp_Host_AddrInfo;
+ #endif /* CODA_IPV6 */
      
      say(0, SFTP_DebugLevel, "SFTP_Init()\n");
  
***************
*** 109,115 ****
--- 113,126 ----
      if (sftp_Port.Tag)
      {
          /* Create socket for SFTP packets */
+ #ifdef CODA_IPV6
+ 	/* sftp_Host_AddrInfo.ai_family = PF_UNSPEC; */
+ 	sftp_Host_AddrInfo.ai_family = AF_INET6;
+ 	sftp_Host.Value.AddrInfo = &sftp_Host_AddrInfo;
+         if (rpc2_CreateIPSocket(&sftp_Socket, &sftp_Port, &sftp_Host)
!= RPC2_SUCCESS)
+ #else /* CODA_IPV6 */
          if (rpc2_CreateIPSocket(&sftp_Socket, &sftp_Port) !=
RPC2_SUCCESS)
+ #endif /* CODA_IPV6 */
              return(RPC2_FAIL);
      }
  
*** rpc2-src/sftp6.c.orig	2002-12-19 11:57:01.000000000 -0800
--- rpc2-src/sftp6.c	2002-12-19 11:57:12.000000000 -0800
***************
*** 451,463 ****
--- 451,472 ----
  	    h_SeqNumber,					/* decrypt first */
  	    h_ThisRPCCall;					/* decrypt first */
      RPC2_PortIdent		XlatePort;
+ #ifdef CODA_IPV6
+     char addr[50];
+ #endif /* CODA_IPV6 */
  
      XlatePort = pb->Prefix.PeerPort;		/* structure assignment */
  
      say(9, SFTP_DebugLevel, "SFXlateMcastPacket()\n");
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(pb->Prefix.PeerHost.Value.AddrInfo, addr, 50);
+     say(9, SFTP_DebugLevel, "Host = %s\tPort = 0x%x\tMgrp = 0x%lx\n",
+ 	addr, (unsigned) XlatePort.Value.InetPortNumber - 1, h_RemoteHandle);
+ #else /* CODA_IPV6 */
      say(9, SFTP_DebugLevel, "Host = %s\tPort = 0x%x\tMgrp = 0x%lx\n",
  	inet_ntoa(pb->Prefix.PeerHost.Value.InetAddress),
  	(unsigned) XlatePort.Value.InetPortNumber - 1, h_RemoteHandle);
+ #endif /* CODA_IPV6 */
  
      /* Find and validate the relevant data structures */
      assert(h_RemoteHandle != 0 && h_LocalHandle == 0);
***************
*** 479,487 ****
--- 488,502 ----
      if (mse->WhoAmI != SFSERVER) {
  	say(9, SFTP_DebugLevel, "mse->WhoAmI != SFSERVER\n"); return(FALSE);}
  
+ #ifdef CODA_IPV6
+     rpc2_addrinfo_ntop(pb->Prefix.PeerHost.Value.AddrInfo, addr, 50);
+     say(9, SFTP_DebugLevel, "Host = %s\tPort = 0x%x\tMgrp = 0x%lx\n",
+ 	addr, XlatePort.Value.InetPortNumber, h_RemoteHandle );
+ #else /* CODA_IPV6 */
      say(9, SFTP_DebugLevel, "Host = %s\tPort = 0x%x\tMgrp = 0x%lx\n",
  	    inet_ntoa(pb->Prefix.PeerHost.Value.InetAddress),
  	    XlatePort.Value.InetPortNumber, h_RemoteHandle );
+ #endif /* CODA_IPV6 */
  
      /* Decrypt the packet with the MULTICAST session key. Clear the
encrypted bit so that we don't
  	decrypt again with the connection session key. */
*** rpc2-src/rpc2.private.h.orig	2002-12-19 12:00:59.000000000 -0800
--- rpc2-src/rpc2.private.h	2002-12-19 13:17:52.000000000 -0800
***************
*** 47,52 ****
--- 47,57 ----
  #include <rpc2/rpc2.h>
  #include <string.h>
  #include <dllist.h>
+ /* for IPv6 */
+ #include <config.h>
+ #ifdef CODA_IPV6
+ #include <netdb.h>
+ #endif /* CODA_IPV6 */
  
  /*
  Magic Number assignments for runtime system objects.
***************
*** 310,318 ****
  		     MagicNumber;
      struct HEntry    *Qname;	/* LinkEntry field */
      struct HEntry    *HLink;	/* for host hash */
      struct in_addr   Host;      /* IP address */
      struct timeval   LastWord;	/* Most recent time we've heard from
this host*/
- 
      unsigned RPC2_NumEntries;	/* number of observations recorded */
      RPC2_NetLogEntry RPC2_Log[RPC2_MAXLOGLENGTH];
  				/* circular buffer for recent observations on
--- 315,326 ----
  		     MagicNumber;
      struct HEntry    *Qname;	/* LinkEntry field */
      struct HEntry    *HLink;	/* for host hash */
+ #ifdef CODA_IPV6
+     struct addrinfo  Host;      /* IP address */
+ #else /* CODA_IPV6 */
      struct in_addr   Host;      /* IP address */
+ #endif /* CODA_IPV6 */
      struct timeval   LastWord;	/* Most recent time we've heard from
this host*/
      unsigned RPC2_NumEntries;	/* number of observations recorded */
      RPC2_NetLogEntry RPC2_Log[RPC2_MAXLOGLENGTH];
  				/* circular buffer for recent observations on
***************
*** 450,456 ****
--- 458,469 ----
  void FreeHeld(struct SL_Entry *sle);
  
  /* Socket creation */
+ 
+ #ifdef CODA_IPV6
+ long rpc2_CreateIPSocket(long *svar, RPC2_PortIdent *pvar,
RPC2_HostIdent *hvar);
+ #else /* CODA_IPV6 */
  long rpc2_CreateIPSocket(long *svar, RPC2_PortIdent *pvar);
+ #endif /* CODA_IPV6 */
  
  /* Packet  routines */
  long rpc2_SendReliably(), rpc2_MSendPacketsReliably();
***************
*** 477,483 ****
--- 490,500 ----
  
  /* Host manipulation routines */
  void rpc2_InitHost(void);
+ #ifdef CODA_IPV6
+ struct HEntry *rpc2_FindHEAddr(struct addrinfo *whichHost);
+ #else /* CODA_IPV6 */
  struct HEntry *rpc2_FindHEAddr(struct in_addr *whichHost);
+ #endif /* CODA_IPV6 */
  struct HEntry *rpc2_GetHost(RPC2_HostIdent *host);
  struct HEntry *rpc2_AllocHost(RPC2_HostIdent *host);
  void rpc2_FreeHost(struct HEntry **whichHost);
***************
*** 524,529 ****
--- 541,550 ----
  void rpc2_InitRandom();
  long rpc2_TrueRandom();
  
+ #ifdef CODA_IPV6
+ void rpc2_addrinfo_ntop();
+ #endif /* CODA_IPV6 */
+ 
  /* encryption */
  void rpc2_ApplyD(RPC2_PacketBuffer *pb, struct CEntry *ce);
  void rpc2_ApplyE(RPC2_PacketBuffer *pb, struct CEntry *ce);
***************
*** 551,562 ****
--- 572,598 ----
  
  /* Macros to check if host and portal ident structures are equal */
  /* The lengths of the names really should be #defined. */
+ #ifdef CODA_IPV6
+ 
+ /* #define rpc2_HostIdentEqual(_hi1p_,_hi2p_) TRUE */
+ 
+ #define rpc2_HostIdentEqual(_hi1p_,_hi2p_) \
+ (((_hi1p_)->Tag == RPC2_HOSTBYINETADDR && (_hi2p_)->Tag ==
RPC2_HOSTBYINETADDR)? \
+  ((_hi1p_)->Value.AddrInfo->ai_family ==
(_hi2p_)->Value.AddrInfo->ai_family && \
+  (_hi1p_)->Value.AddrInfo->ai_addrlen ==
(_hi2p_)->Value.AddrInfo->ai_addrlen &&
!memcmp((_hi1p_)->Value.AddrInfo->ai_addr,(_hi2p_)->Value.AddrInfo->ai_addr,(_hi2p_)->Value.AddrInfo->ai_addrlen)): \
+  (((_hi1p_)->Tag == RPC2_HOSTBYNAME && (_hi2p_)->Tag ==
RPC2_HOSTBYNAME)? \
+   (strncmp((_hi1p_)->Value.Name, (_hi2p_)->Value.Name, 64) == 0):0))
+ 
+ #else /* CODA_IPV6 */
+ 
  #define rpc2_HostIdentEqual(_hi1p_,_hi2p_) \
  (((_hi1p_)->Tag == RPC2_HOSTBYINETADDR && (_hi2p_)->Tag ==
RPC2_HOSTBYINETADDR)? \
   ((_hi1p_)->Value.InetAddress.s_addr ==
(_hi2p_)->Value.InetAddress.s_addr): \
   (((_hi1p_)->Tag == RPC2_HOSTBYNAME && (_hi2p_)->Tag ==
RPC2_HOSTBYNAME)? \
    (strncmp((_hi1p_)->Value.Name, (_hi2p_)->Value.Name, 64) == 0):0))
  
+ #endif /* CODA_IPV6 */
+ 
  #define rpc2_PortIdentEqual(_pi1p_,_pi2p_) \
  (((_pi1p_)->Tag == RPC2_PORTBYINETNUMBER && (_pi2p_)->Tag ==
RPC2_PORTBYINETNUMBER)? \
   ((_pi1p_)->Value.InetPortNumber == (_pi2p_)->Value.InetPortNumber): \
*** include/rpc2/rpc2.h.orig	2002-12-20 08:17:57.000000000 -0800
--- include/rpc2/rpc2.h	2002-12-19 13:10:54.000000000 -0800
***************
*** 333,339 ****
--- 333,343 ----
  	HostTag Tag;
  	union
  	    {
+ #ifdef CODA_IPV6
+ 		struct addrinfo *AddrInfo; /* includes sockaddr, which includes port
*/
+ #else /* CODA_IPV6 */
  	    struct in_addr InetAddress;	/* NOTE: in network order, not host
order */
+ #endif /* CODA_IPV6 */
  	    char Name[64];	/* minimum length for use with domain names */
  	    }
  	    Value;
***************
*** 373,379 ****
  	MgrpTag Tag;
  	union
  	    {
! 	    struct in_addr  InetAddress;    /* NOTE: in network order, not
host order */
  	    char	    Name[64];	    /* minimum length for use with domain
names */
  	    }
  	    Value;
--- 377,387 ----
  	MgrpTag Tag;
  	union
  	    {
! #ifdef CODA_IPV6
! 		struct addrinfo *AddrInfo; /* includes sockaddr, which includes port
*/
! #else /* CODA_IPV6 */
! 	    struct in_addr InetAddress;	/* NOTE: in network order, not host
order */
! #endif /* CODA_IPV6 */
  	    char	    Name[64];	    /* minimum length for use with domain
names */
  	    }
  	    Value;
Received on 2002-12-20 17:41:36