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;
|
return pCon->runLevel;
|
||||||
}
|
}
|
||||||
/*--------------------------------------------------------*/
|
/*--------------------------------------------------------*/
|
||||||
int SCGetIdent(SConnection *pCon)
|
long SCGetIdent(SConnection *pCon)
|
||||||
{
|
{
|
||||||
if (!VerifyConnection(pCon)) {
|
if (!VerifyConnection(pCon)) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -2404,7 +2404,14 @@ char *SCGetDeviceID(SConnection *pCon)
|
|||||||
}
|
}
|
||||||
return pCon->deviceID;
|
return pCon->deviceID;
|
||||||
}
|
}
|
||||||
|
/*-------------------------------------------------------*/
|
||||||
|
int SCGetEnd(SConnection *pCon)
|
||||||
|
{
|
||||||
|
if (!VerifyConnection(pCon)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return pCon->iEnd;
|
||||||
|
}
|
||||||
/*-------------------------------------------------------*/
|
/*-------------------------------------------------------*/
|
||||||
void SCSetConStatus(SConnection *pCon, int conStatus)
|
void SCSetConStatus(SConnection *pCon, int conStatus)
|
||||||
{
|
{
|
||||||
@ -2476,4 +2483,28 @@ void SCSetGrab(SConnection *pCon, int iGrab)
|
|||||||
}
|
}
|
||||||
pCon->iGrab = 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 SCisConnected(SConnection * pCon);
|
||||||
int VerifyConnection(SConnection * pCon);
|
int VerifyConnection(SConnection * pCon);
|
||||||
int SCVerifyConnection(SConnection * self);
|
int SCVerifyConnection(SConnection * self);
|
||||||
|
void SCClose(SConnection *pCon);
|
||||||
/*------------------------------- tasking --------------------------------*/
|
/*------------------------------- tasking --------------------------------*/
|
||||||
int SCTaskFunction(void *pCon);
|
int SCTaskFunction(void *pCon);
|
||||||
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
void SCSignalFunction(void *pCon, int iSignal, void *pSigData);
|
||||||
@ -141,20 +142,22 @@ int SCGetOutClass(SConnection * self);
|
|||||||
int SCGetGrab(SConnection * pCon);
|
int SCGetGrab(SConnection * pCon);
|
||||||
int SCActive(SConnection * pCon);
|
int SCActive(SConnection * pCon);
|
||||||
int SCGetRunLevel(SConnection *pCon);
|
int SCGetRunLevel(SConnection *pCon);
|
||||||
int SCGetIdent(SConnection *pCon);
|
long SCGetIdent(SConnection *pCon);
|
||||||
int SCGetSicsError(SConnection *pCon);
|
int SCGetSicsError(SConnection *pCon);
|
||||||
int SCGetTransID(SConnection *pCon);
|
int SCGetTransID(SConnection *pCon);
|
||||||
int SCGetProtocolID(SConnection *pCon);
|
int SCGetProtocolID(SConnection *pCon);
|
||||||
int SCGetSockHandle(SConnection *pCon);
|
int SCGetSockHandle(SConnection *pCon);
|
||||||
int SCGetConStatus(SConnection *pCon);
|
int SCGetConStatus(SConnection *pCon);
|
||||||
char *SCGetDeviceID(SConnection *pCon);
|
char *SCGetDeviceID(SConnection *pCon);
|
||||||
|
int SCGetEnd(SConnection *pCon);
|
||||||
/************************* connection parameter change **********************/
|
/************************* connection parameter change **********************/
|
||||||
void SCSetConStatus(SConnection *pCon, int conStatus);
|
void SCSetConStatus(SConnection *pCon, int conStatus);
|
||||||
void SCSetEventType(SConnection *pCon, int eventType);
|
void SCSetEventType(SConnection *pCon, int eventType);
|
||||||
void SCSetSicsError(SConnection *pCon, int sicsError);
|
void SCSetSicsError(SConnection *pCon, int sicsError);
|
||||||
void SCSetProtocolID(SConnection *pCon, int proID);
|
void SCSetProtocolID(SConnection *pCon, int proID);
|
||||||
void SCSetGrab(SConnection *pCon, int iGrab);
|
void SCSetGrab(SConnection *pCon, int iGrab);
|
||||||
|
void SCSetEnd(SConnection *pCon, int val);
|
||||||
|
void SCSetTelnet(SConnection *pCon, int val);
|
||||||
/* **************************** Invocation ******************************** */
|
/* **************************** Invocation ******************************** */
|
||||||
int SCInvoke(SConnection * self, SicsInterp * pInter, char *pCommand);
|
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;
|
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)
|
static int NetReadUDP(pNetRead self, pNetItem pItem)
|
||||||
{
|
{
|
||||||
@ -708,13 +275,6 @@ int NetReaderTask(void *pData)
|
|||||||
GetCharArray(self->conList));
|
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 */
|
/* the select itself */
|
||||||
tmo.tv_usec = self->iReadTimeout;
|
tmo.tv_usec = self->iReadTimeout;
|
||||||
@ -731,29 +291,6 @@ int NetReaderTask(void *pData)
|
|||||||
LLDnodeDataTo(self->iList, &NItem);
|
LLDnodeDataTo(self->iList, &NItem);
|
||||||
if (FD_ISSET(NItem.pSock->sockid, &lMask)) { /* data */
|
if (FD_ISSET(NItem.pSock->sockid, &lMask)) { /* data */
|
||||||
switch (NItem.eType) {
|
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:
|
case udp:
|
||||||
NetReadUDP(self, &NItem);
|
NetReadUDP(self, &NItem);
|
||||||
break;
|
break;
|
||||||
@ -1048,6 +585,10 @@ static int testAndInvokeInterrupt(pCommandCBData self, int handle)
|
|||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
/*----------------------------------------------------------------------------------*/
|
||||||
|
#define COLLECT 0
|
||||||
|
#define SKIPTERM 1
|
||||||
|
|
||||||
|
|
||||||
/*----------------------------------------------------------------------------------*/
|
/*----------------------------------------------------------------------------------*/
|
||||||
static int CommandDataCB(int handle, void *userData)
|
static int CommandDataCB(int handle, void *userData)
|
||||||
@ -1114,7 +655,7 @@ static int CommandAcceptCB(int handle, void *userData)
|
|||||||
}
|
}
|
||||||
usData->pCon = pCon;
|
usData->pCon = pCon;
|
||||||
usData->state = COLLECT;
|
usData->state = COLLECT;
|
||||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
|
||||||
TaskRegisterN(pServ->pTasker,
|
TaskRegisterN(pServ->pTasker,
|
||||||
buffer,
|
buffer,
|
||||||
SCTaskFunction,
|
SCTaskFunction,
|
||||||
@ -1123,6 +664,30 @@ static int CommandAcceptCB(int handle, void *userData)
|
|||||||
SCSendOK(pCon);
|
SCSendOK(pCon);
|
||||||
return 1;
|
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)
|
static int ANETTelnetReply(int sockHandle, char code, char cChar)
|
||||||
@ -1329,8 +894,8 @@ static int TelnetAcceptCB(int handle, void *userData)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* register connection and task */
|
/* register connection and task */
|
||||||
pCon->iTelnet = 1;
|
SCSetTelnet(pCon,1);
|
||||||
snprintf(buffer,sizeof(buffer),"con%ld", pCon->ident);
|
snprintf(buffer,sizeof(buffer),"con%ld", SCGetIdent(pCon));
|
||||||
TaskRegisterN(pServ->pTasker,
|
TaskRegisterN(pServ->pTasker,
|
||||||
buffer,
|
buffer,
|
||||||
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);
|
TelnetTask, TelnetSignal, DeleteTelnet, pTel, TASK_PRIO_LOW);
|
||||||
|
32
telnet.c
32
telnet.c
@ -13,6 +13,8 @@
|
|||||||
#include "passwd.h"
|
#include "passwd.h"
|
||||||
#include "telnet.h"
|
#include "telnet.h"
|
||||||
#include "fortify.h"
|
#include "fortify.h"
|
||||||
|
#include "asynnet.h"
|
||||||
|
#include "conman.h"
|
||||||
#define LOGINWAIT 300
|
#define LOGINWAIT 300
|
||||||
/* 300 == 5 minutes to wait for valid username password */
|
/* 300 == 5 minutes to wait for valid username password */
|
||||||
/*-------------------------------------------------------------------------*/
|
/*-------------------------------------------------------------------------*/
|
||||||
@ -96,7 +98,7 @@ static void SendGA(SConnection * pCon)
|
|||||||
|
|
||||||
pReply[0] = (char) 255;
|
pReply[0] = (char) 255;
|
||||||
pReply[1] = (char) 249;
|
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;
|
self = (pTelTask) pData;
|
||||||
assert(self);
|
assert(self);
|
||||||
|
|
||||||
if (self->pCon->iEnd) {
|
if (SCGetEnd(self->pCon)) {
|
||||||
if (SCActive(self->pCon)) {
|
if (SCActive(self->pCon)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@ -122,21 +124,20 @@ int TelnetTask(void *pData)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* pop and execute */
|
/* pop and execute */
|
||||||
iRet = CostaPop(self->pCon->pStack, &pPtr);
|
iRet = SCCostaTop(self->pCon,pPtr);
|
||||||
if (iRet) {
|
if (iRet) {
|
||||||
if (pPtr) {
|
if (pPtr) {
|
||||||
if (self->iLogin) { /* handle normal command */
|
if (self->iLogin) { /* handle normal command */
|
||||||
/* check for logoff */
|
/* check for logoff */
|
||||||
if (strstr(pPtr, "logoff") != NULL) {
|
if (strstr(pPtr, "logoff") != NULL) {
|
||||||
ANETclose(self->pCon->sockHandle);
|
SCClose(self->pCon);
|
||||||
free(pPtr);
|
free(pPtr);
|
||||||
self->pCon->iEnd = 1;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* invoke command */
|
/* invoke command */
|
||||||
CostaLock(self->pCon->pStack);
|
SCCostaLock(self->pCon);
|
||||||
SCInvoke(self->pCon, pServ->pSics, pPtr);
|
SCInvoke(self->pCon, pServ->pSics, pPtr);
|
||||||
CostaUnlock(self->pCon->pStack);
|
SCCostaUnLock(self->pCon);
|
||||||
SendGA(self->pCon);
|
SendGA(self->pCon);
|
||||||
free(pPtr);
|
free(pPtr);
|
||||||
} else { /* handle login messages */
|
} else { /* handle login messages */
|
||||||
@ -149,8 +150,7 @@ int TelnetTask(void *pData)
|
|||||||
if (time(&shit) > self->tStart + LOGINWAIT) {
|
if (time(&shit) > self->tStart + LOGINWAIT) {
|
||||||
SCWrite(self->pCon,
|
SCWrite(self->pCon,
|
||||||
"I cannot stand your login attempts anymore!", eError);
|
"I cannot stand your login attempts anymore!", eError);
|
||||||
ANETclose(self->pCon->sockHandle);
|
SCClose(self->pCon);
|
||||||
self->pCon->iEnd = 1;
|
|
||||||
free(pPtr);
|
free(pPtr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -172,7 +172,7 @@ int TelnetTask(void *pData)
|
|||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
snprintf(pBuffer,sizeof(pBuffer)-1, "Accepted telnet connection on handle %d",
|
snprintf(pBuffer,sizeof(pBuffer)-1, "Accepted telnet connection on handle %d",
|
||||||
self->pCon->sockHandle);
|
SCGetSockHandle(self->pCon));
|
||||||
Log(INFO,"com","%s",pBuffer);
|
Log(INFO,"com","%s",pBuffer);
|
||||||
SendWelcome(self->pCon);
|
SendWelcome(self->pCon);
|
||||||
SCSetRights(self->pCon, iRet);
|
SCSetRights(self->pCon, iRet);
|
||||||
@ -187,14 +187,14 @@ int TelnetTask(void *pData)
|
|||||||
}
|
}
|
||||||
/* check for no commands but timeout on telnet */
|
/* check for no commands but timeout on telnet */
|
||||||
if (!self->iLogin && (time(&shit) > self->tStart + LOGINWAIT)) {
|
if (!self->iLogin && (time(&shit) > self->tStart + LOGINWAIT)) {
|
||||||
self->pCon->iEnd = 1;
|
SCSetEnd(self->pCon,1);
|
||||||
ANETclose(self->pCon->sockHandle);
|
SCClose(self->pCon);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* check for end */
|
/* check for end */
|
||||||
if (self->pCon->iEnd) {
|
if (SCGetEnd(self->pCon)) {
|
||||||
if (SCActive(self->pCon)) {
|
if (SCActive(self->pCon)) {
|
||||||
return 1;
|
return 1;
|
||||||
} else {
|
} else {
|
||||||
@ -219,7 +219,7 @@ void TelnetSignal(void *pData, int iSignal, void *pSigData)
|
|||||||
iInt = (int *) pSigData;
|
iInt = (int *) pSigData;
|
||||||
SCSetInterrupt(self->pCon, *iInt);
|
SCSetInterrupt(self->pCon, *iInt);
|
||||||
if (*iInt == eEndServer) {
|
if (*iInt == eEndServer) {
|
||||||
self->pCon->iEnd = 1;
|
SCSetEnd(self->pCon,1);
|
||||||
}
|
}
|
||||||
} else if (iSignal == SICSBROADCAST) {
|
} else if (iSignal == SICSBROADCAST) {
|
||||||
pPtr = (char *) pSigData;
|
pPtr = (char *) pSigData;
|
||||||
@ -227,9 +227,9 @@ void TelnetSignal(void *pData, int iSignal, void *pSigData)
|
|||||||
SCWrite(self->pCon, pPtr, eWarning);
|
SCWrite(self->pCon, pPtr, eWarning);
|
||||||
}
|
}
|
||||||
} else if (iSignal == TOKENRELEASE) {
|
} else if (iSignal == TOKENRELEASE) {
|
||||||
self->pCon->iGrab = 0;
|
SCSetGrab(self->pCon,0);
|
||||||
} else if (iSignal == TOKENGRAB) {
|
} else if (iSignal == TOKENGRAB) {
|
||||||
self->pCon->iGrab = 1;
|
SCSetGrab(self->pCon,1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user