📄 pcap-remote.c
字号:
return -1;
}
// We cannot check the data port, because this is available only in case of TCP sockets
// Get the name/port of the current host
if (getsockname(fp->rmt_sockctrl, (struct sockaddr *) &saddr, &saddrlen) == -1)
{
sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
return -1;
}
// Get the local port the system picked up
if (getnameinfo( (struct sockaddr *) &saddr, saddrlen, myaddress,
sizeof(myaddress), myctrlport, sizeof(myctrlport), NI_NUMERICHOST | NI_NUMERICSERV) )
{
sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
return -1;
}
// Let's now check the data port
if (getsockname(fp->rmt_sockdata, (struct sockaddr *) &saddr, &saddrlen) == -1)
{
sock_geterror("getsockname(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
return -1;
}
// Get the local port the system picked up
if (getnameinfo( (struct sockaddr *) &saddr, saddrlen,NULL, 0, mydataport, sizeof(mydataport), NI_NUMERICSERV) )
{
sock_geterror("getnameinfo(): ", fp->errbuf, PCAP_ERRBUF_SIZE);
return -1;
}
currentfiltersize= strlen(fp->currentfilter);
newfilter= (char *) malloc (currentfiltersize + newstringsize + 1);
if (currentfiltersize)
{
snprintf(newfilter, currentfiltersize + newstringsize,
"(%s) and not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
fp->currentfilter, myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
}
else
{
snprintf(newfilter, currentfiltersize + newstringsize,
"not (host %s and host %s and port %s and port %s) and not (host %s and host %s and port %s)",
myaddress, peeraddress, myctrlport, peerctrlport, myaddress, peeraddress, mydataport);
}
newfilter[currentfiltersize + newstringsize]= 0;
// This is only an hack to make the pcap_compile() working properly
fp->rmt_clientside= 0;
if (pcap_compile(fp, prog, newfilter, 1, 0) == -1)
RetVal= -1;
// This is only an hack to make the pcap_compile() working properly
fp->rmt_clientside= 1;
free(newfilter);
}
return RetVal;
}
/*!
\ingroup remote_pri_func
\brief Set sampling parameters in the remote host.
This function is called when the user wants to set activate sampling on the remote host.
Sampling parameters are defined into the 'pcap_t' structure.
\param p: the pcap_t descriptor of the device currently opened.
\return '0' if everything is OK, '-1' is something goes wrong. The error message is returned
in the 'errbuf' member of the pcap_t structure.
*/
int pcap_setsampling_remote(pcap_t *p)
{
int retval; // general variable used to keep the return value of other functions
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_header header; // To keep the reply message
struct rpcap_sampling *sampling_pars; // Structure that is needed to send sampling parameters to the remote host
// If no samping is requested, return 'ok'
if (p->rmt_samp.method == PCAP_SAMP_NOSAMP)
return 0;
if ( sock_bufferize(NULL, sizeof(struct rpcap_header), NULL,
&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
return -1;
rpcap_createhdr( (struct rpcap_header *) sendbuf, RPCAP_MSG_SETSAMPLING_REQ, 0, sizeof(struct rpcap_sampling) );
// Fill the structure needed to open an adapter remotely
sampling_pars= (struct rpcap_sampling *) &sendbuf[sendbufidx];
if ( sock_bufferize(NULL, sizeof(struct rpcap_sampling), NULL,
&sendbufidx, RPCAP_NETBUF_SIZE, SOCKBUF_CHECKONLY, p->errbuf, PCAP_ERRBUF_SIZE) )
return -1;
memset(sampling_pars, 0, sizeof(struct rpcap_sampling) );
sampling_pars->method= p->rmt_samp.method;
sampling_pars->value= htonl(p->rmt_samp.value);
if ( sock_send(p->rmt_sockctrl, sendbuf, sendbufidx, p->errbuf, PCAP_ERRBUF_SIZE) )
return -1;
// Waits for the answer
if (sock_recv(p->rmt_sockctrl, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, p->errbuf, PCAP_ERRBUF_SIZE) == -1)
return -1;
// Checks if the message is correct
retval= rpcap_checkmsg(p->errbuf, p->rmt_sockctrl, &header, RPCAP_MSG_SETSAMPLING_REPLY, 0);
if (retval != RPCAP_MSG_SETSAMPLING_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
case RPCAP_MSG_ERROR:
// Do nothing; just exit from here; the error code is already into the errbuf
return -1;
default:
{
SOCK_ASSERT("Internal error", 0);
return -1;
};
}
}
if (ntohl(header.plen) != 0) // the message has an unexpected size
{
if (sock_discard(p->rmt_sockctrl, ntohl(header.plen), p->errbuf, PCAP_ERRBUF_SIZE) == -1)
return -1;
}
return 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, PCAP_ERRBUF_SIZE) )
return -1;
if ( sock_bufferize(error, length, sendbuf, &sendbufidx,
RPCAP_NETBUF_SIZE, SOCKBUF_BUFFERIZE, errbuf, PCAP_ERRBUF_SIZE) )
return -1;
if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
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, PCAP_ERRBUF_SIZE) )
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, PCAP_ERRBUF_SIZE) )
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, PCAP_ERRBUF_SIZE) )
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, PCAP_ERRBUF_SIZE) )
return -1;
rpauth->slen1= htons (rpauth->slen1);
rpauth->slen2= htons (rpauth->slen2);
}
if ( sock_send(sock, sendbuf, sendbufidx, errbuf, PCAP_ERRBUF_SIZE) )
return -1;
if ( sock_recv(sock, (char *) &header, sizeof(struct rpcap_header), SOCK_RECEIVEALL_YES, errbuf, PCAP_ERRBUF_SIZE) == -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, PCAP_ERRBUF_SIZE) )
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 me
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -