📄 daemon.c
字号:
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;
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, fakeerrbuf, PCAP_ERRBUF_SIZE) )
{
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, fakeerrbuf, PCAP_ERRBUF_SIZE);
rpcap_senderror(fp->rmt_sockctrl, fp->errbuf, PCAP_ERR_UPDATEFILTER, fakeerrbuf);
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, fakeerrbuf, PCAP_ERRBUF_SIZE);
return 0;
error:
if (nread != plen)
sock_discard(sockctrl, plen - nread, fakeerrbuf, PCAP_ERRBUF_SIZE);
rpcap_senderror(sockctrl, errbuf, PCAP_ERR_SETSAMPLING, fakeerrbuf);
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, fakeerrbuf);
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, fakeerrbuf);
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[RPCAP_NETBUF_SIZE]; // temporary buffer in which data to be sent is buffered
int sendbufidx; // index which keeps the number of bytes currently buffered
int samp_npkt= 0; // parameter needed for sampling, whtn '1 out of N' method has been requested
struct timeval samp_time; // parameter needed for sampling, whtn '1 every N ms' method has been requested
fp= (pcap_t *) ptr;
memset(&samp_time, 0, sizeof (struct timeval) );
fp->md.TotCapt= 0; // counter which is incremented each time a packet is received
// Initialize errbuf
memset(errbuf, 0, sizeof(errbuf) );
// 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, &pkt_data)) >= 0)
{
if (retval == 0) // Read timeout elapsed
continue;
if (fp->rmt_samp.method == PCAP_SAMP_1_EVERY_N)
{
samp_npkt= (samp_npkt + 1) % fp->rmt_samp.value;
// Discard all packets that are not '1 out of N'
if (samp_npkt != 0)
continue;
}
if (fp->rmt_samp.method == PCAP_SAMP_FIRST_AFTER_N_MS)
{
// Check if the timestamp of the arrived packet is smaller than our target time
if ( (pkt_header->ts.tv_sec < samp_time.tv_sec) ||
( (pkt_header->ts.tv_sec == samp_time.tv_sec) && (pkt_header->ts.tv_usec < samp_time.tv_usec) ) )
continue;
// The arrived packet is suitable for being sent to the remote host
// So, let's update the target time
samp_time.tv_usec= pkt_header->ts.tv_usec + fp->rmt_samp.value * 1000;
if (samp_time.tv_usec > 1000000)
{
samp_time.tv_sec= pkt_header->ts.tv_sec + samp_time.tv_usec / 1000000;
samp_time.tv_usec= samp_time.tv_usec % 1000000;
}
}
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, fakeerrbuf);
goto error;
}
error:
SOCK_ASSERT(errbuf, 1);
closesocket(fp->rmt_sockdata);
fp->rmt_sockdata= 0;
return;
}
/*!
\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 + -