Improved pcap dumping support
Этот коммит содержится в:
родитель
3e90a11599
Коммит
02aecc1278
@ -40,6 +40,12 @@ char *user;
|
|||||||
char *cmds[MAXCMD];
|
char *cmds[MAXCMD];
|
||||||
struct termios terminal;
|
struct termios terminal;
|
||||||
|
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
/* this header file won't be necessary in the future */
|
||||||
|
#include <libssh/pcap.h>
|
||||||
|
char *pcap_file=NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
static int auth_callback(const char *prompt, char *buf, size_t len,
|
static int auth_callback(const char *prompt, char *buf, size_t len,
|
||||||
int echo, int verify, void *userdata) {
|
int echo, int verify, void *userdata) {
|
||||||
char *answer = NULL;
|
char *answer = NULL;
|
||||||
@ -86,19 +92,27 @@ static void usage(){
|
|||||||
" -l user : log in as user\n"
|
" -l user : log in as user\n"
|
||||||
" -p port : connect to port\n"
|
" -p port : connect to port\n"
|
||||||
" -d : use DSS to verify host public key\n"
|
" -d : use DSS to verify host public key\n"
|
||||||
" -r : use RSA to verify host public key\n",
|
" -r : use RSA to verify host public key\n"
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
" -P file : create a pcap debugging file\n"
|
||||||
|
#endif
|
||||||
|
,
|
||||||
ssh_version(0));
|
ssh_version(0));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int opts(int argc, char **argv){
|
static int opts(int argc, char **argv){
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
// for(i=0;i<argc;i++)
|
// for(i=0;i<argc;i++)
|
||||||
// printf("%d : %s\n",i,argv[i]);
|
// printf("%d : %s\n",i,argv[i]);
|
||||||
/* insert your own arguments here */
|
/* insert your own arguments here */
|
||||||
while((i=getopt(argc,argv,""))!=-1){
|
while((i=getopt(argc,argv,"P:"))!=-1){
|
||||||
switch(i){
|
switch(i){
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
case 'P':
|
||||||
|
pcap_file=optarg;
|
||||||
|
break;
|
||||||
|
#endif
|
||||||
default:
|
default:
|
||||||
fprintf(stderr,"unknown option %c\n",optopt);
|
fprintf(stderr,"unknown option %c\n",optopt);
|
||||||
usage();
|
usage();
|
||||||
@ -446,6 +460,31 @@ static int client(ssh_session session){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
ssh_pcap_file pcap;
|
||||||
|
void set_pcap(ssh_session session);
|
||||||
|
void set_pcap(ssh_session session){
|
||||||
|
ssh_pcap_context ctx;
|
||||||
|
if(!pcap_file)
|
||||||
|
return;
|
||||||
|
pcap=ssh_pcap_file_new();
|
||||||
|
if(ssh_pcap_file_open(pcap,pcap_file) == SSH_ERROR){
|
||||||
|
printf("Error opening pcap file\n");
|
||||||
|
ssh_pcap_file_free(pcap);
|
||||||
|
pcap=NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ctx=ssh_pcap_context_new(session);
|
||||||
|
ssh_pcap_context_set_file(ctx,pcap);
|
||||||
|
ssh_set_pcap_context(session,ctx);
|
||||||
|
}
|
||||||
|
void cleanup_pcap(void);
|
||||||
|
void cleanup_pcap(){
|
||||||
|
ssh_pcap_file_free(pcap);
|
||||||
|
pcap=NULL;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int main(int argc, char **argv){
|
int main(int argc, char **argv){
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
|
|
||||||
@ -461,10 +500,17 @@ int main(int argc, char **argv){
|
|||||||
}
|
}
|
||||||
opts(argc,argv);
|
opts(argc,argv);
|
||||||
signal(SIGTERM, do_exit);
|
signal(SIGTERM, do_exit);
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
set_pcap(session);
|
||||||
|
#endif
|
||||||
client(session);
|
client(session);
|
||||||
|
|
||||||
ssh_disconnect(session);
|
ssh_disconnect(session);
|
||||||
ssh_free(session);
|
ssh_free(session);
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
cleanup_pcap();
|
||||||
|
#endif
|
||||||
|
|
||||||
ssh_finalize();
|
ssh_finalize();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#define PCAP_H_
|
#define PCAP_H_
|
||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "libssh/libssh.h"
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
#ifdef WITH_PCAP
|
||||||
typedef struct ssh_pcap_context_struct* ssh_pcap_context;
|
typedef struct ssh_pcap_context_struct* ssh_pcap_context;
|
||||||
@ -10,7 +11,7 @@ typedef struct ssh_pcap_file_struct* ssh_pcap_file;
|
|||||||
ssh_pcap_file ssh_pcap_file_new(void);
|
ssh_pcap_file ssh_pcap_file_new(void);
|
||||||
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename);
|
||||||
int ssh_pcap_file_close(ssh_pcap_file pcap);
|
int ssh_pcap_file_close(ssh_pcap_file pcap);
|
||||||
void ssh_pcap_free(ssh_pcap_file pcap);
|
void ssh_pcap_file_free(ssh_pcap_file pcap);
|
||||||
|
|
||||||
/* to be removed from here after tests */
|
/* to be removed from here after tests */
|
||||||
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len);
|
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, u_int32_t original_len);
|
||||||
@ -25,6 +26,8 @@ void ssh_pcap_context_set_file(ssh_pcap_context, ssh_pcap_file);
|
|||||||
int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data,
|
int ssh_pcap_context_write(ssh_pcap_context,enum ssh_pcap_direction direction, void *data,
|
||||||
u_int32_t len, u_int32_t origlen);
|
u_int32_t len, u_int32_t origlen);
|
||||||
|
|
||||||
|
void ssh_set_pcap_context(ssh_session session, ssh_pcap_context pcap);
|
||||||
|
|
||||||
#endif /* WITH_PCAP */
|
#endif /* WITH_PCAP */
|
||||||
#endif /* PCAP_H_ */
|
#endif /* PCAP_H_ */
|
||||||
/* vim: set ts=2 sw=2 et cindent: */
|
/* vim: set ts=2 sw=2 et cindent: */
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#define SESSION_H_
|
#define SESSION_H_
|
||||||
#include "libssh/priv.h"
|
#include "libssh/priv.h"
|
||||||
#include "libssh/packet.h"
|
#include "libssh/packet.h"
|
||||||
|
#include "libssh/pcap.h"
|
||||||
|
|
||||||
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
typedef struct ssh_kbdint_struct* ssh_kbdint;
|
||||||
|
|
||||||
@ -96,6 +97,9 @@ struct ssh_session_struct {
|
|||||||
ssh_callbacks callbacks; /* Callbacks to user functions */
|
ssh_callbacks callbacks; /* Callbacks to user functions */
|
||||||
|
|
||||||
/* options */
|
/* options */
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
ssh_pcap_context pcap_ctx; /* pcap debugging context */
|
||||||
|
#endif
|
||||||
char *username;
|
char *username;
|
||||||
char *host;
|
char *host;
|
||||||
char *bindaddr; /* TODO: check if needed */
|
char *bindaddr; /* TODO: check if needed */
|
||||||
|
@ -66,7 +66,11 @@ char *ssh_get_banner(ssh_session session) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
if(session->pcap_ctx && buffer[i] == '\n'){
|
||||||
|
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_IN,buffer,i+1,i+1);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (buffer[i] == '\r') {
|
if (buffer[i] == '\r') {
|
||||||
buffer[i] = '\0';
|
buffer[i] = '\0';
|
||||||
}
|
}
|
||||||
@ -197,7 +201,10 @@ int ssh_send_banner(ssh_session session, int server) {
|
|||||||
leave_function();
|
leave_function();
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
if(session->pcap_ctx)
|
||||||
|
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,buffer,strlen(buffer),strlen(buffer));
|
||||||
|
#endif
|
||||||
leave_function();
|
leave_function();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
#include "libssh/channels.h"
|
#include "libssh/channels.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/messages.h"
|
#include "libssh/messages.h"
|
||||||
|
#include "libssh/pcap.h"
|
||||||
|
|
||||||
/* XXX include selected mac size */
|
/* XXX include selected mac size */
|
||||||
static int macsize=SHA_DIGEST_LEN;
|
static int macsize=SHA_DIGEST_LEN;
|
||||||
@ -159,6 +160,14 @@ static int packet_read2(ssh_session session) {
|
|||||||
ssh_set_error(session, SSH_FATAL, "Decrypt error");
|
ssh_set_error(session, SSH_FATAL, "Decrypt error");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
if(session->pcap_ctx){
|
||||||
|
ssh_pcap_context_write(session->pcap_ctx,
|
||||||
|
SSH_PCAP_DIR_IN, buffer_get(session->in_buffer),
|
||||||
|
buffer_get_len(session->in_buffer),
|
||||||
|
buffer_get_len(session->in_buffer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ssh_socket_read(session->socket, mac, macsize);
|
ssh_socket_read(session->socket, mac, macsize);
|
||||||
|
|
||||||
if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
|
if (packet_hmac_verify(session, session->in_buffer, mac) < 0) {
|
||||||
@ -488,7 +497,13 @@ static int packet_send2(ssh_session session) {
|
|||||||
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
|
if (buffer_add_data(session->out_buffer, padstring, padding) < 0) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
if(session->pcap_ctx){
|
||||||
|
ssh_pcap_context_write(session->pcap_ctx,SSH_PCAP_DIR_OUT,
|
||||||
|
buffer_get(session->out_buffer),buffer_get_len(session->out_buffer)
|
||||||
|
,buffer_get_len(session->out_buffer));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
hmac = packet_encrypt(session, buffer_get(session->out_buffer),
|
hmac = packet_encrypt(session, buffer_get(session->out_buffer),
|
||||||
buffer_get_len(session->out_buffer));
|
buffer_get_len(session->out_buffer));
|
||||||
if (hmac) {
|
if (hmac) {
|
||||||
|
100
libssh/pcap.c
100
libssh/pcap.c
@ -26,16 +26,21 @@
|
|||||||
* \addtogroup ssh_pcap
|
* \addtogroup ssh_pcap
|
||||||
* @{ */
|
* @{ */
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#ifdef WITH_PCAP
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "libssh/libssh.h"
|
#include "libssh/libssh.h"
|
||||||
#include "libssh/pcap.h"
|
#include "libssh/pcap.h"
|
||||||
#include "libssh/session.h"
|
#include "libssh/session.h"
|
||||||
#include "libssh/buffer.h"
|
#include "libssh/buffer.h"
|
||||||
|
#include "libssh/socket.h"
|
||||||
|
|
||||||
#ifdef WITH_PCAP
|
|
||||||
/* The header of a pcap file is the following. We are not going to make it
|
/* The header of a pcap file is the following. We are not going to make it
|
||||||
* very complicated.
|
* very complicated.
|
||||||
* Just for information.
|
* Just for information.
|
||||||
@ -83,6 +88,7 @@ struct pcaprec_hdr_s {
|
|||||||
struct ssh_pcap_context_struct {
|
struct ssh_pcap_context_struct {
|
||||||
ssh_session session;
|
ssh_session session;
|
||||||
ssh_pcap_file file;
|
ssh_pcap_file file;
|
||||||
|
int connected;
|
||||||
/* All of these informations are useful to generate
|
/* All of these informations are useful to generate
|
||||||
* the dummy IP and TCP packets
|
* the dummy IP and TCP packets
|
||||||
*/
|
*/
|
||||||
@ -100,6 +106,7 @@ struct ssh_pcap_context_struct {
|
|||||||
*/
|
*/
|
||||||
struct ssh_pcap_file_struct {
|
struct ssh_pcap_file_struct {
|
||||||
FILE *output;
|
FILE *output;
|
||||||
|
u_int16_t ipsequence;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -192,7 +199,7 @@ int ssh_pcap_file_close(ssh_pcap_file pcap){
|
|||||||
return SSH_OK;
|
return SSH_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ssh_pcap_free(ssh_pcap_file pcap){
|
void ssh_pcap_file_free(ssh_pcap_file pcap){
|
||||||
ssh_pcap_file_close(pcap);
|
ssh_pcap_file_close(pcap);
|
||||||
SAFE_FREE(pcap);
|
SAFE_FREE(pcap);
|
||||||
}
|
}
|
||||||
@ -217,10 +224,69 @@ void ssh_pcap_context_set_file(ssh_pcap_context ctx, ssh_pcap_file pcap){
|
|||||||
ctx->file=pcap;
|
ctx->file=pcap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @internal
|
||||||
|
* @brief sets the IP and port parameters in the connection
|
||||||
|
*/
|
||||||
|
static int ssh_pcap_context_connect(ssh_pcap_context ctx){
|
||||||
|
ssh_session session=ctx->session;
|
||||||
|
struct sockaddr_in local, remote;
|
||||||
|
socket_t fd;
|
||||||
|
socklen_t len;
|
||||||
|
if(session==NULL)
|
||||||
|
return SSH_ERROR;
|
||||||
|
if(session->socket==NULL)
|
||||||
|
return SSH_ERROR;
|
||||||
|
fd=ssh_socket_get_fd(session->socket);
|
||||||
|
/* TODO: adapt for windows */
|
||||||
|
if(fd<0)
|
||||||
|
return SSH_ERROR;
|
||||||
|
len=sizeof(local);
|
||||||
|
if(getsockname(fd,(struct sockaddr *)&local,&len)<0){
|
||||||
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting local IP address: %s",strerror(errno));
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
len=sizeof(remote);
|
||||||
|
if(getpeername(fd,(struct sockaddr *)&remote,&len)<0){
|
||||||
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Getting remote IP address: %s",strerror(errno));
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
if(local.sin_family != AF_INET){
|
||||||
|
ssh_set_error(session,SSH_REQUEST_DENIED,"Only IPv4 supported for pcap logging");
|
||||||
|
return SSH_ERROR;
|
||||||
|
}
|
||||||
|
memcpy(&ctx->ipsource,&local.sin_addr,sizeof(ctx->ipsource));
|
||||||
|
memcpy(&ctx->ipdest,&remote.sin_addr,sizeof(ctx->ipdest));
|
||||||
|
memcpy(&ctx->portsource,&local.sin_port,sizeof(ctx->portsource));
|
||||||
|
memcpy(&ctx->portdest,&remote.sin_port,sizeof(ctx->portdest));
|
||||||
|
|
||||||
|
ctx->connected=1;
|
||||||
|
return SSH_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define IPHDR_LEN 20
|
||||||
|
#define TCPHDR_LEN 20
|
||||||
|
#define TCPIPHDR_LEN (IPHDR_LEN + TCPHDR_LEN)
|
||||||
|
/** @internal
|
||||||
|
* @brief write a SSH packet as a TCP over IP in a pcap file
|
||||||
|
* @param ctx open pcap context
|
||||||
|
* @param direction SSH_PCAP_DIRECTION_IN if the packet has been received
|
||||||
|
* @param direction SSH_PCAP_DIRECTION_OUT if the packet has been emitted
|
||||||
|
* @param data pointer to the data to write
|
||||||
|
* @param len data to write in the pcap file. May be smaller than origlen.
|
||||||
|
* @param origlen number of bytes of complete data.
|
||||||
|
* @returns SSH_OK write is successful
|
||||||
|
* @returns SSH_ERROR an error happened.
|
||||||
|
*/
|
||||||
int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction
|
int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction direction
|
||||||
, void *data, u_int32_t len, u_int32_t origlen){
|
, void *data, u_int32_t len, u_int32_t origlen){
|
||||||
ssh_buffer ip=buffer_new();
|
ssh_buffer ip;
|
||||||
int err;
|
int err;
|
||||||
|
if(ctx==NULL || ctx->file ==NULL)
|
||||||
|
return SSH_ERROR;
|
||||||
|
if(ctx->connected==0)
|
||||||
|
if(ssh_pcap_context_connect(ctx)==SSH_ERROR)
|
||||||
|
return SSH_ERROR;
|
||||||
|
ip=buffer_new();
|
||||||
if(ip==NULL){
|
if(ip==NULL){
|
||||||
ssh_set_error_oom(ctx->session);
|
ssh_set_error_oom(ctx->session);
|
||||||
return SSH_ERROR;
|
return SSH_ERROR;
|
||||||
@ -231,9 +297,10 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
|
|||||||
/* tos */
|
/* tos */
|
||||||
buffer_add_u8(ip,0);
|
buffer_add_u8(ip,0);
|
||||||
/* total len */
|
/* total len */
|
||||||
buffer_add_u16(ip,htons(origlen + 40));
|
buffer_add_u16(ip,htons(origlen + TCPIPHDR_LEN));
|
||||||
/* id */
|
/* IP id number */
|
||||||
buffer_add_u16(ip,htons(1));
|
buffer_add_u16(ip,htons(ctx->file->ipsequence));
|
||||||
|
ctx->file->ipsequence++;
|
||||||
/* fragment offset */
|
/* fragment offset */
|
||||||
buffer_add_u16(ip,htons(0));
|
buffer_add_u16(ip,htons(0));
|
||||||
/* TTL */
|
/* TTL */
|
||||||
@ -251,17 +318,19 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
|
|||||||
}
|
}
|
||||||
/* TCP */
|
/* TCP */
|
||||||
if(direction==SSH_PCAP_DIR_OUT){
|
if(direction==SSH_PCAP_DIR_OUT){
|
||||||
buffer_add_u16(ip,ntohs(ctx->portsource));
|
buffer_add_u16(ip,ctx->portsource);
|
||||||
buffer_add_u16(ip,ntohs(ctx->portdest));
|
buffer_add_u16(ip,ctx->portdest);
|
||||||
} else {
|
} else {
|
||||||
buffer_add_u16(ip,ntohs(ctx->portdest));
|
buffer_add_u16(ip,ctx->portdest);
|
||||||
buffer_add_u16(ip,ntohs(ctx->portsource));
|
buffer_add_u16(ip,ctx->portsource);
|
||||||
}
|
}
|
||||||
/* sequence number */
|
/* sequence number */
|
||||||
if(direction==SSH_PCAP_DIR_OUT){
|
if(direction==SSH_PCAP_DIR_OUT){
|
||||||
buffer_add_u32(ip,ntohl(ctx->outsequence));
|
buffer_add_u32(ip,ntohl(ctx->outsequence));
|
||||||
|
ctx->outsequence+=origlen;
|
||||||
} else {
|
} else {
|
||||||
buffer_add_u32(ip,ntohl(ctx->insequence));
|
buffer_add_u32(ip,ntohl(ctx->insequence));
|
||||||
|
ctx->insequence+=origlen;
|
||||||
}
|
}
|
||||||
/* ack number */
|
/* ack number */
|
||||||
if(direction==SSH_PCAP_DIR_OUT){
|
if(direction==SSH_PCAP_DIR_OUT){
|
||||||
@ -269,7 +338,7 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
|
|||||||
} else {
|
} else {
|
||||||
buffer_add_u32(ip,ntohl(ctx->outsequence));
|
buffer_add_u32(ip,ntohl(ctx->outsequence));
|
||||||
}
|
}
|
||||||
/* header len */
|
/* header len = 20 = 5 * 32 bits, at offset 4*/
|
||||||
buffer_add_u8(ip,5 << 4);
|
buffer_add_u8(ip,5 << 4);
|
||||||
/* flags */
|
/* flags */
|
||||||
buffer_add_u8(ip,TH_PUSH | TH_ACK);
|
buffer_add_u8(ip,TH_PUSH | TH_ACK);
|
||||||
@ -281,11 +350,16 @@ int ssh_pcap_context_write(ssh_pcap_context ctx,enum ssh_pcap_direction directio
|
|||||||
buffer_add_u16(ip,0);
|
buffer_add_u16(ip,0);
|
||||||
/* actual data */
|
/* actual data */
|
||||||
buffer_add_data(ip,data,len);
|
buffer_add_data(ip,data,len);
|
||||||
err=ssh_pcap_file_write_packet(ctx->file,ip,origlen + 40);
|
err=ssh_pcap_file_write_packet(ctx->file,ip,origlen + TCPIPHDR_LEN);
|
||||||
buffer_free(ip);
|
buffer_free(ip);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ssh_set_pcap_context(ssh_session session, ssh_pcap_context pcap){
|
||||||
|
session->pcap_ctx=pcap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* WITH_PCAP */
|
#endif /* WITH_PCAP */
|
||||||
/** @} */
|
/** @} */
|
||||||
/* vim: set ts=2 sw=2 et cindent: */
|
/* vim: set ts=2 sw=2 et cindent: */
|
||||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user