Exemplo n.º 1
0
/*!
 * \brief send a Probe to all the network address of this server 
 * 
 * \return 0 if success, else return 1
 */
int
DoProbe(struct ubik_server *server)
{
    struct rx_connection *conns[UBIK_MAX_INTERFACE_ADDR];
    struct rx_connection *connSuccess = 0;
    int i, j;
    afs_uint32 addr;
    char buffer[32];
    char hoststr[16];
    extern afs_int32 ubikSecIndex;
    extern struct rx_securityClass *ubikSecClass;

    for (i = 0; (addr = server->addr[i]) && (i < UBIK_MAX_INTERFACE_ADDR);
	 i++) {
	conns[i] =
	    rx_NewConnection(addr, ubik_callPortal, DISK_SERVICE_ID,
			     ubikSecClass, ubikSecIndex);

	/* user requirement to use only the primary interface */
	if (ubikPrimaryAddrOnly) {
	    i = 1;
	    break;
	}
    }
    assert(i);			/* at least one interface address for this server */

    multi_Rx(conns, i) {
	multi_DISK_Probe();
	if (!multi_error) {	/* first success */
	    addr = server->addr[multi_i];	/* successful interface addr */

	    if (server->disk_rxcid)	/* destroy existing conn */
		rx_DestroyConnection(server->disk_rxcid);
	    if (server->vote_rxcid)
		rx_DestroyConnection(server->vote_rxcid);

	    /* make new connections */
	    server->disk_rxcid = conns[multi_i];
	    server->vote_rxcid = rx_NewConnection(addr, ubik_callPortal, VOTE_SERVICE_ID, ubikSecClass, ubikSecIndex);	/* for vote reqs */

	    connSuccess = conns[multi_i];
	    strcpy(buffer, afs_inet_ntoa_r(server->addr[0], hoststr));
	    ubik_print
		("ubik:server %s is back up: will be contacted through %s\n",
		 buffer, afs_inet_ntoa_r(addr, hoststr));

	    multi_Abort;
	}
    } multi_End_Ignore;
Exemplo n.º 2
0
/**
 * Release all connections for unix user xu at server xs
 * @param xu
 * @param xs
 */
static void
release_conns_user_server(struct unixuser *xu, struct server *xs)
{
    int cix, glocked;
    struct srvAddr *sa;
    struct afs_conn *tc;
    struct sa_conn_vector *tcv, **lcv;
    for (sa = (xs)->addr; sa; sa = sa->next_sa) {
        lcv = &sa->conns;
        for (tcv = *lcv; tcv; lcv = &tcv->next, tcv = *lcv) {
            if (tcv->user == (xu) && tcv->refCount == 0) {
                *lcv = tcv->next;
                /* our old friend, the GLOCK */
                glocked = ISAFS_GLOCK();
                if (glocked)
                    AFS_GUNLOCK();
                for(cix = 0; cix < CVEC_LEN; ++cix) {
                    tc = &(tcv->cvec[cix]);
                    if (tc->activated) {
                        rx_SetConnSecondsUntilNatPing(tc->id, 0);
                        rx_DestroyConnection(tc->id);
                    }
                }
                if (glocked)
                    AFS_GLOCK();
                afs_osi_Free(tcv, sizeof(struct sa_conn_vector));
                break;    /* at most one instance per server */
            } /*Found unreferenced connection for user */
        }
    } /*For each connection on the server */

}        /* release_conns_user_server */
Exemplo n.º 3
0
static void
release_conns_vector(struct sa_conn_vector *xcv)
{
    int cix, glocked;
    struct afs_conn *tc;
    struct sa_conn_vector *tcv = NULL;
    struct sa_conn_vector **lcv = NULL;
    for (tcv = xcv; tcv; lcv = &tcv->next, tcv = *lcv) {
        *lcv = tcv->next;
        /* you know it, you love it, the GLOCK */
        glocked = ISAFS_GLOCK();
        if (glocked)
            AFS_GUNLOCK(); \
        for(cix = 0; cix < CVEC_LEN; ++cix) {
            tc = &(tcv->cvec[cix]);
            if (tc->activated) {
                rx_SetConnSecondsUntilNatPing(tc->id, 0);
                rx_DestroyConnection(tc->id);
            }
        }
        if (glocked)
            AFS_GLOCK();
        afs_osi_Free(tcv, sizeof(struct sa_conn_vector));
    }

}        /* release_conns_vector */
Exemplo n.º 4
0
static int
notify_client (struct ropa_client *c, AFSCBFids *fids, AFSCBs *cbs)
{
#ifdef NO_CALLBACKS
    return 0;
#else
    int i, ret;
    if (c->conn) {
	ret = RXAFSCB_CallBack (c->conn, fids, cbs);
	if (ret == 0)
	    return ret;
    }
    for (i = 0; i < c->numberOfInterfaces ; i++) {
	uint16_t port = c->port;
	DIAGNOSTIC_CHECK_ADDR(&c->addr[i]);

	c->conn = rx_NewConnection (c->addr[i].addr_in,
				 port,
				 CM_SERVICE_ID,
				 rxnull_NewClientSecurityObject(),
				 0);
	mlog_log (MDEBROPA, "notify_client: notifying %x", c->addr[i].addr_in);

	ret = RXAFSCB_CallBack (c->conn, fids, cbs);
	if (ret)
	    rx_DestroyConnection (c->conn);
	else
	    break;

	/* XXX warn */
    }

    return ret;
#endif
}
Exemplo n.º 5
0
/*!
 * \brief Destroy an ubik connection.
 *
 * It calls rx to destroy the component rx connections, then frees the ubik
 * connection structure.
 */
afs_int32
ubik_ClientDestroy(struct ubik_client * aclient)
{
    int c;

    if (aclient == 0)
	return 0;
    LOCK_UBIK_CLIENT(aclient);
    for (c = 0; c < MAXSERVERS; c++) {
	struct rx_connection *rxConn = ubik_GetRPCConn(aclient, c);
	if (rxConn == 0)
	    break;
#ifdef AFS_PTHREAD_ENV
	rx_ReleaseCachedConnection(rxConn);
#else
	rx_DestroyConnection(rxConn);
#endif
    }
    aclient->initializationState = 0;	/* client in not initialized */
    UNLOCK_UBIK_CLIENT(aclient);
#ifdef AFS_PTHREAD_ENV
    pthread_mutex_destroy(&(aclient->cm));	/* ignore failure */
#endif
    free(aclient);
    return 0;
}
Exemplo n.º 6
0
int
xstat_fs_Cleanup(int a_releaseMem)
{
    static char rn[] = "xstat_fs_Cleanup";	/*Routine name */
    int code;			/*Return code */
    int conn_idx;		/*Current connection index */
    struct xstat_fs_ConnectionInfo *curr_conn;	/*Ptr to xstat_fs connection */

    /*
     * Assume the best, but check the worst.
     */
    if (!xstat_fs_initflag) {
	fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
	return (-1);
    } else
	code = 0;

    /*
     * Take care of all Rx connections first.  Check to see that the
     * server count is a legal value.
     */
    if (xstat_fs_numServers <= 0) {
	fprintf(stderr,
		"[%s] Illegal number of servers (xstat_fs_numServers = %d)\n",
		rn, xstat_fs_numServers);
	code = -1;
    } else {
	if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0) {
	    /*
	     * The xstat_fs connection structure array exists.  Go through
	     * it and close up any Rx connections it holds.
	     */
	    curr_conn = xstat_fs_ConnInfo;
	    for (conn_idx = 0; conn_idx < xstat_fs_numServers; conn_idx++) {
		if (curr_conn->rxconn != (struct rx_connection *)0) {
		    rx_DestroyConnection(curr_conn->rxconn);
		    curr_conn->rxconn = (struct rx_connection *)0;
		}
		curr_conn++;
	    }			/*for each xstat_fs connection */
	}			/*xstat_fs connection structure exists */
    }				/*Legal number of servers */

    /*
     * If asked to, release the space we've allocated.
     */
    if (a_releaseMem) {
	if (xstat_fs_ConnInfo != (struct xstat_fs_ConnectionInfo *)0)
	    free(xstat_fs_ConnInfo);
    }

    /*
     * Return the news, whatever it is.
     */
    return (code);
}
Exemplo n.º 7
0
static void
recycle_conn (ConnCacheEntry *e)
{
    assert (e->refcount == 0);

    if (e->parent != NULL) {
	conn_free (e->parent);
	e->parent = NULL;
    }
    if (e->probe_le != NULL) {
	listdel (connprobelist, e->probe_le);
	e->probe_le = NULL;
    }
    if (!e->flags.killme)
	hashtabdel (connhtab, e);
    rx_DestroyConnection (e->connection);
    memset (e, 0, sizeof(*e));
    listaddhead (connfreelist, e);
    --nactive_connections;
}
Exemplo n.º 8
0
/*!
 * \brief So that intermittent failures that cause connections to die
 *     don't kill whole ubik connection, refresh them when the connection is in
 *     error.
 */
struct rx_connection *
ubik_RefreshConn(struct rx_connection *tc)
{
    afs_uint32 host;
    u_short port;
    u_short service;
    struct rx_securityClass *sc;
    int si;
    struct rx_connection *newTc;

    host = rx_HostOf(rx_PeerOf(tc));
    port = rx_PortOf(rx_PeerOf(tc));
    service = rx_ServiceIdOf(tc);
    sc = rx_SecurityObjectOf(tc);
    si = rx_SecurityClassOf(tc);

    /*
     * destroy old one after creating new one so that refCount on security
     * object cannot reach zero.
     */
    newTc = rx_NewConnection(host, port, service, sc, si);
    rx_DestroyConnection(tc);
    return newTc;
}
Exemplo n.º 9
0
static struct ropa_client *
client_query (uint32_t host, uint16_t port)
{
    struct ropa_client *c, *c_new;
    int ret;

    c = client_query_notalkback(host, port);
    if (c == NULL) {
	interfaceAddr remote;
	struct rx_connection *conn = NULL;

	c = obtain_client();
	assert (c->state == ROPAC_FREE && c->li == NULL);
	c->state = ROPAC_LOOKUP_U;
	c->flags |= ROPAF_LOOKUP;
	client_init (c, host, port, NULL, NULL);
	
	conn = rx_NewConnection (host, port, CM_SERVICE_ID,
				 rxnull_NewClientSecurityObject(),
				 0);
	if (conn == NULL) {
	    free(c);
	    return NULL;
	}
    retry:
	switch (c->state) {
	case ROPAC_DEAD:
	    c->li = listaddtail (lru_clients, c);
	    ret = ENETDOWN;
	    break;
	case ROPAC_LOOKUP_U:
	    ret = RXAFSCB_WhoAreYou (conn, &remote);
	    if (ret == RXGEN_OPCODE) {
		c->state = ROPAC_LOOKUP;
		goto retry;
	    } else if (ret == RX_CALL_DEAD) {
		c->state = ROPAC_DEAD;
		goto retry;
	    } else {
		struct ropa_client ckey;
		
		ckey.uuid = remote.uuid;
		c_new = hashtabsearch (ht_clients_uuid, &ckey);
		if (c_new == NULL) {
		    client_init (c, host, port, &remote.uuid, NULL);
		    ret = RXAFSCB_InitCallBackState3(conn, &server_uuid);
		} else {
		    client_update_interfaces (c_new, host, port, &remote);
		    disconnect_client (c);
		    c = c_new;
		    listdel(lru_clients, c->li);
		    c->li = NULL;
		}
	    }
	    break;
	case ROPAC_LOOKUP: {
	    afsUUID uuid;
	    ret = RXAFSCB_InitCallBackState(conn);
	    if (ret == RX_CALL_DEAD) {
		c->state = ROPAC_DEAD;
		goto retry;
	    }
	    uuid_init_simple (&uuid, host);
	    client_init (c, host, port, &uuid, NULL);
	    break;
	}
	default:
	     exit(-1);
	}
	
	rx_DestroyConnection (conn);
	
	if ((c->flags & ROPAF_WAITING) != 0)
	    LWP_NoYieldSignal (c);
	c->flags &= ~(ROPAF_LOOKUP|ROPAF_WAITING);

	if (ret) {
	    assert (c->li != NULL);
	    return NULL;
	}

	assert (c->li == NULL);
	c->li = listaddhead (lru_clients, c);

    } else { /* c != NULL */
	if ((c->flags & ROPAF_LOOKUP) != 0) {
	    c->flags |= ROPAF_WAITING;
	    LWP_WaitProcess (c);
	}
	assert (c->li != NULL);
    }

    return c;
}
Exemplo n.º 10
0
/**
 * Connects to a server by it's server address.
 *
 * @param sap Server address.
 * @param aport Server port.
 * @param acell
 * @param tu Connect as this user.
 * @param force_if_down
 * @param create
 * @param locktype Specifies type of lock to be used for this function.
 *
 * @return The new connection.
 */
struct afs_conn *
afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
	     struct unixuser *tu, int force_if_down, afs_int32 create,
	     afs_int32 locktype, struct rx_connection **rxconn)
{
    int glocked, foundvec;
    struct afs_conn *tc = NULL;
    struct sa_conn_vector *tcv = NULL;
    struct rx_securityClass *csec; /*Security class object */
    int isec; /*Security index */
    int service;

    *rxconn = NULL;

    /* find cached connection */
    ObtainSharedLock(&afs_xconn, 15);
    foundvec = 0;
    for (tcv = sap->conns; tcv; tcv = tcv->next) {
        if (tcv->user == tu && tcv->port == aport) {
            /* return most eligible conn */
            if (!foundvec)
                foundvec = 1;
            UpgradeSToWLock(&afs_xconn, 37);
            tc = find_preferred_connection(tcv, create);
            ConvertWToSLock(&afs_xconn);
            break;
        }
    }

    if (!tc && !create) {
        /* Not found and can't create a new one. */
        ReleaseSharedLock(&afs_xconn);
        return NULL;
    }

    if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
        afs_warnuser("afs_ConnBySA: disconnected\n");
        ReleaseSharedLock(&afs_xconn);
        return NULL;
    }

    if (!foundvec && create) {
	/* No such connection vector exists.  Create one and splice it in.
	 * Make sure the server record has been marked as used (for the purposes
	 * of calculating up & down times, it's now considered to be an
	 * ``active'' server).  Also make sure the server's lastUpdateEvalTime
	 * gets set, marking the time of its ``birth''.
	 */
	UpgradeSToWLock(&afs_xconn, 37);
        new_conn_vector(tcv);

        tcv->user = tu;
        tcv->port = aport;
        tcv->srvr = sap;
        tcv->next = sap->conns;
        sap->conns = tcv;

        /* all struct afs_conn ptrs come from here */
        tc = find_preferred_connection(tcv, create);

	afs_ActivateServer(sap);

	ConvertWToSLock(&afs_xconn);
    } /* end of if (!tcv) */

    if (!tc) {
        /* Not found and no alternatives. */
        ReleaseSharedLock(&afs_xconn);
        return NULL;
    }

    if (tu->states & UTokensBad) {
	/* we may still have an authenticated RPC connection here,
	 * we'll have to create a new, unauthenticated, connection.
	 * Perhaps a better way to do this would be to set
	 * conn->forceConnectFS on all conns when the token first goes
	 * bad, but that's somewhat trickier, due to locking
	 * constraints (though not impossible).
	 */
	if (tc->id && (rx_SecurityClassOf(tc->id) != 0)) {
	    tc->forceConnectFS = 1;	/* force recreation of connection */
	}
	tu->states &= ~UHasTokens;      /* remove the authentication info */
    }

    glocked = ISAFS_GLOCK();
    if (tc->forceConnectFS) {
	UpgradeSToWLock(&afs_xconn, 38);
	csec = (struct rx_securityClass *)0;
	if (tc->id) {
	    if (glocked)
                AFS_GUNLOCK();
            rx_SetConnSecondsUntilNatPing(tc->id, 0);
            rx_DestroyConnection(tc->id);
	    if (glocked)
                AFS_GLOCK();
	}
	/*
	 * Stupid hack to determine if using vldb service or file system
	 * service.
	 */
	if (aport == sap->server->cell->vlport)
	    service = 52;
	else
	    service = 1;
	isec = 0;

	csec = afs_pickSecurityObject(tc, &isec);

	if (glocked)
            AFS_GUNLOCK();
	tc->id = rx_NewConnection(sap->sa_ip, aport, service, csec, isec);
	if (glocked)
            AFS_GLOCK();
	if (service == 52) {
	    rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
	}
	/* set to a RX_CALL_TIMEOUT error to allow MTU retry to trigger */
	rx_SetServerConnIdleDeadErr(tc->id, RX_CALL_DEAD);
	rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead);

	/*
	 * Only do this for the base connection, not per-user.
	 * Will need to be revisited if/when CB gets security.
	 */
	if ((isec == 0) && (service != 52) && !(tu->states & UTokensBad) &&
	    (tu->viceId == UNDEFVID)
#ifndef UKERNEL /* ukernel runs as just one uid anyway */
	    && (tu->uid == 0)
#endif
	    )
	    rx_SetConnSecondsUntilNatPing(tc->id, 20);

	tc->forceConnectFS = 0;	/* apparently we're appropriately connected now */
	if (csec)
	    rxs_Release(csec);
	ConvertWToSLock(&afs_xconn);
    } /* end of if (tc->forceConnectFS)*/

    *rxconn = tc->id;
    rx_GetConnection(*rxconn);

    ReleaseSharedLock(&afs_xconn);
    return tc;
}
Exemplo n.º 11
0
static long
RunHijackTest(struct clientParms *parms, long host,
	      struct rx_securityClass *sc, long si)
{

#ifndef rx_GetPacketCksum

    code = RXKST_BADARGS;
    afs_com_err(whoami, code,
	    "Older versions of Rx don't export packet tracing routines: can't run this HijackTest");
    return code;

#else

    long code;
    struct rx_connection *conn = 0;
    struct rx_connection *otherConn = 0;
#ifdef AFS_PTHREAD_ENV
    pthread_t pid;
#else
    PROCESS pid;
#endif
    int nResp;			/* otherConn responses seen */
    long tmp_rc;

#ifdef AFS_PTHREAD_ENV
    pthread_once(&slowCallOnce, SlowCallInit);
#endif
    rx_justReceived = HandleIncoming;
    rx_almostSent = HandleOutgoing;

    incomingOps.op = IO_NOOP;
    outgoingOps.op = OO_NOOP;

#define HIJACK_CONN(conn) \
    {   if (conn) rx_DestroyConnection (conn); \
	(conn) = rx_NewConnection(host, htons(RXKST_SERVICEPORT), \
				RXKST_SERVICEID, sc, si); \
	if (!(conn)) return RXKST_NEWCONNFAILED; \
	outgoingOps.client = 1; \
	outgoingOps.epoch = (conn)->epoch; \
	outgoingOps.cid = (conn)->cid; }

    HIJACK_CONN(conn);

    /* First try switching from no packet cksum to sending packet cksum between
     * calls, and see if server complains. */

    outgoingOps.op = OO_ZEROCKSUM;
    code = FastCall(conn);
    if (code) {
	afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM");
	return code;
    }
    /* The server thinks we're an old style client.  Now start sending cksums.
     * Server shouldn't care. */
    outgoingOps.op = OO_NOOP;
    code = FastCall(conn);
    if (code) {
	afs_com_err(whoami, code, "doing FastCall with non-ZEROCKSUM");
	return code;
    }
    /* The server now thinks we're a new style client, we can't go back now. */
    outgoingOps.op = OO_ZEROCKSUM;
    code = FastCall(conn);
    if (code == 0)
	code = RXKST_NOBADCKSUM;
    if (code != RXKADSEALEDINCON) {
	afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM");
	return code;
    } else if (!conn->error) {
	code = RXKST_NOCONNERROR;
	afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM");
	return code;
    } else
	code = 0;

    HIJACK_CONN(conn);

    /* Now try modifying packet cksum to see if server complains. */

    outgoingOps.op = OO_MUNGCKSUM;
    code = FastCall(conn);
    if (code == 0)
	code = RXKST_NOBADCKSUM;
    if (code != RXKADSEALEDINCON) {
	afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM");
	return code;
    } else if (!conn->error) {
	code = RXKST_NOCONNERROR;
	afs_com_err(whoami, code, "doing FastCall with ZEROCKSUM");
	return code;
    } else
	code = 0;

    /* Now make two connection and direct the first challenge on one connection
     * to the other connection to see if it generates a response.  The
     * retransmitted challenge should allow the call on the first connection to
     * complete correctly.  Part one is to attack a new connection, then attack
     * it after it has made a call.  Part three, just for comparison, attacks a
     * otherConn while it is making a slow call (and thus has an active call).
     * Against this attack we have no defense so we expect a challenge in this
     * case, which the server will discard. */

#define RedirectChallenge(conn,otherConn)	\
    (incomingOps.epoch = (conn)->epoch,		\
     incomingOps.cid = (conn)->cid,		\
     incomingOps.client = 1,			\
     incomingOps.newEpoch = (otherConn)->epoch,	\
     incomingOps.newCid = (otherConn)->cid,	\
     incomingOps.op = IO_REDIRECTCHALLENGE,	\
     outgoingOps.epoch = (otherConn)->epoch,	\
     outgoingOps.cid = (otherConn)->cid,	\
     outgoingOps.client = 1,			\
     outgoingOps.op = OO_COUNT,			\
     outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] = 0)

    HIJACK_CONN(conn);
    HIJACK_CONN(otherConn)
	RedirectChallenge(conn, otherConn);

    code = FastCall(conn);
    if (code)
	return code;
    assert(incomingOps.op == IO_COUNT);	/* redirect code was triggered */
    if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] > 0) {
      oracle:
	code = RXKST_CHALLENGEORACLE;
	afs_com_err(whoami, code, "misdirecting challenge");
	return code;
    }
    code = FastCall(otherConn);	/* generate some activity here */
    if (code)
	return code;
    nResp = outgoingOps.counts[RX_PACKET_TYPE_RESPONSE];
    assert(nResp >= 1);
    code = FastCall(conn);
    if (code)
	return code;
    if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] > nResp)
	goto oracle;

    HIJACK_CONN(conn);
    RedirectChallenge(conn, otherConn);
    /* otherConn was authenticated during part one */
    code = FastCall(conn);
    if (code)
	return code;
    assert(incomingOps.op == IO_COUNT);	/* redirect code was triggered */
    if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] != 0)
	goto oracle;

    HIJACK_CONN(conn);
    RedirectChallenge(conn, otherConn);
    /* otherConn is still authenticated */
    slowCallCode = RXKST_PROCESSCREATED;
#ifdef AFS_PTHREAD_ENV
    {
	pthread_attr_t tattr;

	code = pthread_attr_init(&tattr);
	if (code) {
	    afs_com_err(whoami, code,
		    "can't pthread_attr_init slow call process");
	    return code;
	}

	code = pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED);
	if (code) {
	    afs_com_err(whoami, code,
		    "can't pthread_attr_setdetachstate slow call process");
	    return code;
	}

	code = pthread_create(&pid, &tattr, SlowCall, (void *)otherConn);
    }
#else
    code =
	LWP_CreateProcess(SlowCall, 16000, LWP_NORMAL_PRIORITY,
			  (opaque) otherConn, "Slow Call Process", &pid);
#endif
    if (code) {
	afs_com_err(whoami, code, "can't create slow call process");
	return code;
    }
#ifdef AFS_PTHREAD_ENV
    pthread_mutex_lock(&slowCallLock);
    while (slowCallCode == RXKST_PROCESSCREATED)
	pthread_cond_wait(&slowCallCV, &slowCallLock);
#else
    while (slowCallCode == RXKST_PROCESSCREATED)
	LWP_WaitProcess(&slowCallCode);	/* wait for process start */
#endif
    if (slowCallCode != RXKST_PROCESSRUNNING) {
	tmp_rc = slowCallCode;
#ifdef AFS_PTHREAD_ENV
	pthread_mutex_unlock(&slowCallLock);
#endif
	return tmp_rc;		/* make sure didn't fail immediately */
    }
    assert(incomingOps.op == IO_REDIRECTCHALLENGE);
    code = FastCall(conn);
    if (code)
	return code;
    assert(incomingOps.op == IO_COUNT);	/* redirect code was triggered */
#ifdef AFS_PTHREAD_ENV
    while (slowCallCode == RXKST_PROCESSRUNNING)
	pthread_cond_wait(&slowCallCV, &slowCallLock);
    pthread_mutex_unlock(&slowCallLock);
#else
    while (slowCallCode == RXKST_PROCESSRUNNING)
	LWP_WaitProcess(&slowCallCode);	/* wait for process finish */
#endif
    if (outgoingOps.counts[RX_PACKET_TYPE_RESPONSE] != 1)
	goto oracle;

    rx_justReceived = 0;
    rx_almostSent = 0;
    rx_DestroyConnection(otherConn);
    rx_DestroyConnection(conn);
    return code;

#endif /* rx_GetPacketCksum */

}
Exemplo n.º 12
0
static long
RunCallTest(struct clientParms *parms, long host,
	    struct rx_securityClass *sc, long si)
{
    long code;

#ifndef rx_GetPacketCksum

    code = RXKST_BADARGS;
    afs_com_err(whoami, code,
	    "Older versions of Rx don't support Get/Set callNumber Vector procedures: can't run this CallTest");
    return code;

#else

    int i, ch;
    struct rx_connection *conn;
    long firstCall;
    afs_int32 callNumbers[RX_MAXCALLS];
    long codes[RX_MAXCALLS];
    long retCode = 0;		/* ret. if nothing fatal goes wrong */

    conn =
	rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc,
			 si);
    if (!conn)
	return RXKST_NEWCONNFAILED;

    /* First check the basic behaviour of call number handling */

    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    for (i = 0; i < RX_MAXCALLS; i++) {
	if (callNumbers[i] != 0) {
	    fprintf(stderr,
		    "Connection's initial call numbers not zero. call[%d] = %d\n",
		    i, callNumbers[i]);
	    return RXKST_BADCALLNUMBERS;
	}
    }
    code = FastCall(conn);
    if (code)
	return code;
    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    firstCall = callNumbers[0];
    code = FastCall(conn);
    if (code)
	return code;
    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    if ((callNumbers[0] != firstCall + 1)
	&& ((firstCall == 1) || (firstCall == 2))) {
	/* The call number after the first call should be one or, more likely,
	 * two (if the call is still DALLYing).  Between first and second call,
	 * the call number should have incremented by one. */
	fprintf(stderr,
		"Connection's first channel call number not one. call[%d] = %d\n",
		0, callNumbers[0]);
	return RXKST_BADCALLNUMBERS;
    }
    for (i = 1; i < RX_MAXCALLS; i++) {
	if (callNumbers[i] != 0) {
	    fprintf(stderr,
		    "Connection's other channel call numbers not zero. call[%d] = %d\n",
		    i, callNumbers[i]);
	    return RXKST_BADCALLNUMBERS;
	}
    }
    code = MakeMultiChannelCall(conn, 1, 0, codes);
    if (code)
	return code;

    /* Now try to resend a call that's already been executed by finding a
     * non-zero call number on a channel other than zero and decrementing it by
     * one.  This should appear to the server as a retransmitted call.  Since
     * this is behaving as a broken client different strange behaviors may be
     * exhibited by different servers.  If the response packet to the original
     * call is discarded by the time the "retransmitted" call arrives (perhaps
     * due to high server or client load) there is no way for the server to
     * respond at all.  Further, it seems, that under some cases the connection
     * will be kept alive indefinitely even though the server has discarded the
     * "retransmitted" call and is making no effort to reexecute the call.  To
     * handle these, accept either a timeout (-1) or and INCFAILED error here,
     * also set the connenction HardDeadTime to punt after a reasonable
     * interval. */

    /* short dead time since may we expect some trouble */
    rx_SetConnHardDeadTime(conn, 30);
    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    for (ch = 1; ch < RX_MAXCALLS; ch++)
	if (callNumbers[ch] > 1) {
	    callNumbers[ch]--;
	    code = rxi_SetCallNumberVector(conn, callNumbers);
	    if (code)
		return code;
	    break;
	}
    if (ch >= RX_MAXCALLS)	/* didn't find any? all DALLYing? */
	return RXKST_BADCALLNUMBERS;
    code = MakeMultiChannelCall(conn, 1, RXKST_INCFAILED, codes);
    code = CheckCallFailure(conn, codes, code, "retransmitted call");
    if (code && !retCode)
	retCode = code;

    /* Get a fresh connection, becasue if the above failed as it should the
     * connection is dead. */
    rx_DestroyConnection(conn);
    conn =
	rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc,
			 si);
    if (!conn)
	return RXKST_NEWCONNFAILED;

    /* Similarly, but decrement call number by two which should be completely
     * unmistakeable as a broken or malicious client. */

    /* short dead time since may we expect some trouble */
    rx_SetConnHardDeadTime(conn, 30);
    code = MakeMultiChannelCall(conn, 2, 0, codes);
    if (code)
	return code;
    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    for (ch = 1; ch < RX_MAXCALLS; ch++)
	if (callNumbers[ch] > 2) {
	    callNumbers[ch] -= 2;
	    code = rxi_SetCallNumberVector(conn, callNumbers);
	    break;
	}
    if (ch >= RX_MAXCALLS)	/* didn't find any? all DALLYing? */
	return RXKST_BADCALLNUMBERS;
    code = MakeMultiChannelCall(conn, 1, -1, codes);
    code = CheckCallFailure(conn, codes, code, "duplicate call");
    if (code && !retCode)
	retCode = code;

    rx_DestroyConnection(conn);
    conn =
	rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID, sc,
			 si);
    if (!conn)
	return RXKST_NEWCONNFAILED;

    /* Next, without waiting for the server to discard its state, we will check
     * to see if the Challenge/Response protocol correctly informs the server
     * of the client's callNumber state.  We do this by artificially increasing
     * the call numbers of a new connection for all channels beyond zero,
     * making a call on channel zero, then resetting the call number for the
     * unused channels back to zero, then making calls on all channels. */

    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    for (i = 0; i < RX_MAXCALLS; i++) {
	if (callNumbers[i] != 0)
	    return RXKST_BADCALLNUMBERS;
	callNumbers[i] = 51;	/* an arbitrary value... */
    }
    code = rxi_SetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    code = FastCall(conn);	/* use channel 0 */
    if (code)
	return code;
    code = rxi_GetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    if (callNumbers[0] != 52)
	return RXKST_BADCALLNUMBERS;
    for (i = 1; i < RX_MAXCALLS; i++) {
	if (callNumbers[i] != 51)
	    return RXKST_BADCALLNUMBERS;
	callNumbers[i] = 37;	/* back up a ways */
    }
    code = rxi_SetCallNumberVector(conn, callNumbers);
    if (code)
	return code;
    /* now try calls on all channels... */
    code = MakeMultiChannelCall(conn, 1, -1, codes);
    code =
	CheckCallFailure(conn, codes, code, "alternate channel call replay");
    if (code && !retCode)
	retCode = code;

    rx_DestroyConnection(conn);
    return retCode;

#endif /* rx_GetPacketCksum */

}
Exemplo n.º 13
0
long
rxkst_StartClient(struct clientParms *parms)
{
    long code;
    long host;
    long scIndex;
    struct rx_securityClass *sc;

    whoami = parms->whoami;	/* set this global variable */

    host = GetServer(parms->server);

    if (parms->authentication >= 0) {
	long kvno = 0;
	char ticket[MAXKTCTICKETLEN];
	int ticketLen;
	struct ktc_encryptionKey Ksession;

	if (parms->useTokens)
	    code =
		GetToken(&kvno, &Ksession, &ticketLen, ticket, parms->cell);
	else
	    code =
		GetTicket(&kvno, &Ksession, &ticketLen, ticket, parms->cell);
	if (code)
	    return code;

	/* next, we have ticket, kvno and session key, authenticate the conn */
	sc = (struct rx_securityClass *)
	    rxkad_NewClientSecurityObject(parms->authentication, &Ksession,
					  kvno, ticketLen, ticket);
	assert(sc);
	scIndex = RX_SECIDX_KAD;
    } else {
	/* unauthenticated connection */
	sc = rxnull_NewClientSecurityObject();
	assert(sc);
	scIndex = RX_SECIDX_NULL;
    }

    code = 0;
    if (!code && parms->callTest) {
	code = RunCallTest(parms, host, sc, scIndex);
    }
    if (!code && parms->hijackTest) {
	code = RunHijackTest(parms, host, sc, scIndex);
    }
    if (!code
	&& (parms->printTiming || parms->fastCalls || parms->slowCalls
	    || parms->copiousCalls)) {
	struct rx_connection *conn;
	conn =
	    rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID,
			     sc, scIndex);
	if (conn) {
	    code = RepeatLoadTest(parms, conn);
	    rx_DestroyConnection(conn);
	} else
	    code = RXKST_NEWCONNFAILED;
    }
    if (!code && parms->stopServer) {
	struct rx_connection *conn;
	conn =
	    rx_NewConnection(host, htons(RXKST_SERVICEPORT), RXKST_SERVICEID,
			     sc, scIndex);
	if (conn) {
	    code = RXKST_Kill(conn);
	    if (code) {
		afs_com_err(whoami, code, "trying to stop server");
	    }
	    rx_DestroyConnection(conn);
	} else
	    code = RXKST_NEWCONNFAILED;
    }

    if (parms->printStats) {
	rx_PrintStats(stdout);
#if 0
	/* use rxdebug style iteration here */
	rx_PrintPeerStats(stdout, rx_PeerOf(conn));
#endif
    }

    rxs_Release(sc);
    rx_Finalize();
    if (code) {
	afs_com_err(parms->whoami, code, "test fails");
	exit(13);
    } else {
	printf("Test Okay\n");
	if (!parms->noExit)
	    exit(0);
    }
    return 0;
}
Exemplo n.º 14
0
void
startClient(char *configPath)
{
    struct afsconf_dir *dir;
    struct rx_identity *testId, *anotherId, *extendedId, *dummy;
    struct rx_securityClass *class;
    struct rx_connection *conn;
    afs_uint32 startTime;
    char ubuffer[256];
    afs_int32 classIndex;
    int code;
    struct hostent *he;
    afs_uint32 addr;
    afs_int32 result;
    char *string = NULL;

    plan(63);

    dir = afsconf_Open(configPath);
    ok(dir!=NULL,
       "Configuration directory opened sucessfully by client");

    /* Add a normal user to the super user file */
    ok(afsconf_AddUser(dir, "test") == 0,
       "Adding a simple user works");

    testId = rx_identity_new(RX_ID_KRB4, "test", "test", strlen("test"));

    /* Check that they are a super user */
    ok(afsconf_IsSuperIdentity(dir, testId),
       "User added with old i/face is identitifed as super user");

    /* Check that nobody else is */
    ok(!afsconf_IsSuperIdentity(dir,
			       rx_identity_new(RX_ID_KRB4, "testy",
					       "testy", strlen("testy"))),
       "Additional users are not super users");

    ok(afsconf_AddUser(dir, "test") == EEXIST,
       "Adding a user that already exists fails");

    ok(afsconf_AddIdentity(dir, testId) == EEXIST,
       "Adding an identity that already exists fails");

    anotherId = rx_identity_new(RX_ID_KRB4, "another",
					    "another", strlen("another"));

    /* Add another normal user, but using the extended interface */
    ok(afsconf_AddIdentity(dir, anotherId) == 0,
       "Adding a KRB4 identity works");

    /* Check that they are a super user */
    ok(afsconf_IsSuperIdentity(dir, anotherId),
       "User added with new i/face is identitifed as super user");

    ok(afsconf_AddIdentity(dir, anotherId) == EEXIST,
       "Adding a KRB4 identity that already exists fails");

    /* Add an extended user to the super user file */
    extendedId = rx_identity_new(RX_ID_GSS, "*****@*****.**",
				 "\x04\x01\x00\x0B\x06\x09\x2A\x86\x48\x86\xF7\x12\x01\x02\x02\x00\x00\x00\[email protected]", 35);

    ok(afsconf_AddIdentity(dir, extendedId) == 0,
       "Adding a GSSAPI identity works");

    /* Check that they are now special */
    ok(afsconf_IsSuperIdentity(dir, extendedId),
       "Added GSSAPI identity is a super user");

    /* Check that display name isn't used for matches */
    ok(!afsconf_IsSuperIdentity(dir,
				rx_identity_new(RX_ID_GSS, "*****@*****.**",
						"abcdefghijklmnopqrstuvwxyz123456789", 35)),
       "Display name is not used for extended matches");

    ok(afsconf_AddIdentity(dir, extendedId) == EEXIST,
       "Adding GSSAPI identity twice fails");

    /* Add a final normal user, so we can check that iteration works */
    /* Add a normal user to the super user file */
    ok(afsconf_AddUser(dir, "test2") == 0,
       "Adding another simple user works");

    testOriginalIterator(dir, 0, "test");
    testOriginalIterator(dir, 1, "another");
    testOriginalIterator(dir, 2, "test2");
    ok(afsconf_GetNthUser(dir, 3, ubuffer, sizeof ubuffer) != 0,
       "Reading past the end of the superuser list fails");

    testNewIterator(dir, 0, testId);
    testNewIterator(dir, 1, anotherId);
    testNewIterator(dir, 2, extendedId);
    testNewIterator(dir, 3, rx_identity_new(RX_ID_KRB4, "test2",
					    "test2", strlen("test2")));
    ok(afsconf_GetNthIdentity(dir, 4, &dummy) != 0,
       "Reading past the end of the superuser list fails");

    ok(afsconf_DeleteUser(dir, "notthere") != 0,
       "Deleting a user that doesn't exist fails");

    /* Delete the normal user */
    ok(afsconf_DeleteUser(dir, "another") == 0,
       "Deleting normal user works");

    ok(!afsconf_IsSuperIdentity(dir, anotherId),
       "Deleted user is no longer super user");

    ok(afsconf_IsSuperIdentity(dir, testId) &&
       afsconf_IsSuperIdentity(dir, extendedId),
       "Other identities still are");

    ok(afsconf_DeleteIdentity(dir, extendedId) == 0,
       "Deleting identity works");

    ok(!afsconf_IsSuperIdentity(dir, extendedId),
       "Deleted identity is no longer special");

    /* Now, what happens if we're doing something over the network instead */

    code = rx_Init(0);
    is_int(code, 0, "Initialised RX");

    /* Fake up an rx ticket. Note that this will be for the magic 'superuser' */
    code = afsconf_ClientAuth(dir, &class, &classIndex);
    is_int(code, 0, "Can successfully create superuser token");

    /* Start a connection to our test service with it */
    he = gethostbyname("localhost");
    if (!he) {
        printf("Couldn't look up server hostname");
        exit(1);
    }

    memcpy(&addr, he->h_addr, sizeof(afs_uint32));

    conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID,
			    class, classIndex);

    /* There's nothing in the list, so this just succeeds because we can */
    code = TEST_CanI(conn, &result);
    is_int(0, code, "Can run a simple RPC");

    code = TEST_WhoAmI(conn, &string);
    is_int(0, code, "Can get identity back");
    is_string("<LocalAuth>", string, "Forged token is super user");

    xdr_free((xdrproc_t)xdr_string, &string);

    /* Throw away this connection and security class */
    rx_DestroyConnection(conn);
    rxs_Release(class);

    /* Now fake an rx ticket for a normal user. We have to do more work by hand
     * here, sadly */

    startTime = time(NULL);
    class = afstest_FakeRxkadClass(dir, "rpctest", "", "", startTime,
				   startTime + 60* 60);

    conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
			    RX_SECIDX_KAD);

    code = TEST_CanI(conn, &result);
    is_int(EPERM, code,
	   "Running RPC as non-super user fails as expected");
    code = TEST_NewCanI(conn, &result);
    is_int(EPERM, code,
	   "Running new interface RPC as non-super user fails as expected");
    code = TEST_WhoAmI(conn, &string);
    xdr_free((xdrproc_t)xdr_string, &string);
    is_int(EPERM, code,
	   "Running RPC returning string fails as expected");
    code = TEST_NewWhoAmI(conn, &string);
    xdr_free((xdrproc_t)xdr_string, &string);
    is_int(EPERM, code,
	   "Running new interface RPC returning string fails as expected");
    ok(afsconf_AddUser(dir, "rpctest") == 0,
       "Adding %s user works", "rpctest");
    code = TEST_CanI(conn, &result);
    is_int(0, code, "Running RPC as rpctest works");
    code = TEST_NewCanI(conn, &result);
    is_int(0, code, "Running new interface RPC as rpctest works");
    code = TEST_WhoAmI(conn, &string);
    is_int(0, code, "Running RPC returning string as %s works", "rpctest");
    is_string("rpctest", string, "Returned user string matches");
    xdr_free((xdrproc_t)xdr_string, &string);
    code = TEST_NewWhoAmI(conn, &string);
    is_int(0, code, "Running new RPC returning string as %s works", "rpctest");
    is_string("rpctest", string, "Returned user string for new interface matches");
    xdr_free((xdrproc_t)xdr_string, &string);
    rx_DestroyConnection(conn);
    rxs_Release(class);

    /* Now try with an admin principal */
    startTime = time(NULL);
    class = afstest_FakeRxkadClass(dir, "rpctest", "admin", "", startTime,
				   startTime + 60* 60);

    conn = rx_NewConnection(addr, htons(TEST_PORT), TEST_SERVICE_ID, class,
			    RX_SECIDX_KAD);

    code = TEST_CanI(conn, &result);
    is_int(EPERM, code,
	   "Running RPC as non-super user fails as expected");
    code = TEST_NewCanI(conn, &result);
    is_int(EPERM, code,
	   "Running new interface RPC as non-super user fails as expected");
    code = TEST_WhoAmI(conn, &string);
    xdr_free((xdrproc_t)xdr_string, &string);
    is_int(EPERM, code,
	   "Running RPC returning string fails as expected");
    code = TEST_NewWhoAmI(conn, &string);
    xdr_free((xdrproc_t)xdr_string, &string);
    is_int(EPERM, code,
	   "Running new interface RPC returning string fails as expected");

    ok(afsconf_AddUser(dir, "rpctest.admin") == 0,
       "Adding %s user works", "rpctest.admin");

    code = TEST_CanI(conn, &result);
    is_int(0, code, "Running RPC as %s works", "rpctest/admin");
    code = TEST_NewCanI(conn, &result);
    is_int(0, code, "Running new interface RPC as %s works", "rpctest/admin");
    code = TEST_WhoAmI(conn, &string);
    is_int(0, code, "Running RPC returning string as %s works", "rpctest/admin");
    is_string("rpctest.admin", string, "Returned user string matches");
    xdr_free((xdrproc_t)xdr_string, &string);
    code = TEST_NewWhoAmI(conn, &string);
    is_int(0, code, "Running new interface RPC returning string as %s works",
	   "rpctest/admin");
    is_string("rpctest.admin", string,
	      "Returned user string from new interface matches");
    xdr_free((xdrproc_t)xdr_string, &string);

    rx_DestroyConnection(conn);
    rxs_Release(class);
}
Exemplo n.º 15
0
int
main(int argc, char **argv)
{
    char scell[MAXCELLCHARS], dcell[MAXCELLCHARS];
    afs_uint32 ssrv, dsrv;
    char *databuffer, *srcf = NULL, *destd = NULL, *destf = NULL, *destpath = NULL;
    struct stat statbuf;

    struct AFSStoreStatus sst;
    struct AFSFetchStatus fst, dfst;
    struct AFSVolSync vs;
    struct AFSCallBack scb, dcb;
    struct AFSFid sf, dd, df;

    int filesz = 0;
    int ch, blksize, bytesremaining, bytes;
    struct timeval start, finish;
    struct timezone tz;
    struct rx_securityClass *ssc = 0, *dsc = 0;
    int sscindex, dscindex;
    struct rx_connection *sconn = NULL, *dconn = NULL;
    struct rx_call *scall = NULL, *dcall = NULL;
    int code = 0, fetchcode, storecode, printcallerrs = 0;
    int slcl = 0, dlcl = 0, unlock = 0;
    int sfd = 0, dfd = 0, unauth = 0;

    struct AFSCBFids theFids;
    struct AFSCBs theCBs;


    blksize = 8 * 1024;

    while ((ch = getopt(argc, argv, "iouUb:")) != -1) {
	switch (ch) {
	case 'b':
	    blksize = atoi(optarg);
	    break;
	case 'i':
	    slcl = 1;
	    break;
	case 'o':
	    dlcl = 1;
	    break;
	case 'u':
	    unauth = 1;
	    break;
	case 'U':
	    unlock = 1;
	    break;
	default:
	    printf("Unknown option '%c'\n", ch);
	    exit(1);
	}
    }


    if (argc - optind + unlock < 2) {
	fprintf(stderr,
		"Usage: afscp [-i|-o]] [-b xfersz] [-u] [-U] source [dest]\n");
	fprintf(stderr, "  -b   Set block size\n");
	fprintf(stderr, "  -i   Source is local (copy into AFS)\n");
	fprintf(stderr, "  -o   Dest is local (copy out of AFS)\n");
	fprintf(stderr, "  -u   Run unauthenticated\n");
	fprintf(stderr, "  -U   Send an unlock request for source. (dest path not required)\n");
	fprintf(stderr, "source and dest can be paths or specified as:\n");
	fprintf(stderr, "     @afs:cellname:servername:volume:vnode:uniq\n");
	exit(1);
    }
    srcf = argv[optind++];
    if (!unlock) {
	destpath = argv[optind++];
	destd = strdup(destpath);
	if (!destd) {
	    perror("strdup");
	    exit(1);
	}
	if ((destf = strrchr(destd, '/'))) {
	    *destf++ = 0;
	} else {
	    destf = destd;
	    destd = ".";
	}
    } else if (slcl) {
	fprintf(stderr, "-i and -U cannot be used together\n");
    }

    if (!slcl && statfile(srcf, scell, &ssrv, &sf)) {
	fprintf(stderr, "Cannot get attributes of %s\n", srcf);
	exit(1);
    }
    if (!unlock && !dlcl && statfile(destd, dcell, &dsrv, &dd)) {
	fprintf(stderr, "Cannot get attributes of %s\n", destd);
	exit(1);
    }

    if ((databuffer = malloc(blksize)) == NULL) {
	perror("malloc");
	exit(1);
    }

    if (do_rx_Init())
	exit(1);

    if (start_cb_server()) {
	printf("Cannot start callback service\n");
	goto Fail_rx;
    }

    if (!slcl) {
	sscindex = scindex_RXKAD;
	if (unauth || (ssc = get_sc(scell)) == NULL) {
	    ssc = rxnull_NewClientSecurityObject();
	    sscindex = scindex_NULL;
	    /*printf("Cannot get authentication for cell %s; running unauthenticated\n", scell); */
	}
	sscindex = scindex_NULL;

	if ((sconn =
	     rx_NewConnection(ssrv, htons(AFSCONF_FILEPORT), 1, ssc,
			      sscindex))
	    == NULL) {
	    struct in_addr s;
	    s.s_addr = ssrv;
	    printf("Cannot initialize rx connection to source server (%s)\n",
		   inet_ntoa(s));
	    goto Fail_sc;
	}
    }

    if (!dlcl && !unlock) {
	if (!slcl && ssrv == dsrv) {
	    dconn = sconn;
	    dsc = NULL;
	} else {
	    if (slcl || strcmp(scell, dcell)) {
		dscindex = scindex_RXKAD;
		if (unauth || (dsc = get_sc(dcell)) == NULL) {
		    dsc = rxnull_NewClientSecurityObject();
		    dscindex = scindex_NULL;
		    /*printf("Cannot get authentication for cell %s; running unauthenticated\n", dcell); */
		}
		dscindex = scindex_NULL;
	    } else {
		dsc = ssc;
		dscindex = sscindex;
	    }

	    if ((dconn =
		 rx_NewConnection(dsrv, htons(AFSCONF_FILEPORT), 1, dsc,
				  dscindex))
		== NULL) {
		struct in_addr s;
		s.s_addr = dsrv;
		printf
		    ("Cannot initialize rx connection to dest server (%s)\n",
		     inet_ntoa(s));
		goto Fail_sconn;
	    }
	}
    }


    memset(&sst, 0, sizeof(struct AFSStoreStatus));

    if (dlcl && !unlock) {
	dfd = open(destpath, O_RDWR | O_CREAT | O_EXCL, 0666);
	if (dfd < 0 && errno == EEXIST) {
	    printf("%s already exists, overwriting\n", destpath);
	    dfd = open(destpath, O_RDWR | O_TRUNC, 0666);
	    if (dfd < 0) {
		fprintf(stderr, "Cannot open %s (%s)\n", destpath,
			afs_error_message(errno));
		goto Fail_dconn;
	    }
	} else if (dfd < 0) {
	    fprintf(stderr, "Cannot open %s (%s)\n", destpath,
		    afs_error_message(errno));
	    goto Fail_dconn;
	}
    } else if (!unlock) {
	if ((code =
	     RXAFS_CreateFile(dconn, &dd, destf, &sst, &df, &fst, &dfst, &dcb,
			      &vs))) {
	    if (code == EEXIST) {
		printf("%s already exits, overwriting\n", destpath);
		if (statfile(destpath, dcell, &dsrv, &df))
		    fprintf(stderr, "Cannot get attributes of %s\n",
			    destpath);
		else
		    code = 0;
	    } else {
		printf("Cannot create %s (%s)\n", destpath,
		       afs_error_message(code));
		if (code)
		    goto Fail_dconn;
	    }
	}
    }

    if (slcl) {
	sfd = open(srcf, O_RDONLY, 0);
	if (sfd < 0) {
	    fprintf(stderr, "Cannot open %s (%s)\n", srcf,
		    afs_error_message(errno));
	    goto Fail_dconn;
	}
	if (fstat(sfd, &statbuf) < 0) {
	    fprintf(stderr, "Cannot stat %s (%s)\n", srcf,
		    afs_error_message(errno));
	    close(sfd);
	    goto Fail_dconn;
	}
    } else {
	if ((code = RXAFS_FetchStatus(sconn, &sf, &fst, &scb, &vs))) {
	    printf("Cannot fetchstatus of %d.%d (%s)\n", sf.Volume, sf.Vnode,
		   afs_error_message(code));
	    goto Fail_dconn;
	}
    }



    if (slcl) {
	filesz = statbuf.st_size;
    } else {
	filesz = fst.Length;
    }

    printcallerrs = 0;
    fetchcode = 0;
    storecode = 0;
    if (!slcl && !unlock)
	scall = rx_NewCall(sconn);
    if (!dlcl && !unlock)
	dcall = rx_NewCall(dconn);
    gettimeofday(&start, &tz);
    if (unlock) {
	if (fst.lockCount) {
	    printf("Sending 1 unlock for %s (%d locks)\n", srcf, fst.lockCount);
	    if ((code = RXAFS_ReleaseLock(sconn, &sf, &vs))) {
		printf("Unable to unlock %s (%s)\n", srcf,
		       afs_error_message(code));
	    }
	} else {
	    printf("No locks for %s\n", srcf);
	}
	fetchcode = code;
	goto Finish;
    }

    if (!slcl) {
	if ((code = StartRXAFS_FetchData(scall, &sf, 0, filesz))) {
	    printf("Unable to fetch data from %s (%s)\n", srcf,
		   afs_error_message(code));
	    goto Fail_call;
	}
    }

    if (!dlcl) {
	if (slcl) {
	    sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
	    sst.ClientModTime = statbuf.st_mtime;
	    sst.UnixModeBits =
		statbuf.st_mode & ~(S_IFMT | S_ISUID | S_ISGID);
	} else {
	    sst.Mask = AFS_SETMODTIME | AFS_SETMODE;
	    sst.ClientModTime = fst.ClientModTime;
	    sst.UnixModeBits =
		fst.UnixModeBits & ~(S_IFMT | S_ISUID | S_ISGID);
	}

	if ((code =
	     StartRXAFS_StoreData(dcall, &df, &sst, 0, filesz, filesz))) {
	    printf("Unable to store data to %s (%s)\n", destpath,
		   afs_error_message(code));
	    goto Fail_call;
	}
    }

    if (slcl) {
	bytesremaining = statbuf.st_size;
    } else {
	rx_Read(scall, (char *)&bytesremaining, sizeof(afs_int32));
	bytesremaining = ntohl(bytesremaining);
    }

    while (bytesremaining > 0) {
	/*printf("%d bytes remaining\n",bytesremaining); */
	if (slcl) {
	    if ((bytes =
		 read(sfd, databuffer, min(blksize, bytesremaining))) <= 0) {
		fetchcode = errno;
		break;
	    }
	} else {
	    if ((bytes =
		 rx_Read(scall, databuffer,
			 min(blksize, bytesremaining))) <= 0)
		break;
	}
	if (dlcl) {
	    if (write(dfd, databuffer, bytes) != bytes) {
		storecode = errno;
		break;
	    }
	} else {
	    if (rx_Write(dcall, databuffer, bytes) != bytes)
		break;
	}
	bytesremaining -= bytes;
	/*printf("%d bytes copied\n",bytes); */
    }


    if (bytesremaining > 0) {
	printf("Some network error occured while copying data\n");
	goto Fail_call;
    }

    if (!slcl)
	fetchcode = EndRXAFS_FetchData(scall, &fst, &scb, &vs);
    if (!dlcl)
	storecode = EndRXAFS_StoreData(dcall, &fst, &vs);
    printcallerrs = 1;
  Fail_call:

    if (slcl) {
	if (close(sfd) && !fetchcode)
	    fetchcode = errno;
    } else {
	fetchcode = rx_EndCall(scall, fetchcode);
    }
    if (fetchcode && printcallerrs)
	printf("Error returned from fetch: %s\n", afs_error_message(fetchcode));

    if (dlcl) {
	if (close(dfd) && !storecode)
	    storecode = errno;
    } else if (!unlock) {
	storecode = rx_EndCall(dcall, storecode);
    }
    if (storecode && printcallerrs)
	printf("Error returned from store: %s\n", afs_error_message(storecode));
Finish:
    gettimeofday(&finish, &tz);

    if (!slcl) {
	theFids.AFSCBFids_len = 1;
	theFids.AFSCBFids_val = &sf;
	theCBs.AFSCBs_len = 1;
	theCBs.AFSCBs_val = &scb;
	scb.CallBackType = CB_DROPPED;
	if ((code = RXAFS_GiveUpCallBacks(sconn, &theFids, &theCBs)))
	    printf("Could not give up source callback: %s\n",
		   afs_error_message(code));
    }

    if (!dlcl) {
	theFids.AFSCBFids_len = 1;
	theFids.AFSCBFids_val = &df;
	theCBs.AFSCBs_len = 1;
	theCBs.AFSCBs_val = &dcb;
	dcb.CallBackType = CB_DROPPED;
	if ((code = RXAFS_GiveUpCallBacks(dconn, &theFids, &theCBs)))
	    printf("Could not give up target callback: %s\n",
		   afs_error_message(code));
    }

    if (code == 0)
	code = storecode;
    if (code == 0)
	code = fetchcode;

  Fail_dconn:
    if (!dlcl && !unlock && (slcl || dconn != sconn))
	rx_DestroyConnection(dconn);
  Fail_sconn:
    if (!slcl)
	rx_DestroyConnection(sconn);
  Fail_sc:
    if (dsc && dsc != ssc)
	RXS_Close(dsc);
    if (ssc)
	RXS_Close(ssc);
  Fail_rx:
    rx_Finalize();

    free(databuffer);
    if (printcallerrs && !unlock) {
	double rate, size, time;
	if (finish.tv_sec == start.tv_sec) {
	    printf("Copied %d bytes in %d microseconds\n", filesz,
		   (int)(finish.tv_usec - start.tv_usec));
	} else {
	    printf("Copied %d bytes in %d seconds\n", filesz,
		   (int)(finish.tv_sec - start.tv_sec));
	}

	size = filesz / 1024.0;
	time =
	    finish.tv_sec - start.tv_sec + (finish.tv_usec -
					    start.tv_usec) / 1e+06;
	rate = size / time;
	printf("Transfer rate %g Kbytes/sec\n", rate);

    }

    exit(code != 0);
}
Exemplo n.º 16
0
/**
 * Connects to a server by it's server address.
 *
 * @param sap Server address.
 * @param aport Server port.
 * @param acell
 * @param tu Connect as this user.
 * @param force_if_down
 * @param create
 * @param locktype Specifies type of lock to be used for this function.
 *
 * @return The new connection.
 */
struct afs_conn *
afs_ConnBySA(struct srvAddr *sap, unsigned short aport, afs_int32 acell,
	     struct unixuser *tu, int force_if_down, afs_int32 create,
	     afs_int32 locktype)
{
    struct afs_conn *tc = 0;
    struct rx_securityClass *csec;	/*Security class object */
    int isec;			/*Security index */
    int service;

    if (!sap || ((sap->sa_flags & SRVR_ISDOWN) && !force_if_down)) {
	/* sa is known down, and we don't want to force it.  */
	return NULL;
    }

    ObtainSharedLock(&afs_xconn, 15);
    /* Get conn by port and user. */
    for (tc = sap->conns; tc; tc = tc->next) {
	if (tc->user == tu && tc->port == aport) {
	    break;
	}
    }

    if (!tc && !create) {
	/* Not found and can't create a new one. */
	ReleaseSharedLock(&afs_xconn);
	return NULL;
    }
    
    if (AFS_IS_DISCONNECTED && !AFS_IN_SYNC) {
        afs_warnuser("afs_ConnBySA: disconnected\n");
        ReleaseSharedLock(&afs_xconn);
        return NULL;
    }

    if (!tc) {
	/* No such connection structure exists.  Create one and splice it in.
	 * Make sure the server record has been marked as used (for the purposes
	 * of calculating up & down times, it's now considered to be an
	 * ``active'' server).  Also make sure the server's lastUpdateEvalTime
	 * gets set, marking the time of its ``birth''.
	 */
	UpgradeSToWLock(&afs_xconn, 37);
	tc = (struct afs_conn *)afs_osi_Alloc(sizeof(struct afs_conn));
	memset(tc, 0, sizeof(struct afs_conn));

	tc->user = tu;
	tc->port = aport;
	tc->srvr = sap;
	tc->refCount = 0;	/* bumped below */
	tc->forceConnectFS = 1;
	tc->id = (struct rx_connection *)0;
	tc->next = sap->conns;
	sap->conns = tc;
	afs_ActivateServer(sap);

	ConvertWToSLock(&afs_xconn);
    } /* end of if (!tc) */
    tc->refCount++;

    if (tu->states & UTokensBad) {
	/* we may still have an authenticated RPC connection here,
	 * we'll have to create a new, unauthenticated, connection.
	 * Perhaps a better way to do this would be to set
	 * conn->forceConnectFS on all conns when the token first goes
	 * bad, but that's somewhat trickier, due to locking
	 * constraints (though not impossible).
	 */
	if (tc->id && (rx_SecurityClassOf(tc->id) != 0)) {
	    tc->forceConnectFS = 1;	/* force recreation of connection */
	}
	tu->vid = UNDEFVID;	/* forcibly disconnect the authentication info */
    }

    if (tc->forceConnectFS) {
	UpgradeSToWLock(&afs_xconn, 38);
	csec = (struct rx_securityClass *)0;
	if (tc->id) {
	    AFS_GUNLOCK();
	    rx_DestroyConnection(tc->id);
	    AFS_GLOCK();
	}
	/*
	 * Stupid hack to determine if using vldb service or file system
	 * service.
	 */
	if (aport == sap->server->cell->vlport)
	    service = 52;
	else
	    service = 1;
	isec = 0;

	csec = afs_pickSecurityObject(tc, &isec);

	AFS_GUNLOCK();
	tc->id = rx_NewConnection(sap->sa_ip, aport, service, csec, isec);
	AFS_GLOCK();
	if (service == 52) {
	    rx_SetConnHardDeadTime(tc->id, afs_rx_harddead);
	}
	/* set to a RX_CALL_TIMEOUT error to allow MTU retry to trigger */
	rx_SetServerConnIdleDeadErr(tc->id, RX_CALL_DEAD);
	rx_SetConnIdleDeadTime(tc->id, afs_rx_idledead);
	rx_SetMsgsizeRetryErr(tc->id, RX_MSGSIZE);

	/*
	 * Only do this for the base connection, not per-user.
	 * Will need to be revisited if/when CB gets security.
	 */
	if ((isec == 0) && (service != 52) && !(tu->states & UTokensBad) &&
	    (tu->vid == UNDEFVID))
	    rx_SetConnSecondsUntilNatPing(tc->id, 20);

	tc->forceConnectFS = 0;	/* apparently we're appropriately connected now */
	if (csec)
	    rxs_Release(csec);
	ConvertWToSLock(&afs_xconn);
    } /* end of if (tc->forceConnectFS)*/

    ReleaseSharedLock(&afs_xconn);
    return tc;
}
Exemplo n.º 17
0
int
fsprobe_Cleanup(int a_releaseMem)
{				/*fsprobe_Cleanup */

    static char rn[] = "fsprobe_Cleanup";	/*Routine name */
    int code;			/*Return code */
    int conn_idx;		/*Current connection index */
    struct fsprobe_ConnectionInfo *curr_conn;	/*Ptr to fsprobe connection */

    /*
     * Assume the best, but check the worst.
     */
    if (!fsprobe_initflag) {
	fprintf(stderr, "[%s] Refused; module not initialized\n", rn);
	return (-1);
    } else
	code = 0;

    /*
     * Take care of all Rx connections first.  Check to see that the
     * server count is a legal value.
     */
    if (fsprobe_numServers <= 0) {
	fprintf(stderr,
		"[%s] Illegal number of servers to clean up (fsprobe_numServers = %d)\n",
		rn, fsprobe_numServers);
	code = -1;
    } else {
	if (fsprobe_ConnInfo != (struct fsprobe_ConnectionInfo *)0) {
	    /*
	     * The fsprobe connection structure array exists.  Go through it
	     * and close up any Rx connections it holds.
	     */
	    curr_conn = fsprobe_ConnInfo;
	    for (conn_idx = 0; conn_idx < fsprobe_numServers; conn_idx++) {
		if (curr_conn->rxconn != (struct rx_connection *)0) {
		    rx_DestroyConnection(curr_conn->rxconn);
		    curr_conn->rxconn = (struct rx_connection *)0;
		}
		if (curr_conn->rxVolconn != (struct rx_connection *)0) {
		    rx_DestroyConnection(curr_conn->rxVolconn);
		    curr_conn->rxVolconn = (struct rx_connection *)0;
		}
		curr_conn++;
	    }			/*for each fsprobe connection */
	}			/*fsprobe connection structure exists */
    }				/*Legal number of servers */

    /*
     * Now, release all the space we've allocated, if asked to.
     */
    if (a_releaseMem) {
	if (fsprobe_ConnInfo != (struct fsprobe_ConnectionInfo *)0)
	    free(fsprobe_ConnInfo);
	if (fsprobe_Results.stats != NULL)
	    free(fsprobe_Results.stats);
	if (fsprobe_Results.probeOK != (int *)0)
	    free(fsprobe_Results.probeOK);
    }

    /*
     * Return the news, whatever it is.
     */
    return (code);

}				/*fsprobe_Cleanup */
Exemplo n.º 18
0
int
ubik_ClientInit(struct rx_connection **serverconns,
		struct ubik_client **aclient)
{
    int i, j;
    int count;
    int offset;
    struct ubik_client *tc;

    initialize_U_error_table();

    if (*aclient) {		/* the application is doing a re-initialization */
	LOCK_UBIK_CLIENT((*aclient));
	/* this is an important defensive check */
	if (!((*aclient)->initializationState)) {
	    UNLOCK_UBIK_CLIENT((*aclient));
	    return UREINITIALIZE;
	}

	/* release all existing connections */
	for (tc = *aclient, i = 0; i < MAXSERVERS; i++) {
	    struct rx_connection *rxConn = ubik_GetRPCConn(tc, i);
	    if (rxConn == 0)
		break;
#ifdef AFS_PTHREAD_ENV
	    rx_ReleaseCachedConnection(rxConn);
#else
	    rx_DestroyConnection(rxConn);
#endif
	}
	UNLOCK_UBIK_CLIENT((*aclient));
#ifdef AFS_PTHREAD_ENV
	if (pthread_mutex_destroy(&((*aclient)->cm)))
	    return UMUTEXDESTROY;
#endif
    } else {
	tc = (struct ubik_client *)malloc(sizeof(struct ubik_client));
    }
    if (tc == NULL)
	return UNOMEM;
    memset((void *)tc, 0, sizeof(*tc));
#ifdef AFS_PTHREAD_ENV
    if (pthread_mutex_init(&(tc->cm), (const pthread_mutexattr_t *)0)) {
	return UMUTEXINIT;
    }
#endif
    tc->initializationState = ++ubik_initializationState;

    /* first count the # of server conns so we can randomize properly */
    count = 0;
    for (i = 0; i < MAXSERVERS; i++) {
	if (serverconns[i] == (struct rx_connection *)0)
	    break;
	count++;
    }

    /* here count is the # of servers we're actually passed in.  Compute
     * offset, a number between 0..count-1, where we'll start copying from the
     * client-provided array. */
    for (i = 0; i < count; i++) {
	offset = afs_randomMod15() % count;
	for (j = abs(offset); j < 2 * count; j++) {
	    if (!tc->conns[abs(j % count)]) {
		tc->conns[abs(j % count)] = serverconns[i];
		break;
	    }
	}
    }

    *aclient = tc;
    return 0;
}