📄 daemon.c
字号:
if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &filter, sizeof(struct rpcap_filter), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
{
// to avoid blocking on the sock_discard()
*plen= *nread;
return -1;
}
bf_prog.bf_len= ntohl(filter.nitems);
if (ntohs(filter.filtertype) != RPCAP_UPDATEFILTER_BPF)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Only BPF/NPF filters are currently supported");
return -1;
}
bf_insn= (struct bpf_insn *) malloc ( sizeof(struct bpf_insn) * bf_prog.bf_len);
if (bf_insn == NULL)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "malloc() failed: %s", pcap_strerror(errno));
return -1;
}
bf_prog.bf_insns= bf_insn;
for (i= 0; i < bf_prog.bf_len; i++)
{
if ( ( *nread+= sock_recv(fp->rmt_sockctrl, (char *) &insn,
sizeof(struct rpcap_filterbpf_insn), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
return -1;
bf_insn->code= ntohs(insn.code);
bf_insn->jf= insn.jf;
bf_insn->jt= insn.jt;
bf_insn->k= ntohl(insn.k);
bf_insn++;
}
if (bpf_validate(bf_prog.bf_insns, bf_prog.bf_len) == 0)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "The filter contains bogus instructions");
return -1;
}
if (pcap_setfilter(fp, &bf_prog) )
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "RPCAP error: %s", fp->errbuf);
return -1;
}
return 0;
}
int daemon_updatefilter(pcap_t *fp, uint32 plen)
{
struct rpcap_header header; // keeps the answer to the updatefilter command
unsigned int nread;
nread= 0;
if ( daemon_unpackapplyfilter(fp, &nread, &plen, fp->errbuf) )
goto error;
// Check if all the data has been read; if not, discard the data in excess
if (nread != plen)
{
if (sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0) )
{
nread= plen; // just to avoid to call discard again in the 'error' section
goto error;
}
}
// A response is needed, otherwise the other host does not know that everything went well
rpcap_createhdr( &header, RPCAP_MSG_UPDATEFILTER_REPLY, 0, 0);
if ( sock_send(fp->rmt_sockctrl, (char *) &header, sizeof (struct rpcap_header), fp->errbuf, PCAP_ERRBUF_SIZE) )
goto error;
return 0;
error:
if (nread != plen)
sock_discard(fp->rmt_sockctrl, plen - nread, NULL, 0);
rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, NULL);
return -1;
}
/*!
\brief Received the sampling parameters from remote host and it stores in the pcap_t structure.
*/
int daemon_setsampling(SOCKET sockctrl, struct rpcap_sampling *samp_param, int plen, char *errbuf)
{
struct rpcap_header header;
struct rpcap_sampling rpcap_samp;
int nread; // number of bytes of the payload read from the socket
if ( ( nread= sock_recv(sockctrl, (char *) &rpcap_samp, sizeof(struct rpcap_sampling),
SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE)) == -1)
goto error;
// Save these settings in the pcap_t
samp_param->method= rpcap_samp.method;
samp_param->value= ntohl(rpcap_samp.value);
// A response is needed, otherwise the other host does not know that everything went well
rpcap_createhdr( &header, RPCAP_MSG_SETSAMPLING_REPLY, 0, 0);
if ( sock_send(sockctrl, (char *) &header, sizeof (struct rpcap_header), errbuf, PCAP_ERRBUF_SIZE) )
goto error;
if (nread != plen)
sock_discard(sockctrl, plen - nread, NULL, 0);
return 0;
error:
if (nread != plen)
sock_discard(sockctrl, plen - nread, NULL, 0);
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, NULL);
return -1;
}
int daemon_getstats(pcap_t *fp)
{
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
struct pcap_stat stats; // local statistics
struct rpcap_stats *netstats; // statistics sent on the network
if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
if (pcap_stats(fp, &stats) )
goto error;
netstats->ifdrop= htonl(stats.ps_ifdrop);
netstats->ifrecv= htonl(stats.ps_recv);
netstats->krnldrop= htonl(stats.ps_drop);
netstats->svrcapt= htonl(fp->md.TotCapt);
// Send the packet
if ( sock_send(fp->rmt_sockctrl, sendbuf, sendbufidx, fp->errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
return 0;
error:
rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_GETSTATS, NULL);
return -1;
}
int daemon_getstatsnopcap(SOCKET sockctrl, unsigned int ifdrops, unsigned int ifrecv,
unsigned int krnldrop, unsigned int svrcapt, char *errbuf)
{
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
struct rpcap_stats *netstats; // statistics sent on the network
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_STATS_REPLY, 0, (uint16) sizeof(struct rpcap_stats));
netstats= (struct rpcap_stats *) &sendbuf[sendbufidx];
if ( sock_bufferize(NULL, sizeof(struct rpcap_stats), NULL,
&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
netstats->ifdrop= htonl(ifdrops);
netstats->ifrecv= htonl(ifrecv);
netstats->krnldrop= htonl(krnldrop);
netstats->svrcapt= htonl(svrcapt);
// Send the packet
if ( sock_send(sockctrl, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
return 0;
error:
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_GETSTATS, NULL);
return -1;
}
void *daemon_thrdatamain(void *ptr)
{
char errbuf[PCAP_ERRBUF_SIZE + 1]; // error buffer
pcap_t *fp; // pointer to a 'pcap' structure
int retval; // general variable used to keep the return value of other functions
struct rpcap_pkthdr *net_pkt_header;// header of the packet
struct pcap_pkthdr *pkt_header; // pointer to the buffer that contains the header of the current packet
u_char *pkt_data; // pointer to the buffer that contains the current packet
char *sendbuf; // temporary buffer in which data to be sent is buffered
int sendbufidx; // index which keeps the number of bytes currently buffered
fp= (pcap_t *) ptr;
fp->md.TotCapt= 0; // counter which is incremented each time a packet is received
// Initialize errbuf
memset(errbuf, 0, sizeof(errbuf) );
// Some platforms (e.g. Win32) allow creating a static variable with this size
// However, others (e.g. BSD) do not, so we're forced to allocate this buffer dynamically
sendbuf= (char *) malloc (sizeof(char) * RPCAP_NETBUF_SIZE);
if (sendbuf == NULL)
{
snprintf(errbuf, sizeof(errbuf) - 1, "Unable to create the buffer for this child thread");
goto error;
}
// Modify thread params so that it can be killed at any time
if (pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) )
goto error;
if (pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL) )
goto error;
// Retrieve the packets
while ((retval = pcap_next_ex(fp, &pkt_header, (const u_char **) &pkt_data)) >= 0) // cast to avoid a compiler warning
{
if (retval == 0) // Read timeout elapsed
continue;
sendbufidx= 0;
// Bufferize the general header
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_PACKET, 0,
(uint16) (sizeof(struct rpcap_pkthdr) + pkt_header->caplen) );
net_pkt_header= (struct rpcap_pkthdr *) &sendbuf[sendbufidx];
// Bufferize the pkt header
if ( sock_bufferize(NULL, sizeof(struct rpcap_pkthdr), NULL, &sendbufidx,
RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
net_pkt_header->caplen= htonl(pkt_header->caplen);
net_pkt_header->len= htonl(pkt_header->len);
net_pkt_header->npkt= htonl( ++(fp->md.TotCapt) );
net_pkt_header->timestamp_sec= htonl(pkt_header->ts.tv_sec);
net_pkt_header->timestamp_usec= htonl(pkt_header->ts.tv_usec);
// Bufferize the pkt data
if ( sock_bufferize((char *) pkt_data, pkt_header->caplen, sendbuf, &sendbufidx,
RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
// Send the packet
if ( sock_send(fp->rmt_sockdata, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) == -1)
goto error;
}
if (retval == -1)
{
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Error reading the packets: %s", pcap_geterr(fp) );
rpcap_senderror(fp->rmt_sockctrl, errbuf, PCAP_ERR_READEX, NULL);
goto error;
}
error:
SOCK_ASSERT(errbuf, 1);
closesocket(fp->rmt_sockdata);
fp->rmt_sockdata= 0;
free(sendbuf);
return NULL;
}
/*!
\brief It serializes a network address.
It accepts a 'sockaddr_storage' structure as input, and it converts it appropriately into a format
that can be used to be sent on the network. Basically, it applies all the hton()
conversion required to the input variable.
\param sockaddrin: a 'sockaddr_storage' pointer to the variable that has to be
serialized. This variable can be both a 'sockaddr_in' and 'sockaddr_in6'.
\param sockaddrout: a 'sockaddr_storage' pointer to the variable that will contain
the serialized data. This variable has to be allocated by the user.
\return None
\warning This function supports only AF_INET and AF_INET6 address families.
*/
void daemon_seraddr(struct sockaddr_storage *sockaddrin, struct sockaddr_storage *sockaddrout)
{
memset(sockaddrout, 0, sizeof(struct sockaddr_storage) );
// There can be the case in which the sockaddrin is not available
if (sockaddrin == NULL) return;
// Warning: we support only AF_INET and AF_INET6
if (sockaddrin->ss_family == AF_INET)
{
struct sockaddr_in *sockaddr;
sockaddr= (struct sockaddr_in *) sockaddrin;
sockaddr->sin_family= htons(sockaddr->sin_family);
sockaddr->sin_port= htons(sockaddr->sin_port);
memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in) );
}
else
{
struct sockaddr_in6 *sockaddr;
sockaddr= (struct sockaddr_in6 *) sockaddrin;
sockaddr->sin6_family= htons(sockaddr->sin6_family);
sockaddr->sin6_port= htons(sockaddr->sin6_port);
sockaddr->sin6_flowinfo= htonl(sockaddr->sin6_flowinfo);
sockaddr->sin6_scope_id= htonl(sockaddr->sin6_scope_id);
memcpy(sockaddrout, sockaddr, sizeof(struct sockaddr_in6) );
}
}
/*!
\brief Suspends a pthread for msec milliseconds.
This function is provided since pthreads do not have a suspend() call.
*/
void pthread_suspend(int msec)
{
#ifdef WIN32
Sleep(msec);
#else
struct timespec abstime;
struct timeval now;
pthread_cond_t cond;
pthread_mutex_t mutex;
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutex_init(&mutex, &attr);
pthread_mutex_lock(&mutex);
pthread_cond_init(&cond, NULL);
gettimeofday(&now, NULL);
abstime.tv_sec = now.tv_sec + msec/1000;
abstime.tv_nsec = now.tv_usec * 1000 + (msec%1000) * 1000 * 1000;
pthread_cond_timedwait(&cond, &mutex, &abstime);
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cond);
#endif
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -