📄 pcap-new.c
字号:
if ( (nread+= sock_recv(sockctrl, dev->description, findalldevs_if.desclen, errbuf) ) == -1)
goto error;
dev->description[findalldevs_if.desclen]= 0;
}
else
dev->description= NULL;
dev->flags= ntohl(findalldevs_if.flags);
naddr= 0;
// loop until all addresses have been received
for (j= 0; j < findalldevs_if.naddr; j++)
{
struct rpcap_findalldevs_ifaddr ifaddr;
// Retrieve the interface addresses
if ( (nread+= sock_recv(sockctrl, (char *) &ifaddr,
sizeof(struct rpcap_findalldevs_ifaddr), errbuf) ) == -1)
goto error;
// WARNING libpcap bug: the address listing is available only for AF_INET
if ( ntohs(ifaddr.addr.ss_family) == AF_INET)
{
struct pcap_addr *addr;
if (naddr == 0)
{
dev->addresses= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
addr= dev->addresses;
}
else
{
addr->next= (struct pcap_addr *) malloc ( sizeof(struct pcap_addr) );
addr= addr->next;
}
naddr++;
if (addr == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
goto error;
}
addr->next= NULL;
if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.addr,
(struct sockaddr_storage **) &addr->addr, errbuf) == -1)
goto error;
if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.netmask,
(struct sockaddr_storage **) &addr->netmask, errbuf) == -1)
goto error;
if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.broadaddr,
(struct sockaddr_storage **) &addr->broadaddr, errbuf) == -1)
goto error;
if (rpcap_deseraddr( (struct sockaddr_storage *) &ifaddr.dstaddr,
(struct sockaddr_storage **) &addr->dstaddr, errbuf) == -1)
goto error;
if ( (addr->addr == NULL) && (addr->netmask == NULL) &&
(addr->broadaddr == NULL) && (addr->dstaddr == NULL) )
{
free(addr);
addr= NULL;
if (naddr == 1)
naddr= 0; // the first item of the list had NULL addresses
}
}
}
}
// Checks if all the data has been read; if not, discard the data in excess
if (nread != ntohl(header.plen))
{
if (sock_discard(sockctrl, ntohl(header.plen) - nread, errbuf) == 1)
return -1;
}
// Control connection has to be closed only in case the remote machine is in passive mode
if (!active)
{
// DO not send RPCAP_CLOSE, since we did not open a pcap_t; no need to free resources
if ( sock_close(sockctrl, errbuf) )
return -1;
}
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
return 0;
error:
// In case there has been an error, I don't want to overwrite it with a new one
// if the following call fails. I want to return always the original error.
//
// Take care: this connection can already be closed when we try to close it.
// This happens because a previous error in the rpcapd, which requested to
// closed the connection. In that case, we already recognized that into the
// rpspck_isheaderok() and we already acknowledged the closing.
// In that sense, this call is useless here (however it is needed in case
// the client generates the error).
// Checks if all the data has been read; if not, discard the data in excess
if (nread != ntohl(header.plen))
{
if (sock_discard(sockctrl, ntohl(header.plen) - nread, fakeerrbuf) == 1)
return -1;
}
// Control connection has to be closed only in case the remote machine is in passive mode
if (!active)
sock_close(sockctrl, fakeerrbuf);
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
return -1;
}
/*! \ingroup remote_func
\brief Accepts a set of strings (host name, port, ...), and it returns the complete
source string according to the new format (e.g. 'rpcap://1.2.3.4/eth0').
This function is provided in order to help the user to create the source string
according to the new format.
An unique source string is used in order to make easy for old applications to use the
remote facilities. Think about tcpdump, for example, which has only one way to specify
the interface on which the capture has to be started.
However, GUI-based programs can find more useful to specify hostname, port and
interface name separately. In that case, they can use this function to create the
source string before passing it to the pcap_open() function.
\param source: a user-allocated buffer that will contain the complete source string
wen the function returns.
This function assumes that the allocated buffer is at least PCAP_BUF_SIZE bytes.
\param type: its value tells the type of the source we want to create. It can assume
the following values:
- PCAP_SRC_FILE: if we want a local file
- PCAP_SRC_IFLOCAL: if we want a local interface
- PCAP_SRC_IFREMOTE: if we want a remote interface
\param host: an user-allocated buffer that keeps the host (e.g. "foo.bar.com") we
want to connect to.
It can be NULL in case we want to open an interface on a local host.
\param port: an user-allocated buffer that keeps the network port (e.g. "2002") we
want to use for the RPCAP protocol.
It can be NULL in case we want to open an interface on a local host.
\param name: an user-allocated buffer that keeps the interface name we want to use
(e.g. "eth0").
\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 string containing
the complete source is returned in the 'source' variable.
\warning If the source is longer than PCAP_BUF_SIZE, the excess characters are truncated.
*/
int pcap_createsrcstr(char *source, int type, const char *host, const char *port, const char *name, char *errbuf)
{
switch (type)
{
case PCAP_SRC_FILE:
{
strncpy(source, PCAP_SRC_FILE_KEY, PCAP_BUF_SIZE);
if ((name) && (*name) )
{
strncat(source, name, PCAP_BUF_SIZE);
return 0;
}
else
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The file name cannot be NULL.");
return -1;
}
}
case PCAP_SRC_IFREMOTE:
{
strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE);
if ((host) && (*host) )
{
if ( (strcspn(host, "aAbBcCdDeEfFgGhHjJkKlLmMnNoOpPqQrRsStTuUvVwWxXyYzZ")) == strlen(host) )
{
// the host name does not contains alphabetic chars. So, it is a numeric address
// In this case we have to include it between square brackets
strncat(source, "[", PCAP_BUF_SIZE);
strncat(source, host, PCAP_BUF_SIZE);
strncat(source, "]", PCAP_BUF_SIZE);
}
else
strncat(source, host, PCAP_BUF_SIZE);
if ((port) && (*port) )
{
strncat(source, ":", PCAP_BUF_SIZE);
strncat(source, port, PCAP_BUF_SIZE);
}
strncat(source, "/", PCAP_BUF_SIZE);
}
else
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The host name cannot be NULL.");
return -1;
}
if ((name) && (*name) )
{
strncat(source, name, PCAP_BUF_SIZE);
return 0;
}
else
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL.");
return -1;
}
}
case PCAP_SRC_IFLOCAL:
{
strncpy(source, PCAP_SRC_IF_KEY, PCAP_BUF_SIZE);
if ((name) && (*name) )
{
strncat(source, name, PCAP_BUF_SIZE);
return 0;
}
else
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name cannot be NULL.");
return -1;
}
}
default:
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
return -1;
}
}
}
/*! \ingroup remote_func
\brief Parses the source string and returns the pieces in which the source can be split.
This call is the other way round of pcap_createsrcstr().
It accepts a null-terminated string and it returns the parameters related
to the source. This includes:
- the type of the source (file, winpcap on a remote adapter, winpcap on local adapter),
which is determined by the source prefix (PCAP_SRC_IF_KEY and so on)
- the host on which the capture has to be started (only for remote captures)
- the 'raw' name of the source (file name, name of the remote adapter, name
of the local adapter), without the source prefix. The string returned does not
include the type of the source itself (i.e. the string returned does not include "file://"
or rpcap:// or such).
The user can omit some parameters in case it is not interested in them.
\param source: a null-terminated string containing the WinPcap source
\param type: pointer to an integer, which is used to return the code corrisponding to the
selected source. The code will be one of the following:
- PCAP_SRC_FILE
- PCAP_SRC_IFLOCAL
- PCAP_SRC_IFREMOTE
In case the source string does not exists (i.e. 'source == NULL') or it is empty
('*source == NULL'), it returns PCAP_SRC_IF_LOCAL (i.e. you are ready to
call pcap_open_live() ). This behavior is kept only for compatibility with older
applications (e.g. tcpdump); therefore we suggest to move to the new syntax for sources.
This parameter can be NULL in case the user is not interested in that.
\param host: user-allocated buffer (of size PCAP_BUF_SIZE) that is used to return
the host name on which the capture has to be started.
This value is meaningful only in case of remote capture; otherwise, the returned
string will be empty ("").
This parameter can be NULL in case the user is not interested in that.
\param port: user-allocated buffer (of size PCAP_BUF_SIZE) that is used to return
the port that has to be used by the RPCAP protocol to contact the other host.
This value is meaningful only in case of remote capture and if the user wants to use
a non-standard port; otherwise, the returned string will be empty ("").
In case of remote capture, an emply string means "use the standard RPCAP port".
This parameter can be NULL in case the user is not interested in that.
\param name: user-allocated buffer (of size PCAP_BUF_SIZE) that is used to return
the source name, without the source prefix.
If the name does not exist (for example because source contains 'rpcap://' that means
'default local adapter'), it returns NULL.
This parameter can be NULL in case the user is not interested in that.
\param errbuf: pointer to a user-allocated buffer (of size PCAP_ERRBUF_SIZE)
that will contain the error message (in case there is one).
This parameter can be NULL in case the user is not interested in that.
\return '0' if everything is fine, '-1' if some errors occurred. The requested values
(host name, network port, type of the source) are returned into the proper variables
passed by reference.
*/
int pcap_parsesrcstr(const char *source, int *type, char *host, char *port, char *name, char *errbuf)
{
char *ptr;
int ntoken;
char tmpname[PCAP_BUF_SIZE];
char tmphost[PCAP_BUF_SIZE];
char tmpport[PCAP_BUF_SIZE];
int tmptype;
// Initialization stuff
tmpname[0]= 0;
tmphost[0]= 0;
tmpport[0]= 0;
if (host)
*host= 0;
if (port)
*port= 0;
if (name)
*name= 0;
// Look for a 'rpcap://' identifier
if ( (ptr= strstr(source, PCAP_SRC_IF_KEY)) != NULL)
{
ptr+= strlen(PCAP_SRC_IF_KEY);
if (strchr(ptr, '[')) // This is probably a numeric address
{
ntoken= sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -