/*! * \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;
/** * 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 */
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 */
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 }
/*! * \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; }
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); }
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; }
/*! * \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; }
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; }
/** * 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; }
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 */ }
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 */ }
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; }
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); }
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); }
/** * 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; }
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 */
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; }