/* called with locked scp; ensures that we have an ACL cache entry for the * user specified by the parameter "userp." * In pathological race conditions, this function may return success without * having loaded the entry properly (due to a racing callback revoke), so this * function must also be called in a while loop to make sure that we eventually * succeed. */ long cm_GetAccessRights(struct cm_scache *scp, struct cm_user *userp, struct cm_req *reqp) { long code; cm_fid_t tfid; cm_scache_t *aclScp = NULL; int got_cb = 0; cm_volume_t * volp = cm_FindVolumeByFID(&scp->fid, userp, reqp); /* pretty easy: just force a pass through the fetch status code */ osi_Log2(afsd_logp, "GetAccessRights scp 0x%p user 0x%p", scp, userp); /* first, start by finding out whether we have a directory or something * else, so we can find what object's ACL we need. */ if (scp->fileType == CM_SCACHETYPE_DIRECTORY || cm_accessPerFileCheck || !volp || (volp->flags & CM_VOLUMEFLAG_DFS_VOLUME)) { code = cm_SyncOp(scp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB); if (!code) cm_SyncOpDone(scp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); else osi_Log3(afsd_logp, "GetAccessRights syncop failure scp %x user %x code %x", scp, userp, code); } else { /* not a dir, use parent dir's acl */ cm_SetFid(&tfid, scp->fid.cell, scp->fid.volume, scp->parentVnode, scp->parentUnique); lock_ReleaseWrite(&scp->rw); code = cm_GetSCache(&tfid, NULL, &aclScp, userp, reqp); if (code) { lock_ObtainWrite(&scp->rw); goto _done; } osi_Log2(afsd_logp, "GetAccessRights parent scp %x user %x", aclScp, userp); lock_ObtainWrite(&aclScp->rw); code = cm_SyncOp(aclScp, NULL, userp, reqp, 0, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS | CM_SCACHESYNC_FORCECB); if (!code) cm_SyncOpDone(aclScp, NULL, CM_SCACHESYNC_NEEDCALLBACK | CM_SCACHESYNC_GETSTATUS); else osi_Log3(afsd_logp, "GetAccessRights parent syncop failure scp %x user %x code %x", aclScp, userp, code); lock_ReleaseWrite(&aclScp->rw); cm_ReleaseSCache(aclScp); lock_ObtainWrite(&scp->rw); } _done: if (volp) cm_PutVolume(volp); return code; }
/* function called as callback proc from cm_SearchCellFile. Return 0 to * continue processing. * * At the present time the return value is ignored by the caller. */ long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *hostnamep, unsigned short adminRank) { cm_server_t *tsp; cm_serverRef_t *tsrp; cm_cell_t *cellp; cm_cell_rock_t *cellrockp = (cm_cell_rock_t *)rockp; afs_uint32 probe; cellp = cellrockp->cellp; probe = !(cellrockp->flags & CM_FLAG_NOPROBE); /* if this server was previously created by fs setserverprefs */ if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB, FALSE)) { if ( !tsp->cellp ) tsp->cellp = cellp; else if (tsp->cellp != cellp) { osi_Log3(afsd_logp, "found a vlserver %s associated with two cells named %s and %s", osi_LogSaveString(afsd_logp,hostnamep), osi_LogSaveString(afsd_logp,tsp->cellp->name), osi_LogSaveString(afsd_logp,cellp->name)); } } else tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, NULL, probe ? 0 : CM_FLAG_NOPROBE); if (adminRank) tsp->adminRank = adminRank; /* Insert the vlserver into a sorted list, sorted by server rank */ tsrp = cm_NewServerRef(tsp, 0); cm_InsertServerList(&cellp->vlServersp, tsrp); return 0; }
/** Handle a SMB_COM_READ for an RPC fid Called from smb_ReceiveCoreRead when we receive a read on the RPC fid */ afs_int32 smb_RPCRead(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_rpc_t *rpcp; long count; char *op; afs_int32 code; cm_user_t *userp; count = smb_GetSMBParm(inp, 1); userp = smb_GetUserFromVCP(vcp, inp); osi_Log3(smb_logp, "smb_RPCRead for user[0x%p] fid[0x%p (%d)]", userp, fidp, fidp->fid); lock_ObtainMutex(&fidp->mx); rpcp = fidp->rpcp; code = smb_RPC_BeginOp(rpcp); lock_ReleaseMutex(&fidp->mx); if (code) { cm_ReleaseUser(userp); return code; } code = smb_RPC_PrepareRead(rpcp); if (code) { cm_ReleaseUser(userp); smb_RPC_EndOp(rpcp); return code; } count = smb_RPC_ReadPacketLength(rpcp, count); /* now set the parms for a read of count bytes */ smb_SetSMBParm(outp, 0, count); smb_SetSMBParm(outp, 1, 0); smb_SetSMBParm(outp, 2, 0); smb_SetSMBParm(outp, 3, 0); smb_SetSMBParm(outp, 4, 0); smb_SetSMBDataLength(outp, count+3); op = smb_GetSMBData(outp, NULL); *op++ = 1; *op++ = (char)(count & 0xff); *op++ = (char)((count >> 8) & 0xff); smb_RPC_ReadPacket(rpcp, op, count); smb_RPC_EndOp(rpcp); cm_ReleaseUser(userp); return 0; }
unsigned long main_Scan2(unsigned long parm) { while (1) { osi_Log0(main_logp, "scan2"); /* check to see if we're done */ lock_ObtainRead(&main_doneRWLock); lock_AssertAny(&main_doneRWLock); if (done >= 2) break; lock_ReleaseRead(&main_doneRWLock); /* check state for consistency without locks */ if (a+b != 100) s2Events++; /* and record that we went around again */ s2Loops++; /* give others a chance */ Sleep(0); osi_Log3(main_logp, "scan2 done %d %d %d", s2Loops, 2, 3); } lock_ReleaseRead(&main_doneRWLock); lock_ObtainWrite(&main_doneRWLock); lock_AssertAny(&main_doneRWLock); done++; lock_ReleaseWrite(&main_doneRWLock); return 0; }
/** Handle SMB_COM_WRITE_ANDX for an RPC fid Called from smb_ReceiveV3WriteX when we receive a write call on the RPC file descriptor. */ afs_int32 smb_RPCV3Write(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_rpc_t *rpcp; long count; afs_int32 code; char *op; cm_user_t *userp = NULL; code = 0; count = smb_GetSMBParm(inp, 10); userp = smb_GetUserFromVCP(vcp, inp); osi_Log3(smb_logp, "smb_RPCV3Write for user[0x%p] fid[0x%p (%d)]", userp, fidp, fidp->fid); if (userp == NULL) { code = CM_ERROR_BADSMB; goto done; } lock_ObtainMutex(&fidp->mx); rpcp = fidp->rpcp; code = smb_RPC_BeginOp(rpcp); lock_ReleaseMutex(&fidp->mx); if (code) goto done; smb_RPC_PrepareWrite(rpcp); op = inp->data + smb_GetSMBParm(inp, 11); code = smb_RPC_WritePacket(rpcp, op, count, userp); smb_RPC_EndOp(rpcp); done: /* return # of bytes written */ if (code == 0) { smb_SetSMBParm(outp, 2, count); smb_SetSMBParm(outp, 3, 0); /* reserved */ smb_SetSMBParm(outp, 4, 0); /* reserved */ smb_SetSMBParm(outp, 5, 0); /* reserved */ smb_SetSMBDataLength(outp, 0); } if (userp) cm_ReleaseUser(userp); return code; }
/* function called as callback proc from cm_SearchCellFile. Return 0 to * continue processing. * * At the present time the return value is ignored by the caller. */ long cm_AddCellProc(void *rockp, struct sockaddr_in *addrp, char *hostnamep) { cm_server_t *tsp; cm_serverRef_t *tsrp; cm_cell_t *cellp; cm_cell_rock_t *cellrockp = (cm_cell_rock_t *)rockp; afs_uint32 probe; cellp = cellrockp->cellp; probe = !(cellrockp->flags & CM_FLAG_NOPROBE); /* if this server was previously created by fs setserverprefs */ if ( tsp = cm_FindServer(addrp, CM_SERVER_VLDB)) { if ( !tsp->cellp ) tsp->cellp = cellp; else if (tsp->cellp != cellp) { osi_Log3(afsd_logp, "found a vlserver %s associated with two cells named %s and %s", osi_LogSaveString(afsd_logp,hostnamep), osi_LogSaveString(afsd_logp,tsp->cellp->name), osi_LogSaveString(afsd_logp,cellp->name)); } } else tsp = cm_NewServer(addrp, CM_SERVER_VLDB, cellp, probe ? 0 : CM_FLAG_NOPROBE); /* Insert the vlserver into a sorted list, sorted by server rank */ tsrp = cm_NewServerRef(tsp, 0); cm_InsertServerList(&cellp->vlServersp, tsrp); /* drop the allocation reference */ lock_ObtainWrite(&cm_serverLock); tsrp->refCount--; lock_ReleaseWrite(&cm_serverLock); return 0; }
cm_cell_t *cm_GetCell_Gen(char *namep, char *newnamep, afs_uint32 flags) { cm_cell_t *cp, *cp2; long code; char fullname[CELL_MAXNAMELEN]=""; char linkedName[CELL_MAXNAMELEN]=""; char name[CELL_MAXNAMELEN]=""; int hasWriteLock = 0; int hasMutex = 0; afs_uint32 hash; cm_cell_rock_t rock; size_t len; if (namep == NULL || !namep[0] || !strcmp(namep,CM_IOCTL_FILENAME_NOSLASH)) return NULL; /* * Strip off any trailing dots at the end of the cell name. * Failure to do so results in an undesireable alias as the * result of DNS AFSDB record lookups where a trailing dot * has special meaning. */ strncpy(name, namep, CELL_MAXNAMELEN); for (len = strlen(namep); len > 0 && namep[len-1] == '.'; len--) { name[len-1] = '\0'; } if (len == 0) return NULL; namep = name; hash = CM_CELL_NAME_HASH(namep); lock_ObtainRead(&cm_cellLock); for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (!cp) { for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } } if (cp) { lock_ReleaseRead(&cm_cellLock); cm_UpdateCell(cp, flags); } else if (flags & CM_FLAG_CREATE) { lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; /* when we dropped the lock the cell could have been added * to the list so check again while holding the write lock */ for (cp = cm_data.cellNameHashTablep[hash]; cp; cp=cp->nameNextp) { if (cm_stricmp_utf8(namep, cp->name) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) goto done; for (cp = cm_data.allCellsp; cp; cp=cp->allNextp) { if (strnicmp(namep, cp->name, strlen(namep)) == 0) { strncpy(fullname, cp->name, CELL_MAXNAMELEN); fullname[CELL_MAXNAMELEN-1] = '\0'; break; } } if (cp) { lock_ReleaseWrite(&cm_cellLock); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); goto done; } if ( cm_data.freeCellsp != NULL ) { cp = cm_data.freeCellsp; cm_data.freeCellsp = cp->freeNextp; /* * The magic, cellID, and mx fields are already set. */ } else { if ( cm_data.currentCells >= cm_data.maxCells ) osi_panic("Exceeded Max Cells", __FILE__, __LINE__); /* don't increment currentCells until we know that we * are going to keep this entry */ cp = &cm_data.cellBaseAddress[cm_data.currentCells]; memset(cp, 0, sizeof(cm_cell_t)); cp->magic = CM_CELL_MAGIC; /* the cellID cannot be 0 */ cp->cellID = ++cm_data.currentCells; /* otherwise we found the cell, and so we're nearly done */ lock_InitializeMutex(&cp->mx, "cm_cell_t mutex", LOCK_HIERARCHY_CELL); } lock_ReleaseWrite(&cm_cellLock); hasWriteLock = 0; rock.cellp = cp; rock.flags = flags; code = cm_SearchCellRegistry(1, namep, fullname, linkedName, cm_AddCellProc, &rock); if (code && code != CM_ERROR_FORCE_DNS_LOOKUP) code = cm_SearchCellFileEx(namep, fullname, linkedName, cm_AddCellProc, &rock); if (code) { osi_Log4(afsd_logp,"in cm_GetCell_gen cm_SearchCellFileEx(%s) returns code= %d fullname= %s linkedName= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname), osi_LogSaveString(afsd_logp,linkedName)); if (cm_dnsEnabled) { int ttl; code = cm_SearchCellByDNS(namep, fullname, &ttl, cm_AddCellProc, &rock); if ( code ) { osi_Log3(afsd_logp,"in cm_GetCell_gen cm_SearchCellByDNS(%s) returns code= %d fullname= %s", osi_LogSaveString(afsd_logp,namep), code, osi_LogSaveString(afsd_logp,fullname)); lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); cm_FreeCell(cp); cp = NULL; goto done; } else { /* got cell from DNS */ lock_ObtainMutex(&cp->mx); hasMutex = 1; _InterlockedOr(&cp->flags, CM_CELLFLAG_DNS); _InterlockedAnd(&cp->flags, ~CM_CELLFLAG_VLSERVER_INVALID); cp->timeout = time(0) + ttl; } } else { lock_ObtainMutex(&cp->mx); lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); cm_FreeCell(cp); cp = NULL; goto done; } } else { lock_ObtainMutex(&cp->mx); hasMutex = 1; cp->timeout = time(0) + 7200; /* two hour timeout */ } /* we have now been given the fullname of the cell. It may * be that we already have a cell with that name. If so, * we should use it instead of completing the allocation * of a new cm_cell_t */ lock_ObtainRead(&cm_cellLock); hash = CM_CELL_NAME_HASH(fullname); for (cp2 = cm_data.cellNameHashTablep[hash]; cp2; cp2=cp2->nameNextp) { if (cm_stricmp_utf8(fullname, cp2->name) == 0) { break; } } if (cp2) { if (!hasMutex) { lock_ObtainMutex(&cp->mx); hasMutex = 1; } lock_ConvertRToW(&cm_cellLock); hasWriteLock = 1; cm_RemoveCellFromIDHashTable(cp); cm_RemoveCellFromNameHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; cm_FreeCell(cp); cp = cp2; goto done; } lock_ReleaseRead(&cm_cellLock); /* randomise among those vlservers having the same rank*/ cm_RandomizeServer(&cp->vlServersp); if (!hasMutex) lock_ObtainMutex(&cp->mx); /* copy in name */ strncpy(cp->name, fullname, CELL_MAXNAMELEN); cp->name[CELL_MAXNAMELEN-1] = '\0'; strncpy(cp->linkedName, linkedName, CELL_MAXNAMELEN); cp->linkedName[CELL_MAXNAMELEN-1] = '\0'; lock_ObtainWrite(&cm_cellLock); hasWriteLock = 1; cm_AddCellToNameHashTable(cp); cm_AddCellToIDHashTable(cp); lock_ReleaseMutex(&cp->mx); hasMutex = 0; /* append cell to global list */ if (cm_data.allCellsp == NULL) { cm_data.allCellsp = cp; } else { for (cp2 = cm_data.allCellsp; cp2->allNextp; cp2=cp2->allNextp) ; cp2->allNextp = cp; } cp->allNextp = NULL; } else { lock_ReleaseRead(&cm_cellLock); } done: if (hasMutex && cp) lock_ReleaseMutex(&cp->mx); if (hasWriteLock) lock_ReleaseWrite(&cm_cellLock); /* fullname is not valid if cp == NULL */ if (newnamep) { if (cp) { strncpy(newnamep, fullname, CELL_MAXNAMELEN); newnamep[CELL_MAXNAMELEN-1]='\0'; } else { newnamep[0] = '\0'; } } if (cp && cp->linkedName[0]) { cm_cell_t * linkedCellp = NULL; if (!strcmp(cp->name, cp->linkedName)) { cp->linkedName[0] = '\0'; } else if (!(flags & CM_FLAG_NOMOUNTCHASE)) { linkedCellp = cm_GetCell(cp->linkedName, CM_FLAG_CREATE|CM_FLAG_NOPROBE|CM_FLAG_NOMOUNTCHASE); lock_ObtainWrite(&cm_cellLock); if (!linkedCellp || (linkedCellp->linkedName[0] && strcmp(cp->name, linkedCellp->linkedName))) { cp->linkedName[0] = '\0'; } else { strncpy(linkedCellp->linkedName, cp->name, CELL_MAXNAMELEN); linkedCellp->linkedName[CELL_MAXNAMELEN-1]='\0'; } lock_ReleaseWrite(&cm_cellLock); } } return cp; }
long cm_SearchCellFileEx(char *cellNamep, char *newCellNamep, char *linkedNamep, cm_configProc_t *procp, void *rockp) { char wdir[MAX_PATH]=""; FILE *tfilep = NULL, *bestp, *tempp; char *tp, *linkp; char lineBuffer[257]; struct hostent *thp; char *valuep; struct sockaddr_in vlSockAddr; int inRightCell = 0; int foundCell = 0; long code; int tracking = 1, partial = 0; size_t len; if ( IsWindowsModule(cellNamep) ) return -3; cm_GetCellServDB(wdir, sizeof(wdir)); if (*wdir) tfilep = fopen(wdir, "r"); if (!tfilep) return -2; bestp = fopen(wdir, "r"); #ifdef CELLSERV_DEBUG osi_Log2(afsd_logp,"cm_searchfile fopen handle[%p], wdir[%s]", bestp, osi_LogSaveString(afsd_logp,wdir)); #endif /* have we seen the cell line for the guy we're looking for? */ while (1) { linkp = NULL; tp = fgets(lineBuffer, sizeof(lineBuffer), tfilep); if (tracking) (void) fgets(lineBuffer, sizeof(lineBuffer), bestp); if (tp == NULL) { if (feof(tfilep)) { /* hit EOF */ if (partial) { /* * found partial match earlier; * now go back to it */ tempp = bestp; bestp = tfilep; tfilep = tempp; inRightCell = 1; partial = 0; continue; } else { fclose(tfilep); fclose(bestp); return (foundCell? 0 : -3); } } } /* turn trailing cr or lf into null */ tp = strrchr(lineBuffer, '\r'); if (tp) *tp = 0; tp = strrchr(lineBuffer, '\n'); if (tp) *tp = 0; /* skip blank lines */ if (lineBuffer[0] == 0) continue; /* * The format is: * >[cell] [linked-cell] #[Description] * where linked-cell and Description are optional */ if (lineBuffer[0] == '>') { if (inRightCell) { fclose(tfilep); fclose(bestp); return(foundCell ? 0 : -6); } /* * terminate the cellname at the first white space * leaving 'tp' pointing to the next string if any */ for (tp = &lineBuffer[1]; tp && !isspace(*tp); tp++); if (tp) { *tp = '\0'; for (tp++ ;tp && isspace(*tp); tp++); if (*tp != '#') { linkp = tp; for (; tp && !isspace(*tp); tp++); if (tp) *tp = '\0'; } } /* now see if this is the right cell */ if (stricmp(lineBuffer+1, cellNamep) == 0) { /* found the cell we're looking for */ if (newCellNamep) { if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) { fclose(tfilep); fclose(bestp); return(-1); } strlwr(newCellNamep); } if (linkedNamep) { if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) { fclose(tfilep); fclose(bestp); return(-1); } strlwr(linkedNamep); } inRightCell = 1; tracking = 0; #ifdef CELLSERV_DEBUG osi_Log2(afsd_logp, "cm_searchfile is cell inRightCell[%p], linebuffer[%s]", inRightCell, osi_LogSaveString(afsd_logp,lineBuffer)); #endif } else if (cm_stricmp_utf8(lineBuffer+1, cellNamep) == 0) { /* partial match */ if (partial) { /* ambiguous */ fclose(tfilep); fclose(bestp); return -5; } if (newCellNamep) { if (FAILED(StringCchCopy(newCellNamep, CELL_MAXNAMELEN, lineBuffer+1))) { fclose(tfilep); fclose(bestp); return(-1); } strlwr(newCellNamep); } if (linkedNamep) { if (FAILED(StringCchCopy(linkedNamep, CELL_MAXNAMELEN, linkp ? linkp : ""))) { fclose(tfilep); fclose(bestp); return(-1); } strlwr(linkedNamep); } inRightCell = 0; tracking = 0; partial = 1; } else inRightCell = 0; } else { valuep = strchr(lineBuffer, '#'); if (valuep == NULL) { fclose(tfilep); fclose(bestp); return -4; } valuep++; /* skip the "#" */ valuep += strspn(valuep, " \t"); /* skip SP & TAB */ /* * strip spaces and tabs in the end. They should not be there according to CellServDB format * so do this just in case */ if(FAILED(StringCchLength(valuep, sizeof(lineBuffer), &len))) { fclose(tfilep); fclose(bestp); return(-1); } else { len--; while(isspace(valuep[len])) valuep[len--] = '\0'; while(isspace(*valuep)) valuep++; } if (inRightCell) { char hostname[256]; int i, isClone = 0; isClone = (lineBuffer[0] == '['); /* copy just the first word and ignore trailing white space */ for ( i=0; valuep[i] && !isspace(valuep[i]) && i<sizeof(hostname); i++) hostname[i] = valuep[i]; hostname[i] = '\0'; /* add the server to the VLDB list */ WSASetLastError(0); thp = gethostbyname(hostname); #ifdef CELLSERV_DEBUG osi_Log3(afsd_logp,"cm_searchfile inRightCell thp[%p], valuep[%s], WSAGetLastError[%d]", thp, osi_LogSaveString(afsd_logp,hostname), WSAGetLastError()); #endif if (thp) { int foundAddr = 0; for (i=0 ; thp->h_addr_list[i]; i++) { if (thp->h_addrtype != AF_INET) continue; memcpy(&vlSockAddr.sin_addr.s_addr, thp->h_addr_list[i], sizeof(long)); vlSockAddr.sin_port = htons(7003); vlSockAddr.sin_family = AF_INET; /* sin_port supplied by connection code */ if (procp) (*procp)(rockp, &vlSockAddr, hostname, 0); foundAddr = 1; } /* if we didn't find a valid address, force the use of the specified one */ if (!foundAddr) thp = NULL; } if (!thp) { afs_uint32 ip_addr; unsigned int c1, c2, c3, c4; /* Since there is no gethostbyname() data * available we will read the IP address * stored in the CellServDB file */ if (isClone) code = sscanf(lineBuffer, "[%u.%u.%u.%u]", &c1, &c2, &c3, &c4); else code = sscanf(lineBuffer, " %u.%u.%u.%u", &c1, &c2, &c3, &c4); if (code == 4 && c1<256 && c2<256 && c3<256 && c4<256) { tp = (unsigned char *) &ip_addr; *tp++ = c1; *tp++ = c2; *tp++ = c3; *tp++ = c4; memcpy(&vlSockAddr.sin_addr.s_addr, &ip_addr, sizeof(long)); vlSockAddr.sin_port = htons(7003); vlSockAddr.sin_family = AF_INET; /* sin_port supplied by connection code */ if (procp) (*procp)(rockp, &vlSockAddr, hostname, 0); } } foundCell = 1; } } /* a vldb line */ } /* while loop processing all lines */ /* if for some unknown reason cell is not found, return negative code (-11) ??? */ return (foundCell) ? 0 : -11; }
afs_int32 smb_RPCNmpipeTransact(smb_fid_t *fidp, smb_vc_t *vcp, smb_tran2Packet_t *p, smb_packet_t *op) { smb_tran2Packet_t *outp = NULL; struct smb_rpc *rpcp; afs_int32 code = 0; cm_user_t * userp = NULL; smb_user_t * uidp = NULL; int len; osi_Log0(smb_logp, "smb_RPCNmpipeTransact() begin"); uidp = smb_FindUID(vcp, p->uid, 0); if (!uidp) return CM_ERROR_BADSMB; userp = smb_GetUserFromUID(uidp); osi_assertx(userp != NULL, "null cm_user_t"); if (uidp && uidp->unp) { osi_Log3(afsd_logp, "RPC Transact uid %d user %x name %S", uidp->userID, userp, osi_LogSaveClientString(afsd_logp, uidp->unp->name)); } else { if (uidp) osi_Log2(afsd_logp, "RPC Transact uid %d user %x no name", uidp->userID, userp); else osi_Log1(afsd_logp, "RPC Transact no uid user %x no name", userp); } lock_ObtainMutex(&fidp->mx); rpcp = fidp->rpcp; code = smb_RPC_BeginOp(rpcp); if (code) { osi_Log0(smb_logp, "Can't begin RPC op. Aborting"); lock_ReleaseMutex(&fidp->mx); smb_ReleaseUID(uidp); cm_ReleaseUser(userp); return code; } osi_assertx((fidp->flags & SMB_FID_RPC), "FID wasn't setup for RPC"); osi_assertx(fidp->rpcp, "smb_rpc_t not associated with RPC FID"); lock_ReleaseMutex(&fidp->mx); code = smb_RPC_PrepareWrite(rpcp); if (code) goto done; code = smb_RPC_WritePacket(rpcp, p->datap, p->totalData, userp); if (code) goto done; code = smb_RPC_PrepareRead(rpcp); if (code) goto done; len = smb_RPC_ReadPacketLength(rpcp, p->maxReturnData); outp = smb_GetTran2ResponsePacket(vcp, p, op, 0, len); if (len > 0) { code = smb_RPC_ReadPacket(rpcp, outp->datap, len); if (code == CM_ERROR_RPC_MOREDATA) { outp->error_code = CM_ERROR_RPC_MOREDATA; } } if (code == 0 || code == CM_ERROR_RPC_MOREDATA) smb_SendTran2Packet(vcp, outp, op); smb_FreeTran2Packet(outp); done: smb_RPC_EndOp(rpcp); osi_Log1(smb_logp, "smb_RPCNmpipeTransact() end code=%d", code); if (uidp) smb_ReleaseUID(uidp); if (userp) cm_ReleaseUser(userp); return code; }
/** Handle SMB_COM_READ_ANDX for an RPC fid Called from smb_ReceiveV3ReadX to handle RPC descriptor reads */ afs_int32 smb_RPCV3Read(smb_fid_t *fidp, smb_vc_t *vcp, smb_packet_t *inp, smb_packet_t *outp) { smb_rpc_t *rpcp; long count; afs_int32 code; char *op; cm_user_t *userp; smb_user_t *uidp; count = smb_GetSMBParm(inp, 5); uidp = smb_FindUID(vcp, ((smb_t *)inp)->uid, 0); if (!uidp) return CM_ERROR_BADSMB; userp = smb_GetUserFromUID(uidp); osi_assertx(userp != NULL, "null cm_user_t"); osi_Log3(smb_logp, "smb_RPCV3Read for user[0x%p] fid[0x%p (%d)]", userp, fidp, fidp->fid); if (uidp && uidp->unp) { osi_Log3(afsd_logp, "RPC uid %d user %x name %S", uidp->userID, userp, osi_LogSaveClientString(afsd_logp, uidp->unp->name)); } else { if (uidp) osi_Log2(afsd_logp, "RPC uid %d user %x no name", uidp->userID, userp); else osi_Log1(afsd_logp, "RPC no uid user %x no name", userp); } lock_ObtainMutex(&fidp->mx); rpcp = fidp->rpcp; code = smb_RPC_BeginOp(rpcp); lock_ReleaseMutex(&fidp->mx); if (code) { if (uidp) smb_ReleaseUID(uidp); cm_ReleaseUser(userp); return code; } code = smb_RPC_PrepareRead(rpcp); if (uidp) { smb_ReleaseUID(uidp); } if (code) { cm_ReleaseUser(userp); smb_RPC_EndOp(rpcp); return code; } count = smb_RPC_ReadPacketLength(rpcp, count); /* 0 and 1 are reserved for request chaining, were setup by our caller, * and will be further filled in after we return. */ smb_SetSMBParm(outp, 2, 0); /* remaining bytes, for pipes */ smb_SetSMBParm(outp, 3, 0); /* resvd */ smb_SetSMBParm(outp, 4, 0); /* resvd */ smb_SetSMBParm(outp, 5, count); /* # of bytes we're going to read */ /* fill in #6 when we have all the parameters' space reserved */ smb_SetSMBParm(outp, 7, 0); /* resv'd */ smb_SetSMBParm(outp, 8, 0); /* resv'd */ smb_SetSMBParm(outp, 9, 0); /* resv'd */ smb_SetSMBParm(outp, 10, 0); /* resv'd */ smb_SetSMBParm(outp, 11, 0); /* reserved */ /* get op ptr after putting in the last parm, since otherwise we don't * know where the data really is. */ op = smb_GetSMBData(outp, NULL); /* now fill in offset from start of SMB header to first data byte (to op) */ smb_SetSMBParm(outp, 6, ((int) (op - outp->data))); /* set the packet data length the count of the # of bytes */ smb_SetSMBDataLength(outp, count); smb_RPC_ReadPacket(rpcp, op, count); smb_RPC_EndOp(rpcp); /* and cleanup things */ cm_ReleaseUser(userp); return 0; }
void * cm_BkgDaemon(void * vparm) { cm_bkgRequest_t *rp; afs_int32 code; char name[32] = ""; long daemonID = (long)(LONG_PTR)vparm; snprintf(name, sizeof(name), "cm_BkgDaemon_ShutdownEvent%u", daemonID); cm_BkgDaemon_ShutdownEvent[daemonID] = thrd_CreateEvent(NULL, FALSE, FALSE, name); if ( GetLastError() == ERROR_ALREADY_EXISTS ) afsi_log("Event Object Already Exists: %s", name); rx_StartClientThread(); lock_ObtainWrite(&cm_daemonLockp[daemonID]); while (daemon_ShutdownFlag == 0) { int willBlock = 0; if (powerStateSuspended) { Sleep(1000); continue; } if (!cm_bkgListEndpp[daemonID]) { osi_SleepW((LONG_PTR)&cm_bkgListpp[daemonID], &cm_daemonLockp[daemonID]); lock_ObtainWrite(&cm_daemonLockp[daemonID]); continue; } /* we found a request */ for (rp = cm_bkgListEndpp[daemonID]; rp; rp = (cm_bkgRequest_t *) osi_QPrev(&rp->q)) { if (rp->scp->flags & CM_SCACHEFLAG_DELETED) break; /* * If the request has active I/O such that this worker would * be forced to block, leave the request in the queue and move * on to one that might be available for servicing. */ if (cm_RequestWillBlock(rp)) { willBlock++; continue; } if (cm_ServerAvailable(&rp->scp->fid, rp->userp)) break; } if (rp == NULL) { /* * Couldn't find a request that we could process at the * current time. If there were requests that would cause * the worker to block, sleep for 25ms so it can promptly * respond when it is available. Otherwise, sleep for 1s. * * This polling cycle needs to be replaced with a proper * producer/consumer dynamic worker pool. */ osi_Log2(afsd_logp,"cm_BkgDaemon[%u] sleeping %dms all tasks would block", daemonID, willBlock ? 100 : 1000); lock_ReleaseWrite(&cm_daemonLockp[daemonID]); Sleep(willBlock ? 100 : 1000); lock_ObtainWrite(&cm_daemonLockp[daemonID]); continue; } osi_QRemoveHT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **) &cm_bkgListEndpp[daemonID], &rp->q); osi_assertx(cm_bkgQueueCountp[daemonID]-- > 0, "cm_bkgQueueCount 0"); lock_ReleaseWrite(&cm_daemonLockp[daemonID]); osi_Log2(afsd_logp,"cm_BkgDaemon[%u] processing request 0x%p", daemonID, rp); if (rp->scp->flags & CM_SCACHEFLAG_DELETED) { osi_Log2(afsd_logp,"cm_BkgDaemon[%u] DELETED scp 0x%x", daemonID, rp->scp); code = CM_ERROR_BADFD; } else { #ifdef DEBUG_REFCOUNT osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (before) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount); #endif code = (*rp->procp)(rp->scp, rp->p1, rp->p2, rp->p3, rp->p4, rp->userp, &rp->req); #ifdef DEBUG_REFCOUNT osi_Log3(afsd_logp,"cm_BkgDaemon[%u] (after) scp 0x%x ref %d", daemonID, rp->scp, rp->scp->refCount); #endif } /* * Keep the following list synchronized with the * error code list in cm_BkgStore. * cm_SyncOpDone(CM_SCACHESYNC_ASYNCSTORE) will be called there unless * one of these errors has occurred. */ switch ( code ) { case CM_ERROR_TIMEDOUT: /* or server restarting */ case CM_ERROR_RETRY: case CM_ERROR_WOULDBLOCK: case CM_ERROR_ALLBUSY: case CM_ERROR_ALLDOWN: case CM_ERROR_ALLOFFLINE: case CM_ERROR_PARTIALWRITE: if (rp->procp == cm_BkgStore || rp->procp == RDR_BkgFetch) { osi_Log3(afsd_logp, "cm_BkgDaemon[%u] re-queueing failed request 0x%p code 0x%x", daemonID, rp, code); lock_ObtainWrite(&cm_daemonLockp[daemonID]); cm_bkgQueueCountp[daemonID]++; osi_QAddT((osi_queue_t **) &cm_bkgListpp[daemonID], (osi_queue_t **)&cm_bkgListEndpp[daemonID], &rp->q); break; } /* otherwise fall through */ case 0: /* success */ default: /* other error */ if (code == 0) { osi_Log2(afsd_logp,"cm_BkgDaemon[%u] SUCCESS: request 0x%p", daemonID, rp); } else { osi_Log3(afsd_logp,"cm_BkgDaemon[%u] FAILED: request dropped 0x%p code 0x%x", daemonID, rp, code); } cm_ReleaseUser(rp->userp); cm_ReleaseSCache(rp->scp); free(rp); lock_ObtainWrite(&cm_daemonLockp[daemonID]); } } lock_ReleaseWrite(&cm_daemonLockp[daemonID]); thrd_SetEvent(cm_BkgDaemon_ShutdownEvent[daemonID]); pthread_exit(NULL); return NULL; }
void cm_PingServer(cm_server_t *tsp) { long code; int wasDown = 0; cm_conn_t *connp; struct rx_connection * rxconnp; Capabilities caps = {0, 0}; char hoststr[16]; cm_req_t req; lock_ObtainMutex(&tsp->mx); if (InterlockedIncrement(&tsp->pingCount) > 1) { tsp->waitCount++; osi_SleepM((LONG_PTR)tsp, &tsp->mx); lock_ObtainMutex(&tsp->mx); InterlockedDecrement(&tsp->pingCount); if (--tsp->waitCount > 0) osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); return; } wasDown = tsp->flags & CM_SERVERFLAG_DOWN; afs_inet_ntoa_r(tsp->addr.sin_addr.S_un.S_addr, hoststr); lock_ReleaseMutex(&tsp->mx); if (cm_noIPAddr > 0) code = cm_ConnByServer(tsp, cm_rootUserp, FALSE, &connp); else code = RX_CALL_DEAD; /* No network */ if (code == 0) { /* now call the appropriate ping call. Drop the timeout if * the server is known to be down, so that we don't waste a * lot of time retiming out down servers. */ osi_Log4(afsd_logp, "cm_PingServer server %s (%s) was %s with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", wasDown ? "down" : "up", tsp->capabilities); rxconnp = cm_GetRxConn(connp); if (wasDown) rx_SetConnHardDeadTime(rxconnp, 10); if (tsp->type == CM_SERVER_VLDB) { code = VL_ProbeServer(rxconnp); } else { /* file server */ code = RXAFS_GetCapabilities(rxconnp, &caps); } if (wasDown) rx_SetConnHardDeadTime(rxconnp, HardDeadtimeout); rx_PutConnection(rxconnp); cm_PutConn(connp); } /* got an unauthenticated connection to this server */ lock_ObtainMutex(&tsp->mx); if (code >= 0 || code == RXGEN_OPCODE) { /* mark server as up */ _InterlockedAnd(&tsp->flags, ~CM_SERVERFLAG_DOWN); tsp->downTime = 0; /* we currently handle 32-bits of capabilities */ if (code != RXGEN_OPCODE && caps.Capabilities_len > 0) { tsp->capabilities = caps.Capabilities_val[0]; xdr_free((xdrproc_t) xdr_Capabilities, &caps); caps.Capabilities_len = 0; caps.Capabilities_val = 0; } else { tsp->capabilities = 0; } osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is up with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); /* Now update the volume status if necessary */ if (wasDown) { cm_server_vols_t * tsrvp; cm_volume_t * volp; int i; for (tsrvp = tsp->vols; tsrvp; tsrvp = tsrvp->nextp) { for (i=0; i<NUM_SERVER_VOLS; i++) { if (tsrvp->ids[i] != 0) { cm_InitReq(&req); lock_ReleaseMutex(&tsp->mx); code = cm_FindVolumeByID(tsp->cellp, tsrvp->ids[i], cm_rootUserp, &req, CM_GETVOL_FLAG_NO_LRU_UPDATE, &volp); lock_ObtainMutex(&tsp->mx); if (code == 0) { cm_UpdateVolumeStatus(volp, tsrvp->ids[i]); cm_PutVolume(volp); } } } } cm_RankServer(tsp); } } else { cm_MarkServerDown(tsp, code, wasDown); osi_Log3(afsd_logp, "cm_PingServer server %s (%s) is down with caps 0x%x", osi_LogSaveString(afsd_logp, hoststr), tsp->type == CM_SERVER_VLDB ? "vldb" : "file", tsp->capabilities); } InterlockedDecrement(&tsp->pingCount); if (tsp->waitCount > 0) osi_Wakeup((LONG_PTR)tsp); lock_ReleaseMutex(&tsp->mx); }