Unix CM: Don't blow up if we have non-rxkad tokens
[openafs.git] / src / afs / afs_pioctl.c
index b17f425..08d47f0 100644 (file)
@@ -15,7 +15,7 @@
 #ifdef AFS_OBSD_ENV
 #include "h/syscallargs.h"
 #endif
-#ifdef AFS_FBSD50_ENV
+#ifdef AFS_FBSD_ENV
 #include "h/sysproto.h"
 #endif
 #ifdef AFS_NBSD40_ENV
 #include "afs/vice.h"
 #include "afs/afs_bypasscache.h"
 #include "rx/rx_globals.h"
+#include "token.h"
 
 struct VenusFid afs_rootFid;
 afs_int32 afs_waitForever = 0;
 short afs_waitForeverCount = 0;
 afs_int32 afs_showflags = GAGUSER | GAGCONSOLE;        /* show all messages */
 
-#ifdef AFS_DISCON_ENV
 afs_int32 afs_is_disconnected;
 afs_int32 afs_is_discon_rw;
 /* On reconnection, turn this knob on until it finishes,
  * then turn it off.
  */
 afs_int32 afs_in_sync = 0;
-#endif
 
 struct afs_pdata {
     char *ptr;
@@ -108,31 +107,26 @@ afs_pd_skip(struct afs_pdata *apd, size_t skip)
 }
 
 static_inline int
-afs_pd_getInt(struct afs_pdata *apd, afs_int32 *val)
+afs_pd_getBytes(struct afs_pdata *apd, void *dest, size_t bytes)
 {
-    if (apd == NULL || apd->remaining < sizeof(afs_int32))
+    if (apd == NULL || apd->remaining < bytes)
        return EINVAL;
-    apd->remaining -= sizeof(afs_int32);
-    *val = *(afs_int32 *)apd->ptr;
-    apd->ptr += sizeof(afs_int32);
+    apd->remaining -= bytes;
+    memcpy(dest, apd->ptr, bytes);
+    apd->ptr += bytes;
     return 0;
 }
 
 static_inline int
-afs_pd_getUint(struct afs_pdata *apd, afs_uint32 *val)
+afs_pd_getInt(struct afs_pdata *apd, afs_int32 *val)
 {
-    return afs_pd_getInt(apd, (afs_int32 *)val);
+    return afs_pd_getBytes(apd, val, sizeof(*val));
 }
 
 static_inline int
-afs_pd_getBytes(struct afs_pdata *apd, void *dest, size_t bytes)
+afs_pd_getUint(struct afs_pdata *apd, afs_uint32 *val)
 {
-    if (apd == NULL || apd->remaining < bytes)
-       return EINVAL;
-    apd->remaining -= bytes;
-    memcpy(dest, apd->ptr, bytes);
-    apd->ptr += bytes;
-    return 0;
+    return afs_pd_getBytes(apd, val, sizeof(*val));
 }
 
 static_inline void *
@@ -151,6 +145,23 @@ afs_pd_inline(struct afs_pdata *apd, size_t bytes)
     return ret;
 }
 
+static_inline void
+afs_pd_xdrStart(struct afs_pdata *apd, XDR *xdrs, enum xdr_op op) {
+    xdrmem_create(xdrs, apd->ptr, apd->remaining, op);
+}
+
+static_inline void
+afs_pd_xdrEnd(struct afs_pdata *apd, XDR *xdrs) {
+    size_t pos;
+
+    pos = xdr_getpos(xdrs);
+    apd->ptr += pos;
+    apd->remaining -= pos;
+    xdr_destroy(xdrs);
+}
+
+
+
 static_inline int
 afs_pd_getString(struct afs_pdata *apd, char *str, size_t maxLen)
 {
@@ -182,18 +193,6 @@ afs_pd_getStringPtr(struct afs_pdata *apd, char **str)
 }
 
 static_inline int
-afs_pd_putInt(struct afs_pdata *apd, afs_int32 val)
-{
-    if (apd == NULL || apd->remaining < sizeof(afs_int32))
-       return E2BIG;
-    *(afs_int32 *)apd->ptr = val;
-    apd->ptr += sizeof(afs_int32);
-    apd->remaining -= sizeof(afs_int32);
-
-    return 0;
-}
-
-static_inline int
 afs_pd_putBytes(struct afs_pdata *apd, const void *bytes, size_t len)
 {
     if (apd == NULL || apd->remaining < len)
@@ -205,6 +204,12 @@ afs_pd_putBytes(struct afs_pdata *apd, const void *bytes, size_t len)
 }
 
 static_inline int
