📄 pcap-new.c
字号:
case -1: // The other endpoint has a version number that is not compatible with our
break;
case RPCAP_MSG_ERROR: // The other endpoint reported an error
break;
default:
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Internal error");
break;
};
}
if (!active)
sock_close(sockctrl, NULL, 0);
return -1;
}
// read the number of interfaces
nif= ntohs(header.value);
// loop until all interfaces have been received
for (i= 0; i < nif; i++)
{
struct rpcap_findalldevs_if findalldevs_if;
char tmpstring2[PCAP_BUF_SIZE + 1]; // Needed to convert names and descriptions from 'old' syntax to the 'new' one
int stringlen;
tmpstring2[PCAP_BUF_SIZE]= 0;
// receive the findalldevs structure from remote hsot
if ( (nread+= sock_recv(sockctrl, (char *) &findalldevs_if,
sizeof(struct rpcap_findalldevs_if), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
goto error;
findalldevs_if.namelen= ntohs(findalldevs_if.namelen);
findalldevs_if.desclen= ntohs(findalldevs_if.desclen);
findalldevs_if.naddr= ntohs(findalldevs_if.naddr);
// allocate the main structure
if (i == 0)
{
(*alldevs)= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
dev= (*alldevs);
}
else
{
dev->next= (pcap_if_t *) malloc(sizeof(pcap_if_t) );
dev= dev->next;
}
// check that the malloc() didn't fail
if (dev == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
goto error;
}
// Initialize the structure to 'zero'
memset(dev, 0, sizeof(pcap_if_t) );
// allocate mem for name and description
if (findalldevs_if.namelen)
{
if (findalldevs_if.namelen >= sizeof(tmpstring) )
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface name too long");
goto error;
}
// Retrieve adapter name
if ( (nread+= sock_recv(sockctrl, tmpstring, findalldevs_if.namelen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
goto error;
tmpstring[findalldevs_if.namelen]= 0;
// Create the new device identifier
if (pcap_createsrcstr(tmpstring2, PCAP_SRC_IFREMOTE, host, port, tmpstring, errbuf) == -1)
return -1;
stringlen= strlen(tmpstring2);
dev->name= (char *) malloc(stringlen + 1);
if (dev->name == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
goto error;
}
// Copy the new device name into the correct memory location
strncpy(dev->name, tmpstring2, stringlen + 1);
}
if (findalldevs_if.desclen)
{
if (findalldevs_if.desclen >= sizeof(tmpstring) )
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Interface description too long");
goto error;
}
// Retrieve adapter description
if ( (nread+= sock_recv(sockctrl, tmpstring, findalldevs_if.desclen, SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -1)
goto error;
tmpstring[findalldevs_if.desclen]= 0;
snprintf(tmpstring2, sizeof(tmpstring2) - 1, "%s '%s' %s %s", PCAP_TEXT_SOURCE_ADAPTER,
tmpstring, PCAP_TEXT_SOURCE_ON_REMOTE_HOST, host);
stringlen= strlen(tmpstring2);
dev->description= (char *) malloc(stringlen + 1);
if (dev->description == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
goto error;
}
// Copy the new device description into the correct memory location
strncpy(dev->description, tmpstring2, stringlen + 1);
}
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), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) ) == -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, PCAP_ERRBUF_SIZE) == 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, PCAP_ERRBUF_SIZE) )
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, NULL, 0) == 1)
return -1;
}
// Control connection has to be closed only in case the remote machine is in passive mode
if (!active)
sock_close(sockctrl, NULL, 0);
// To avoid inconsistencies in the number of sock_init()
sock_cleanup();
return -1;
}
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_STRING, 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_STRING, 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;
}
case PCAP_SRC_IFLOCAL:
{
strncpy(source, PCAP_SRC_IF_STRING, PCAP_BUF_SIZE);
if ((name) && (*name) )
strncat(source, name, PCAP_BUF_SIZE);
return 0;
}
default:
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface type is not valid.");
return -1;
}
}
}
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_STRING)) != NULL)
{
if (strlen(PCAP_SRC_IF_STRING) == strlen(source) )
{
// The source identifier contains only the 'rpcap://' string.
// So, this is a local capture.
*type= PCAP_SRC_IFLOCAL;
return 0;
}
ptr+= strlen(PCAP_SRC_IF_STRING);
if (strchr(ptr, '[')) // This is probably a numeric address
{
ntoken= sscanf(ptr, "[%[1234567890:.]]:%[^/]/%s", tmphost, tmpport, tmpname);
if (ntoken == 1) // probably the port is missing
ntoken= sscanf(ptr, "[%[1234567890:.]]/%s", tmphost, tmpname);
tmptype= PCAP_SRC_IFREMOTE;
}
else
{
ntoken= sscanf(ptr, "%[^/:]:%[^/]/%s", tmphost, tmpport, tmpname);
if (ntoken == 1)
{
// This can be due to two reasons:
// - we want a remote capture, but the network port is missing
// - we want to do a local capture
// To distinguish between the two, we look for the '/' char
if (strchr(ptr, '/'))
{
// We're on a remote capture
sscanf(ptr, "%[^/]/%s", tmphost, tmpname);
tmptype= PCAP_SRC_IFREMOTE;
}
else
{
// We're on a local capture
if (*ptr)
strncpy(tmpname, ptr, PCAP_BUF_SIZE);
// Clean the host name, since it is a remote capture
// NOTE: the host name has been assigned in the previous "ntoken= sscanf(...)" line
tmphost[0]= 0;
tmptype= PCAP_SRC_IFLOCAL;
}
}
else
tmptype= PCAP_SRC_IFREMOTE;
}
if (host)
strcpy(host, tmphost);
if (port)
strcpy(port, tmpport);
if (type)
*type= tmptype;
if (name)
{
// If the user wants the host name, but it cannot be located into the source string, return error
// However, if the user is not interested in the interface name (e.g. if we're called by
// pcap_findalldevs_ex(), which does not have interface name, do not return error
if (tmpname[0])
{
strcpy(name, tmpname);
}
else
{
if (errbuf)
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The interface name has not been specified in the source string.");
return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -