DECL_PIOCTL(PRxStatPeer);
DECL_PIOCTL(PPrefetchFromTape);
DECL_PIOCTL(PResidencyCmd);
+DECL_PIOCTL(PCallBackAddr);
/*
* A macro that says whether we're going to need HandleClientContext().
PBogus, /* 0 */
PNewAlias, /* 1 -- create new cell alias */
PListAliases, /* 2 -- list cell aliases */
+ PCallBackAddr, /* 3 -- request addr for callback rxcon */
};
#define PSetClientContext 99 /* Special pioctl to setup caller's creds */
}
return code;
}
+
+DECL_PIOCTL(PCallBackAddr)
+{
+#ifndef UKERNEL
+ afs_uint32 addr, code;
+ int srvAddrCount;
+ struct server *ts;
+ struct srvAddr *sa;
+ struct conn *tc;
+ afs_int32 i, j;
+ struct unixuser *tu;
+ struct srvAddr **addrs;
+
+ /*AFS_STATCNT(PCallBackAddr);*/
+ if ( !afs_resourceinit_flag ) /* afs deamons havn't started yet */
+ return EIO; /* Inappropriate ioctl for device */
+
+ if (!afs_osi_suser(acred))
+ return EACCES;
+
+ if ( ainSize < sizeof(afs_int32) )
+ return EINVAL;
+
+ memcpy(&addr, ain, sizeof(afs_int32));
+
+ ObtainReadLock(&afs_xinterface);
+ for ( i=0; (unsigned short)i < afs_cb_interface.numberOfInterfaces; i++) {
+ if (afs_cb_interface.addr_in[i] == addr) break;
+ }
+
+ ReleaseWriteLock(&afs_xinterface);
+
+ if (afs_cb_interface.addr_in[i] != addr) return EINVAL;
+
+ ObtainReadLock(&afs_xserver); /* Necessary? */
+ ObtainReadLock(&afs_xsrvAddr);
+
+ srvAddrCount = 0;
+ for (i=0;i<NSERVERS;i++) {
+ for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
+ srvAddrCount++;
+ }
+ }
+
+ addrs = afs_osi_Alloc(srvAddrCount * sizeof(*addrs));
+ j = 0;
+ for (i=0;i<NSERVERS;i++) {
+ for (sa = afs_srvAddrs[i]; sa; sa = sa->next_bkt) {
+ if (j >= srvAddrCount) break;
+ addrs[j++] = sa;
+ }
+ }
+
+ ReleaseReadLock(&afs_xsrvAddr);
+ ReleaseReadLock(&afs_xserver);
+
+ for (i=0; i<j; i++) {
+ sa = addrs[i];
+ ts = sa->server;
+ if (!ts)
+ continue;
+
+ /* vlserver has no callback conn */
+ if (sa->sa_portal == AFS_VLPORT) {
+ continue;
+ }
+
+ if (!ts->cell) /* not really an active server, anyway, it must */
+ continue; /* have just been added by setsprefs */
+
+ /* get a connection, even if host is down; bumps conn ref count */
+ tu = afs_GetUser(areq->uid, ts->cell->cellNum, SHARED_LOCK);
+ tc = afs_ConnBySA(sa, ts->cell->fsport, ts->cell->cellNum, tu, 1/*force*/, 1/*create*/, SHARED_LOCK);
+ afs_PutUser(tu, SHARED_LOCK);
+ if (!tc) continue;
+
+ if ((sa->sa_flags & SRVADDR_ISDOWN) || HaveCallBacksFrom(ts)) {
+ if (sa->sa_flags & SRVADDR_ISDOWN) {
+ rx_SetConnDeadTime(tc->id, 3);
+ }
+
+#ifdef RX_ENABLE_LOCKS
+ AFS_GUNLOCK();
+#endif /* RX_ENABLE_LOCKS */
+ code = RXAFS_CallBackRxConnAddr(tc->id, &addr);
+#ifdef RX_ENABLE_LOCKS
+ AFS_GLOCK();
+#endif /* RX_ENABLE_LOCKS */
+ }
+ afs_PutConn(tc, SHARED_LOCK); /* done with it now */
+ } /* Outer loop over addrs */
+#endif /* UKERNEL */
+ return 0;
+}
/* Coordinated 'C' pioctl's */
#define VIOC_NEWALIAS _CVICEIOCTL(1) /* create new cell alias */
#define VIOC_GETALIAS _CVICEIOCTL(2) /* get alias info */
+#define VIOC_CBADDR _CVICEIOCTL(3) /* push callback addr */
#endif /* AFS_VENUS_H */
GetCapabilities(
Capabilities *capabilities
) = 65540;
+
+CallBackRxConnAddr(
+ IN afs_int32 *addr
+) = 65541;
return 0;
}
+static int
+CallBackRxConnCmd(struct cmd_syndesc *as)
+{
+ afs_int32 code;
+ struct ViceIoctl blob;
+ struct cmd_item *ti;
+ afs_int32 hostAddr;
+ struct hostent *thp;
+ char *tp;
+ int setp;
+
+ ti = as->parms[0].items;
+ setp = 1;
+ if (ti) {
+ thp = hostutil_GetHostByName(ti->data);
+ if (!thp) {
+ fprintf(stderr, "host %s not found in host table.\n", ti->data);
+ return 1;
+ }
+ else memcpy(&hostAddr, thp->h_addr, sizeof(afs_int32));
+ } else {
+ hostAddr = 0; /* means don't set host */
+ setp = 0; /* aren't setting host */
+ }
+
+ /* now do operation */
+ blob.in_size = sizeof(afs_int32);
+ blob.out_size = sizeof(afs_int32);
+ blob.in = (char *) &hostAddr;
+ blob.out = (char *) &hostAddr;
+
+ code = pioctl(0, VIOC_CBADDR, &blob, 1);
+ if (code < 0) {
+ Die(errno, 0);
+ return 1;
+ }
+ return 0;
+}
+
static int
NewCellCmd(struct cmd_syndesc *as)
{
cmd_AddParm(ts, "-disable", CMD_FLAG, CMD_OPTIONAL, "Disable RX stats");
cmd_AddParm(ts, "-clear", CMD_FLAG, CMD_OPTIONAL, "Clear RX stats");
+ ts = cmd_CreateSyntax("setcbaddr", CallBackRxConnCmd, 0, "configure callback connection address");
+ cmd_AddParm(ts, "-addr", CMD_SINGLE, CMD_OPTIONAL, "host name or address");
+
code = cmd_Dispatch(argc, argv);
if (rxInitDone)
rx_Finalize();
return 0;
}
+
sys2et[EMEDIUMTYPE] = UAEMEDIUMTYPE;
}
+afs_int32
+SRXAFS_CallBackRxConnAddr (struct rx_call * acall, afs_int32 *addr)
+{
+ Error errorCode = 0;
+ struct host *thost;
+ struct client *tclient;
+ static struct rx_securityClass *sc = 0;
+ int i,j;
+ struct rx_connection *tcon;
+ struct rx_connection *conn;
+
+ if (errorCode = CallPreamble(acall, ACTIVECALL, &tcon))
+ goto Bad_CallBackRxConnAddr1;
+
+#ifndef __EXPERIMENTAL_CALLBACK_CONN_MOVING
+ errorCode = 1;
+#else
+
+ H_LOCK
+ tclient = h_FindClient_r(tcon);
+ thost = tclient->host;
+
+ /* nothing more can be done */
+ if ( !thost->interface )
+ goto Bad_CallBackRxConnAddr;
+
+ assert(thost->interface->numberOfInterfaces > 0 );
+
+ /* the only address is the primary interface */
+ /* can't change when there's only 1 address, anyway */
+ if ( thost->interface->numberOfInterfaces == 1 )
+ goto Bad_CallBackRxConnAddr;
+
+ /* initialise a security object only once */
+ if ( !sc )
+ sc = (struct rx_securityClass *) rxnull_NewClientSecurityObject();
+
+ for ( i=0; i < thost->interface->numberOfInterfaces; i++)
+ {
+ if ( *addr == thost->interface->addr[i] ) {
+ break;
+ }
+ }
+
+ if ( *addr != thost->interface->addr[i] )
+ goto Bad_CallBackRxConnAddr;
+
+ conn = rx_NewConnection (thost->interface->addr[i],
+ thost->port, 1, sc, 0);
+ rx_SetConnDeadTime(conn, 2);
+ rx_SetConnHardDeadTime(conn, AFS_HARDDEADTIME);
+ H_UNLOCK
+ errorCode = RXAFSCB_Probe(conn);
+ H_LOCK
+ if (!errorCode) {
+ if ( thost->callback_rxcon )
+ rx_DestroyConnection(thost->callback_rxcon);
+ thost->callback_rxcon = conn;
+ thost->host = addr;
+ rx_SetConnDeadTime(thost->callback_rxcon, 50);
+ rx_SetConnHardDeadTime(thost->callback_rxcon, AFS_HARDDEADTIME);
+ H_UNLOCK;
+ errorCode = CallPostamble(tcon, errorCode);
+ return errorCode;
+ } else {
+ rx_DestroyConnection(conn);
+ }
+#endif
+
+ Bad_CallBackRxConnAddr:
+ H_UNLOCK;
+ errorCode = CallPostamble(tcon, errorCode);
+ Bad_CallBackRxConnAddr1:
+ return errorCode; /* failure */
+}
+
afs_int32
sys_error_to_et(afs_int32 in)
{