+afs_pd_putInt(struct afs_pdata *apd, afs_int32 val)
+{
+    return afs_pd_putBytes(apd, &val, sizeof(val));
+}
+
+static_inline int
 afs_pd_putString(struct afs_pdata *apd, char *str) {
 
     /* Add 1 so we copy the NULL too */
@@ -247,11 +252,13 @@ DECL_PIOCTL(PGetFileCell);
 DECL_PIOCTL(PGetWSCell);
 DECL_PIOCTL(PGetUserCell);
 DECL_PIOCTL(PSetTokens);
+DECL_PIOCTL(PSetTokens2);
 DECL_PIOCTL(PGetVolumeStatus);
 DECL_PIOCTL(PSetVolumeStatus);
 DECL_PIOCTL(PFlush);
 DECL_PIOCTL(PNewStatMount);
 DECL_PIOCTL(PGetTokens);
+DECL_PIOCTL(PGetTokens2);
 DECL_PIOCTL(PUnlog);
 DECL_PIOCTL(PMariner);
 DECL_PIOCTL(PCheckServers);
@@ -293,11 +300,10 @@ DECL_PIOCTL(PCallBackAddr);
 DECL_PIOCTL(PDiscon);
 DECL_PIOCTL(PNFSNukeCreds);
 DECL_PIOCTL(PNewUuid);
-DECL_PIOCTL(PPrecache); 
+DECL_PIOCTL(PPrecache);
 DECL_PIOCTL(PGetPAG);
-#if defined(AFS_CACHE_BYPASS)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
 DECL_PIOCTL(PSetCachingThreshold);
-DECL_PIOCTL(PSetCachingBlkSize);
 #endif
 
 /*
@@ -314,10 +320,10 @@ static int HandleClientContext(struct afs_ioctl *ablob, int *com,
                               afs_ucred_t **acred,
                               afs_ucred_t *credp);
 #endif
-int HandleIoctl(register struct vcache *avc, register afs_int32 acom,
+int HandleIoctl(struct vcache *avc, afs_int32 acom,
                struct afs_ioctl *adata);
 int afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
-                    register struct afs_ioctl *ablob, int afollow,
+                    struct afs_ioctl *ablob, int afollow,
                     afs_ucred_t **acred);
 static int Prefetch(uparmtype apath, struct afs_ioctl *adata, int afollow,
                    afs_ucred_t *acred);
@@ -407,8 +413,8 @@ static pioctlFunction CpioctlSw[] = {
     PBogus,                     /* 4 */
     PDiscon,                    /* 5 -- get/set discon mode */
     PBogus,                     /* 6 */
-    PBogus,                     /* 7 */
-    PBogus,                     /* 8 */
+    PGetTokens2,                /* 7 */
+    PSetTokens2,                /* 8 */
     PNewUuid,                   /* 9 */
     PBogus,                     /* 10 */
     PBogus,                     /* 11 */
@@ -419,7 +425,7 @@ static pioctlFunction CpioctlSw[] = {
 static pioctlFunction OpioctlSw[]  = {
     PBogus,                    /* 0 */
     PNFSNukeCreds,             /* 1 -- nuke all creds for NFS client */
-#if defined(AFS_CACHE_BYPASS)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
     PSetCachingThreshold        /* 2 -- get/set cache-bypass size threshold */
 #else
     PNoop                       /* 2 -- get/set cache-bypass size threshold */
@@ -430,10 +436,10 @@ static pioctlFunction OpioctlSw[]  = {
 int afs_nobody = NFS_NOBODY;
 
 int
-HandleIoctl(register struct vcache *avc, register afs_int32 acom,
+HandleIoctl(struct vcache *avc, afs_int32 acom,
            struct afs_ioctl *adata)
 {
-    register afs_int32 code;
+    afs_int32 code;
 
     code = 0;
     AFS_STATCNT(HandleIoctl);
@@ -451,8 +457,8 @@ HandleIoctl(register struct vcache *avc, register afs_int32 acom,
 
     case 3:{
            /* return the name of the cell this file is open on */
-           register struct cell *tcell;
-           register afs_int32 i;
+           struct cell *tcell;
+           afs_int32 i;
 
            tcell = afs_GetCell(avc->f.fid.Cell, READ_LOCK);
            if (tcell) {
@@ -540,8 +546,8 @@ kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
 #  endif
     } u_uap, *uap = &u_uap;
     struct file *fd;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
     uap->fd = fdes;
@@ -560,7 +566,7 @@ kioctl(int fdes, int com, caddr_t arg, caddr_t ext)
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
-               register struct afs_ioctl *datap;
+               struct afs_ioctl *datap;
                AFS_GLOCK();
                datap =
                    (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
@@ -653,12 +659,12 @@ struct afs_ioctl_sys {
     int arg;
 };
 
-int 
+int
 afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
 {
     struct file *fd;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
 # if defined(AFS_SUN57_ENV)
@@ -679,7 +685,7 @@ afs_xioctl(struct afs_ioctl_sys *uap, rval_t *rvp)
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
-               register struct afs_ioctl *datap;
+               struct afs_ioctl *datap;
                AFS_GLOCK();
                datap =
                    (struct afs_ioctl *)osi_AllocSmallSpace(AFS_SMALLOCSIZ);
@@ -723,8 +729,8 @@ afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
           unsigned long arg)
 {
     struct afs_ioctl_sys ua, *uap = &ua;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
     ua.com = com;
@@ -734,7 +740,7 @@ afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
     if (tvc && IsAfsVnode(AFSTOV(tvc))) {
        /* This is an AFS vnode */
        if (((uap->com >> 8) & 0xff) == 'V') {
-           register struct afs_ioctl *datap;
+           struct afs_ioctl *datap;
            AFS_GLOCK();
            datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
            code = copyin_afs_ioctl((char *)uap->arg, datap);
@@ -761,11 +767,11 @@ struct ioctl_args {
 };
 
 int
-afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
+afs_xioctl(afs_proc_t *p, struct ioctl_args *uap, register_t *retval)
 {
     struct file *fd;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
     if ((code = fdgetf(p, uap->fd, &fd)))
@@ -775,7 +781,7 @@ afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
-               register struct afs_ioctl *datap;
+               struct afs_ioctl *datap;
                AFS_GLOCK();
                datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
                code = copyin_afs_ioctl((char *)uap->arg, datap);
@@ -798,10 +804,10 @@ afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
     return (code);
 }
 #elif defined(AFS_XBSD_ENV)
-# if defined(AFS_FBSD50_ENV)
+# if defined(AFS_FBSD_ENV)
 #  define arg data
 int
-afs_xioctl(struct thread *td, register struct ioctl_args *uap,
+afs_xioctl(struct thread *td, struct ioctl_args *uap,
           register_t *retval)
 {
     afs_proc_t *p = td->td_proc;
@@ -813,12 +819,12 @@ struct ioctl_args {
 };
 
 int
-afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
+afs_xioctl(afs_proc_t *p, struct ioctl_args *uap, register_t *retval)
 {
 # endif
-    register struct filedesc *fdp;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct filedesc *fdp;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
     struct file *fd;
 
     AFS_STATCNT(afs_xioctl);
@@ -845,7 +851,7 @@ afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
-               register struct afs_ioctl *datap;
+               struct afs_ioctl *datap;
                AFS_GLOCK();
                datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
                code = copyin_afs_ioctl((char *)uap->arg, datap);
@@ -863,10 +869,8 @@ afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
     }
 
     if (!ioctlDone) {
-# if defined(AFS_FBSD50_ENV)
+# if defined(AFS_FBSD_ENV)
        return ioctl(td, uap);
-# elif defined(AFS_FBSD_ENV)
-       return ioctl(p, uap);
 # elif defined(AFS_OBSD_ENV)
        code = sys_ioctl(p, uap, retval);
 # elif defined(AFS_NBSD_ENV)
@@ -881,14 +885,14 @@ afs_xioctl(afs_proc_t *p, register struct ioctl_args *uap, register_t *retval)
 int
 afs_xioctl(void)
 {
-    register struct a {
+    struct a {
        int fd;
        int com;
        caddr_t arg;
     } *uap = (struct a *)get_user_struct()->u_ap;
-    register struct file *fd;
-    register struct vcache *tvc;
-    register int ioctlDone = 0, code = 0;
+    struct file *fd;
+    struct vcache *tvc;
+    int ioctlDone = 0, code = 0;
 
     AFS_STATCNT(afs_xioctl);
 
@@ -902,7 +906,7 @@ afs_xioctl(void)
        if (tvc && IsAfsVnode(AFSTOV(tvc))) {
            /* This is an AFS vnode */
            if (((uap->com >> 8) & 0xff) == 'V') {
-               register struct afs_ioctl *datap;
+               struct afs_ioctl *datap;
                AFS_GLOCK();
                datap = osi_AllocSmallSpace(AFS_SMALLOCSIZ);
                code=copyin_afs_ioctl((char *)uap->arg, datap);
@@ -953,7 +957,7 @@ afs_pioctl(struct pioctlargs *uap, rval_t * rvp)
 # endif
 }
 
-#elif defined(AFS_FBSD50_ENV)
+#elif defined(AFS_FBSD_ENV)
 int
 afs_pioctl(struct thread *td, void *args, int *retval)
 {
@@ -971,11 +975,7 @@ afs_pioctl(struct thread *td, void *args, int *retval)
 
 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
 int
-# if defined(AFS_FBSD_ENV)
-afs_pioctl(struct thread *td, void *args)
-# else
 afs_pioctl(afs_proc_t *p, void *args, int *retval)
-# endif
 {
     struct a {
        char *path;
@@ -1011,14 +1011,14 @@ afs_pioctl(afs_proc_t *p, void *args, int *retval)
 
 int
 #ifdef AFS_SUN5_ENV
-afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow, 
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
                   rval_t *vvp, afs_ucred_t *credp)
 #else
 #ifdef AFS_DARWIN100_ENV
 afs_syscall64_pioctl(user_addr_t path, unsigned int com, user_addr_t cmarg,
                   int follow, afs_ucred_t *credp)
 #elif defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow, 
+afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow,
                   afs_ucred_t *credp)
 #else
 afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
@@ -1032,7 +1032,7 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #if defined(AFS_NEED_CLIENTCONTEXT) || defined(AFS_SUN5_ENV) || defined(AFS_AIX41_ENV) || defined(AFS_LINUX22_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     afs_ucred_t *foreigncreds = NULL;
 #endif
-    register afs_int32 code = 0;
+    afs_int32 code = 0;
     struct vnode *vp = NULL;
 #ifdef AFS_AIX41_ENV
     struct ucred *credp = crref();     /* don't free until done! */
@@ -1133,7 +1133,8 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
 #else
        code = gop_lookupname_user(path, AFS_UIOUSER, follow, &vp);
 #if defined(AFS_FBSD80_ENV) /* XXX check on 7x */
-       VN_HOLD(vp);
+       if (vp != NULL)
+               VN_HOLD(vp);
 #endif /* AFS_FBSD80_ENV */
 #endif /* AFS_LINUX22_ENV */
 #endif /* AFS_AIX41_ENV */
@@ -1153,13 +1154,13 @@ afs_syscall_pioctl(char *path, unsigned int com, caddr_t cmarg, int follow)
        struct vnode *realvp;
        if
 #ifdef AFS_SUN511_ENV
-          (VOP_REALVP(vp, &realvp, NULL) == 0) 
+          (VOP_REALVP(vp, &realvp, NULL) == 0)
 #else
-         (VOP_REALVP(vp, &realvp) == 0) 
+         (VOP_REALVP(vp, &realvp) == 0)
 #endif
 {
            struct vnode *oldvp = vp;
-           
+
            VN_HOLD(realvp);
            vp = realvp;
            AFS_RELE(oldvp);
@@ -1268,13 +1269,13 @@ afs_syscall_pioctl(char * path, unsigned int com, caddr_t cmarg,
 
 int
 afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
-                register struct afs_ioctl *ablob, int afollow,
+                struct afs_ioctl *ablob, int afollow,
                 afs_ucred_t **acred)
 {
     struct vcache *avc;
     struct vrequest treq;
-    register afs_int32 code;
-    register afs_int32 function, device;
+    afs_int32 code;
+    afs_int32 function, device;
     struct afs_pdata input, output;
     struct afs_pdata copyInput, copyOutput;
     size_t outSize;
@@ -1342,7 +1343,8 @@ afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
     if (code)
        goto out;
 
-    if (function == 8 && device == 'V') {      /* PGetTokens */
+    if ((function == 8 && device == 'V') ||
+       (function == 7 && device == 'C')) {     /* PGetTokens */
        code = afs_pd_alloc(&output, MAXPIOCTLTOKENLEN);
     } else {
        code = afs_pd_alloc(&output, AFS_LRALLOCSIZ);
@@ -1417,7 +1419,7 @@ dummy_PSetAcl(char *ain, char *aout)
 
 DECL_PIOCTL(PSetAcl)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct afs_conn *tconn;
     struct AFSOpaque acl;
     struct AFSVolSync tsync;
@@ -1679,7 +1681,7 @@ DECL_PIOCTL(PBogus)
  */
 DECL_PIOCTL(PGetFileCell)
 {
-    register struct cell *tcell;
+    struct cell *tcell;
 
     AFS_STATCNT(PGetFileCell);
     if (!avc)
@@ -1743,9 +1745,9 @@ DECL_PIOCTL(PGetWSCell)
  */
 DECL_PIOCTL(PGetUserCell)
 {
-    register afs_int32 i;
-    register struct unixuser *tu;
-    register struct cell *tcell;
+    afs_int32 i;
+    struct unixuser *tu;
+    struct cell *tcell;
 
     AFS_STATCNT(PGetUserCell);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -1777,6 +1779,47 @@ DECL_PIOCTL(PGetUserCell)
     return 0;
 }
 
+/* Work out which cell we're changing tokens for */
+static_inline int
+_settok_tokenCell(char *cellName, int *cellNum, int *primary) {
+    int t1;
+    struct cell *cell;
+
+    if (cellName && strlen(cellName) > 0) {
+       cell = afs_GetCellByName(cellName, READ_LOCK);
+    } else {
+       cell = afs_GetPrimaryCell(READ_LOCK);
+       if (primary)
+           *primary = 1;
+    }
+    if (!cell) {
+       t1 = afs_initState;
+       if (t1 < 101)
+           return EIO;
+       else
+           return ESRCH;
+    }
+    *cellNum = cell->cellNum;
+    afs_PutCell(cell, READ_LOCK);
+
+    return 0;
+}
+
+
+static_inline int
+_settok_setParentPag(afs_ucred_t **cred) {
+    afs_uint32 pag;
+#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
+    char procname[256];
+    osi_procname(procname, 256);
+    afs_warnuser("Process %d (%s) tried to change pags in PSetTokens\n",
+                MyPidxx2Pid(MyPidxx), procname);
+    return setpag(osi_curproc(), cred, -1, &pag, 1);
+#else
+    return setpag(cred, -1, &pag, 1);
+#endif
+}
+
 /*!
  * VIOCSETTOK (3) - Set authentication tokens
  *
@@ -1799,10 +1842,11 @@ DECL_PIOCTL(PGetUserCell)
  */
 DECL_PIOCTL(PSetTokens)
 {
-    afs_int32 i;
-    register struct unixuser *tu;
+    afs_int32 cellNum;
+    afs_int32 size;
+    afs_int32 code;
+    struct unixuser *tu;
     struct ClearToken clear;
-    register struct cell *tcell;
     char *stp;
     char *cellName;
     int stLen;
@@ -1823,9 +1867,9 @@ DECL_PIOCTL(PSetTokens)
     if (afs_pd_skip(ain, stLen) != 0)
        return EINVAL;
 
-    if (afs_pd_getInt(ain, &i) != 0)
+    if (afs_pd_getInt(ain, &size) != 0)
        return EINVAL;
-    if (i != sizeof(struct ClearToken))
+    if (size != sizeof(struct ClearToken))
        return EINVAL;
 
     if (afs_pd_getBytes(ain, &clear, sizeof(struct ClearToken)) !=0)
@@ -1851,59 +1895,28 @@ DECL_PIOCTL(PSetTokens)
        if (afs_pd_getStringPtr(ain, &cellName) != 0)
            return EINVAL;
 
-       /* rest is cell name, look it up */
-       tcell = afs_GetCellByName(cellName, READ_LOCK);
-       if (!tcell)
-           goto nocell;
+       code = _settok_tokenCell(cellName, &cellNum, NULL);
+       if (code)
+           return code;
     } else {
        /* default to primary cell, primary id */
-       flag = 1;               /* primary id */
-       tcell = afs_GetPrimaryCell(READ_LOCK);
-       if (!tcell)
-           goto nocell;
+       code = _settok_tokenCell(NULL, &cellNum, &flag);
+       if (code)
+           return code;
     }
-    i = tcell->cellNum;
-    afs_PutCell(tcell, READ_LOCK);
+
     if (set_parent_pag) {
-       afs_uint32 pag;
-#if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
-# if defined(AFS_DARWIN_ENV)
-       afs_proc_t *p = current_proc(); /* XXX */
-       char procname[256];
-       proc_selfname(procname, 256);
-# elif defined(AFS_FBSD_ENV)
-       struct thread *p = curthread;
-       char *procname = p->td_proc->p_comm;
-# elif defined(AFS_NBSD40_ENV)
-       afs_proc_t *p = curproc;        /* XXX */
-       char *procname = p->l_proc->p_comm;
-# else
-       afs_proc_t *p = curproc;        /* XXX */
-       char *procname = p->p_comm;
-# endif
-       afs_warnuser("Process %d (%s) tried to change pags in PSetTokens\n",
-                    MyPidxx2Pid(MyPidxx), procname);
-       if (!setpag(p, acred, -1, &pag, 1)) {
-#else
-       if (!setpag(acred, -1, &pag, 1)) {
-#endif
+       if (_settok_setParentPag(acred) == 0) {
            afs_InitReq(&treq, *acred);
            areq = &treq;
        }
     }
+
     /* now we just set the tokens */
-    tu = afs_GetUser(areq->uid, i, WRITE_LOCK);        /* i has the cell # */
-    tu->vid = clear.ViceId;
-    if (tu->stp != NULL) {
-       afs_osi_Free(tu->stp, tu->stLen);
-    }
-    tu->stp = (char *)afs_osi_Alloc(stLen);
-    if (tu->stp == NULL) {
-       return ENOMEM;
-    }
-    tu->stLen = stLen;
-    memcpy(tu->stp, stp, stLen);
-    tu->ct = clear;
+    tu = afs_GetUser(areq->uid, cellNum, WRITE_LOCK);
+    /* Set tokens destroys any that are already there */
+    afs_FreeTokens(&tu->tokens);
+    afs_AddRxkadToken(&tu->tokens, stp, stLen, &clear);
 #ifndef AFS_NOSTATS
     afs_stats_cmfullperf.authent.TicketUpdates++;
     afs_ComputePAGStats();
@@ -1917,16 +1930,6 @@ DECL_PIOCTL(PSetTokens)
     afs_PutUser(tu, WRITE_LOCK);
 
     return 0;
-
-  nocell:
-    {
-       int t1;
-       t1 = afs_initState;
-       if (t1 < 101)
-           return EIO;
-       else
-           return ESRCH;
-    }
 }
 
 /*!
@@ -1948,12 +1951,14 @@ DECL_PIOCTL(PGetVolumeStatus)
     char volName[32];
     char *offLineMsg = afs_osi_Alloc(256);
     char *motd = afs_osi_Alloc(256);
-    register struct afs_conn *tc;
-    register afs_int32 code = 0;
+    struct afs_conn *tc;
+    afs_int32 code = 0;
     struct AFSFetchVolumeStatus volstat;
     char *Name;
     XSTATS_DECLS;
 
+    osi_Assert(offLineMsg != NULL);
+    osi_Assert(motd != NULL);
     AFS_STATCNT(PGetVolumeStatus);
     if (!avc) {
        code = EINVAL;
@@ -2022,11 +2027,11 @@ DECL_PIOCTL(PSetVolumeStatus)
     char *volName;
     char *offLineMsg;
     char *motd;
-    register struct afs_conn *tc;
-    register afs_int32 code = 0;
+    struct afs_conn *tc;
+    afs_int32 code = 0;
     struct AFSFetchVolumeStatus volstat;
     struct AFSStoreVolumeStatus storeStat;
-    register struct volume *tvp;
+    struct volume *tvp;
     XSTATS_DECLS;
 
     AFS_STATCNT(PSetVolumeStatus);
@@ -2155,9 +2160,9 @@ DECL_PIOCTL(PFlush)
  */
 DECL_PIOCTL(PNewStatMount)
 {
-    register afs_int32 code;
-    register struct vcache *tvc;
-    register struct dcache *tdc;
+    afs_int32 code;
+    struct vcache *tvc;
+    struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
     char *name;
@@ -2230,13 +2235,41 @@ DECL_PIOCTL(PNewStatMount)
 }
 
 /*!
+ * A helper function to get the n'th cell which a particular user has tokens
+ * for. This is racy. If new tokens are added whilst we're iterating, then
+ * we may return some cells twice. If tokens expire mid run, then we'll
+ * miss some cells from our output. So, could be better, but that would
+ * require an interface change.
+ */
+
+static struct unixuser *
+getNthCell(afs_int32 uid, afs_int32 iterator) {
+    int i;
+    struct unixuser *tu = NULL;
+
+    i = UHash(uid);
+    ObtainReadLock(&afs_xuser);
+    for (tu = afs_users[i]; tu; tu = tu->next) {
+       if (tu->uid == uid && (tu->states & UHasTokens)) {
+           if (iterator-- == 0)
+           break;      /* are we done yet? */
+       }
+    }
+    if (tu) {
+       tu->refCount++;
+    }
+    ReleaseReadLock(&afs_xuser);
+
+    return tu;
+}
+/*!
  * VIOCGETTOK (8) - Get authentication tokens
- *  
+ *
  * \ingroup pioctl
- *      
+ *
  * \param[in] ain       cellid to return tokens for
  * \param[out] aout     token
- * 
+ *
  * \retval EIO
  *     Error if the afs daemon hasn't started yet
  * \retval EDOM
@@ -2244,7 +2277,7 @@ DECL_PIOCTL(PNewStatMount)
  *     tokens
  * \retval ENOTCONN
  *     Error if there aren't tokens for this cell
- *  
+ *
  * \post
  *     If the input paramater exists, get the token that corresponds to
  *     the parameter value, if there is no token at this value, get the
@@ -2255,11 +2288,12 @@ DECL_PIOCTL(PNewStatMount)
 
 DECL_PIOCTL(PGetTokens)
 {
-    register struct cell *tcell;
-    register afs_int32 i;
-    register struct unixuser *tu;
+    struct cell *tcell;
+    struct unixuser *tu = NULL;
+    union tokenUnion *token;
     afs_int32 iterator = 0;
     int newStyle;
+    int cellNum;
     int code = E2BIG;
 
     AFS_STATCNT(PGetTokens);
@@ -2280,55 +2314,50 @@ DECL_PIOCTL(PGetTokens)
        if (afs_pd_getInt(ain, &iterator) != 0)
            return EINVAL;
     }
-    i = UHash(areq->uid);
-    ObtainReadLock(&afs_xuser);
-    for (tu = afs_users[i]; tu; tu = tu->next) {
-       if (newStyle) {
-           if (tu->uid == areq->uid && (tu->states & UHasTokens)) {
-               if (iterator-- == 0)
-                   break;      /* are we done yet? */
-           }
-       } else {
-           if (tu->uid == areq->uid && afs_IsPrimaryCellNum(tu->cell))
-               break;
-       }
-    }
-    if (tu) {
-       /*
-        * No need to hold a read lock on each user entry
-        */
-       tu->refCount++;
+    if (newStyle) {
+       tu = getNthCell(areq->uid, iterator);
+    } else {
+       cellNum = afs_GetPrimaryCellNum();
+       if (cellNum)
+           tu = afs_FindUser(areq->uid, cellNum, READ_LOCK);
     }
-    ReleaseReadLock(&afs_xuser);
-
     if (!tu) {
        return EDOM;
     }
-    if (((tu->states & UHasTokens) == 0)
-       || (tu->ct.EndTimestamp < osi_Time())) {
+    if (!(tu->states & UHasTokens)
+       || !afs_HasUsableTokens(tu->tokens, osi_Time())) {
        tu->states |= (UTokensBad | UNeedsReset);
        afs_NotifyUser(tu, UTokensDropped);
        afs_PutUser(tu, READ_LOCK);
        return ENOTCONN;
     }
-    iterator = tu->stLen;      /* for compat, we try to return 56 byte tix if they fit */
+    token = afs_FindToken(tu->tokens, RX_SECIDX_KAD);
+
+    /* If they don't have an RXKAD token, but do have other tokens,
+     * then sadly there's nothing this interface can do to help them. */
+    if (token == NULL)
+       return ENOTCONN;
+
+    /* for compat, we try to return 56 byte tix if they fit */
+    iterator = token->rxkad.ticketLen;
     if (iterator < 56)
        iterator = 56;          /* # of bytes we're returning */
 
     if (afs_pd_putInt(aout, iterator) != 0)
        goto out;
-    if (afs_pd_putBytes(aout, tu->stp, tu->stLen) != 0)
+    if (afs_pd_putBytes(aout, token->rxkad.ticket, token->rxkad.ticketLen) != 0)
        goto out;
-    if (tu->stLen < 56) {
+    if (token->rxkad.ticketLen < 56) {
        /* Tokens are always 56 bytes or larger */
-       if (afs_pd_skip(aout, iterator - tu->stLen) != 0) {
+       if (afs_pd_skip(aout, iterator - token->rxkad.ticketLen) != 0) {
            goto out;
        }
     }
 
     if (afs_pd_putInt(aout, sizeof(struct ClearToken)) != 0)
        goto out;
-    if (afs_pd_putBytes(aout, &tu->ct, sizeof(struct ClearToken)) != 0)
+    if (afs_pd_putBytes(aout, &token->rxkad.clearToken,
+                       sizeof(struct ClearToken)) != 0)
        goto out;
 
     if (newStyle) {
@@ -2369,8 +2398,8 @@ out:
  */
 DECL_PIOCTL(PUnlog)
 {
-    register afs_int32 i;
-    register struct unixuser *tu;
+    afs_int32 i;
+    struct unixuser *tu;
 
     AFS_STATCNT(PUnlog);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -2380,10 +2409,8 @@ DECL_PIOCTL(PUnlog)
     ObtainWriteLock(&afs_xuser, 227);
     for (tu = afs_users[i]; tu; tu = tu->next) {
        if (tu->uid == areq->uid) {
-           tu->vid = UNDEFVID;
            tu->states &= ~UHasTokens;
-           /* security is not having to say you're sorry */
-           memset(&tu->ct, 0, sizeof(struct ClearToken));
+           afs_FreeTokens(&tu->tokens);
            tu->refCount++;
            ReleaseWriteLock(&afs_xuser);
            afs_NotifyUser(tu, UTokensDropped);
@@ -2402,7 +2429,6 @@ DECL_PIOCTL(PUnlog)
            /* set the expire times to 0, causes
             * afs_GCUserData to remove this entry
             */
-           tu->ct.EndTimestamp = 0;
            tu->tokenTime = 0;
 #endif /* UKERNEL */
        }
@@ -2473,8 +2499,8 @@ DECL_PIOCTL(PMariner)
  */
 DECL_PIOCTL(PCheckServers)
 {
-    register int i;
-    register struct server *ts;
+    int i;
+    struct server *ts;
     afs_int32 temp;
     char *cellName = NULL;
     struct cell *cellp;
@@ -2605,7 +2631,7 @@ DECL_PIOCTL(PCheckAuth)
 {
     int i;
     struct srvAddr *sa;
-    struct afs_conn *tc;
+    struct sa_conn_vector *tcv;
     struct unixuser *tu;
     afs_int32 retValue;
 
@@ -2628,8 +2654,8 @@ DECL_PIOCTL(PCheckAuth)
        /* all connections in cell 1 working? */
        for (i = 0; i < NSERVERS; i++) {
            for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
-               for (tc = sa->conns; tc; tc = tc->next) {
-                   if (tc->user == tu && (tu->states & UTokensBad))
+               for (tcv = sa->conns; tcv; tcv = tcv->next) {
+                   if (tcv->user == tu && (tu->states & UTokensBad))
                        retValue = EACCES;
                }
            }
@@ -2647,8 +2673,8 @@ static int
 Prefetch(uparmtype apath, struct afs_ioctl *adata, int afollow,
         afs_ucred_t *acred)
 {
-    register char *tp;
-    register afs_int32 code;
+    char *tp;
+    afs_int32 code;
 #if defined(AFS_SGI61_ENV) || defined(AFS_SUN57_ENV) || defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV)
     size_t bufferSize;
 #else
@@ -2690,9 +2716,9 @@ Prefetch(uparmtype apath, struct afs_ioctl *adata, int afollow,
  */
 DECL_PIOCTL(PFindVolume)
 {
-    register struct volume *tvp;
-    register struct server *ts;
-    register afs_int32 i;
+    struct volume *tvp;
+    struct server *ts;
+    afs_int32 i;
     int code = 0;
 
     AFS_STATCNT(PFindVolume);
@@ -2738,7 +2764,7 @@ out:
  */
 DECL_PIOCTL(PViceAccess)
 {
-    register afs_int32 code;
+    afs_int32 code;
     afs_int32 temp;
 
     AFS_STATCNT(PViceAccess);
@@ -2858,9 +2884,9 @@ DECL_PIOCTL(PGetCacheSize)
 {
     afs_int32 results[MAXGCSTATS];
     afs_int32 flags;
-    register struct dcache * tdc;
+    struct dcache * tdc;
     int i, size;
-    
+
     AFS_STATCNT(PGetCacheSize);
 
     if (afs_pd_remaining(ain) == sizeof(afs_int32)) {
@@ -2870,12 +2896,12 @@ DECL_PIOCTL(PGetCacheSize)
     } else {
        return EINVAL;
     }
-    
+
     memset(results, 0, sizeof(results));
     results[0] = afs_cacheBlocks;
     results[1] = afs_blocksUsed;
     results[2] = afs_cacheFiles;
-    
+
     if (1 == flags){
         for (i = 0; i < afs_cacheFiles; i++) {
            if (afs_indexFlags[i] & IFFree) results[3]++;
@@ -2923,8 +2949,8 @@ DECL_PIOCTL(PGetCacheSize)
  */
 DECL_PIOCTL(PRemoveCallBack)
 {
-    register struct afs_conn *tc;
-    register afs_int32 code = 0;
+    struct afs_conn *tc;
+    afs_int32 code = 0;
     struct AFSCallBack CallBacks_Array[1];
     struct AFSCBFids theFids;
     struct AFSCBs theCBs;
@@ -3097,8 +3123,8 @@ DECL_PIOCTL(PNewAlias)
 DECL_PIOCTL(PListCells)
 {
     afs_int32 whichCell;
-    register struct cell *tcell = 0;
-    register afs_int32 i;
+    struct cell *tcell = 0;
+    afs_int32 i;
     int code;
 
     AFS_STATCNT(PListCells);
@@ -3136,7 +3162,7 @@ out:
 DECL_PIOCTL(PListAliases)
 {
     afs_int32 whichAlias;
-    register struct cell_alias *tcalias = 0;
+    struct cell_alias *tcalias = 0;
     int code;
 
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -3183,14 +3209,14 @@ out:
  */
 DECL_PIOCTL(PRemoveMount)
 {
-    register afs_int32 code;
+    afs_int32 code;
     char *bufp;
     char *name;
     struct sysname_info sysState;
     afs_size_t offset, len;
-    register struct afs_conn *tc;
-    register struct dcache *tdc;
-    register struct vcache *tvc;
+    struct afs_conn *tc;
+    struct dcache *tdc;
+    struct vcache *tvc;
     struct AFSFetchStatus OutDirStatus;
     struct VenusFid tfid;
     struct AFSVolSync tsync;
@@ -3320,7 +3346,7 @@ DECL_PIOCTL(PRemoveMount)
  */
 DECL_PIOCTL(PGetCellStatus)
 {
-    register struct cell *tcell;
+    struct cell *tcell;
     char *cellName;
     afs_int32 temp;
 
@@ -3360,7 +3386,7 @@ DECL_PIOCTL(PGetCellStatus)
  */
 DECL_PIOCTL(PSetCellStatus)
 {
-    register struct cell *tcell;
+    struct cell *tcell;
     char *cellName;
     afs_int32 flags0, flags1;
 
@@ -3409,10 +3435,10 @@ DECL_PIOCTL(PSetCellStatus)
  */
 DECL_PIOCTL(PFlushVolumeData)
 {
-    register afs_int32 i;
-    register struct dcache *tdc;
-    register struct vcache *tvc;
-    register struct volume *tv;
+    afs_int32 i;
+    struct dcache *tdc;
+    struct vcache *tvc;
+    struct volume *tv;
     afs_int32 cell, volume;
     struct afs_q *tq, *uq;
 #ifdef AFS_DARWIN80_ENV
@@ -3445,17 +3471,13 @@ DECL_PIOCTL(PFlushVolumeData)
                    goto loop;
                }
 #ifdef AFS_DARWIN80_ENV
-           if (tvc->f.states & CDeadVnode) {
-               if (!(tvc->f.states & CBulkFetching)) {
-                   ReleaseReadLock(&afs_xvcache);
-                   afs_osi_Sleep(&tvc->f.states);
-                   goto loop;
+               if (tvc->f.states & CDeadVnode) {
+                   if (!(tvc->f.states & CBulkFetching)) {
+                       ReleaseReadLock(&afs_xvcache);
+                       afs_osi_Sleep(&tvc->f.states);
+                       goto loop;
+                   }
                }
-           }
-#endif
-#if    defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV)  || defined(AFS_HPUX_ENV) || defined(AFS_LINUX20_ENV)
-               VN_HOLD(AFSTOV(tvc));
-#elif defined(AFS_DARWIN80_ENV)
                vp = AFSTOV(tvc);
                if (vnode_get(vp))
                    continue;
@@ -3515,7 +3537,7 @@ DECL_PIOCTL(PFlushVolumeData)
                     * then someone probably has the file open and is writing
                     * into it. Better to skip flushing such a file, it will be
                     * brought back immediately on the next write anyway.
-                    * 
+                    *
                     * If we *must* flush, then this code has to be rearranged
                     * to call afs_storeAllSegments() first */
                    afs_FlushDCache(tdc);
@@ -3570,7 +3592,7 @@ DECL_PIOCTL(PFlushVolumeData)
  */
 DECL_PIOCTL(PGetVnodeXStatus)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct vcxstat stat;
     afs_int32 mode, i;
 
@@ -3618,7 +3640,7 @@ DECL_PIOCTL(PGetVnodeXStatus)
 
 DECL_PIOCTL(PGetVnodeXStatus2)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct vcxstat2 stat;
     afs_int32 mode;
 
@@ -3677,9 +3699,9 @@ DECL_PIOCTL(PSetSysName)
     char outname[MAXSYSNAME];
     afs_int32 setsysname;
     int foundname = 0;
-    register struct afs_exporter *exporter;
-    register struct unixuser *au;
-    register afs_int32 pag, error;
+    struct afs_exporter *exporter;
+    struct unixuser *au;
+    afs_int32 pag, error;
     int t, count, num = 0, allpags = 0;
     char **sysnamelist;
     struct afs_pdata validate;
@@ -3845,11 +3867,12 @@ ReSortCells(int s, afs_int32 * l, int vlonly)
 {
     int i;
     struct volume *j;
-    register int k;
+    int k;
 
     if (vlonly) {
        afs_int32 *p;
-       p = (afs_int32 *) afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
+       p = afs_osi_Alloc(sizeof(afs_int32) * (s + 1));
+        osi_Assert(p != NULL);
        p[0] = s;
        memcpy(p + 1, l, s * sizeof(afs_int32));
        afs_TraverseCells(&ReSortCells_cb, p);
@@ -3993,7 +4016,7 @@ DECL_PIOCTL(PSetSPrefs)
     return 0;
 }
 
-/* 
+/*
  * VIOC_SETPREFS33 (42) - Set server ranks (deprecated)
  *
  * \param[in] ain      the server preferences to be set
@@ -4022,7 +4045,7 @@ DECL_PIOCTL(PSetSPrefs33)
     return 0;
 }
 
-/* 
+/*
  * VIOC_GETSPREFS (43) - Get server ranks
  *
  * \ingroup pioctl
@@ -4144,7 +4167,7 @@ DECL_PIOCTL(PExportAfs)
     afs_int32 export, newint = 0;
     afs_int32 type, changestate, handleValue, convmode, pwsync, smounts;
     afs_int32 rempags = 0, pagcb = 0;
-    register struct afs_exporter *exporter;
+    struct afs_exporter *exporter;
 
     AFS_STATCNT(PExportAfs);
     if (afs_pd_getInt(ain, &handleValue) != 0)
@@ -4344,7 +4367,6 @@ DECL_PIOCTL(PGetInitParams)
 
     return afs_pd_putBytes(aout, &cm_initParams,
                           sizeof(struct cm_initparams));
-    return 0;
 }
 
 #ifdef AFS_SGI65_ENV
@@ -4508,15 +4530,15 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
     newcred->cr_groupset.gs_union.un_groups[1] = g1;
 #elif defined(AFS_LINUX26_ENV)
 # ifdef AFS_LINUX26_ONEGROUP_ENV
-    set_cr_group_info(newcred, groups_alloc(1)); /* nothing sets this */
+    afs_set_cr_group_info(newcred, groups_alloc(1)); /* nothing sets this */
     l = (((g0-0x3f00) & 0x3fff) << 14) | ((g1-0x3f00) & 0x3fff);
     h = ((g0-0x3f00) >> 14);
     h = ((g1-0x3f00) >> 14) + h + h + h;
-    GROUP_AT(cr_group_info(newcred), 0) = ((h << 28) | l);
+    GROUP_AT(afs_cr_group_info(newcred), 0) = ((h << 28) | l);
 # else
-    set_cr_group_info(newcred, groups_alloc(2));
-    GROUP_AT(cr_group_info(newcred), 0) = g0;
-    GROUP_AT(cr_group_info(newcred), 1) = g1;
+    afs_set_cr_group_info(newcred, groups_alloc(2));
+    GROUP_AT(afs_cr_group_info(newcred), 0) = g0;
+    GROUP_AT(afs_cr_group_info(newcred), 1) = g1;
 # endif
 #elif defined(AFS_SUN510_ENV)
     gids[0] = g0;
@@ -4573,14 +4595,14 @@ HandleClientContext(struct afs_ioctl *ablob, int *com,
     } else if (!code) {
        EXP_RELE(outexporter);
     }
-    if (!code) 
+    if (!code)
        *com = (*com) | comp;
     return code;
 }
 #endif /* AFS_NEED_CLIENTCONTEXT */
 
 
-/*! 
+/*!
  * VIOC_GETCPREFS (50) - Get client interface
  *
  * \ingroup pioctl
@@ -4713,9 +4735,9 @@ DECL_PIOCTL(PSetCPrefs)
  */
 DECL_PIOCTL(PFlushMount)
 {
-    register afs_int32 code;
-    register struct vcache *tvc;
-    register struct dcache *tdc;
+    afs_int32 code;
+    struct vcache *tvc;
+    struct dcache *tdc;
     struct VenusFid tfid;
     char *bufp;
     char *mount;
@@ -4874,7 +4896,7 @@ DECL_PIOCTL(PRxStatPeer)
 
 DECL_PIOCTL(PPrefetchFromTape)
 {
-    register afs_int32 code, code1;
+    afs_int32 code, code1;
     afs_int32 bytes, outval;
     struct afs_conn *tc;
     struct rx_call *tcall;
@@ -4940,7 +4962,7 @@ DECL_PIOCTL(PPrefetchFromTape)
 
 DECL_PIOCTL(PFsCmd)
 {
-    register afs_int32 code;
+    afs_int32 code;
     struct afs_conn *tc;
     struct vcache *tvc;
     struct FsCmdInputs *Inputs;
@@ -4980,7 +5002,7 @@ DECL_PIOCTL(PFsCmd)
            if (tc) {
                RX_AFS_GUNLOCK();
                code =
-                   RXAFS_FsCmd(tc->id, Fid, Inputs, 
+                   RXAFS_FsCmd(tc->id, Fid, Inputs,
                                        (struct FsCmdOutputs *)aout);
                RX_AFS_GLOCK();
            } else
@@ -5023,13 +5045,13 @@ DECL_PIOCTL(PNewUuid)
     return 0;
 }
 
-#if defined(AFS_CACHE_BYPASS)
+#if defined(AFS_CACHE_BYPASS) && defined(AFS_LINUX24_ENV)
 
 DECL_PIOCTL(PSetCachingThreshold)
 {
     afs_int32 getting = 1;
     afs_int32 setting = 1;
-    afs_int32 threshold;
+    afs_int32 threshold = AFS_CACHE_BYPASS_DISABLED;
 
     if (afs_pd_getInt(ain, &threshold) != 0)
        setting = 0;
@@ -5039,19 +5061,19 @@ DECL_PIOCTL(PSetCachingThreshold)
 
     if (setting == 0 && getting == 0)
        return EINVAL;
-       
-    /* 
+
+    /*
      * If setting, set first, and return the value now in effect
      */
     if (setting) {
        if (!afs_osi_suser(*acred))
            return EPERM;
        cache_bypass_threshold = threshold;
-        afs_warn("Cache Bypass Threshold set to: %d\n", threshold);            
+        afs_warn("Cache Bypass Threshold set to: %d\n", threshold);
        /* TODO:  move to separate pioctl, or enhance pioctl */
        cache_bypass_strategy = LARGE_FILES_BYPASS_CACHE;
     }
-       
+
     /* Return the current size threshold */
     if (getting)
        return afs_pd_putInt(aout, cache_bypass_threshold);
@@ -5105,6 +5127,7 @@ DECL_PIOCTL(PCallBackAddr)
     }
 
     addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+    osi_Assert(addrs != NULL);
     j = 0;
     for (i = 0; i < NSERVERS; i++) {
        for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
@@ -5159,13 +5182,13 @@ DECL_PIOCTL(PCallBackAddr)
 
 DECL_PIOCTL(PDiscon)
 {
-#ifdef AFS_DISCON_ENV
     static afs_int32 mode = 1; /* Start up in 'off' */
     afs_int32 force = 0;
     int code = 0;
-    char flags[3];
+    char flags[4];
+    struct vrequest lreq;
 
-    if (afs_pd_getBytes(ain, &flags, 3) == 0) {
+    if (afs_pd_getBytes(ain, &flags, 4) == 0) {
        if (!afs_osi_suser(*acred))
            return EPERM;
 
@@ -5175,6 +5198,12 @@ DECL_PIOCTL(PDiscon)
            afs_ConflictPolicy = flags[1] - 1;
        if (flags[2])
            force = 1;
+       if (flags[3]) {
+           /* Fake InitReq support for UID override */
+           memset(&lreq, 0, sizeof(lreq));
+           lreq.uid = flags[3];
+           areq = &lreq; /* override areq we got */
+       }
 
        /*
         * All of these numbers are hard coded in fs.c. If they
@@ -5226,16 +5255,193 @@ DECL_PIOCTL(PDiscon)
        return code;
 
     return afs_pd_putInt(aout, mode);
-#else
-    return EINVAL;
-#endif
 }
 
+#define MAX_PIOCTL_TOKENS 10
+
+DECL_PIOCTL(PSetTokens2)
+{
+    int code =0;
+    int i, cellNum, primaryFlag;
+    XDR xdrs;
+    struct unixuser *tu;
+    struct vrequest treq;
+    struct ktc_setTokenData tokenSet;
+    struct ktc_tokenUnion decodedToken;
+
+    memset(&tokenSet, 0, sizeof(tokenSet));
+
+    AFS_STATCNT(PSetTokens2);
+    if (!afs_resourceinit_flag)
+       return EIO;
+
+    afs_pd_xdrStart(ain, &xdrs, XDR_DECODE);
+
+    if (!xdr_ktc_setTokenData(&xdrs, &tokenSet)) {
+       afs_pd_xdrEnd(ain, &xdrs);
+       return EINVAL;
+    }
+
+    afs_pd_xdrEnd(ain, &xdrs);
+
+    /* We limit each PAG to 10 tokens to prevent a malicous (or runaway)
+     * process from using up the whole of the kernel memory by allocating
+     * tokens.
+     */
+    if (tokenSet.tokens.tokens_len > MAX_PIOCTL_TOKENS) {
+       xdr_free((xdrproc_t) xdr_ktc_setTokenData, &tokenSet);
+       return E2BIG;
+    }
+
+    code = _settok_tokenCell(tokenSet.cell, &cellNum, &primaryFlag);
+    if (code) {
+       xdr_free((xdrproc_t) xdr_ktc_setTokenData, &tokenSet);
+       return code;
+    }
+
+    if (tokenSet.flags & AFSTOKEN_EX_SETPAG) {
+       if (_settok_setParentPag(acred) == 0) {
+           afs_InitReq(&treq, *acred);
+           areq = &treq;
+       }
+    }
+
+    tu = afs_GetUser(areq->uid, cellNum, WRITE_LOCK);
+    /* Free any tokens that we've already got */
+    afs_FreeTokens(&tu->tokens);
+
+    /* Iterate across the set of tokens we've received, and stuff them
+     * into this user's tokenJar
+     */
+    for (i=0; i < tokenSet.tokens.tokens_len; i++) {
+       xdrmem_create(&xdrs,
+                     tokenSet.tokens.tokens_val[i].token_opaque_val,
+                     tokenSet.tokens.tokens_val[i].token_opaque_len,
+                     XDR_DECODE);
+
+       memset(&decodedToken, 0, sizeof(decodedToken));
+       if (!xdr_ktc_tokenUnion(&xdrs, &decodedToken)) {
+           xdr_destroy(&xdrs);
+           code = EINVAL;
+           goto out;
+       }
+
+       xdr_destroy(&xdrs);
+
+       afs_AddTokenFromPioctl(&tu->tokens, &decodedToken);
+       /* This is untidy - the old token interface supported passing
+        * the primaryFlag as part of the token interface. Current
+        * OpenAFS userland never sets this, but it's specified as being
+        * part of the XG interface, so we should probably still support
+        * it. Rather than add it to our AddToken interface, just handle
+        * it here.
+        */
+       if (decodedToken.at_type == AFSTOKEN_UNION_KAD) {
+           if (decodedToken.ktc_tokenUnion_u.at_kad.rk_primary_flag)
+               primaryFlag = 1;
+       }
+
+       /* XXX - We should think more about destruction here. It's likely that
+        * there is key material in what we're about to throw away, which
+        * we really should zero out before giving back to the allocator */
+       xdr_free((xdrproc_t) xdr_ktc_tokenUnion, &decodedToken);
+    }
+
+    tu->states |= UHasTokens;
+    tu->states &= ~UTokensBad;
+    afs_SetPrimary(tu, primaryFlag);
+    tu->tokenTime = osi_Time();
+
+    xdr_free((xdrproc_t) xdr_ktc_setTokenData, &tokenSet);
+
+out:
+    afs_ResetUserConns(tu);
+    afs_PutUser(tu, WRITE_LOCK);
+
+    return code;
+}
+
+DECL_PIOCTL(PGetTokens2)
+{
+    struct cell *cell;
+    struct unixuser *tu = NULL;
+    afs_int32 iterator;
+    char *cellName = NULL;
+    afs_int32 cellNum;
+    int code = 0;
+    time_t now;
+    XDR xdrs;
+    struct ktc_setTokenData tokenSet;
+
+    AFS_STATCNT(PGetTokens);
+    if (!afs_resourceinit_flag)
+       return EIO;
+
+    memset(&tokenSet, 0, sizeof(tokenSet));
+
+    /* No input data - return tokens for primary cell */
+    /* 4 octets of data is an iterator count */
+    /* Otherwise, treat as string & return tokens for that cell name */
+
+    if (afs_pd_remaining(ain) == sizeof(afs_int32)) {
+       /* Integer iterator - return tokens for the n'th cell found for user */
+       if (afs_pd_getInt(ain, &iterator) != 0)
+           return EINVAL;
+       tu = getNthCell(areq->uid, iterator);
+    } else {
+        if (afs_pd_remaining(ain) > 0) {
+           if (afs_pd_getStringPtr(ain, &cellName) != 0)
+               return EINVAL;
+        } else {
+           cellName = NULL;
+       }
+       code = _settok_tokenCell(cellName, &cellNum, NULL);
+       if (code)
+           return code;
+       tu = afs_FindUser(areq->uid, cellNum, READ_LOCK);
+    }
+    if (tu == NULL)
+       return EDOM;
+
+    now = osi_Time();
+
+    if (!(tu->states & UHasTokens)
+       || !afs_HasValidTokens(tu->tokens, now)) {
+       tu->states |= (UTokensBad | UNeedsReset);
+       afs_PutUser(tu, READ_LOCK);
+       return ENOTCONN;
+    }
+
+    code = afs_ExtractTokensForPioctl(tu->tokens, now, &tokenSet);
+    if (code)
+       goto out;
+
+    cell = afs_GetCell(tu->cell, READ_LOCK);
+    tokenSet.cell = cell->cellName;
+    afs_pd_xdrStart(aout, &xdrs, XDR_ENCODE);
+    if (!xdr_ktc_setTokenData(&xdrs, &tokenSet)) {
+       code = E2BIG;
+       goto out;
+    }
+    afs_pd_xdrEnd(aout, &xdrs);
+
+out:
+    tokenSet.cell = NULL;
+
+    if (tu)
+       afs_PutUser(tu, READ_LOCK);
+    if (cell)
+       afs_PutCell(cell, READ_LOCK);
+    xdr_free((xdrproc_t)xdr_ktc_setTokenData, &tokenSet);
+
+    return code;
+};
+
 DECL_PIOCTL(PNFSNukeCreds)
 {
     afs_uint32 addr;
-    register afs_int32 i;
-    register struct unixuser *tu;
+    afs_int32 i;
+    struct unixuser *tu;
 
     AFS_STATCNT(PUnlog);
     if (!afs_resourceinit_flag)        /* afs daemons haven't started yet */
@@ -5259,10 +5465,8 @@ DECL_PIOCTL(PNFSNukeCreds)
     for (i = 0; i < NUSERS; i++) {
        for (tu = afs_users[i]; tu; tu = tu->next) {
            if (tu->exporter && EXP_CHECKHOST(tu->exporter, addr)) {
-               tu->vid = UNDEFVID;
                tu->states &= ~UHasTokens;
-               /* security is not having to say you're sorry */
-               memset(&tu->ct, 0, sizeof(struct ClearToken));
+               afs_FreeTokens(&tu->tokens);
                tu->refCount++;
                ReleaseWriteLock(&afs_xuser);
                afs_ResetUserConns(tu);
@@ -5272,7 +5476,6 @@ DECL_PIOCTL(PNFSNukeCreds)
                /* set the expire times to 0, causes
                 * afs_GCUserData to remove this entry
                 */
-               tu->ct.EndTimestamp = 0;
                tu->tokenTime = 0;
 #endif /* UKERNEL */
            }