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 */
#elif defined(AFS_AMD64_LINUX20_ENV)
if (current->thread.flags & THREAD_IA32)
#elif defined(AFS_PPC64_LINUX20_ENV)
- if (current->thread.flags & PPC_FLAG_32BIT)
+#ifdef AFS_PPC64_LINUX26_ENV
+ if (current->thread_info->flags & _TIF_32BIT)
+#else /*Linux 2.6*/
+ if (current->thread.flags & PPC_FLAG_32BIT)
+#endif
+#elif defined(AFS_S390X_LINUX20_ENV)
+ if (current->thread.flags & S390_FLAG_31BIT)
#else
#error Not done for this linux type
#endif
unsigned int com;
unsigned long arg;
};
-asmlinkage int
+int
afs_xioctl(struct inode *ip, struct file *fp, unsigned int com,
unsigned long arg)
{
#endif
}
+#define MAXPIOCTLTOKENLEN \
+(3*sizeof(afs_int32)+MAXKTCTICKETLEN+sizeof(struct ClearToken)+MAXKTCREALMLEN)
int
afs_HandlePioctl(struct vnode *avp, afs_int32 acom,
struct vrequest treq;
register afs_int32 code;
register afs_int32 function, device;
- afs_int32 inSize, outSize;
+ afs_int32 inSize, outSize, outSizeMax;
char *inData, *outData;
int (*(*pioctlSw)) ();
int pioctlSwSize;
inSize = ablob->in_size;
/* Do all range checking before continuing */
- if (inSize >= PIGGYSIZE || inSize < 0 || ablob->out_size < 0)
+ if (inSize > MAXPIOCTLTOKENLEN || inSize < 0 || ablob->out_size < 0)
return E2BIG;
- inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ if (inSize > AFS_LRALLOCSIZ) {
+ inData = osi_AllocLargeSpace(inSize+1);
+ } else {
+ inData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ }
+ if (!inData)
+ return ENOMEM;
if (inSize > 0) {
AFS_COPYIN(ablob->in, inData, inSize, code);
inData[inSize] = '\0';
} else
code = 0;
if (code) {
- osi_FreeLargeSpace(inData);
- afs_PutFakeStat(&fakestate);
- return code;
+ if (inSize > AFS_LRALLOCSIZ) {
+ osi_Free(inData, inSize+1);
+ } else {
+ osi_FreeLargeSpace(inData);
+ }
+ afs_PutFakeStat(&fakestate);
+ return code;
+ }
+ if (function == 8 && device == 'V') { /* PGetTokens */
+ outSizeMax = MAXPIOCTLTOKENLEN;
+ outData = osi_Alloc(outSizeMax);
+ } else {
+ outSizeMax = AFS_LRALLOCSIZ;
+ outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
+ }
+ if (!outData) {
+ if (inSize > AFS_LRALLOCSIZ) {
+ osi_Free(inData, inSize+1);
+ } else {
+ osi_FreeLargeSpace(inData);
+ }
+ return ENOMEM;
}
- outData = osi_AllocLargeSpace(AFS_LRALLOCSIZ);
outSize = 0;
code =
(*pioctlSw[function]) (avc, function, &treq, inData, outData, inSize,
&outSize, acred);
- osi_FreeLargeSpace(inData);
+ if (inSize > AFS_LRALLOCSIZ) {
+ osi_Free(inData, inSize+1);
+ } else {
+ osi_FreeLargeSpace(inData);
+ }
if (code == 0 && ablob->out_size > 0) {
- if (outSize > ablob->out_size)
- outSize = ablob->out_size;
- if (outSize >= PIGGYSIZE)
- code = E2BIG;
- else if (outSize) {
- outData[outSize] = '\0';
- AFS_COPYOUT(outData, ablob->out, outSize, code);
- }
+ if (outSize > ablob->out_size) {
+ code = E2BIG; /* data wont fit in user buffer */
+ } else if (outSize) {
+ AFS_COPYOUT(outData, ablob->out, outSize, code);
+ }
+ }
+ if (outSizeMax > AFS_LRALLOCSIZ) {
+ osi_Free(outData, outSizeMax);
+ } else {
+ osi_FreeLargeSpace(outData);
}
- osi_FreeLargeSpace(outData);
afs_PutFakeStat(&fakestate);
return afs_CheckCode(code, &treq, 41);
}
memcpy((char *)&i, ain, sizeof(afs_int32));
ain += sizeof(afs_int32);
stp = ain; /* remember where the ticket is */
- if (i < 0 || i > 2000)
+ if (i < 0 || i > MAXKTCTICKETLEN)
return EINVAL; /* malloc may fail */
- if (i > MAXKTCTICKETLEN)
- return EINVAL;
stLen = i;
ain += i; /* skip over ticket */
memcpy((char *)&i, ain, sizeof(afs_int32));
XSTATS_DECLS;
AFS_STATCNT(PSetVolumeStatus);
- if (!avc)
- return EINVAL;
+ if (!avc) {
+ code = EINVAL;
+ goto out;
+ }
tvp = afs_GetVolume(&avc->fid, areq, READ_LOCK);
if (tvp) {
if (tvp->states & (VRO | VBackup)) {
afs_PutVolume(tvp, READ_LOCK);
- return EROFS;
+ code = EROFS;
+ goto out;
}
afs_PutVolume(tvp, READ_LOCK);
- } else
- return ENODEV;
+ } else {
+ code = ENODEV;
+ goto out;
+ }
/* Copy the junk out, using cp as a roving pointer. */
cp = ain;
memcpy((char *)&volstat, cp, sizeof(AFSFetchVolumeStatus));
cp += sizeof(AFSFetchVolumeStatus);
- if (strlen(cp) >= sizeof(volName))
- return E2BIG;
+ if (strlen(cp) >= sizeof(volName)) {
+ code = E2BIG;
+ goto out;
+ }
strcpy(volName, cp);
cp += strlen(volName) + 1;
- if (strlen(cp) >= sizeof(offLineMsg))
- return E2BIG;
+ if (strlen(cp) >= sizeof(offLineMsg)) {
+ code = E2BIG;
+ goto out;
+ }
strcpy(offLineMsg, cp);
cp += strlen(offLineMsg) + 1;
- if (strlen(cp) >= sizeof(motd))
- return E2BIG;
+ if (strlen(cp) >= sizeof(motd)) {
+ code = E2BIG;
+ goto out;
+ }
strcpy(motd, cp);
storeStat.Mask = 0;
if (volstat.MinQuota != -1) {
Check_AtSys(avc, ain, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
+ code = afs_dir_Lookup(&tdc->f, sysState.name, &tfid.Fid);
} while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc); /* we're done with the data */
Check_AtSys(avc, ain, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
+ code = afs_dir_Lookup(&tdc->f, sysState.name, &tfid.Fid);
} while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
ReleaseReadLock(&tdc->lock);
bufp = sysState.name;
ObtainWriteLock(&tdc->lock, 661);
if (afs_LocalHero(avc, tdc, &OutDirStatus, 1)) {
/* we can do it locally */
- code = afs_dir_Delete(&tdc->f.inode, bufp);
+ code = afs_dir_Delete(&tdc->f, bufp);
if (code) {
ZapDCE(tdc); /* surprise error -- invalid value */
- DZap(&tdc->f.inode);
+ DZap(&tdc->f);
}
}
ReleaseWriteLock(&tdc->lock);
/* for the reader. */
DECL_PIOCTL(PSetSysName)
{
- char *cp, inname[MAXSYSNAME], outname[MAXSYSNAME];
+ char *cp, *cp2, inname[MAXSYSNAME], outname[MAXSYSNAME];
int setsysname, foundname = 0;
register struct afs_exporter *exporter;
register struct unixuser *au;
register afs_int32 pag, error;
- int t, count;
-
+ int t, count, num = 0;
+ char **sysnamelist[MAXSYSNAME];
AFS_STATCNT(PSetSysName);
if (!afs_globalVFS) {
/* Check my args */
if (setsysname < 0 || setsysname > MAXNUMSYSNAMES)
return EINVAL;
+ cp2 = ain;
for (cp = ain, count = 0; count < setsysname; count++) {
/* won't go past end of ain since maxsysname*num < ain length */
t = strlen(cp);
}
/* args ok */
- /* inname gets first entry in case we're being a translater */
+ /* inname gets first entry in case we're being a translator */
t = strlen(ain);
memcpy(inname, ain, t + 1); /* include terminating null */
ain += t + 1;
+ num = count;
}
if ((*acred)->cr_gid == RMTUSER_REQ) { /* Handles all exporters */
pag = PagInCred(*acred);
afs_PutUser(au, READ_LOCK);
return EINVAL; /* Better than panicing */
}
- error = EXP_SYSNAME(exporter, (setsysname ? inname : NULL), outname);
+ error = EXP_SYSNAME(exporter, (setsysname ? cp2 : NULL), sysnamelist,
+ &num);
if (error) {
if (error == ENODEV)
foundname = 0; /* sysname not set yet! */
afs_PutUser(au, READ_LOCK);
return error;
}
- } else
- foundname = 1;
+ } else {
+ foundname = num;
+ strcpy(outname, (*sysnamelist)[0]);
+ }
afs_PutUser(au, READ_LOCK);
} else {
-
/* Not xlating, so local case */
if (!afs_sysname)
osi_Panic("PSetSysName: !afs_sysname\n");
if (!setsysname) { /* user just wants the info */
strcpy(outname, afs_sysname);
foundname = afs_sysnamecount;
+ *sysnamelist = afs_sysnamelist;
} else { /* Local guy; only root can change sysname */
if (!afs_osi_suser(*acred))
return EACCES;
strcpy(cp, outname); /* ... the entry, ... */
cp += strlen(outname) + 1;
for (count = 1; count < foundname; ++count) { /* ... or list. */
- /* Note: we don't support @sys lists for exporters */
- if (!afs_sysnamelist[count])
+ if (!(*sysnamelist)[count])
osi_Panic
("PSetSysName: no afs_sysnamelist entry to read\n");
- t = strlen(afs_sysnamelist[count]);
+ t = strlen((*sysnamelist)[count]);
if (t >= MAXSYSNAME)
osi_Panic("PSetSysName: sysname entry garbled\n");
- strcpy(cp, afs_sysnamelist[count]);
+ strcpy(cp, (*sysnamelist)[count]);
cp += t + 1;
}
}
Check_AtSys(avc, ain, &sysState, areq);
ObtainReadLock(&tdc->lock);
do {
- code = afs_dir_Lookup(&tdc->f.inode, sysState.name, &tfid.Fid);
+ code = afs_dir_Lookup(&tdc->f, sysState.name, &tfid.Fid);
} while (code == ENOENT && Next_AtSys(avc, areq, &sysState));
ReleaseReadLock(&tdc->lock);
afs_PutDCache(tdc); /* we're done with the data */
}
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) || afs_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;
+}