First completed version of cleaned up connection object.
First testing is promising
This commit is contained in:
37
conman.c
37
conman.c
@ -2349,7 +2349,7 @@ int SCGetRunLevel(SConnection *pCon)
|
||||
return pCon->runLevel;
|
||||
}
|
||||
/*--------------------------------------------------------*/
|
||||
int SCGetIdent(SConnection *pCon)
|
||||
long SCGetIdent(SConnection *pCon)
|
||||
{
|
||||
if (!VerifyConnection(pCon)) {
|
||||
return 0;
|
||||
@ -2404,7 +2404,14 @@ char *SCGetDeviceID(SConnection *pCon)
|
||||
}
|
||||
return pCon->deviceID;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------*/
|
||||
int SCGetEnd(SConnection *pCon)
|
||||
{
|
||||
if (!VerifyConnection(pCon)) {
|
||||
return 0;
|
||||
}
|
||||
return pCon->iEnd;
|
||||
}
|
||||
/*-------------------------------------------------------*/
|
||||
void SCSetConStatus(SConnection *pCon, int conStatus)
|
||||
{
|
||||
@ -2476,4 +2483,28 @@ void SCSetGrab(SConnection *pCon, int iGrab)
|
||||
}
|
||||
pCon->iGrab = iGrab;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------*/
|
||||
void SCSetEnd(SConnection *pCon, int val)
|
||||
{
|
||||
if (!VerifyConnection(pCon)) {
|
||||
return;
|
||||
}
|
||||
pCon->iEnd = val;
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
void SCSetTelnet(SConnection *pCon, int val)
|
||||
{
|
||||
if (!VerifyConnection(pCon)) {
|
||||
return;
|
||||
}
|
||||
pCon->iTelnet = val;
|
||||
}
|
||||
/*------------------------------------------------------------*/
|
||||
void SCClose(SConnection *pCon)
|
||||
{
|
||||
if (!VerifyConnection(pCon)) {
|
||||
return;
|
||||
}
|
||||
ANETclose(pCon->sockHandle);
|
||||
pCon->iEnd = 1;
|
||||
}
|
||||
|
7
conman.h
7
conman.h
@ -86,6 +86,7 @@ SConnection *SCfindMaster(SConnection * pCon);
|
||||
int SCisConnected(SConnection * pCon);
|
||||
int VerifyConnection(SConnection * pCon);
|
||||
int SCVerifyConnection(SConnection * self);
|
||||
void SCClose(SConnection *pCon);
|
||||
/*------------------------------- tasking --------------------------------*/
|
||||
int SCTaskFunction(void *pCon);
|
||||
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
||||
@ -141,20 +142,22 @@ int SCGetOutClass(SConnection * self);
|
||||
int SCGetGrab(SConnection * pCon);
|
||||
int SCActive(SConnection * pCon);
|
||||
int SCGetRunLevel(SConnection *pCon);
|
||||
int SCGetIdent(SConnection *pCon);
|
||||
long SCGetIdent(SConnection *pCon);
|
||||
int SCGetSicsError(SConnection *pCon);
|
||||
int SCGetTransID(SConnection *pCon);
|
||||
int SCGetProtocolID(SConnection *pCon);
|
||||
int SCGetSockHandle(SConnection *pCon);
|
||||
int SCGetConStatus(SConnection *pCon);
|
||||
char *SCGetDeviceID(SConnection *pCon);
|
||||
int SCGetEnd(SConnection *pCon);
|
||||
/************************* connection parameter change **********************/
|
||||
void SCSetConStatus(SConnection *pCon, int conStatus);
|
||||
void SCSetEventType(SConnection *pCon, int eventType);
|
||||
void SCSetSicsError(SConnection *pCon, int sicsError);
|
||||
void SCSetProtocolID(SConnection *pCon, int proID);
|
||||
void SCSetGrab(SConnection *pCon, int iGrab);
|
||||
|
||||
void SCSetEnd(SConnection *pCon, int val);
|
||||
void SCSetTelnet(SConnection *pCon, int val);
|
||||
/* **************************** Invocation ******************************** */
|
||||
int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand);
|
||||
|
||||
|
497
nread.c
497
nread.c
@ -194,439 +194,6 @@ int NetReadRemove(pNetRead self, mkChannel * pSock)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*-------------------------------------------------------------------------*/
|
||||
static int NetReadAccept(pNetRead self, mkChannel * pSock)
|
||||
{
|
||||
mkChannel *pNew = NULL;
|
||||
char pBuffer[1064];
|
||||
int iRet;
|
||||
SConnection *pRes = NULL;
|
||||
char *pUser = NULL, *pPasswd = NULL;
|
||||
time_t target;
|
||||
|
||||
if (!VerifyChannel(pSock)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for new connection */
|
||||
pNew = NETAccept(pSock, 0);
|
||||
if (pNew) {
|
||||
/* create connection object */
|
||||
/* TODO
|
||||
pRes = SCreateConnection(self->pMain->pSics,pNew,3);
|
||||
*/
|
||||
if (!pRes) {
|
||||
Log(ERROR,"sys","%s","Failure to allocate new Connection");
|
||||
NETClosePort(pNew);
|
||||
free(pNew);
|
||||
return 0;
|
||||
} else {
|
||||
/* register the connection and create a task for it here */
|
||||
NetReadRegister(self, pNew, command, pRes);
|
||||
TaskRegisterN(self->pMain->pTasker, "NetReadAccept",
|
||||
SCTaskFunction,
|
||||
SCSignalFunction, SCDeleteConnection, pRes, TASK_PRIO_LOW);
|
||||
SCSendOK(pRes);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
#define COLLECT 0
|
||||
#define SKIPTERM 1
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int NetReadRead(pNetRead self, pNetItem pItem)
|
||||
{
|
||||
char *pPtr, *pEnd, *pBufEnd;
|
||||
char pBuffer[1024], pMuell[20];
|
||||
char pBueffel[80];
|
||||
int i, iInt, iRet, iStat, state;
|
||||
|
||||
/* read first */
|
||||
memset(pBuffer, 0, 1024);
|
||||
iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0);
|
||||
if (iRet < 0) { /* EOF */
|
||||
pItem->pCon->iEnd = 1;
|
||||
NetReadRemove(self, pItem->pCon->pSock);
|
||||
return 0;
|
||||
} else if (iRet == 0) { /* should not happen */
|
||||
return 1;
|
||||
}
|
||||
/* iRet is now the number of bytes read. Now we check for command
|
||||
interrupts */
|
||||
pPtr = strstr(pBuffer, "INT1712");
|
||||
if (pPtr) {
|
||||
sscanf(pPtr, "%s %d", pMuell, &iInt);
|
||||
if (SCMatchRights(pItem->pCon, usUser)) {
|
||||
TaskSignal(self->pMain->pTasker, SICSINT, &iInt);
|
||||
Log(ERROR,"com","sock%03.3d:INTERRUPT", pItem->pCon->pSock->sockid);
|
||||
if (iInt == eEndServer) {
|
||||
TaskStop(self->pMain->pTasker);
|
||||
}
|
||||
} else {
|
||||
SCWrite(pItem->pCon,
|
||||
"ERROR: insufficient privilege to invoke Interrupt", eError);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* split into command lines
|
||||
and put into fifo
|
||||
*/
|
||||
pBufEnd = pBuffer + iRet;
|
||||
pPtr = pBuffer;
|
||||
pEnd = pBuffer;
|
||||
state = COLLECT;
|
||||
while (pEnd < pBufEnd) {
|
||||
switch (state) {
|
||||
case COLLECT:
|
||||
if ((*pEnd != '\r') && (*pEnd != '\n')) {
|
||||
pEnd++;
|
||||
} else {
|
||||
/* there is a string between pPtr and pEnd */
|
||||
*pEnd = '\0';
|
||||
/* do we have something in hold ? */
|
||||
if (strlen(pItem->pHold) > 0) {
|
||||
strlcat(pItem->pHold, pPtr, 511);
|
||||
/* DFC locking for protocol zero only */
|
||||
if (pItem->pCon->iProtocolID == PROTSICS &&
|
||||
CostaLocked(pItem->pCon->pStack))
|
||||
iStat = 0;
|
||||
else
|
||||
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
|
||||
if (!iStat) {
|
||||
SCWrite(pItem->pCon, "ERROR: Busy", eError);
|
||||
}
|
||||
pItem->pHold[0] = '\0';
|
||||
} else {
|
||||
/* no, normal command */
|
||||
/* DFC locking for protocol zero only */
|
||||
if (pItem->pCon->iProtocolID == PROTSICS &&
|
||||
CostaLocked(pItem->pCon->pStack))
|
||||
iStat = 0;
|
||||
else
|
||||
iStat = CostaTop(pItem->pCon->pStack, pPtr);
|
||||
if (!iStat) {
|
||||
SCWrite(pItem->pCon, "ERROR: Busy", eError);
|
||||
}
|
||||
}
|
||||
pPtr = pEnd + 1;
|
||||
pEnd = pPtr;
|
||||
state = SKIPTERM;
|
||||
}
|
||||
break;
|
||||
case SKIPTERM:
|
||||
if ((*pEnd != '\r') && (*pEnd != '\n')) {
|
||||
state = COLLECT;
|
||||
pPtr = pEnd;
|
||||
} else {
|
||||
pEnd++;
|
||||
pPtr = pEnd;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* when we are here we may still have an incomplete command pending */
|
||||
if (pEnd != pPtr && strlen(pPtr) > 0) {
|
||||
strlcpy(pItem->pHold, pPtr, 511);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*-------------------------- telnet protocoll code -------------------------*/
|
||||
static int TelnetAccept(pNetRead self, mkChannel * pSock)
|
||||
{
|
||||
mkChannel *pNew = NULL;
|
||||
char pBuffer[1064];
|
||||
int iRet;
|
||||
SConnection *pRes = NULL;
|
||||
pTelTask pTel = NULL;
|
||||
|
||||
if (!VerifyChannel(pSock)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* check for new connection */
|
||||
pNew = NETAccept(pSock, 0);
|
||||
if (pNew) {
|
||||
/* create connection object */
|
||||
/* TODO
|
||||
pRes = SCreateConnection(self->pMain->pSics,pNew,usSpy);
|
||||
*/
|
||||
if (!pRes) {
|
||||
Log(ERROR,"sys","%s","Failure to allocate new Connection");
|
||||
NETClosePort(pNew);
|
||||
free(pNew);
|
||||
return 0;
|
||||
} else {
|
||||
/* Create a task object for the telnet connection */
|
||||
pTel = CreateTelnet(pRes);
|
||||
if (!pTel) {
|
||||
Log(ERROR,"sys","%s","Failure to allocate new Telnet Task Object");
|
||||
SCDeleteConnection(pRes);
|
||||
return 0;
|
||||
}
|
||||
/* register connection and task */
|
||||
pRes->iTelnet = 1;
|
||||
NetReadRegister(self, pNew, tcommand, pRes);
|
||||
TaskRegisterN(self->pMain->pTasker," TelnetAccept",
|
||||
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------
|
||||
Telnet is fully described in RFC-854. This implementation is very simple.
|
||||
It just supports the NVT and no options. Implementation is via a state
|
||||
machine with the state tStatus in the pItem structure. This is necessary
|
||||
as single characters may be sent by telnet clients.
|
||||
-------------------------------------------------------------------------*/
|
||||
/* Telnet codes */
|
||||
#define SE 240
|
||||
#define NOP 241
|
||||
#define DM 242 /* data mark */
|
||||
#define BRK 243
|
||||
#define IP 244
|
||||
#define AO 245
|
||||
#define AYT 246
|
||||
#define EC 247
|
||||
#define EL 248
|
||||
#define GA 249
|
||||
#define SB 250
|
||||
#define WILL 251
|
||||
#define WONT 252
|
||||
#define DO 253
|
||||
#define DONT 254
|
||||
#define IAC 255
|
||||
#define EOR 239
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int TelnetReply(pNetItem pItem, char code, char cChar)
|
||||
{
|
||||
char pReply[3];
|
||||
|
||||
pReply[0] = IAC;
|
||||
pReply[1] = code;
|
||||
pReply[2] = cChar;
|
||||
|
||||
NETWrite(pItem->pCon->pSock, pReply, 3);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*------------------------------------------------------------------------*/
|
||||
static int TelnetRead(pNetRead self, pNetItem pItem)
|
||||
{
|
||||
char pBuffer[1024], pMuell[20], pError[256];
|
||||
int i, iStat, iInt, iRet;
|
||||
int cChar;
|
||||
char *pPtr = NULL;
|
||||
SConnection *pOwner = NULL;
|
||||
|
||||
/* read first */
|
||||
memset(pBuffer, 0, 1023);
|
||||
iRet = NETRead(pItem->pCon->pSock, pBuffer, 1022, 0);
|
||||
if (iRet < 0) { /* EOF */
|
||||
pItem->pCon->iEnd = 1;
|
||||
NetReadRemove(self, pItem->pCon->pSock);
|
||||
return 0;
|
||||
} else if (iRet == 0) { /* should not happen */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* iRet is now the number of bytes read. Now we check for command
|
||||
interrupts */
|
||||
pPtr = strstr(pBuffer, "INT1712");
|
||||
if (pPtr) {
|
||||
sscanf(pPtr, "%s %d", pMuell, &iInt);
|
||||
if (SCMatchRights(pItem->pCon, usUser)) {
|
||||
/* owners may kill own tasks, otherwise manager
|
||||
privilege is required.
|
||||
*/
|
||||
pOwner = GetExeOwner(pServ->pExecutor);
|
||||
if (pOwner) {
|
||||
if (pOwner != pItem->pCon) {
|
||||
if (!SCMatchRights(pItem->pCon, usMugger)) {
|
||||
SCWrite(pItem->pCon,
|
||||
"ERROR: Insufficient privilege to stop other people's experiments",
|
||||
eError);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
TaskSignal(self->pMain->pTasker, SICSINT, &iInt);
|
||||
Log(ERROR,"com","%s:interrupt: %d", ConID(pItem->pCon),iInt);
|
||||
if (iInt == eEndServer) {
|
||||
TaskStop(self->pMain->pTasker);
|
||||
}
|
||||
} else {
|
||||
SCWrite(pItem->pCon,
|
||||
"ERROR: insufficient privilege to invoke Interrupt", eError);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* do telnet analysis of the data buffer */
|
||||
for (i = 0; i < iRet; i++) {
|
||||
cChar = (int) pBuffer[i];
|
||||
#ifdef TELNETDEBUG
|
||||
if ((cChar > 48) && (cChar < 128)) {
|
||||
printf("char: %c\n", cChar);
|
||||
} else {
|
||||
printf("Control: %d\n", cChar);
|
||||
}
|
||||
#endif
|
||||
/* Telnet status switching */
|
||||
switch (pItem->tStatus) {
|
||||
case tData:
|
||||
switch (cChar) {
|
||||
case IAC:
|
||||
pItem->tStatus = tIAC;
|
||||
break;
|
||||
case '\r':
|
||||
case '\n':
|
||||
/* DFC locking for protocol zero only */
|
||||
if (pItem->pCon->iProtocolID == PROTSICS &&
|
||||
CostaLocked(pItem->pCon->pStack))
|
||||
iStat = 0;
|
||||
else
|
||||
iStat = CostaTop(pItem->pCon->pStack, pItem->pHold);
|
||||
/* printf("%s\n",pItem->pHold); */
|
||||
if (!iStat) {
|
||||
SCWrite(pItem->pCon, "ERROR: Busy", eError);
|
||||
}
|
||||
memset(pItem->pHold, 0, 511);
|
||||
pItem->iEOD = 0;
|
||||
pItem->tStatus = tCR;
|
||||
break;
|
||||
case (char) 8: /* backspace */
|
||||
pItem->iEOD--;
|
||||
if (pItem->iEOD < 0) {
|
||||
pItem->iEOD = 0;
|
||||
}
|
||||
break;
|
||||
case (char) 0: /* ignore 0 character sent as end of text */
|
||||
break;
|
||||
default:
|
||||
pItem->pHold[pItem->iEOD] = cChar;
|
||||
pItem->iEOD++;
|
||||
break;
|
||||
|
||||
} /* end of tData case */
|
||||
break;
|
||||
case tCR: /* ignore the second character after a newline.
|
||||
Telnet gives you two characters for newline
|
||||
*/
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case tIAC:
|
||||
switch (cChar) {
|
||||
case IAC:
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case WILL:
|
||||
pItem->tStatus = tWill;
|
||||
break;
|
||||
case WONT:
|
||||
pItem->tStatus = tWont;
|
||||
break;
|
||||
case DONT:
|
||||
pItem->tStatus = tDont;
|
||||
break;
|
||||
case DO:
|
||||
pItem->tStatus = tDo;
|
||||
break;
|
||||
case EOR:
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case SB:
|
||||
pItem->tStatus = tSB;
|
||||
break;
|
||||
case EC:
|
||||
pItem->iEOD--;
|
||||
if (pItem->iEOD < 0) {
|
||||
pItem->iEOD = 0;
|
||||
}
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case EL:
|
||||
memset(pItem->pHold, 0, 511);
|
||||
pItem->iEOD = 0;
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case IP:
|
||||
SCSetInterrupt(pItem->pCon, eAbortBatch);
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
default:
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
} /* end of tIAC */
|
||||
break;
|
||||
case tWill: /* we do not do options! */
|
||||
TelnetReply(pItem, DONT, cChar);
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case tWont: /* we do not do options! A Wont is sent by the client
|
||||
if it cannot do a option we requested it to have. As
|
||||
we do not try to force options, this should not happen
|
||||
*/
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case tDo: /* we do not do options! */
|
||||
TelnetReply(pItem, WONT, cChar);
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case tDont: /* we do not do options! A Dont is sent by the client
|
||||
if it cannot do a option we requested it to have. As
|
||||
we do not try to force options, this should not happen
|
||||
*/
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
case tSB: /* as we do not have options, we cannot have suboption
|
||||
negotaitions. Something is seriously wrong when
|
||||
we are here. It is a protocoll error. However, we
|
||||
ignore it silently. tSB marks the start of the
|
||||
subnegotiation. The current character must be the
|
||||
option code we are dealing with.
|
||||
*/
|
||||
pItem->tStatus = tSE;
|
||||
break;
|
||||
case tSE:
|
||||
/* now we are in the suboption parameter. Normally data
|
||||
should be copied to a suboption string buffer here
|
||||
until SE.
|
||||
*/
|
||||
switch (cChar) {
|
||||
case IAC:
|
||||
break;
|
||||
case SE:
|
||||
pItem->tStatus = tData;
|
||||
/* suboption interpretation would go here */
|
||||
break;
|
||||
default:
|
||||
/* copy data to suboption buffer */
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* There is something wrong here! */
|
||||
snprintf(pError,sizeof(pError)-1, "ERROR: bad telnet code %d", cChar);
|
||||
Log(ERROR,"sys","%s",pError);
|
||||
pItem->tStatus = tData;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
static int NetReadUDP(pNetRead self, pNetItem pItem)
|
||||
{
|
||||
@ -708,13 +275,6 @@ int NetReaderTask(void *pData)
|
||||
GetCharArray(self->conList));
|
||||
}
|
||||
|
||||
/*
|
||||
* This costs a surprising amount of CPU-time, in a test 10%!
|
||||
* This is why it has been commented away
|
||||
snprintf(num, sizeof num, "%d", conCount);
|
||||
IFSetOption(pSICSOptions, "ConnectionCount", num);
|
||||
IFSetOption(pSICSOptions, "ConMask", GetCharArray(self->conList));
|
||||
*/
|
||||
|
||||
/* the select itself */
|
||||
tmo.tv_usec = self->iReadTimeout;
|
||||
@ -731,29 +291,6 @@ int NetReaderTask(void *pData)
|
||||
LLDnodeDataTo(self->iList, &NItem);
|
||||
if (FD_ISSET(NItem.pSock->sockid, &lMask)) { /* data */
|
||||
switch (NItem.eType) {
|
||||
/* lists have been changed after accept, return */
|
||||
case naccept:
|
||||
NetReadAccept(self, NItem.pSock);
|
||||
return 1;
|
||||
break;
|
||||
case taccept:
|
||||
TelnetAccept(self, NItem.pSock);
|
||||
return 1;
|
||||
break;
|
||||
case command:
|
||||
iStatus = NetReadRead(self, &NItem);
|
||||
if (iStatus == 0) { /* there was an eof */
|
||||
/* do not continue, list is messy */
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case tcommand:
|
||||
iStatus = TelnetRead(self, &NItem);
|
||||
if (iStatus == 0) { /* there was an eof */
|
||||
/* do not continue, list is messy */
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
case udp:
|
||||
NetReadUDP(self, &NItem);
|
||||
break;
|
||||
@ -1048,6 +585,10 @@ static int testAndInvokeInterrupt(pCommandCBData self, int handle)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
#define COLLECT 0
|
||||
#define SKIPTERM 1
|
||||
|
||||
|
||||
/*----------------------------------------------------------------------------------*/
|
||||
static int CommandDataCB(int handle, void *userData)
|
||||
@ -1114,7 +655,7 @@ static int CommandAcceptCB(int handle, void *userData)
|
||||
}
|
||||
usData->pCon = pCon;
|
||||
usData->state = COLLECT;
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
|
||||
TaskRegisterN(pServ->pTasker,
|
||||
buffer,
|
||||
SCTaskFunction,
|
||||
@ -1123,6 +664,30 @@ static int CommandAcceptCB(int handle, void *userData)
|
||||
SCSendOK(pCon);
|
||||
return 1;
|
||||
}
|
||||
/*------------------------------------------------------------------------
|
||||
Telnet is fully described in RFC-854. This implementation is very simple.
|
||||
It just supports the NVT and no options. Implementation is via a state
|
||||
machine with the state tStatus in the pItem structure. This is necessary
|
||||
as single characters may be sent by telnet clients.
|
||||
-------------------------------------------------------------------------*/
|
||||
/* Telnet codes */
|
||||
#define SE 240
|
||||
#define NOP 241
|
||||
#define DM 242 /* data mark */
|
||||
#define BRK 243
|
||||
#define IP 244
|
||||
#define AO 245
|
||||
#define AYT 246
|
||||
#define EC 247
|
||||
#define EL 248
|
||||
#define GA 249
|
||||
#define SB 250
|
||||
#define WILL 251
|
||||
#define WONT 252
|
||||
#define DO 253
|
||||
#define DONT 254
|
||||
#define IAC 255
|
||||
#define EOR 239
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
static int ANETTelnetReply(int sockHandle, char code, char cChar)
|
||||
@ -1329,8 +894,8 @@ static int TelnetAcceptCB(int handle, void *userData)
|
||||
return 0;
|
||||
}
|
||||
/* register connection and task */
|
||||
pCon->iTelnet = 1;
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
||||
SCSetTelnet(pCon,1);
|
||||
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
|
||||
TaskRegisterN(pServ->pTasker,
|
||||
buffer,
|
||||
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);
|
||||
|
32
telnet.c
32
telnet.c
@ -13,6 +13,8 @@
|
||||
#include "passwd.h"
|
||||
#include "telnet.h"
|
||||
#include "fortify.h"
|
||||
#include "asynnet.h"
|
||||
#include "conman.h"
|
||||
#define LOGINWAIT 300
|
||||
/* 300 == 5 minutes to wait for valid username password */
|
||||
/*-------------------------------------------------------------------------*/
|
||||
@ -96,7 +98,7 @@ static void SendGA(SConnection * pCon)
|
||||
|
||||
pReply[0] = (char) 255;
|
||||
pReply[1] = (char) 249;
|
||||
NETWrite(pCon->pSock, pReply, 2);
|
||||
ANETwrite(SCGetSockHandle(pCon), pReply, 2);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
@ -113,7 +115,7 @@ int TelnetTask(void *pData)
|
||||
self = (pTelTask) pData;
|
||||
assert(self);
|
||||
|
||||
if (self->pCon->iEnd) {
|
||||
if (SCGetEnd(self->pCon)) {
|
||||
if (SCActive(self->pCon)) {
|
||||
return 1;
|
||||
} else {
|
||||
@ -122,21 +124,20 @@ int TelnetTask(void *pData)
|
||||
}
|
||||
|
||||
/* pop and execute */
|
||||
iRet = CostaPop(self->pCon->pStack, &pPtr);
|
||||
iRet = SCCostaTop(self->pCon,pPtr);
|
||||
if (iRet) {
|
||||
if (pPtr) {
|
||||
if (self->iLogin) { /* handle normal command */
|
||||
/* check for logoff */
|
||||
if (strstr(pPtr, "logoff") != NULL) {
|
||||
ANETclose(self->pCon->sockHandle);
|
||||
SCClose(self->pCon);
|
||||
free(pPtr);
|
||||
self->pCon->iEnd = 1;
|
||||
return 0;
|
||||
}
|
||||
/* invoke command */
|
||||
CostaLock(self->pCon->pStack);
|
||||
SCCostaLock(self->pCon);
|
||||
SCInvoke(self->pCon, pServ->pSics, pPtr);
|
||||
CostaUnlock(self->pCon->pStack);
|
||||
SCCostaUnLock(self->pCon);
|
||||
SendGA(self->pCon);
|
||||
free(pPtr);
|
||||
} else { /* handle login messages */
|
||||
@ -149,8 +150,7 @@ int TelnetTask(void *pData)
|
||||
if (time(&shit) > self->tStart + LOGINWAIT) {
|
||||
SCWrite(self->pCon,
|
||||
"I cannot stand your login attempts anymore!", eError);
|
||||
ANETclose(self->pCon->sockHandle);
|
||||
self->pCon->iEnd = 1;
|
||||
SCClose(self->pCon);
|
||||
free(pPtr);
|
||||
return 0;
|
||||
}
|
||||
@ -172,7 +172,7 @@ int TelnetTask(void *pData)
|
||||
return 1;
|
||||
} else {
|
||||
snprintf(pBuffer,sizeof(pBuffer)-1, "Accepted telnet connection on handle %d",
|
||||
self->pCon->sockHandle);
|
||||
SCGetSockHandle(self->pCon));
|
||||
Log(INFO,"com","%s",pBuffer);
|
||||
SendWelcome(self->pCon);
|
||||
SCSetRights(self->pCon, iRet);
|
||||
@ -187,14 +187,14 @@ int TelnetTask(void *pData)
|
||||
}
|
||||
/* check for no commands but timeout on telnet */
|
||||
if (!self->iLogin && (time(&shit) > self->tStart + LOGINWAIT)) {
|
||||
self->pCon->iEnd = 1;
|
||||
ANETclose(self->pCon->sockHandle);
|
||||
SCSetEnd(self->pCon,1);
|
||||
SCClose(self->pCon);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* check for end */
|
||||
if (self->pCon->iEnd) {
|
||||
if (SCGetEnd(self->pCon)) {
|
||||
if (SCActive(self->pCon)) {
|
||||
return 1;
|
||||
} else {
|
||||
@ -219,7 +219,7 @@ void TelnetSignal(void *pData, int iSignal, void *pSigData)
|
||||
iInt = (int *) pSigData;
|
||||
SCSetInterrupt(self->pCon, *iInt);
|
||||
if (*iInt == eEndServer) {
|
||||
self->pCon->iEnd = 1;
|
||||
SCSetEnd(self->pCon,1);
|
||||
}
|
||||
} else if (iSignal == SICSBROADCAST) {
|
||||
pPtr = (char *) pSigData;
|
||||
@ -227,9 +227,9 @@ void TelnetSignal(void *pData, int iSignal, void *pSigData)
|
||||
SCWrite(self->pCon, pPtr, eWarning);
|
||||
}
|
||||
} else if (iSignal == TOKENRELEASE) {
|
||||
self->pCon->iGrab = 0;
|
||||
SCSetGrab(self->pCon,0);
|
||||
} else if (iSignal == TOKENGRAB) {
|
||||
self->pCon->iGrab = 1;
|
||||
SCSetGrab(self->pCon,1);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user