📄 pcap-new.c
字号:
{
// socket-related variables
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; // generic sockaddr_storage variable
socklen_t fromlen; // keeps the length of the sockaddr_storage variable
SOCKET sockctrl; // keeps the main socket identifier
struct activehosts *temp, *prev; // temp var needed to scan he host list chain
*connectinghost= 0; // just in case
// 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_flags = AI_PASSIVE; // Ready to a bind() socket
hints.ai_socktype = SOCK_STREAM;
// Warning: this call can be the first one called by the user.
// For this reason, we have to initialize the WinSock support.
if (sock_init(errbuf) == -1)
return -1;
// Do the work
if ((port == NULL) || (port[0] == 0) )
{
if (sock_validaddr(address, RPCAP_DEFAULT_NETPORT_ACTIVE, &hints, &addrinfo, errbuf) == -1)
{
SOCK_ASSERT(errbuf, 1);
return -2;
}
}
else
{
if (sock_validaddr(address, port, &hints, &addrinfo, errbuf) == -1)
{
SOCK_ASSERT(errbuf, 1);
return -2;
}
}
if ( (sockmain= sock_open(addrinfo, SOCKOPEN_SERVER, 1, errbuf)) == -1)
{
SOCK_ASSERT(errbuf, 1);
return -2;
}
// Connection creation
fromlen = sizeof(struct sockaddr_storage);
sockctrl= accept(sockmain, (struct sockaddr *) &from, &fromlen);
// We're not using sock_close, since we do not want to send a shutdown
// (which is not allowed on a non-connected socket)
closesocket(sockmain);
sockmain= 0;
if (sockctrl == -1)
{
sock_geterror("accept(): ", errbuf, PCAP_ERRBUF_SIZE);
return -2;
}
// Get the numeric for of the name of the connecting host
if (getnameinfo( (struct sockaddr *) &from, fromlen, connectinghost,
RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
{
sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
sock_close(sockctrl, fakeerrbuf);
return -1;
}
// checks if the connecting host is among the ones allowed
if ( (hostlist) && (hostlist[0]) )
{
if (sock_check_hostlist((char *) hostlist, RPCAP_HOSTLIST_SEP, &from, errbuf) )
{
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
sock_close(sockctrl, fakeerrbuf);
return -1;
}
}
// Send authentication to the remote machine
if ( rpcap_sendauth(sockctrl, auth, errbuf) == -1)
{
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
sock_close(sockctrl, fakeerrbuf);
return -3;
}
// Checks that this host does not already have a cntrl connection in place
// Initialize pointers
temp= activeHosts;
prev= NULL;
while (temp)
{
// This host already has an active connection in place, so I don't have to update the host list
if (sock_cmpaddr(&temp->host, &from) == 0)
return sockctrl;
prev= temp;
temp= temp->next;
}
// The host does not exist in the list; so I have to update the list
if (prev)
{
prev->next= (struct activehosts *) malloc (sizeof (struct activehosts) );
temp= prev->next;
}
else
{
activeHosts= (struct activehosts *) malloc (sizeof (struct activehosts) );
temp= activeHosts;
}
if (temp == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_REMOTEACCEPT, fakeerrbuf);
sock_close(sockctrl, fakeerrbuf);
return -1;
}
memcpy(&temp->host, &from, fromlen);
temp->sockctrl= sockctrl;
temp->next= NULL;
return sockctrl;
}
/*! \ingroup remote_func
\brief It drops an active connection (active mode only).
This function has been defined to allow the client dealing with the 'active mode'.
This function closes an active connection that is still in place and it purges
the host name from the 'activeHost' list.
From this point on, the client will not have any connection with that host in place.
\param host: a string that keeps the host name of the host for which we want to
close the active connection.
\param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
that will contain the error message (in case there is one).
\return '0' if everything is fine, '-1' if some errors occurred. The error message is
returned into the errbuf variable.
*/
int pcap_remoteact_close(const char *host, char *errbuf)
{
struct activehosts *temp, *prev; // temp var needed to scan the host list chain
struct addrinfo hints, *addrinfo, *ai_next; // temp var needed to translate between hostname to its address
int retval;
temp= activeHosts;
prev= NULL;
// retrieve the network address corresponding to 'host'
addrinfo = NULL;
memset(&hints, 0, sizeof (struct addrinfo) );
hints.ai_family = PF_UNSPEC;
hints.ai_socktype= SOCK_STREAM;
retval = getaddrinfo(host, "0", &hints, &addrinfo);
if (retval != 0)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "getaddrinfo() %s", gai_strerror(retval));
return -1;
}
while (temp)
{
ai_next= addrinfo;
while(ai_next)
{
if (sock_cmpaddr(&temp->host, (struct sockaddr_storage *) ai_next->ai_addr ) == 0)
{
struct rpcap_header header;
// Close this connection
rpcap_createhdr( &header, RPCAP_MSG_CLOSE, 0, 0);
// I don't check for errors, since I'm going to close everything
sock_send(temp->sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf);
if (sock_close(temp->sockctrl, errbuf) )
{
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
return -1;
}
if (prev)
prev->next= temp->next;
else
activeHosts= temp->next;
freeaddrinfo(addrinfo);
free(temp);
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
return 0;
}
ai_next= ai_next->ai_next;
}
prev= temp;
temp= temp->next;
}
if (addrinfo)
freeaddrinfo(addrinfo);
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host you want to close the active connection is not known");
return -1;
}
/*! \ingroup remote_func
\brief Cleans the socket that is currently used in waiting active connections.
This function does a very dirty job. The fact is that is the waiting socket is not
freed if the pcap_remoteaccept() is killed inside a new thread. This function is
able to clean the socket in order to allow the next calls to pcap_remoteact_accept() to work.
This function is useful *only* if you launch pcap_remoteact_accept() inside a new thread,
and you stops (not very gracefully) the thread (for example because the user changed idea,
and it does no longer want to wait for an active connection).
So, basically, the flow should be the following:
- launch a new thread
- call the pcap_remoteact_accept
- if this new thread is killed, call pcap_remoteact_cleanup().
This function has no effects in other cases.
\return None.
*/
void pcap_remoteact_cleanup()
{
// Very dirty, but it works
if (sockmain)
{
closesocket(sockmain);
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
}
}
/*! \ingroup remote_func
\brief Returns the hostname of the host that have an active connection with us (active mode only).
This function has been defined to allow the client dealing with the 'active mode'.
This function returns the list of hosts that are currently having an active connection
with us. This function is useful in order to delete an active connection that is still
in place.
\param hostlist: a user-allocated string that will keep the list of host that are
currently connected with us.
\param sep: the character that has to be sued as a separator between the hosts (',' for example).
\param size: size of the hostlist buffer.
\param errbuf: a pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
that will contain the error message (in case there is one).
\return '0' if everything is fine, '-1' if some errors occurred. The error message is
returned into the errbuf variable.
*/
int pcap_remoteact_list(char *hostlist, char sep, int size, char *errbuf)
{
struct activehosts *temp; // temp var needed to scan the host list chain
int len;
char hoststr[RPCAP_HOSTLIST_SIZE + 1];
temp= activeHosts;
len= 0;
*hostlist= 0;
while (temp)
{
// Get the numeric for of the name of the connecting host
if (getnameinfo( (struct sockaddr *) &temp->host, sizeof (struct sockaddr_storage), hoststr,
RPCAP_HOSTLIST_SIZE, NULL, 0, NI_NUMERICHOST) )
{
sock_geterror("getnameinfo(): ", errbuf, PCAP_ERRBUF_SIZE);
return -1;
}
len= len + strlen(hoststr) + 1 /* the separator */;
if (len >= size)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The string you provided is not able to keep "
"the hostnames for all the active connections");
return -1;
}
strcat(hostlist, hoststr);
hostlist[len - 1]= sep;
hostlist[len]= 0;
temp= temp->next;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -