/** * forceConnectFS is set whenever we must recompute the connection. UTokensBad * is true only if we know that the tokens are bad. We thus clear this flag * when we get a new set of tokens.. * Having force... true and UTokensBad true simultaneously means that the tokens * went bad and we're supposed to create a new, unauthenticated, connection. * * @param aserver Server to connect to. * @param aport Connection port. * @param acell The cell where all of this happens. * @param areq The request. * @param aforce Force connection? * @param locktype Type of lock to be used. * * @return The established connection. */ struct afs_conn * afs_ConnByHost(struct server *aserver, unsigned short aport, afs_int32 acell, struct vrequest *areq, int aforce, afs_int32 locktype, struct rx_connection **rxconn) { struct unixuser *tu; struct afs_conn *tc = NULL; struct srvAddr *sa = NULL; *rxconn = NULL; AFS_STATCNT(afs_ConnByHost); if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) { afs_warnuser("afs_ConnByHost: disconnected\n"); return NULL; } /* 1. look for an existing connection 2. create a connection at an address believed to be up (if aforce is true, create a connection at the first address) */ tu = afs_GetUser(areq->uid, acell, SHARED_LOCK); for (sa = aserver->addr; sa; sa = sa->next_sa) { tc = afs_ConnBySA(sa, aport, acell, tu, aforce, 0 /*don't create one */ , locktype, rxconn); if (tc) break; } if (!tc) { for (sa = aserver->addr; sa; sa = sa->next_sa) { tc = afs_ConnBySA(sa, aport, acell, tu, aforce, 1 /*create one */ , locktype, rxconn); if (tc) break; } } afs_PutUser(tu, SHARED_LOCK); return tc; } /*afs_ConnByHost */
int afspag_PSetTokens(char *ain, afs_int32 ainSize, struct AFS_UCRED **acred) { afs_int32 i; register struct unixuser *tu; struct afspag_cell *tcell; struct ClearToken clear; char *stp; int stLen; afs_int32 flag, set_parent_pag = 0; afs_int32 pag, uid; AFS_STATCNT(PSetTokens); if (!afs_resourceinit_flag) { return EIO; } memcpy((char *)&i, ain, sizeof(afs_int32)); ain += sizeof(afs_int32); stp = ain; /* remember where the ticket is */ if (i < 0 || i > MAXKTCTICKETLEN) return EINVAL; /* malloc may fail */ stLen = i; ain += i; /* skip over ticket */ memcpy((char *)&i, ain, sizeof(afs_int32)); ain += sizeof(afs_int32); if (i != sizeof(struct ClearToken)) { return EINVAL; } memcpy((char *)&clear, ain, sizeof(struct ClearToken)); if (clear.AuthHandle == -1) clear.AuthHandle = 999; /* more rxvab compat stuff */ ain += sizeof(struct ClearToken); if (ainSize != 2 * sizeof(afs_int32) + stLen + sizeof(struct ClearToken)) { /* still stuff left? we've got primary flag and cell name. Set these */ memcpy((char *)&flag, ain, sizeof(afs_int32)); /* primary id flag */ ain += sizeof(afs_int32); /* skip id field */ /* rest is cell name, look it up */ /* some versions of gcc appear to need != 0 in order to get this right */ if ((flag & 0x8000) != 0) { /* XXX Use Constant XXX */ flag &= ~0x8000; set_parent_pag = 1; } tcell = afspag_GetCell(ain); } else { /* default to primary cell, primary id */ flag = 1; /* primary id */ tcell = afspag_GetPrimaryCell(); } if (!tcell) return ESRCH; if (set_parent_pag) { #if defined(AFS_DARWIN_ENV) || defined(AFS_XBSD_ENV) #if defined(AFS_DARWIN_ENV) struct proc *p = current_proc(); /* XXX */ #else struct proc *p = curproc; /* XXX */ #endif #ifndef AFS_DARWIN80_ENV uprintf("Process %d (%s) tried to change pags in PSetTokens\n", p->p_pid, p->p_comm); #endif setpag(p, acred, -1, &pag, 1); #else #ifdef AFS_OSF_ENV setpag(u.u_procp, acred, -1, &pag, 1); /* XXX u.u_procp is a no-op XXX */ #else setpag(acred, -1, &pag, 1); #endif #endif } pag = PagInCred(*acred); uid = (pag == NOPAG) ? (*acred)->cr_uid : pag; /* now we just set the tokens */ tu = afs_GetUser(uid, tcell->cellnum, WRITE_LOCK); if (!tu->cellinfo) tu->cellinfo = (void *)tcell; tu->vid = clear.ViceId; if (tu->stp != NULL) { afs_osi_Free(tu->stp, tu->stLen); } tu->stp = (char *)afs_osi_Alloc(stLen); tu->stLen = stLen; memcpy(tu->stp, stp, stLen); tu->ct = clear; #ifndef AFS_NOSTATS afs_stats_cmfullperf.authent.TicketUpdates++; afs_ComputePAGStats(); #endif /* AFS_NOSTATS */ tu->states |= UHasTokens; tu->states &= ~UTokensBad; afs_SetPrimary(tu, flag); tu->tokenTime = osi_Time(); afs_PutUser(tu, WRITE_LOCK); return 0; }
/** * Try setting up a connection to the server containing the specified fid. * Gets the volume, checks if it's up and does the connection by server address. * * @param afid * @param areq Request filled in by the caller. * @param locktype Type of lock that will be used. * * @return The conn struct, or NULL. */ struct afs_conn * afs_Conn(struct VenusFid *afid, struct vrequest *areq, afs_int32 locktype, struct rx_connection **rxconn) { u_short fsport = AFS_FSPORT; struct volume *tv; struct afs_conn *tconn = NULL; struct srvAddr *lowp = NULL; struct unixuser *tu; int notbusy; int i; struct srvAddr *sa1p; *rxconn = NULL; AFS_STATCNT(afs_Conn); /* Get fid's volume. */ tv = afs_GetVolume(afid, areq, READ_LOCK); if (!tv) { if (areq) { afs_FinalizeReq(areq); areq->volumeError = 1; } return NULL; } if (tv->serverHost[0] && tv->serverHost[0]->cell) { fsport = tv->serverHost[0]->cell->fsport; } else { VNOSERVERS++; } /* First is always lowest rank, if it's up */ if ((tv->status[0] == not_busy) && tv->serverHost[0] && !(tv->serverHost[0]->addr->sa_flags & SRVR_ISDOWN) && !(((areq->idleError > 0) || (areq->tokenError > 0)) && (areq->skipserver[0] == 1))) lowp = tv->serverHost[0]->addr; /* Otherwise we look at all of them. There are seven levels of * not_busy. This means we will check a volume seven times before it * is marked offline. Ideally, we only need two levels, but this * serves a second purpose of waiting some number of seconds before * the client decides the volume is offline (ie: a clone could finish * in this time). */ for (notbusy = not_busy; (!lowp && (notbusy <= end_not_busy)); notbusy++) { for (i = 0; i < AFS_MAXHOSTS && tv->serverHost[i]; i++) { if (((areq->tokenError > 0)||(areq->idleError > 0)) && (areq->skipserver[i] == 1)) continue; if (tv->status[i] != notbusy) { if (tv->status[i] == rd_busy || tv->status[i] == rdwr_busy) { if (!areq->busyCount) areq->busyCount++; } else if (tv->status[i] == offline) { if (!areq->volumeError) areq->volumeError = VOLMISSING; } continue; } for (sa1p = tv->serverHost[i]->addr; sa1p; sa1p = sa1p->next_sa) { if (sa1p->sa_flags & SRVR_ISDOWN) continue; if (!lowp || (lowp->sa_iprank > sa1p->sa_iprank)) lowp = sa1p; } } } afs_PutVolume(tv, READ_LOCK); if (lowp) { tu = afs_GetUser(areq->uid, afid->Cell, SHARED_LOCK); tconn = afs_ConnBySA(lowp, fsport, afid->Cell, tu, 0 /*!force */ , 1 /*create */ , locktype, rxconn); afs_PutUser(tu, SHARED_LOCK); } return tconn; } /*afs_Conn */