/*! \brief It translates an address from the 'presentation' form into the 'network' form. This function basically replaces inet_pton(), which does not exist in WIN32 because the same result can be obtained by using the getaddrinfo(). An addictional advantage is that 'Address' can be both a numeric address (e.g. '127.0.0.1', like in inet_pton() ) and a literal name (e.g. 'localhost'). This function does the reverse job of sock_getascii_addrport(). \param address: a zero-terminated string which contains the name you have to translate. The name can be either literal (e.g. 'localhost') or numeric (e.g. '::1'). \param sockaddr: a user-allocated sockaddr_storage structure which will contains the 'network' form of the requested address. \param addr_family: a constant which can assume the following values: - 'AF_INET' if we want to ping an IPv4 host - 'AF_INET6' if we want to ping an IPv6 host - 'AF_UNSPEC' if we do not have preferences about the protocol used to ping the host \param errbuf: a pointer to an user-allocated buffer that will contain the complete error message. This buffer has to be at least 'errbuflen' in length. It can be NULL; in this case the error cannot be printed. \param errbuflen: length of the buffer that will contains the error. The error message cannot be larger than 'errbuflen - 1' because the last char is reserved for the string terminator. \return '-1' if the translation succeded, '-2' if there was some non critical error, '0' otherwise. In case it fails, the content of the SockAddr variable remains unchanged. A 'non critical error' can occur in case the 'Address' is a literal name, which can be mapped to several network addresses (e.g. 'foo.bar.com' => '10.2.2.2' and '10.2.2.3'). In this case the content of the SockAddr parameter will be the address corresponding to the first mapping. \warning The sockaddr_storage structure MUST be allocated by the user. */ int sock_present2network(const char *address, struct sockaddr_storage *sockaddr, int addr_family, char *errbuf, int errbuflen) { int retval; struct addrinfo *addrinfo; struct addrinfo hints; memset(&hints, 0, sizeof(hints) ); hints.ai_family= addr_family; if ( (retval= sock_initaddress(address, "22222" /* fake port */, &hints, &addrinfo, errbuf, errbuflen)) == -1 ) return 0; if (addrinfo->ai_family == PF_INET) memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in) ); else memcpy(sockaddr, addrinfo->ai_addr, sizeof(struct sockaddr_in6) ); if (addrinfo->ai_next != NULL) { freeaddrinfo(addrinfo); if (errbuf) { snprintf(errbuf, errbuflen, "More than one socket requested; using the first one returned"); errbuf[errbuflen - 1]= 0; } return -2; } freeaddrinfo(addrinfo); return -1; }
void Client(char *Address, char *Port, int AddressFamily, int TransportProtocol) { char ErrBuf[1024]; char DataBuffer[1024]; int ClientSocket; // keeps the socket ID for this connection struct addrinfo Hints; // temporary struct to keep settings needed to open the new socket struct addrinfo *AddrInfo; // keeps the addrinfo chain; required to open a new socket int WrittenBytes; // Number of bytes written on the socket // Prepare to open a new server socket memset(&Hints, 0, sizeof(struct addrinfo)); Hints.ai_family= AddressFamily; Hints.ai_socktype= TransportProtocol; // Open a TCP or UDP connection if (sock_initaddress (Address, Port, &Hints, &AddrInfo, ErrBuf, sizeof(ErrBuf)) == sockFAILURE) { printf("Error resolving given address/port: %s\n\n", ErrBuf); return; } printf("Trying to connect to server on address %s, port %s, using protocol %s\n", Address ? Address : "all local addresses", Port, (AddrInfo->ai_family == AF_INET) ? "IPv4" : "IPv6"); if ( (ClientSocket= sock_open(AddrInfo, 0, 0, ErrBuf, sizeof(ErrBuf))) == sockFAILURE) { // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); printf("Cannot opening the socket: %s\n\n", ErrBuf); return; } // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); printf("Connection established.\n"); printf("Type the string you want to send to the server: "); // Warning: possible buffer overflow here fgets(DataBuffer, sizeof(DataBuffer), stdin); // fgets reads also the newline character, so we have to reset it DataBuffer[strlen(DataBuffer) - 1]= 0; printf("\n\n"); WrittenBytes= sock_send(ClientSocket, DataBuffer, strlen(DataBuffer), ErrBuf, sizeof(ErrBuf)); if (WrittenBytes == sockFAILURE) { printf("Error sending data: %s\n\n", ErrBuf); return; } printf("String '%s' sent. Press ENTER to terminate the program\n", DataBuffer); fgets(DataBuffer, sizeof(DataBuffer), stdin); }
void *doControlConnection(void *parameters) { int AddressFamily = AF_INET; //use IPv4 int TransportProtocol = SOCK_STREAM; //use TCP char ErrBuf[1024]; char DataBuffer[1024]; int ChildSocket; // keeps the socket ID for connections from clients struct addrinfo Hints; // temporary struct to keep settings needed to open the new socket struct addrinfo *AddrInfo; // keeps the addrinfo chain; required to open a new socket struct sockaddr_storage From; // temp variable that keeps the parameters of the incoming connection int ReadBytes, WrittenBytes; int ServerSocket; // Prepare to open a new server socket memset(&Hints, 0, sizeof(struct addrinfo)); Hints.ai_family= AddressFamily; Hints.ai_socktype= TransportProtocol; // Open a TCP/UDP connection Hints.ai_flags = AI_PASSIVE; // This is a server: ready to bind() a socket if (sock_initaddress (NULL, nf_params.tcp_port, &Hints, &AddrInfo, ErrBuf, sizeof(ErrBuf)) == sockFAILURE) { fprintf(logFile,"%s Error resolving given port (%s): %s\n",module_name, nf_params.tcp_port,ErrBuf); exit(EXIT_FAILURE); } if ( (ServerSocket= sock_open(AddrInfo, 1, 10, ErrBuf, sizeof(ErrBuf))) == sockFAILURE) { // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); fprintf(logFile,"%s Cannot opening the socket: %s\n",module_name, ErrBuf); exit(EXIT_FAILURE); } // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); while(1) { if ( (ChildSocket= sock_accept(ServerSocket, &From, ErrBuf, sizeof(ErrBuf))) == sockFAILURE) { fprintf(logFile,"%s Error when accepting a new connection: %s\n",module_name, ErrBuf); exit(EXIT_FAILURE); } ReadBytes= sock_recv(ChildSocket, DataBuffer, sizeof(DataBuffer), SOCK_RECEIVEALL_NO, 0/*no timeout*/, ErrBuf, sizeof(ErrBuf)); if (ReadBytes == sockFAILURE) { fprintf(logFile,"%s Error reading data: %s\n",module_name, ErrBuf); exit(EXIT_FAILURE); } // Terminate buffer, just for printing purposes // Warning: this can originate a buffer overflow DataBuffer[ReadBytes]= 0; fprintf(logFile,"%sData received (%d bytes):\n",module_name, ReadBytes); fprintf(logFile,"%s %s\n",module_name,DataBuffer); char answer[1024]; sprintf(answer,"Greeting from network function\"%s\"",nf_params.nf_name); fprintf(logFile,"%s Answer to be sent: %s\n",module_name,answer); WrittenBytes= sock_send(ChildSocket, answer, strlen(answer), ErrBuf, sizeof(ErrBuf)); if (WrittenBytes == sockFAILURE) { fprintf(logFile,"%s Error sending data: %s",module_name, ErrBuf); exit(EXIT_FAILURE); } sock_close(ChildSocket,ErrBuf,sizeof(ErrBuf)); } }
void Server(char *Address, char *Port, int AddressFamily, int TransportProtocol) { char ErrBuf[1024]; char DataBuffer[1024]; int ServerSocket, ChildSocket; // keeps the socket ID for this connection struct addrinfo Hints; // temporary struct to keep settings needed to open the new socket struct addrinfo *AddrInfo; // keeps the addrinfo chain; required to open a new socket struct sockaddr_storage From; // temp variable that keeps the parameters of the incoming connection int ReadBytes; // Number of bytes read from the socket char RemoteAddress[1024]; // temp variable to store the address of the connecting host char RemotePort[1024]; // temp variable to store the port used by the connecting host // Prepare to open a new server socket memset(&Hints, 0, sizeof(struct addrinfo)); Hints.ai_family= AddressFamily; Hints.ai_socktype= TransportProtocol; // Open a TCP/UDP connection Hints.ai_flags = AI_PASSIVE; // This is a server: ready to bind() a socket if (sock_initaddress (Address, Port, &Hints, &AddrInfo, ErrBuf, sizeof(ErrBuf)) == sockFAILURE) { printf("Error resolving given address/port: %s\n\n", ErrBuf); return; } printf("Server waiting on address %s, port %s, using protocol %s\n", Address ? Address : "all local addresses", Port, (AddrInfo->ai_family == AF_INET) ? "IPv4" : "IPv6"); if ( (ServerSocket= sock_open(AddrInfo, 1, 10, ErrBuf, sizeof(ErrBuf))) == sockFAILURE) { // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); printf("Cannot opening the socket: %s\n\n", ErrBuf); return; } // AddrInfo is no longer required sock_freeaddrinfo(AddrInfo); if (TransportProtocol == SOCK_STREAM) { if ( (ChildSocket= sock_accept(ServerSocket, &From, ErrBuf, sizeof(ErrBuf))) == sockFAILURE) { printf("Error when accepting a new connection: %s\n\n", ErrBuf); return; } if (sock_getascii_addrport(&From, RemoteAddress, sizeof(RemoteAddress), RemotePort, sizeof(RemotePort), NI_NUMERICHOST | NI_NUMERICSERV, ErrBuf, sizeof(ErrBuf)) == sockFAILURE) { printf("Error getting information related to the connecting host: %s\n\n", ErrBuf); return; } printf("Accepting a new connection from host %s, using remote port %s.\n\n", RemoteAddress, RemotePort); ReadBytes= sock_recv(ChildSocket, DataBuffer, sizeof(DataBuffer), SOCK_RECEIVEALL_NO, 30, ErrBuf, sizeof(ErrBuf)); if (ReadBytes == sockFAILURE) { printf("Error reading data: %s\n\n", ErrBuf); return; } } else { ReadBytes= sock_recvdgram(ServerSocket, DataBuffer, sizeof(DataBuffer), SOCK_RECEIVEALL_NO, 30, ErrBuf, sizeof(ErrBuf)); if (ReadBytes == sockFAILURE) { printf("Error reading data: %s\n\n", ErrBuf); return; } } if (ReadBytes == sockWARNING) { printf("We waited for enough time and no data has been received so far.\nAborting the connection.\n\n"); return; } // Terminate buffer, just for printing purposes // Warning: this can originate a buffer overflow DataBuffer[ReadBytes]= 0; printf("Received the following string: '%s'\n\n", DataBuffer); }
/* \param plen: the length of the current message (needed in order to be able to discard excess data in the message, if present) */ pcap_t *daemon_startcapture(SOCKET sockctrl, pthread_t *threaddata, char *source, int active, struct rpcap_sampling *samp_param, uint32 plen, char *errbuf) { char portdata[PCAP_BUF_SIZE]; // temp variable needed to derive the data port char peerhost[PCAP_BUF_SIZE]; // temp variable needed to derive the host name of our peer pcap_t *fp= NULL; // pcap_t main variable unsigned int nread; // number of bytes of the payload read from the socket char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered int sendbufidx= 0; // index which keeps the number of bytes currently buffered // socket-related variables SOCKET sockdata= 0; // socket descriptor of the data connection struct addrinfo hints; // temp, needed to open a socket connection struct addrinfo *addrinfo; // temp, needed to open a socket connection struct sockaddr_storage saddr; // temp, needed to retrieve the network data port chosen on the local machine socklen_t saddrlen; // temp, needed to retrieve the network data port chosen on the local machine pthread_attr_t detachedAttribute; // temp, needed to set the created thread as detached // RPCAP-related variables struct rpcap_startcapreq startcapreq; // start capture request message struct rpcap_startcapreply *startcapreply; // start capture reply message int serveropen_dp; // keeps who is going to open the data connection addrinfo= NULL; if ( (nread= sock_recv(sockctrl, (char *) &startcapreq, sizeof(struct rpcap_startcapreq), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1) return NULL; startcapreq.flags= ntohs(startcapreq.flags); // Open the selected device if ( (fp= pcap_open(source, ntohl(startcapreq.snaplen), (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_PROMISC) ? PCAP_OPENFLAG_PROMISCUOUS : 0 /* local device, other flags not needed */, ntohl(startcapreq.read_timeout), NULL /* local device, so no auth */, errbuf)) == NULL) { rpcap_senderror(sockctrl, errbuf, PCAP_ERR_OPEN, NULL); return NULL; } // Apply sampling parameters fp->rmt_samp.method= samp_param->method; fp->rmt_samp.value= samp_param->value; /* We're in active mode if: - we're using TCP, and the user wants us to be in active mode - we're using UDP */ serveropen_dp= (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_SERVEROPEN) || (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) || active; /* Gets the sockaddr structure referred to the other peer in the ctrl connection We need that because: - if we're in passive mode, we need to know the address family we want to use (the same used for the ctrl socket) - if we're in active mode, we need to know the network address of the other host we want to connect to */ saddrlen = sizeof(struct sockaddr_storage); if (getpeername(sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1) { sock_geterror("getpeername(): ", errbuf, PCAP_ERRBUF_SIZE); goto error; } memset(&hints, 0, sizeof(struct addrinfo) ); hints.ai_socktype = (startcapreq.flags & RPCAP_STARTCAPREQ_FLAG_DGRAM) ? SOCK_DGRAM : SOCK_STREAM; hints.ai_family = saddr.ss_family; // Now we have to create a new socket to send packets if (serveropen_dp) // Data connection is opened by the server toward the client { sprintf(portdata, "%d", ntohs(startcapreq.portdata) ); // Get the name of the other peer (needed to connect to that specific network address) if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, peerhost, sizeof(peerhost), NULL, 0, NI_NUMERICHOST) ) { sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); goto error; } if (sock_initaddress(peerhost, portdata, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) goto error; if ( (sockdata= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1) goto error; } else // Data connection is opened by the client toward the server { hints.ai_flags = AI_PASSIVE; // Let's the server socket pick up a free network port for us if (sock_initaddress(NULL, "0", &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) goto error; if ( (sockdata= sock_open(addrinfo, SOCKOPEN_SERVER, 1 /* max 1 connection in queue */, errbuf, PCAP_ERRBUF_SIZE)) == -1) goto error; // get the complete sockaddr structure used in the data connection saddrlen = sizeof(struct sockaddr_storage); if (getsockname(sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1) { sock_geterror("getsockname(): ", errbuf, PCAP_ERRBUF_SIZE); goto error; } // Get the local port the system picked up if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, NULL, 0, portdata, sizeof(portdata), NI_NUMERICSERV) ) { sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE); goto error; } } // addrinfo is no longer used freeaddrinfo(addrinfo); addrinfo= NULL; // save the socket ID for the next calls fp->rmt_sockctrl= sockctrl; // Needed to send an error on the ctrl connection // Now I can set the filter if ( daemon_unpackapplyfilter(fp, &nread, &plen, errbuf) ) goto error; // Now, I can send a RPCAP start capture reply message if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) goto error; rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STARTCAP_REPLY, 0, sizeof(struct rpcap_startcapreply) ); startcapreply= (struct rpcap_startcapreply *) &sendbuf[sendbufidx]; if ( sock_bufferize(NULL, sizeof(struct rpcap_startcapreply), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1) goto error; memset(startcapreply, 0, sizeof(struct rpcap_startcapreply) ); startcapreply->bufsize= htonl(fp->bufsize); if (!serveropen_dp) { unsigned short port = (unsigned short)strtoul(portdata,NULL,10); startcapreply->portdata= htons(port); } if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1) goto error; if (!serveropen_dp) { SOCKET socktemp; // We need another socket, since we're going to accept() a connection // Connection creation saddrlen = sizeof(struct sockaddr_storage); socktemp= accept(sockdata, (struct sockaddr *) &saddr, &saddrlen); if (socktemp == -1) { sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE); goto error; } // Now that I accepted the connection, the server socket is no longer needed sock_close(sockdata, errbuf, PCAP_ERRBUF_SIZE); sockdata= socktemp; } fp->rmt_sockdata= sockdata; /* GV we need this to create the thread as detached. */ /* GV otherwise, the thread handle is not destroyed */ pthread_attr_init(&detachedAttribute); pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED); // Now we have to create a new thread to receive packets if ( pthread_create(threaddata, &detachedAttribute, (void *) daemon_thrdatamain, (void *) fp) ) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error creating the data thread"); pthread_attr_destroy(&detachedAttribute); goto error; } pthread_attr_destroy(&detachedAttribute); // Check if all the data has been read; if not, discard the data in excess if (nread != plen) sock_discard(sockctrl, plen - nread, NULL, 0); return fp; error: rpcap_senderror(sockctrl, errbuf, PCAP_ERR_STARTCAPTURE, NULL); if (addrinfo) freeaddrinfo(addrinfo); if (threaddata) pthread_cancel(*threaddata); if (sockdata) sock_close(sockdata, NULL, 0); // Check if all the data has been read; if not, discard the data in excess if (nread != plen) sock_discard(sockctrl, plen - nread, NULL, 0); if (fp) { pcap_close(fp); fp= NULL; } return NULL; }
/*! \brief 'true' main of the program in case the active mode is turned on. It does not have any return value nor parameters. This function loops forever trying to connect to the remote host, until the daemon is turned down. \param ptr: it keeps the 'activepars' parameters. It is a 'void *' just because pthreads want this format. */ void main_active(void *ptr) { char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed SOCKET sockctrl; // keeps the socket ID for this control connection struct addrinfo hints; // temporary struct to keep settings needed to open the new socket struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket struct active_pars *activepars; struct daemon_slpars *pars; // parameters needed by the daemon_serviceloop() activepars= (struct active_pars *) ptr; // Prepare to open a new server socket memset(&hints, 0, sizeof(struct addrinfo)); // WARNING Currently it supports only ONE socket family among IPv4 and IPv6 hints.ai_family = AF_INET; // PF_UNSPEC to have both IPv4 and IPv6 server hints.ai_socktype = SOCK_STREAM; hints.ai_family= activepars->ai_family; log_info("Connecting to host %s, port %s, using protocol %s", activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified"); // Initialize errbuf memset(errbuf, 0, sizeof(errbuf) ); // Do the work if (sock_initaddress(activepars->address, activepars->port, &hints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) { log_warn("%s", errbuf); return; } while (1) { int activeclose; if ( (sockctrl= sock_open(addrinfo, SOCKOPEN_CLIENT, 0, errbuf, PCAP_ERRBUF_SIZE)) == -1) { log_warn("%s", errbuf); snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error connecting to host %s, port %s, using protocol %s", activepars->address, activepars->port, (hints.ai_family == AF_INET) ? "IPv4": (hints.ai_family == AF_INET6) ? "IPv6" : "Unspecified" ); log_warn("%s", errbuf); pthread_suspend(RPCAP_ACTIVE_WAIT * 1000); continue; } pars= (struct daemon_slpars *) malloc ( sizeof(struct daemon_slpars) ); if (pars == NULL) { snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno)); continue; } pars->sockctrl= sockctrl; pars->activeclose= 0; pars->isactive= 1; pars->nullAuthAllowed= nullAuthAllowed; pars->preselected_ifname = (activepars->ifname[0] != '\0') ? activepars->ifname : NULL; daemon_serviceloop( (void *) pars); activeclose= pars->activeclose; free(pars); // If the connection is closed by the user explicitely, don't try to connect to it again // just exit the program if (activeclose == 1) break; } }
void main_startup(void) { char errbuf[PCAP_ERRBUF_SIZE + 1]; // keeps the error string, prior to be printed struct addrinfo *addrinfo; // keeps the addrinfo chain; required to open a new socket int i; #ifdef WIN32 pthread_t threadId; // Pthread variable that keeps the thread structures pthread_attr_t detachedAttribute; // PThread attribute needed to create the thread as detached #else pid_t pid; #endif i= 0; addrinfo= NULL; memset(errbuf, 0, sizeof(errbuf) ); // Starts all the active threads while ( (activelist[i].address[0] != 0) && (i < MAX_ACTIVE_LIST) ) { activelist[i].ai_family= mainhints.ai_family; // use global preselected interface if not set in config file if ((activelist[i].ifname[0] == '\0') && (rpcapd_opt.preselected_ifname[0] != '\0')) { snprintf(activelist[i].ifname, sizeof(activelist[i].ifname), "%s", rpcapd_opt.preselected_ifname); } #ifdef WIN32 /* GV we need this to create the thread as detached. */ /* GV otherwise, the thread handle is not destroyed */ pthread_attr_init(&detachedAttribute); pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED); if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_active, (void *) &activelist[i]) ) { log_warn("Error creating the active child thread"); pthread_attr_destroy(&detachedAttribute); continue; } pthread_attr_destroy(&detachedAttribute); #else if ( (pid= fork() ) == 0) // I am the child { main_active( (void *) &activelist[i]); exit(0); } #endif i++; } /* The code that manages the active connections is not blocking; vice versa, the code that manages the passive connection is blocking. So, if the user do not want to run in passive mode, we have to block the main thread here, otherwise the program ends and all threads are stopped. WARNING: this means that in case we have only active mode, the program does not terminate even if all the child thread terminates. The user has always to press Ctrl+C (or send a SIGTERM) to terminate the program. */ if (passivemode) { struct addrinfo *tempaddrinfo; // Do the work if (sock_initaddress((address[0]) ? address : NULL, port, &mainhints, &addrinfo, errbuf, PCAP_ERRBUF_SIZE) == -1) { log_warn("%s", errbuf); return; } tempaddrinfo= addrinfo; while (tempaddrinfo) { SOCKET *socktemp; if ( (sockmain= sock_open(tempaddrinfo, SOCKOPEN_SERVER, SOCKET_MAXCONN, errbuf, PCAP_ERRBUF_SIZE)) == -1) { log_warn("%s", errbuf); tempaddrinfo= tempaddrinfo->ai_next; continue; } // This trick is needed in order to allow the child thread to save the 'sockmain' variable // withouth getting it overwritten by the sock_open, in case we want to open more than one waiting sockets // For instance, the pthread_create() will accept the socktemp variable, and it will deallocate immediately that variable socktemp= (SOCKET *) malloc (sizeof (SOCKET)); if (socktemp == NULL) exit(0); *socktemp= sockmain; #ifdef WIN32 /* GV we need this to create the thread as detached. */ /* GV otherwise, the thread handle is not destroyed */ pthread_attr_init(&detachedAttribute); pthread_attr_setdetachstate(&detachedAttribute, PTHREAD_CREATE_DETACHED); if ( pthread_create( &threadId, &detachedAttribute, (void *) &main_passive, (void *) socktemp ) ) { log_warn("Error creating the passive child thread"); pthread_attr_destroy(&detachedAttribute); continue; } pthread_attr_destroy(&detachedAttribute); #else if ( (pid= fork() ) == 0) // I am the child { main_passive( (void *) socktemp); return; } #endif tempaddrinfo= tempaddrinfo->ai_next; } freeaddrinfo(addrinfo); } // All the previous calls are no blocking, so the main line of execution goes here // and I have to avoid that the program terminates while (1) pthread_suspend(10*60*1000); // it wakes up every 10 minutes; it seems to me reasonable }