static void rpc2_ProcessPacket(int fd) { RPC2_PacketBuffer *pb = NULL; struct timeval tv; int rc; /* We are guaranteed that there is a packet in the socket buffer at this point */ RPC2_AllocBuffer(RPC2_MAXPACKETSIZE - sizeof(RPC2_PacketBuffer), &pb); assert(pb != NULL); assert(pb->Prefix.LE.Queue == &rpc2_PBList); if (rpc2_RecvPacket(fd, pb) < 0) { say(9, RPC2_DebugLevel, "Recv error, ignoring.\n"); RPC2_FreeBuffer(&pb); return; } #ifdef RPC2DEBUG if (RPC2_DebugLevel > 9) { fprintf(rpc2_tracefile, "Packet received from "); rpc2_printaddrinfo(pb->Prefix.PeerAddr, rpc2_tracefile); if (pb->Prefix.sa && pb->Prefix.sa->decrypt) fprintf(rpc2_tracefile, " (secure)"); fprintf(rpc2_tracefile, "\n"); } #endif if (pb->Prefix.LengthOfPacket < (ssize_t)sizeof(struct RPC2_PacketHeader)) { /* avoid memory reference errors */ BOGUS(pb, "Runt packet\n"); return; } rc = LUA_fail_delay(pb->Prefix.PeerAddr, pb, 0, &tv); if (rc == -1) { say(9, RPC2_DebugLevel, "Dropping incoming packet\n"); RPC2_FreeBuffer(&pb); return; } if (rc && rpc2_DelayedRecv(pb, &tv)) { return; } /* delay */ DispatchPacket(pb); }
static RPC2_PacketBuffer *ShrinkPacket(RPC2_PacketBuffer *pb) { RPC2_PacketBuffer *pb2 = NULL; size_t len = pb->Prefix.LengthOfPacket - sizeof(struct RPC2_PacketHeader); if (pb->Prefix.LengthOfPacket > MEDIUMPACKET) return pb; RPC2_AllocBuffer(len, &pb2); if (!pb2) return pb; pb2->Prefix.PeerAddr = pb->Prefix.PeerAddr; pb->Prefix.PeerAddr = NULL; pb2->Prefix.sa = pb->Prefix.sa; pb2->Prefix.RecvStamp = pb->Prefix.RecvStamp; pb2->Prefix.LengthOfPacket = pb->Prefix.LengthOfPacket; memcpy(&pb2->Header, &pb->Header, pb->Prefix.LengthOfPacket); RPC2_FreeBuffer(&pb); return (pb2); }
static void SendBusy(struct CEntry *ce, int doEncrypt) { RPC2_PacketBuffer *pb; unsigned int delta; rpc2_Sent.Busies++; RPC2_AllocBuffer(0, &pb); rpc2_InitPacket(pb, ce, 0); delta = TSDELTA(rpc2_MakeTimeStamp(), ce->RequestTime); pb->Header.TimeStamp = (unsigned int)ce->TimeStampEcho + delta; pb->Header.SeqNumber = ce->NextSeqNumber - 1; pb->Header.Opcode = RPC2_BUSY; rpc2_htonp(pb); if (doEncrypt) rpc2_ApplyE(pb, ce); rpc2_XmitPacket(pb, ce->HostInfo->Addr, 1); RPC2_FreeBuffer(&pb); }
/* Sends a NAK packet for remoteHandle on (whichHost, whichPort) pair */ static void SendNak(RPC2_PacketBuffer *pb) { RPC2_PacketBuffer *nakpb; RPC2_Handle remoteHandle = pb->Header.LocalHandle; if (pb->Header.Opcode == RPC2_NAKED) return; say(1, RPC2_DebugLevel, "Sending NAK\n"); RPC2_AllocBuffer(0, &nakpb); rpc2_InitPacket(nakpb, NULL, 0); nakpb->Prefix.sa = pb->Prefix.sa; nakpb->Header.RemoteHandle = remoteHandle; nakpb->Header.LocalHandle = -1; /* "from SocketListener" */ nakpb->Header.Opcode = RPC2_NAKED; rpc2_htonp(nakpb); /* use the same security association on which we received the packet * we're currently nak-ing */ rpc2_XmitPacket(nakpb, pb->Prefix.PeerAddr, 1); RPC2_FreeBuffer(&nakpb); rpc2_Sent.Naks++; }
long VENUS_GetMsg(RPC2_Handle _cid, RPC2_Integer *arg) { char *_ptr; long _length, _rpc2val, _code; RPC2_PacketBuffer *_rspbuffer = NULL; struct timeval _timestart, _timeend; RPC2_PacketBuffer *_reqbuffer = NULL; struct timeval *_timeout; char *_EOB; int opengate = 0; /* START_ELAPSE */ coda_CallCount[1].countent++; if (coda_ElapseSwitch) { gettimeofday(&_timestart, NULL); opengate = 1; } _length = 0; _rpc2val = RPC2_AllocBuffer(_length, &_reqbuffer); if (_rpc2val != RPC2_SUCCESS) return _rpc2val; _EOB = (char *)_reqbuffer + _reqbuffer->Prefix.BufferSize; /* Avoid compiler warnings */ _ptr = NULL; /* Generate RPC2 call */ _reqbuffer->Header.Opcode = GetMsg_OP; _rspbuffer = NULL; _timeout = NULL; _rpc2val = RPC2_MakeRPC(_cid, _reqbuffer, NULL, &_rspbuffer, _timeout, coda_EnqueueRequest); RPC2_FreeBuffer(&_reqbuffer); if (_rpc2val != RPC2_SUCCESS) { RPC2_FreeBuffer(&_rspbuffer); return _rpc2val; } if (_rspbuffer->Header.ReturnCode == RPC2_INVALIDOPCODE) { RPC2_FreeBuffer(&_rspbuffer); return RPC2_INVALIDOPCODE; } /* Unpack arguments */ _ptr = (char *)_rspbuffer->Body; _EOB = (char *)_rspbuffer + _rspbuffer->Prefix.LengthOfPacket + sizeof(struct RPC2_PacketBufferPrefix); if ( (char *)_ptr + 4 > _EOB) goto bufferoverflow; *arg = ntohl(*(RPC2_Integer *) _ptr); _ptr += 4; _code = _rspbuffer->Header.ReturnCode; RPC2_FreeBuffer(&_rspbuffer); /* END_ELAPSE */ if (opengate) { gettimeofday(&_timeend, NULL); coda_CallCount[1].tsec += _timeend.tv_sec - _timestart.tv_sec; coda_CallCount[1].tusec += _timeend.tv_usec - _timestart.tv_usec; if (coda_CallCount[1].tusec < 0) { coda_CallCount[1].tusec += 1000000; coda_CallCount[1].tsec--; } else if (coda_CallCount[1].tusec >= 1000000) { coda_CallCount[1].tusec -= 1000000; coda_CallCount[1].tsec++; } coda_CallCount[1].counttime++; } coda_CallCount[1].countexit++; return _code; bufferoverflow: fprintf(stderr,"%s:%d Buffer overflow in (un)marshalling !\n",__FILE__,__LINE__); RPC2_FreeBuffer(&_rspbuffer); return RPC2_BADDATA; }
static void ClientBody(void *arg) { RPC2_Handle thisconn; RPC2_Integer thisopcode; RPC2_PacketBuffer *request, *reply; long retcode, rpctime = 0; struct timeval t1, t2; char myprivatefile[256]; char myhashmark; RPC2_BindParms bp; SE_Descriptor sed; #define MakeTimedCall(whichse)\ if (VerboseFlag) gettimeofday(&t1, 0);\ retcode = RPC2_MakeRPC(ConnVector[thisconn].ConnHandle, request, whichse, &reply, NULL, 0);\ if (VerboseFlag) gettimeofday(&t2, 0);\ if (VerboseFlag) rpctime = ((t2.tv_sec - t1.tv_sec)*1000) + ((t2.tv_usec - t1.tv_usec)/1000); memset(&sed, 0, sizeof(SE_Descriptor)); sed.Tag = SMARTFTP; strcpy(myprivatefile, MakeName(LWP_Name())); myhashmark = NextHashMark++; LWP_DispatchProcess(); /* initial courtesy to parent */ RPC2_AllocBuffer(1000, &request); reply = NULL; ClientsReady++; LWP_WaitProcess((char *)&ClientsReady); /* wait for main() to tap me on shoulder */ while(1) { if (reply) RPC2_FreeBuffer(&reply); RanDelay(MaxThinkTime); SelectParms(&thisconn, &thisopcode); ConnVector[thisconn].Status = BUSY; request->Header.Opcode = thisopcode; if (VerboseFlag) fprintf(stderr, "Making request %d to %s for %s\n", thisopcode, ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].NameBuf); switch(thisopcode) { case 1: /* return Unix epoch time */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "Time on %s is %s (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, reply->Body, rpctime); break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); } case 2: /* square the input integer */ { uint32_t *op = (uint32_t *)request->Body; uint32_t x = (uint32_t)random() % 100; op[0] = htonl(x); request->Header.BodyLength = sizeof(uint32_t); MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) { uint32_t *ip = (uint32_t *)reply->Body; fprintf(stderr, " %s says square of %u is %u (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, x, ntohl(ip[0]), rpctime); } break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 3: /* cube the input integer */ { uint32_t *op = (uint32_t *)request->Body; uint32_t x = (uint32_t)random() % 100; op[0] = htonl(x); request->Header.BodyLength = sizeof(uint32_t); MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) { uint32_t *ip = (uint32_t *)reply->Body; fprintf(stderr, "%s says cube of %d is %u (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, x, ntohl(ip[0]), rpctime); } break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 4: /* Return your machine name */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "%s says its name is \"%s\" (%ld msecs)\n", ConnVector[thisconn].RemoteHost.Value.Name, reply->Body, rpctime); break; } else HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } case 5: /* Fetch a random file */ { if (AvoidBulk) { ConnVector[thisconn].Status = SFREE; continue; } request->Header.BodyLength = 0; sed.Value.SmartFTPD.TransmissionDirection = SERVERTOCLIENT; sed.Value.SmartFTPD.FileInfo.ByName.ProtectionBits = 0644; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, myprivatefile); if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; MakeTimedCall(&sed); if (retcode != RPC2_SUCCESS) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); break; } case 6: /* Store a random file */ { uint32_t randval; if (AvoidBulk) { ConnVector[thisconn].Status = SFREE; continue; } request->Header.BodyLength = 0; sed.Value.SmartFTPD.TransmissionDirection = CLIENTTOSERVER; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; randval = (uint32_t)random(); strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, SysFiles[randval % SysFileCount]); if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; MakeTimedCall(&sed); if (retcode != RPC2_SUCCESS) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); break; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); break; } case 7: /* Unbind */ { request->Header.BodyLength = 0; MakeTimedCall(NULL); if (retcode == RPC2_SUCCESS) { if (VerboseFlag) fprintf(stderr, "Unbound connection to %s for %s after %ld calls\n", ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].Identity.SeqBody, ConnVector[thisconn].CallsMade); assert(RPC2_Unbind(ConnVector[thisconn].ConnHandle) == RPC2_SUCCESS); } else {HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode));} ConnVector[thisconn].Status = UNBOUND; break; } case 8: /* Rebind */ { bp.SecurityLevel = ConnVector[thisconn].SecurityLevel; bp.EncryptionType = RPC2_XOR; bp.SideEffectType = SMARTFTP; bp.ClientIdent = &ConnVector[thisconn].Identity; bp.SharedSecret = &ConnVector[thisconn].Password; retcode = RPC2_NewBinding(&ConnVector[thisconn].RemoteHost, &PortId, &SubsysId, &bp, &ConnVector[thisconn].ConnHandle); if (retcode < RPC2_ELIMIT) { HandleRPCFailure(thisconn, retcode, ntohl(request->Header.Opcode)); } else { if (VerboseFlag) fprintf(stderr, "Rebound connection to %s for %s\n", ConnVector[thisconn].RemoteHost.Value.Name, ConnVector[thisconn].Identity.SeqBody); } break; } case 999: /* Quit */ { } default: /* unknown opcode */ printf("Arrrgggghhh .... bogus opcode\n"); abort(); break; } if (ConnVector[thisconn].Status == BUSY) ConnVector[thisconn].Status = SFREE; if (retcode == RPC2_CONNBUSY) continue; /* you didn't really do it */ /* Indicate progress */ ConnVector[thisconn].CallsMade++; if(ConnVector[thisconn].CallsMade % Announce == 1) { struct CVEntry *ce = &ConnVector[thisconn]; printf("\n%ld successful calls to %s for %s at %s", ce->CallsMade, ce->RemoteHost.Value.Name, ce->NameBuf, TimeNow()); PrintStats(); } else { int xx; xx = (1.0*Announce)/100.0 + 0.5; /* ceiling */ if (xx == 0 || ConnVector[thisconn].CallsMade % xx == 1) printf("%c", myhashmark); } } }
static void WorkerBody(void *arg) { long i, rc; RPC2_RequestFilter reqfilter; RPC2_PacketBuffer *InBuff, *OutBuff; RPC2_Handle workercid; char myprivatefile[256]; char myhashmark; SE_Descriptor sed; memset(&sed, 0, sizeof(SE_Descriptor)); sed.Tag = SMARTFTP; strcpy(myprivatefile, MakeName(LWP_Name())); myhashmark = NextHashMark++; LWP_DispatchProcess(); /* initial courtesy to parent */ reqfilter.FromWhom = ONESUBSYS; reqfilter.ConnOrSubsys.SubsysId = SUBSYS_SRV; assert(reqfilter.ConnOrSubsys.SubsysId != -1); reqfilter.OldOrNew = OLD; RPC2_AllocBuffer(1000, &OutBuff); InBuff = NULL; while (1) { RanDelay(MaxComputeTime); if (InBuff != NULL) RPC2_FreeBuffer(&InBuff); i = RPC2_GetRequest(&reqfilter, &workercid, &InBuff, NULL, NULL, 0, NULL); if (i != RPC2_SUCCESS) { printf("\n%s: GetRequest failed (%s) at %s", MYNAME, RPC2_ErrorMsg(i), TimeNow()); DumpAndQuit(0); } switch(InBuff->Header.Opcode) { case 1: /* return Unix epoch time */ { strcpy((char *)OutBuff->Body, TimeNow()); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(struct RPC2_PacketHeader) + strlen((char *)OutBuff->Body) + 1; break; } case 2: /* square the input integer */ { uint32_t *ip = (uint32_t *)InBuff->Body; uint32_t *op = (uint32_t *)OutBuff->Body; uint32_t x = ntohl(*ip); *op = htonl(x * x); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(RPC2_Integer); break; } case 3: /* cube the input integer */ { uint32_t *ip = (uint32_t *)InBuff->Body; uint32_t *op = (uint32_t *)OutBuff->Body; uint32_t x = ntohl(*ip); *op = htonl(x*x*x); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = sizeof(RPC2_Integer); break; } case 4: /* Return your machine name */ { gethostname((char *)OutBuff->Body, 100); OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = strlen((char *)OutBuff->Body) + 1; break; } case 5: /* Fetch a random file */ { uint32_t randval; if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; randval = (uint32_t)random(); strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, SysFiles[randval % SysFileCount]); sed.Value.SmartFTPD.TransmissionDirection = SERVERTOCLIENT; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; if ((rc = RPC2_InitSideEffect(workercid, &sed)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); continue; } if ((rc = RPC2_CheckSideEffect(workercid, &sed, SE_AWAITLOCALSTATUS)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); continue; } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); OutBuff->Header.ReturnCode = (long)sed.LocalStatus; OutBuff->Header.BodyLength = 0; break; } case 6: /* Store a random file */ { if (VerboseFlag) sed.Value.SmartFTPD.hashmark = myhashmark; else sed.Value.SmartFTPD.hashmark = 0; strcpy(sed.Value.SmartFTPD.FileInfo.ByName.LocalFileName, myprivatefile); sed.Value.SmartFTPD.FileInfo.ByName.ProtectionBits = 0644; sed.Value.SmartFTPD.TransmissionDirection = CLIENTTOSERVER; sed.Value.SmartFTPD.SeekOffset = 0; sed.Value.SmartFTPD.Tag = FILEBYNAME; if ((rc = RPC2_InitSideEffect(workercid, &sed)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); } if ((rc = RPC2_CheckSideEffect(workercid, &sed, SE_AWAITLOCALSTATUS)) != RPC2_SUCCESS) { BulkErr(workercid, &sed, rc, InBuff->Header.Opcode); } else if (VerboseFlag) fprintf(stderr, "%ld bytes transferred\n", sed.Value.SmartFTPD.BytesTransferred); OutBuff->Header.ReturnCode = (long)sed.LocalStatus; OutBuff->Header.BodyLength = 0; break; } case 7: /* Unbind */ { OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = 0; break; } case 999: /* Quit */ { OutBuff->Header.ReturnCode = RPC2_SUCCESS; OutBuff->Header.BodyLength = 0; break; } default: /* unknown opcode */ OutBuff->Header.ReturnCode = RPC2_FAIL; OutBuff->Header.BodyLength = 1 + strlen("Get your act together"); strcpy((char *)OutBuff->Body, "Get your act together"); break; } i = RPC2_SendResponse(workercid, OutBuff); if (i != RPC2_SUCCESS) { printf ("\n%s: response for opcode %d on connection %#x failed (%s) at %s", MYNAME, InBuff->Header.Opcode, workercid, RPC2_ErrorMsg(i), TimeNow()); DumpAndQuit(InBuff->Header.Opcode); } if (InBuff->Header.Opcode == 7) assert(RPC2_Unbind(workercid) == RPC2_SUCCESS); } }