Beispiel #1
0
/* 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;
}
Beispiel #2
0
/* 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;
}
Beispiel #3
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;
}
Beispiel #4
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;
}
Beispiel #5
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;
}
Beispiel #6
0
/* 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;
}
Beispiel #7
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #10
0
/**
   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;
}
Beispiel #11
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;
}
Beispiel #12
0
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);
}