diff options
Diffstat (limited to 'runtime/nsd_ptcp.c')
-rw-r--r-- | runtime/nsd_ptcp.c | 187 |
1 files changed, 94 insertions, 93 deletions
diff --git a/runtime/nsd_ptcp.c b/runtime/nsd_ptcp.c index 6f7dd04d..c737c168 100644 --- a/runtime/nsd_ptcp.c +++ b/runtime/nsd_ptcp.c @@ -56,30 +56,29 @@ DEFobjCurrIf(glbl) DEFobjCurrIf(net) +/* a few deinit helpers */ + +/* close socket if open (may always be called) */ +static void +sockClose(int *pSock) +{ + if(*pSock >= 0) { + close(*pSock); + *pSock = -1; + } +} + /* Standard-Constructor */ BEGINobjConstruct(nsd_ptcp) /* be sure to specify the object type also in END macro! */ pThis->sock = -1; - pThis->iSessMax = 500; /* default max nbr of sessions -TODO:make configurable--rgerhards, 2008-04-17*/ ENDobjConstruct(nsd_ptcp) /* destructor for the nsd_ptcp object */ BEGINobjDestruct(nsd_ptcp) /* be sure to specify the object type also in END and CODESTART macros! */ - int i; CODESTARTobjDestruct(nsd_ptcp) - if(pThis->sock != -1) { - close(pThis->sock); - pThis->sock = -1; - } - - if(pThis->socks != NULL) { - /* if we have some sockets at this stage, we need to close them */ - for(i = 1 ; i <= pThis->socks[0] ; ++i) - close(pThis->socks[i]); - free(pThis->socks); - } - + sockClose(&pThis->sock); if(pThis->pRemHostIP != NULL) free(pThis->pRemHostIP); if(pThis->pRemHostName != NULL) @@ -189,33 +188,34 @@ finalize_it: -/* accept an incoming connection request, sock provides the socket on which we can - * accept the new session. - * rgerhards, 2008-03-17 +/* accept an incoming connection request + * rgerhards, 2008-04-22 */ static rsRetVal -AcceptConnReq(nsd_t **ppThis, int sock) +AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew) { int sockflags; + nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd; struct sockaddr_storage addr; socklen_t addrlen = sizeof(addr); - nsd_ptcp_t *pThis = NULL; + nsd_ptcp_t *pNew = NULL; int iNewSock = -1; DEFiRet; - assert(ppThis != NULL); + assert(ppNew != NULL); + ISOBJ_TYPE_assert(pThis, nsd_ptcp_t); - iNewSock = accept(sock, (struct sockaddr*) &addr, &addrlen); + iNewSock = accept(pThis->sock, (struct sockaddr*) &addr, &addrlen); if(iNewSock < 0) { ABORT_FINALIZE(RS_RET_ACCEPT_ERR); } /* construct our object so that we can use it... */ - CHKiRet(nsd_ptcpConstruct(&pThis)); + CHKiRet(nsd_ptcpConstruct(&pNew)); - CHKiRet(FillRemHost(pThis, (struct sockaddr*) &addr)); + CHKiRet(FillRemHost(pNew, (struct sockaddr*) &addr)); - /* set the new socket to non-blocking IO */ + /* set the new socket to non-blocking IO -TODO:do we really need to do this here? Do we always want it? */ if((sockflags = fcntl(iNewSock, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* SETFL could fail too, so get it caught by the subsequent @@ -228,41 +228,41 @@ AcceptConnReq(nsd_t **ppThis, int sock) ABORT_FINALIZE(RS_RET_IO_ERROR); } - pThis->sock = iNewSock; - - *ppThis = (nsd_t*) pThis; + pNew->sock = iNewSock; + *ppNew = (nsd_t*) pNew; finalize_it: if(iRet != RS_RET_OK) { - if(pThis != NULL) - nsd_ptcpDestruct(&pThis); + if(pNew != NULL) + nsd_ptcpDestruct(&pNew); /* the close may be redundant, but that doesn't hurt... */ - if(iNewSock >= 0) - close(iNewSock); + sockClose(&iNewSock); } RETiRet; } -/* initialize the tcp socket for a listner - * pLstnPort must point to a port name or number. NULL is NOT permitted - * (hint: we need to be careful when we use this module together with librelp, - * there NULL indicates the default port - * default is used. - * gerhards, 2008-03-17 +/* initialize tcp sockets for a listner. This function returns an array of nds_t + * objects. The size of this array is returend in pLstnArrSize. + * pLstnPort must point to a port name or number. NULL is NOT permitted. pLstnIP + * points to the port to listen to (NULL means "all"), iMaxSess has the maximum + * number of sessions permitted. + * rgerhards, 2008-04-22 */ static rsRetVal -LstnInit(nsd_t *pNsd, uchar *pLstnPort) +LstnInit(nsd_t ***parrLstnNsd, int *pLstnArrSize, uchar *pLstnPort, uchar *pLstnIP, int iSessMax) { - nsd_ptcp_t *pThis = (nsd_ptcp_t*) pNsd; - struct addrinfo hints, *res, *r; - int error, maxs, *s, on = 1; + DEFiRet; + struct addrinfo hints, *res = NULL, *r; + nsd_ptcp_t **arrLstn = NULL; + int error, maxs, on = 1; + int sock; int sockflags; - DEFiRet; - ISOBJ_TYPE_assert(pThis, nsd_ptcp); + assert(parrLstnNsd != NULL); assert(pLstnPort != NULL); + assert(iSessMax >= 0); dbgprintf("creating tcp listen socket on port %s\n", pLstnPort); @@ -271,7 +271,7 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort) hints.ai_family = glbl.GetDefPFFamily(); hints.ai_socktype = SOCK_STREAM; - error = getaddrinfo(NULL, (char*) pLstnPort, &hints, &res); + error = getaddrinfo((char*)pLstnIP, (char*) pLstnPort, &hints, &res); if(error) { dbgprintf("error %d querying port '%s'\n", error, pLstnPort); ABORT_FINALIZE(RS_RET_INVALID_PORT); @@ -280,20 +280,14 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort) /* Count max number of sockets we may open */ for(maxs = 0, r = res; r != NULL ; r = r->ai_next, maxs++) /* EMPTY */; - pThis->socks = malloc((maxs+1) * sizeof(int)); - if (pThis->socks == NULL) { - dbgprintf("couldn't allocate memory for TCP listen sockets, suspending RELP message reception."); - freeaddrinfo(res); - ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY); - } + CHKmalloc(arrLstn = (nsd_ptcp_t**) malloc((maxs+1) * sizeof(nsd_ptcp_t*))); - *pThis->socks = 0; /* num of sockets counter at start of array */ - s = pThis->socks + 1; + *pLstnArrSize = 0; /* num of sockets counter at start of array */ for(r = res; r != NULL ; r = r->ai_next) { - *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol); - if (*s < 0) { + sock = socket(r->ai_family, r->ai_socktype, r->ai_protocol); + if(sock < 0) { if(!(r->ai_family == PF_INET6 && errno == EAFNOSUPPORT)) - dbgprintf("creating tcp listen socket"); + dbgprintf("error %d creating tcp listen socket", errno); /* it is debatable if PF_INET with EAFNOSUPPORT should * also be ignored... */ @@ -301,35 +295,32 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort) } #ifdef IPV6_V6ONLY - if (r->ai_family == AF_INET6) { + if(r->ai_family == AF_INET6) { int iOn = 1; - if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY, + if(setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&iOn, sizeof (iOn)) < 0) { - close(*s); - *s = -1; - continue; + close(sock); + continue; } } #endif - if(setsockopt(*s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) { + if(setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0 ) { dbgprintf("error %d setting tcp socket option\n", errno); - close(*s); - *s = -1; + close(sock); continue; } /* We use non-blocking IO! */ - if((sockflags = fcntl(*s, F_GETFL)) != -1) { + if((sockflags = fcntl(sock, F_GETFL)) != -1) { sockflags |= O_NONBLOCK; /* SETFL could fail too, so get it caught by the subsequent * error check. */ - sockflags = fcntl(*s, F_SETFL, sockflags); + sockflags = fcntl(sock, F_SETFL, sockflags); } if(sockflags == -1) { dbgprintf("error %d setting fcntl(O_NONBLOCK) on tcp socket", errno); - close(*s); - *s = -1; + close(sock); continue; } @@ -340,62 +331,75 @@ LstnInit(nsd_t *pNsd, uchar *pLstnPort) */ #ifndef BSD if(net.should_use_so_bsdcompat()) { - if (setsockopt(*s, SOL_SOCKET, SO_BSDCOMPAT, + if (setsockopt(sock, SOL_SOCKET, SO_BSDCOMPAT, (char *) &on, sizeof(on)) < 0) { errmsg.LogError(NO_ERRCODE, "TCP setsockopt(BSDCOMPAT)"); - close(*s); - *s = -1; + close(sock); continue; } } #endif - if( (bind(*s, r->ai_addr, r->ai_addrlen) < 0) + if( (bind(sock, r->ai_addr, r->ai_addrlen) < 0) #ifndef IPV6_V6ONLY && (errno != EADDRINUSE) #endif ) { + /* TODO: check if *we* bound the socket - else we *have* an error! */ dbgprintf("error %d while binding tcp socket", errno); - close(*s); - *s = -1; + close(sock); continue; } - if(listen(*s,pThis->iSessMax / 10 + 5) < 0) { + if(listen(sock, iSessMax / 10 + 5) < 0) { /* If the listen fails, it most probably fails because we ask * for a too-large backlog. So in this case we first set back * to a fixed, reasonable, limit that should work. Only if * that fails, too, we give up. */ dbgprintf("listen with a backlog of %d failed - retrying with default of 32.", - pThis->iSessMax / 10 + 5); - if(listen(*s, 32) < 0) { + iSessMax / 10 + 5); + if(listen(sock, 32) < 0) { dbgprintf("tcp listen error %d, suspending\n", errno); - close(*s); - *s = -1; + close(sock); continue; } } - (*pThis->socks)++; - s++; + /* if we reach this point, we were able to obtain a valid socket, which we + * now can save to the array of listen sockets. -- rgerhards, 2008-04-22 + */ + CHKiRet(nsd_ptcpConstruct(arrLstn+*pLstnArrSize)); + arrLstn[*pLstnArrSize]->sock = sock; + ++(*pLstnArrSize); } if(res != NULL) freeaddrinfo(res); - if(*pThis->socks != maxs) - dbgprintf("We could initialize %d RELP TCP listen sockets out of %d we received " - "- this may or may not be an error indication.\n", *pThis->socks, maxs); + if(*pLstnArrSize != maxs) + dbgprintf("We could initialize %d TCP listen sockets out of %d we received " + "- this may or may not be an error indication.\n", *pLstnArrSize, maxs); - if(*pThis->socks == 0) { - dbgprintf("No RELP TCP listen socket could successfully be initialized, " - "message reception via RELP disabled.\n"); - free(pThis->socks); + if(*pLstnArrSize == 0) { + dbgprintf("No TCP listen sockets could successfully be initialized, " + "message reception disabled.\n"); ABORT_FINALIZE(RS_RET_COULD_NOT_BIND); } + *parrLstnNsd = (nsd_t**) arrLstn; + arrLstn = NULL; /* prevent from being freed in error handler */ + finalize_it: + if(iRet != RS_RET_OK) { + if(res != NULL) + freeaddrinfo(res); + if(arrLstn != NULL) { + for(maxs = 0 ; maxs < *pLstnArrSize ; ++maxs) + nsd_ptcpDestruct(arrLstn+*pLstnArrSize); + } + } + RETiRet; } @@ -494,10 +498,7 @@ finalize_it: freeaddrinfo(res); if(iRet != RS_RET_OK) { - if(pThis->sock != -1) { - close(pThis->sock); - pThis->sock = -1; - } + sockClose(&pThis->sock); } RETiRet; @@ -519,10 +520,10 @@ CODESTARTobjQueryInterface(nsd_ptcp) pIf->Construct = (rsRetVal(*)(nsd_t**)) nsd_ptcpConstruct; pIf->Destruct = (rsRetVal(*)(nsd_t**)) nsd_ptcpDestruct; pIf->Abort = Abort; - pIf->LstnInit = LstnInit; - pIf->AcceptConnReq = AcceptConnReq; pIf->Rcv = Rcv; pIf->Send = Send; + pIf->LstnInit = LstnInit; + pIf->AcceptConnReq = AcceptConnReq; pIf->Connect = Connect; finalize_it: ENDobjQueryInterface(nsd_ptcp) |