📄 pcap-remote.c
字号:
*errbuf= 0; // Initialize 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;
// Watch out sockdata to see if it has input
FD_ZERO(&rfds);
// We do not have to block here
tv.tv_sec = 0;
tv.tv_usec = 0;
while (1)
{
if (fp->cc == 0)
{
u_char *bp= fp->buffer;
cc= 0;
while (1)
{
again:
FD_SET(fp->rmt_sockdata, &rfds);
retval = select(1, &rfds, NULL, NULL, &tv);
if (retval == -1)
{
sock_geterror("select(): ", errbuf, PCAP_ERRBUF_SIZE);
goto error;
}
// There is no data waiting
if (retval == 0)
{
// Update the pcap_t pointers so that the user application can read from the buffer
fp->bp= fp->buffer;
fp->cc= cc;
pthread_suspend(100); // Suspend 100 ms
break;
}
if (!pending)
{
// Read the entire message from the network
if (sock_recv_dgram(fp->rmt_sockdata, netbuf, RPCAP_NETBUF_SIZE, errbuf) == -1)
goto error;
header= (struct rpcap_header *) netbuf;
// Checks if the message is correct
retval= rpcap_checkmsg(errbuf, fp->rmt_sockdata, (struct rpcap_header *) netbuf, RPCAP_MSG_PACKET, 0);
if (retval != RPCAP_MSG_PACKET) // the message is not the one expected
{
switch (retval)
{
case -3: // Unrecoverable network error
goto error; // Do nothing; just exit from here; the error code is already into the errbuf
case -2: // The other endpoint sent a message that is not allowed here
case -1: // The other endpoint has a version number that is not compatible with our
goto again;
default:
{
SOCK_ASSERT("Internal error", 0);
goto error;
};
}
}
// Set a pointer to the RPCAP packet header
net_pkt_header= (struct rpcap_pkthdr *) (netbuf + sizeof(struct rpcap_header));
}
if ( (cc + ntohl(net_pkt_header->caplen) + sizeof(struct pcap_pkthdr) ) <= ( (unsigned) fp->bufsize) )
{
unsigned int npkt;
pending= 0;
pkt_header= (struct pcap_pkthdr *) bp;
pkt_header->caplen= ntohl(net_pkt_header->caplen);
pkt_header->len= ntohl(net_pkt_header->len);
pkt_header->ts.tv_sec= ntohl(net_pkt_header->timestamp_sec);
pkt_header->ts.tv_usec= ntohl(net_pkt_header->timestamp_usec);
// Update the number of packets received correctly
fp->md.TotCapt++;
// We're using UDP, so I need to update the counter of the packets dropped by the network
npkt= ntohl(net_pkt_header->npkt);
if (fp->md.TotCapt != npkt)
{
fp->md.TotNetDrops+= (npkt - fp->md.TotCapt);
fp->md.TotCapt= npkt;
}
// Copies the packet into the data buffer
memcpy( bp + sizeof(struct pcap_pkthdr), netbuf + sizeof(struct rpcap_header), pkt_header->caplen);
bp += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
cc += BPF_WORDALIGN(pkt_header->caplen + sizeof(struct pcap_pkthdr));
}
else
{
pending= 1;
// Update the pcap_t pointers so that the user application can read from the buffer
fp->bp= fp->buffer;
fp->cc= cc;
break;
}
} // end while (1)
}
else
{
pthread_suspend(100); // Suspend 100 ms
}
} // end main while(1)
error:
SOCK_ASSERT("Exiting from the child data thread", 1);
SOCK_ASSERT(errbuf, 1);
// Removes the descriptor s from set
FD_CLR(fp->rmt_sockdata, &rfds);
closesocket(fp->rmt_sockdata);
fp->rmt_sockdata= 0;
fp->rmt_threaddata= 0;
}
/*********************************************************
* *
* Miscellaneous functions *
* *
*********************************************************/
/*! \ingroup remote_pri_func
\brief It sends a RPCAP error to the other peer.
This function has to be called when the main program detects an error. This funcion
will send on the other peer the 'buffer' specified by the user.
This function *does not* request a RPCAP CLOSE connection. A CLOSE command must be sent
explicitely by the program, since we do not know it the error can be recovered in some
way or it is a non-recoverable one.
\param sock: the socket we are currently using.
\param error: an user-allocated (and '0' termined) buffer that contains the error
description thas has to be transmitted on the other peer. The error message cannot
be longer than PCAP_ERRBUF_SIZE.
\param errcode: a integer which tells the other party the type of error we had;
currently is is not too much used.
\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). It could be network problem.
\return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
in the 'errbuf' variable.
*/
int rpcap_senderror(SOCKET sock, char *error, unsigned short errcode, 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
uint16 length;
length= (uint16) strlen(error);
if (length > PCAP_ERRBUF_SIZE)
length= PCAP_ERRBUF_SIZE;
rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_ERROR, errcode, length);
if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
return -1;
if ( sock_bufferize(error, length, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
return -1;
if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
return -1;
return 0;
}
/*! \ingroup remote_pri_func
\brief Sends the authentication message.
It sends the authentication parameters on the control socket.
Ths function is required in order to open the connection with the other end party.
\param sock: the socket we are currently using.
\param auth: authentication parameters that have to be sent.
\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). It could be network problem
ot the fact that the authorization failed.
\return '0' if everything is fine, '-1' if some errors occurred. The error message is returned
in the 'errbuf' variable.
The error message could be also 'the authentication failed'.
*/
int rpcap_sendauth(SOCKET sock, struct pcap_rmtauth *auth, char *errbuf)
{
char sendbuf[RPCAP_NETBUF_SIZE]; // temporary buffer in which data that has to be sent is buffered
int sendbufidx= 0; // index which keeps the number of bytes currently buffered
uint16 length; // length of the payload of this message
struct rpcap_auth *rpauth;
uint16 auth_type;
struct rpcap_header header;
int retval; // temp variable which stores functions return value
if (auth)
{
auth_type= auth->type;
switch (auth->type)
{
case RPCAP_RMTAUTH_NULL:
length= sizeof (struct rpcap_auth);
break;
case RPCAP_RMTAUTH_PWD:
length= sizeof (struct rpcap_auth);
if (auth->username) length+= strlen(auth->username);
if (auth->password) length+= strlen(auth->password);
break;
default:
snprintf(errbuf, PCAP_ERRBUF_SIZE, "Authentication type not recognized.");
return -1;
}
}
else
{
auth_type= RPCAP_RMTAUTH_NULL;
length= sizeof (struct rpcap_auth);
}
if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
return -1;
rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_AUTH_REQ, 0, length);
rpauth= (struct rpcap_auth *) &sendbuf[sendbufidx];
if ( sock_bufferize(NULL, sizeof(struct rpcap_auth), NULL, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, errbuf) )
return -1;
memset(rpauth, 0, sizeof (struct rpcap_auth) );
rpauth->type= htons(auth_type);
if (auth_type == RPCAP_RMTAUTH_PWD)
{
if (auth->username)
rpauth->slen1= strlen(auth->username);
else
rpauth->slen1= 0;
if ( sock_bufferize(auth->username, rpauth->slen1, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
return -1;
if (auth->password)
rpauth->slen2= strlen(auth->password);
else
rpauth->slen2= 0;
if ( sock_bufferize(auth->password, rpauth->slen2, sendbuf, &sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf) )
return -1;
rpauth->slen1= htons (rpauth->slen1);
rpauth->slen2= htons (rpauth->slen2);
}
if ( sock_send(sock, sendbuf, sendbufidx, errbuf) )
return -1;
if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), errbuf) == -1)
return -1;
retval= rpcap_checkmsg(errbuf, sock, &header, RPCAP_MSG_AUTH_REPLY, RPCAP_MSG_ERROR, 0);
if (retval != RPCAP_MSG_AUTH_REPLY) // the message is not the one expected
{
switch (retval)
{
case -3: // Unrecoverable network error
case -2: // The other endpoint sent a message that is not allowed here
case -1: // The other endpoint has a version number that is not compatible with our
// Do nothing; just exit from here; the error code is already into the errbuf
return -1;
case RPCAP_MSG_ERROR:
{
return -1;
};
default:
{
SOCK_ASSERT("Internal error", 0);
return -1;
};
}
}
if (ntohl(header.plen) )
{
if (sock_discard(sock, ntohl(header.plen), errbuf) )
return -1;
}
return 0;
}
/*! \ingroup remote_pri_func
\brief Creates a structure of type rpcap_header.
This function is provided just because the creation of an rpcap header is quite a common
task. It accepts all the values that appears into an rpcap_header, and it puts them in
place using the proper hton() calls.
\param header: a pointer to a user-allocated buffer which will contain the serialized
header, ready to be sent on the network.
\param type: a value (in the host by order) which will be placed into the header.type
field and that represents the type of the current message.
\param value: a value (in the host by order) which will be placed into the header.value
field and that has a message-dependent meaning.
\param length: a value (in the host by order) which will be placed into the header.length
field and that represents the payload length of the message.
\return Nothing. The serialized header is returned into the 'header' variable.
*/
void rpcap_createhdr(struct rpcap_header *header, uint8 type, uint16 value, uint32 length)
{
memset(header, 0, sizeof (struct rpcap_header) );
header->ver= RPCAP_VERSION;
header->type= type;
header->value= htons(value);
header->plen= htonl(length);
}
/*! \ingroup remote_pri_func
\brief Checks if the header of the received message is correct.
This function is a way to easily check if the message received, in a certain
state of the RPCAP protocol Finite State Machine, is valid. This function accepts,
as a parameter, the list of message types that are allowed in a certain situation,
and it returns the one which occurs.
\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). It could be either problem
occurred inside this function (e.g. a network problem in ca
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -