/* allocate a new connetion ID in place */ int rxkad_AllocCID(struct rx_securityClass *aobj, struct rx_connection *aconn) { struct rxkad_cprivate *tcp; struct rxkad_cidgen tgen; static afs_int32 counter = 0; /* not used anymore */ LOCK_CUID; if (Cuid[0] == 0) { afs_uint32 xor[2]; tgen.ipAddr = rxi_getaddr(); /* comes back in net order */ clock_GetTime(&tgen.time); /* changes time1 and time2 */ tgen.time.sec = htonl(tgen.time.sec); tgen.time.usec = htonl(tgen.time.usec); tgen.counter = htonl(counter); counter++; #ifdef KERNEL tgen.random1 = afs_random() & 0x7fffffff; /* was "80000" */ tgen.random2 = afs_random() & 0x7fffffff; /* was "htonl(100)" */ #else tgen.random1 = htonl(getpid()); tgen.random2 = htonl(100); #endif if (aobj) { /* block is ready for encryption with session key, let's go for it. */ tcp = (struct rxkad_cprivate *)aobj->privateData; memcpy((void *)xor, (void *)tcp->ivec, 2 * sizeof(afs_int32)); fc_cbc_encrypt((char *)&tgen, (char *)&tgen, sizeof(tgen), tcp->keysched, xor, ENCRYPT); } else { /* Create a session key so that we can encrypt it */ } memcpy((void *)Cuid, ((char *)&tgen) + sizeof(tgen) - ENCRYPTIONBLOCKSIZE, ENCRYPTIONBLOCKSIZE); Cuid[0] = (Cuid[0] & ~0x40000000) | 0x80000000; Cuid[1] &= RX_CIDMASK; rx_SetEpoch(Cuid[0]); /* for future rxnull connections */ rxkad_EpochWasSet++; } if (!aconn) { UNLOCK_CUID; return 0; } aconn->epoch = Cuid[0]; aconn->cid = Cuid[1]; Cuid[1] += 1 << RX_CIDSHIFT; UNLOCK_CUID; return 0; }
/*! * \brief Returns int 0..14 using the high bits of a pseudo-random number instead of * the low bits, as the low bits are "less random" than the high ones... * * \todo Slight roundoff error exists, an excercise for the reader. * * Need to multiply by something with lots of ones in it, so multiply by * 8 or 16 is right out. */ static unsigned int afs_randomMod15(void) { afs_uint32 temp; temp = afs_random() >> 4; temp = (temp * 15) >> 28; return temp; }
char * afs_newname(void) { char *name, *sp, *p = ".__afs"; afs_int32 rd = afs_random() & 0xffff; sp = name = osi_AllocSmallSpace(AFS_SMALLOCSIZ); while (*p != '\0') *sp++ = *p++; while (rd) { *sp++ = "0123456789ABCDEF"[rd & 0x0f]; rd >>= 4; } *sp = '\0'; return (name); }
/* This function always holds the GLOCK whilst it is running. The caller * gets the GLOCK before invoking it, and afs_osi_Sleep drops the GLOCK * whilst we are sleeping, and regains it when we're woken up. */ void afs_Daemon(void) { afs_int32 code; struct afs_exporter *exporter; afs_int32 now; afs_int32 last3MinCheck, last10MinCheck, last60MinCheck, lastNMinCheck; afs_int32 last1MinCheck, last5MinCheck; afs_uint32 lastCBSlotBump; char cs_warned = 0; AFS_STATCNT(afs_Daemon); afs_rootFid.Fid.Volume = 0; while (afs_initState < 101) afs_osi_Sleep(&afs_initState); #ifdef AFS_DARWIN80_ENV if (afs_osi_ctxtp_initialized) osi_Panic("vfs context already initialized"); while (afs_osi_ctxtp && vfs_context_ref) afs_osi_Sleep(&afs_osi_ctxtp); if (afs_osi_ctxtp && !vfs_context_ref) vfs_context_rele(afs_osi_ctxtp); afs_osi_ctxtp = vfs_context_create(NULL); afs_osi_ctxtp_initialized = 1; #endif now = osi_Time(); lastCBSlotBump = now; /* when a lot of clients are booted simultaneously, they develop * annoying synchronous VL server bashing behaviors. So we stagger them. */ last1MinCheck = now + ((afs_random() & 0x7fffffff) % 60); /* an extra 30 */ last3MinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180); last60MinCheck = now - 1800 + ((afs_random() & 0x7fffffff) % 3600); last10MinCheck = now - 300 + ((afs_random() & 0x7fffffff) % 600); last5MinCheck = now - 150 + ((afs_random() & 0x7fffffff) % 300); lastNMinCheck = now - 90 + ((afs_random() & 0x7fffffff) % 180); /* start off with afs_initState >= 101 (basic init done) */ while (1) { afs_CheckCallbacks(20); /* unstat anything which will expire soon */ /* things to do every 20 seconds or less - required by protocol spec */ if (afs_nfsexporter) afs_FlushActiveVcaches(0); /* flush NFS writes */ afs_FlushVCBs(1); /* flush queued callbacks */ afs_MaybeWakeupTruncateDaemon(); /* free cache space if have too */ rx_CheckPackets(); /* Does RX need more packets? */ now = osi_Time(); if (lastCBSlotBump + CBHTSLOTLEN < now) { /* pretty time-dependant */ lastCBSlotBump = now; if (afs_BumpBase()) { afs_CheckCallbacks(20); /* unstat anything which will expire soon */ } } if (last1MinCheck + 60 < now) { /* things to do every minute */ DFlush(); /* write out dir buffers */ afs_WriteThroughDSlots(); /* write through cacheinfo entries */ ObtainWriteLock(&afs_xvcache, 736); afs_FlushReclaimedVcaches(); ReleaseWriteLock(&afs_xvcache); afs_FlushActiveVcaches(1); /* keep flocks held & flush nfs writes */ #if 0 afs_StoreDirtyVcaches(); #endif afs_CheckRXEpoch(); last1MinCheck = now; } if (last3MinCheck + 180 < now) { afs_CheckTokenCache(); /* check for access cache resets due to expired * tickets */ last3MinCheck = now; } if (afsd_dynamic_vcaches && (last5MinCheck + 300 < now)) { /* start with trying to drop us back to our base usage */ int anumber = VCACHE_FREE + (afs_vcount - afs_cacheStats); if (anumber > 0) { ObtainWriteLock(&afs_xvcache, 734); afs_ShakeLooseVCaches(anumber); ReleaseWriteLock(&afs_xvcache); } last5MinCheck = now; } if (!afs_CheckServerDaemonStarted) { /* Do the check here if the correct afsd is not installed. */ if (!cs_warned) { cs_warned = 1; afs_warn("Please install afsd with check server daemon.\n"); } if (lastNMinCheck + afs_probe_interval < now) { /* only check down servers */ afs_CheckServers(1, NULL); lastNMinCheck = now; } } if (last10MinCheck + 600 < now) { #ifdef AFS_USERSPACE_IP_ADDR extern int rxi_GetcbiInfo(void); #endif afs_Trace1(afs_iclSetp, CM_TRACE_PROBEUP, ICL_TYPE_INT32, 600); #ifdef AFS_USERSPACE_IP_ADDR if (rxi_GetcbiInfo()) { /* addresses changed from last time */ afs_FlushCBs(); } #else /* AFS_USERSPACE_IP_ADDR */ if (rxi_GetIFInfo()) { /* addresses changed from last time */ afs_FlushCBs(); } #endif /* else AFS_USERSPACE_IP_ADDR */ if (!afs_CheckServerDaemonStarted) afs_CheckServers(0, NULL); afs_GCUserData(0); /* gc old conns */ /* This is probably the wrong way of doing GC for the various exporters but it will suffice for a while */ for (exporter = root_exported; exporter; exporter = exporter->exp_next) { (void)EXP_GC(exporter, 0); /* Generalize params */ } { static int cnt = 0; if (++cnt < 12) { afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED | AFS_VOLCHECK_BUSY); } else { cnt = 0; afs_CheckVolumeNames(AFS_VOLCHECK_EXPIRED | AFS_VOLCHECK_BUSY | AFS_VOLCHECK_MTPTS); } } last10MinCheck = now; } if (last60MinCheck + 3600 < now) { afs_Trace1(afs_iclSetp, CM_TRACE_PROBEVOLUME, ICL_TYPE_INT32, 3600); afs_CheckRootVolume(); #if AFS_GCPAGS if (afs_gcpags == AFS_GCPAGS_OK) { afs_int32 didany; afs_GCPAGs(&didany); } #endif last60MinCheck = now; } if (afs_initState < 300) { /* while things ain't rosy */ code = afs_CheckRootVolume(); if (code == 0) afs_initState = 300; /* succeeded */ if (afs_initState < 200) afs_initState = 200; /* tried once */ afs_osi_Wakeup(&afs_initState); } /* 18285 is because we're trying to divide evenly into 128, that is, * CBSlotLen, while staying just under 20 seconds. If CBSlotLen * changes, should probably change this interval, too. * Some of the preceding actions may take quite some time, so we * might not want to wait the entire interval */ now = 18285 - (osi_Time() - now); if (now > 0) { afs_osi_Wait(now, &AFS_WaitHandler, 0); } if (afs_termState == AFSOP_STOP_AFS) { if (afs_CheckServerDaemonStarted) afs_termState = AFSOP_STOP_CS; else afs_termState = AFSOP_STOP_TRUNCDAEMON; afs_osi_Wakeup(&afs_termState); return; } } }