Blame src/pcap.c

Packit 6c0a39
/*
Packit 6c0a39
 * This file is part of the SSH Library
Packit 6c0a39
 *
Packit 6c0a39
 * Copyright (c) 2009 by Aris Adamantiadis
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is free software; you can redistribute it and/or modify
Packit 6c0a39
 * it under the terms of the GNU Lesser General Public License as published by
Packit 6c0a39
 * the Free Software Foundation; either version 2.1 of the License, or (at your
Packit 6c0a39
 * option) any later version.
Packit 6c0a39
 *
Packit 6c0a39
 * The SSH Library is distributed in the hope that it will be useful, but
Packit 6c0a39
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
Packit 6c0a39
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
Packit 6c0a39
 * License for more details.
Packit 6c0a39
 *
Packit 6c0a39
 * You should have received a copy of the GNU Lesser General Public License
Packit 6c0a39
 * along with the SSH Library; see the file COPYING.  If not, write to
Packit 6c0a39
 * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
Packit 6c0a39
 * MA 02111-1307, USA.
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
/* pcap.c */
Packit 6c0a39
#include "config.h"
Packit 6c0a39
#ifdef WITH_PCAP
Packit 6c0a39
Packit 6c0a39
#include <stdio.h>
Packit 6c0a39
#ifdef _WIN32
Packit 6c0a39
#include <winsock2.h>
Packit 6c0a39
#include <ws2tcpip.h>
Packit 6c0a39
#else
Packit 6c0a39
#include <netinet/in.h>
Packit 6c0a39
#include <sys/socket.h>
Packit 6c0a39
#endif
Packit 6c0a39
#ifdef HAVE_SYS_TIME_H
Packit 6c0a39
#include <sys/time.h>
Packit 6c0a39
#endif /* HAVE_SYS_TIME_H */
Packit 6c0a39
#include <errno.h>
Packit 6c0a39
#include <stdlib.h>
Packit 6c0a39
Packit 6c0a39
#include "libssh/libssh.h"
Packit 6c0a39
#include "libssh/pcap.h"
Packit 6c0a39
#include "libssh/session.h"
Packit 6c0a39
#include "libssh/buffer.h"
Packit 6c0a39
#include "libssh/socket.h"
Packit 6c0a39
Packit 6c0a39
/**
Packit 6c0a39
 * @internal
Packit 6c0a39
 *
Packit 6c0a39
 * @defgroup libssh_pcap The libssh pcap functions
Packit 6c0a39
 * @ingroup libssh
Packit 6c0a39
 *
Packit 6c0a39
 * The pcap file generation
Packit 6c0a39
 *
Packit 6c0a39
 *
Packit 6c0a39
 * @{
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
/* The header of a pcap file is the following. We are not going to make it
Packit 6c0a39
 * very complicated.
Packit 6c0a39
 * Just for information.
Packit 6c0a39
 */
Packit 6c0a39
struct pcap_hdr_s {
Packit 6c0a39
	uint32_t magic_number;   /* magic number */
Packit 6c0a39
	uint16_t version_major;  /* major version number */
Packit 6c0a39
	uint16_t version_minor;  /* minor version number */
Packit 6c0a39
	int32_t   thiszone;       /* GMT to local correction */
Packit 6c0a39
	uint32_t sigfigs;        /* accuracy of timestamps */
Packit 6c0a39
	uint32_t snaplen;        /* max length of captured packets, in octets */
Packit 6c0a39
	uint32_t network;        /* data link type */
Packit 6c0a39
};
Packit 6c0a39
Packit 6c0a39
#define PCAP_MAGIC 0xa1b2c3d4
Packit 6c0a39
#define PCAP_VERSION_MAJOR 2
Packit 6c0a39
#define PCAP_VERSION_MINOR 4
Packit 6c0a39
Packit 6c0a39
#define DLT_RAW         12      /* raw IP */
Packit 6c0a39
Packit 6c0a39
/* TCP flags */
Packit 6c0a39
#define TH_FIN        0x01
Packit 6c0a39
#define TH_SYN        0x02
Packit 6c0a39
#define TH_RST        0x04
Packit 6c0a39
#define TH_PUSH       0x08
Packit 6c0a39
#define TH_ACK        0x10
Packit 6c0a39
#define TH_URG        0x20
Packit 6c0a39
Packit 6c0a39
/* The header of a pcap packet.
Packit 6c0a39
 * Just for information.
Packit 6c0a39
 */
Packit 6c0a39
struct pcaprec_hdr_s {
Packit 6c0a39
	uint32_t ts_sec;         /* timestamp seconds */
Packit 6c0a39
	uint32_t ts_usec;        /* timestamp microseconds */
Packit 6c0a39
	uint32_t incl_len;       /* number of octets of packet saved in file */
Packit 6c0a39
	uint32_t orig_len;       /* actual length of packet */
Packit 6c0a39
};
Packit 6c0a39
Packit 6c0a39
/** @private
Packit 6c0a39
 * @brief a pcap context expresses the state of a pcap dump
Packit 6c0a39
 * in a SSH session only. Multiple pcap contexts may be used into
Packit 6c0a39
 * a single pcap file.
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
struct ssh_pcap_context_struct {
Packit 6c0a39
	ssh_session session;
Packit 6c0a39
	ssh_pcap_file file;
Packit 6c0a39
	int connected;
Packit 6c0a39
	/* All of these information are useful to generate
Packit 6c0a39
	 * the dummy IP and TCP packets
Packit 6c0a39
	 */
Packit 6c0a39
	uint32_t ipsource;
Packit 6c0a39
	uint32_t ipdest;
Packit 6c0a39
	uint16_t portsource;
Packit 6c0a39
	uint16_t portdest;
Packit 6c0a39
	uint32_t outsequence;
Packit 6c0a39
	uint32_t insequence;
Packit 6c0a39
};
Packit 6c0a39
Packit 6c0a39
/** @private
Packit 6c0a39
 * @brief a pcap file expresses the state of a pcap file which may
Packit 6c0a39
 * contain several streams.
Packit 6c0a39
 */
Packit 6c0a39
struct ssh_pcap_file_struct {
Packit 6c0a39
	FILE *output;
Packit 6c0a39
	uint16_t ipsequence;
Packit 6c0a39
};
Packit 6c0a39
Packit 6c0a39
/**
Packit 6c0a39
 * @brief create a new ssh_pcap_file object
Packit 6c0a39
 */
Packit 6c0a39
ssh_pcap_file ssh_pcap_file_new(void) {
Packit 6c0a39
    struct ssh_pcap_file_struct *pcap;
Packit 6c0a39
Packit 6c0a39
    pcap = (struct ssh_pcap_file_struct *) malloc(sizeof(struct ssh_pcap_file_struct));
Packit 6c0a39
    if (pcap == NULL) {
Packit 6c0a39
        return NULL;
Packit 6c0a39
    }
Packit 6c0a39
    ZERO_STRUCTP(pcap);
Packit 6c0a39
Packit 6c0a39
    return pcap;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief writes a packet on file
Packit 6c0a39
 */
Packit 6c0a39
static int ssh_pcap_file_write(ssh_pcap_file pcap, ssh_buffer packet){
Packit 6c0a39
	int err;
Packit 6c0a39
	uint32_t len;
Packit 6c0a39
	if(pcap == NULL || pcap->output==NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	len=ssh_buffer_get_len(packet);
Packit 6c0a39
	err=fwrite(ssh_buffer_get(packet),len,1,pcap->output);
Packit 6c0a39
	if(err<0)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	else
Packit 6c0a39
		return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief prepends a packet with the pcap header and writes packet
Packit 6c0a39
 * on file
Packit 6c0a39
 */
Packit 6c0a39
int ssh_pcap_file_write_packet(ssh_pcap_file pcap, ssh_buffer packet, uint32_t original_len){
Packit 6c0a39
	ssh_buffer header=ssh_buffer_new();
Packit 6c0a39
	struct timeval now;
Packit 6c0a39
	int err;
Packit 6c0a39
	if(header == NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	gettimeofday(&now,NULL);
Packit 6c0a39
    err = ssh_buffer_allocate_size(header,
Packit 6c0a39
                                   sizeof(uint32_t) * 4 +
Packit 6c0a39
                                   ssh_buffer_get_len(packet));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(now.tv_sec));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(now.tv_usec));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(ssh_buffer_get_len(packet)));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(original_len));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_buffer(header,packet);
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	err=ssh_pcap_file_write(pcap,header);
Packit 6c0a39
error:
Packit Service fcc0d2
	SSH_BUFFER_FREE(header);
Packit 6c0a39
	return err;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/**
Packit 6c0a39
 * @brief opens a new pcap file and create header
Packit 6c0a39
 */
Packit 6c0a39
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){
Packit 6c0a39
	ssh_buffer header;
Packit 6c0a39
	int err;
Packit 6c0a39
	if(pcap == NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	if(pcap->output){
Packit 6c0a39
		fclose(pcap->output);
Packit 6c0a39
		pcap->output=NULL;
Packit 6c0a39
	}
Packit 6c0a39
	pcap->output=fopen(filename,"wb");
Packit 6c0a39
	if(pcap->output==NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	header=ssh_buffer_new();
Packit 6c0a39
	if(header==NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
    err = ssh_buffer_allocate_size(header,
Packit 6c0a39
                                   sizeof(uint32_t) * 5 +
Packit 6c0a39
                                   sizeof(uint16_t) * 2);
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(PCAP_MAGIC));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u16(header,htons(PCAP_VERSION_MAJOR));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    err = ssh_buffer_add_u16(header,htons(PCAP_VERSION_MINOR));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	/* currently hardcode GMT to 0 */
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(0));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	/* accuracy */
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(0));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	/* size of the biggest packet */
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(MAX_PACKET_LEN));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	/* we will write sort-of IP */
Packit 6c0a39
    err = ssh_buffer_add_u32(header,htonl(DLT_RAW));
Packit 6c0a39
    if (err < 0) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
	err=ssh_pcap_file_write(pcap,header);
Packit 6c0a39
error:
Packit Service fcc0d2
	SSH_BUFFER_FREE(header);
Packit 6c0a39
	return err;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_pcap_file_close(ssh_pcap_file pcap){
Packit 6c0a39
	int err;
Packit 6c0a39
	if(pcap ==NULL || pcap->output==NULL)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	err=fclose(pcap->output);
Packit 6c0a39
	pcap->output=NULL;
Packit 6c0a39
	if(err != 0)
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	else
Packit 6c0a39
		return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_pcap_file_free(ssh_pcap_file pcap){
Packit 6c0a39
	ssh_pcap_file_close(pcap);
Packit 6c0a39
	SAFE_FREE(pcap);
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief allocates a new ssh_pcap_context object
Packit 6c0a39
 */
Packit 6c0a39
Packit 6c0a39
ssh_pcap_context ssh_pcap_context_new(ssh_session session){
Packit 6c0a39
	ssh_pcap_context ctx = (struct ssh_pcap_context_struct *) malloc(sizeof(struct ssh_pcap_context_struct));
Packit 6c0a39
	if(ctx==NULL){
Packit 6c0a39
		ssh_set_error_oom(session);
Packit 6c0a39
		return NULL;
Packit 6c0a39
	}
Packit 6c0a39
	ZERO_STRUCTP(ctx);
Packit 6c0a39
	ctx->session=session;
Packit 6c0a39
	return ctx;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_pcap_context_free(ssh_pcap_context ctx){
Packit 6c0a39
	SAFE_FREE(ctx);
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_pcap_context_set_file(ssh_pcap_context ctx, ssh_pcap_file pcap){
Packit 6c0a39
	ctx->file=pcap;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief sets the IP and port parameters in the connection
Packit 6c0a39
 */
Packit 6c0a39
static int ssh_pcap_context_connect(ssh_pcap_context ctx)
Packit 6c0a39
{
Packit 6c0a39
    ssh_session session=ctx->session;
Packit 6c0a39
    struct sockaddr_in local = {
Packit 6c0a39
        .sin_family = AF_UNSPEC,
Packit 6c0a39
    };
Packit 6c0a39
    struct sockaddr_in remote = {
Packit 6c0a39
        .sin_family = AF_UNSPEC,
Packit 6c0a39
    };
Packit 6c0a39
    socket_t fd;
Packit 6c0a39
    socklen_t len;
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    if (session == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (session->socket == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    fd = ssh_socket_get_fd(session->socket);
Packit 6c0a39
Packit 6c0a39
    /* TODO: adapt for windows */
Packit 6c0a39
    if (fd < 0) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    len = sizeof(local);
Packit 6c0a39
    rc = getsockname(fd, (struct sockaddr *)&local, &len;;
Packit 6c0a39
    if (rc < 0) {
Packit 6c0a39
        ssh_set_error(session,
Packit 6c0a39
                      SSH_REQUEST_DENIED,
Packit 6c0a39
                      "Getting local IP address: %s",
Packit 6c0a39
                      strerror(errno));
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    len = sizeof(remote);
Packit 6c0a39
    rc = getpeername(fd, (struct sockaddr *)&remote, &len;;
Packit 6c0a39
    if (rc < 0) {
Packit 6c0a39
        ssh_set_error(session,
Packit 6c0a39
                      SSH_REQUEST_DENIED,
Packit 6c0a39
                      "Getting remote IP address: %s",
Packit 6c0a39
                      strerror(errno));
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    if (local.sin_family != AF_INET) {
Packit 6c0a39
        ssh_set_error(session,
Packit 6c0a39
                      SSH_REQUEST_DENIED,
Packit 6c0a39
                      "Only IPv4 supported for pcap logging");
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    memcpy(&ctx->ipsource, &local.sin_addr, sizeof(ctx->ipsource));
Packit 6c0a39
    memcpy(&ctx->ipdest, &remote.sin_addr, sizeof(ctx->ipdest));
Packit 6c0a39
    memcpy(&ctx->portsource, &local.sin_port, sizeof(ctx->portsource));
Packit 6c0a39
    memcpy(&ctx->portdest, &remote.sin_port, sizeof(ctx->portdest));
Packit 6c0a39
Packit 6c0a39
    ctx->connected = 1;
Packit 6c0a39
    return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
#define IPHDR_LEN 20
Packit 6c0a39
#define TCPHDR_LEN 20
Packit 6c0a39
#define TCPIPHDR_LEN (IPHDR_LEN + TCPHDR_LEN)
Packit 6c0a39
/** @internal
Packit 6c0a39
 * @brief write a SSH packet as a TCP over IP in a pcap file
Packit 6c0a39
 * @param ctx open pcap context
Packit 6c0a39
 * @param direction SSH_PCAP_DIRECTION_IN if the packet has been received
Packit 6c0a39
 * @param direction SSH_PCAP_DIRECTION_OUT if the packet has been emitted
Packit 6c0a39
 * @param data pointer to the data to write
Packit 6c0a39
 * @param len data to write in the pcap file. May be smaller than origlen.
Packit 6c0a39
 * @param origlen number of bytes of complete data.
Packit 6c0a39
 * @returns SSH_OK write is successful
Packit 6c0a39
 * @returns SSH_ERROR an error happened.
Packit 6c0a39
 */
Packit 6c0a39
int ssh_pcap_context_write(ssh_pcap_context ctx,
Packit 6c0a39
                           enum ssh_pcap_direction direction,
Packit 6c0a39
		           void *data,
Packit 6c0a39
                           uint32_t len,
Packit 6c0a39
                           uint32_t origlen)
Packit 6c0a39
{
Packit 6c0a39
    ssh_buffer ip;
Packit 6c0a39
    int rc;
Packit 6c0a39
Packit 6c0a39
    if (ctx == NULL || ctx->file == NULL) {
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
    if (ctx->connected == 0) {
Packit 6c0a39
        if (ssh_pcap_context_connect(ctx) == SSH_ERROR) {
Packit 6c0a39
            return SSH_ERROR;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
    ip = ssh_buffer_new();
Packit 6c0a39
    if (ip == NULL) {
Packit 6c0a39
        ssh_set_error_oom(ctx->session);
Packit 6c0a39
        return SSH_ERROR;
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    /* build an IP packet */
Packit 6c0a39
    rc = ssh_buffer_pack(ip,
Packit 6c0a39
                         "bbwwwbbw",
Packit 6c0a39
                         4 << 4 | 5, /* V4, 20 bytes */
Packit 6c0a39
                         0,          /* tos */
Packit 6c0a39
                         origlen + TCPIPHDR_LEN, /* total len */
Packit 6c0a39
                         ctx->file->ipsequence,  /* IP id number */
Packit 6c0a39
                         0,          /* fragment offset */
Packit 6c0a39
                         64,         /* TTL */
Packit 6c0a39
                         6,          /* protocol TCP=6 */
Packit 6c0a39
                         0);         /* checksum */
Packit 6c0a39
Packit 6c0a39
    ctx->file->ipsequence++;
Packit 6c0a39
    if (rc != SSH_OK){
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    if (direction == SSH_PCAP_DIR_OUT) {
Packit 6c0a39
        rc = ssh_buffer_add_u32(ip, ctx->ipsource);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        rc = ssh_buffer_add_u32(ip, ctx->ipdest);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    } else {
Packit 6c0a39
        rc = ssh_buffer_add_u32(ip, ctx->ipdest);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        rc = ssh_buffer_add_u32(ip, ctx->ipsource);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
    /* TCP */
Packit 6c0a39
    if (direction == SSH_PCAP_DIR_OUT) {
Packit 6c0a39
        rc = ssh_buffer_add_u16(ip, ctx->portsource);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        rc = ssh_buffer_add_u16(ip, ctx->portdest);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    } else {
Packit 6c0a39
        rc = ssh_buffer_add_u16(ip, ctx->portdest);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        rc = ssh_buffer_add_u16(ip, ctx->portsource);
Packit 6c0a39
        if (rc < 0) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
    /* sequence number */
Packit 6c0a39
    if (direction == SSH_PCAP_DIR_OUT) {
Packit 6c0a39
        rc = ssh_buffer_pack(ip, "d", ctx->outsequence);
Packit 6c0a39
        if (rc != SSH_OK) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        ctx->outsequence += origlen;
Packit 6c0a39
    } else {
Packit 6c0a39
        rc = ssh_buffer_pack(ip, "d", ctx->insequence);
Packit 6c0a39
        if (rc != SSH_OK) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
        ctx->insequence += origlen;
Packit 6c0a39
    }
Packit 6c0a39
    /* ack number */
Packit 6c0a39
    if (direction == SSH_PCAP_DIR_OUT) {
Packit 6c0a39
        rc = ssh_buffer_pack(ip, "d", ctx->insequence);
Packit 6c0a39
        if (rc != SSH_OK) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    } else {
Packit 6c0a39
        rc = ssh_buffer_pack(ip, "d", ctx->outsequence);
Packit 6c0a39
        if (rc != SSH_OK) {
Packit 6c0a39
            goto error;
Packit 6c0a39
        }
Packit 6c0a39
    }
Packit 6c0a39
Packit 6c0a39
    rc = ssh_buffer_pack(ip,
Packit 6c0a39
                         "bbwwwP",
Packit 6c0a39
                         5 << 4,             /* header len = 20 = 5 * 32 bits, at offset 4*/
Packit 6c0a39
                         TH_PUSH | TH_ACK,   /* flags */
Packit 6c0a39
                         65535,              /* window */
Packit 6c0a39
                         0,                  /* checksum */
Packit 6c0a39
                         0,                  /* urgent data ptr */
Packit 6c0a39
                         (size_t)len, data); /* actual data */
Packit 6c0a39
    if (rc != SSH_OK) {
Packit 6c0a39
        goto error;
Packit 6c0a39
    }
Packit 6c0a39
    rc = ssh_pcap_file_write_packet(ctx->file, ip, origlen + TCPIPHDR_LEN);
Packit 6c0a39
Packit 6c0a39
error:
Packit Service fcc0d2
    SSH_BUFFER_FREE(ip);
Packit 6c0a39
    return rc;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
/** @brief sets the pcap file used to trace the session
Packit 6c0a39
 * @param current session
Packit 6c0a39
 * @param pcap an handler to a pcap file. A pcap file may be used in several
Packit 6c0a39
 * sessions.
Packit 6c0a39
 * @returns SSH_ERROR in case of error, SSH_OK otherwise.
Packit 6c0a39
 */
Packit 6c0a39
int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcap){
Packit 6c0a39
	ssh_pcap_context ctx=ssh_pcap_context_new(session);
Packit 6c0a39
	if(ctx==NULL){
Packit 6c0a39
		ssh_set_error_oom(session);
Packit 6c0a39
		return SSH_ERROR;
Packit 6c0a39
	}
Packit 6c0a39
	ctx->file=pcap;
Packit 6c0a39
	if(session->pcap_ctx)
Packit 6c0a39
		ssh_pcap_context_free(session->pcap_ctx);
Packit 6c0a39
	session->pcap_ctx=ctx;
Packit 6c0a39
	return SSH_OK;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
Packit 6c0a39
#else /* WITH_PCAP */
Packit 6c0a39
Packit 6c0a39
/* Simple stub returning errors when no pcap compiled in */
Packit 6c0a39
Packit 6c0a39
#include "libssh/libssh.h"
Packit 6c0a39
#include "libssh/priv.h"
Packit 6c0a39
Packit 6c0a39
int ssh_pcap_file_close(ssh_pcap_file pcap){
Packit 6c0a39
	(void) pcap;
Packit 6c0a39
	return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
void ssh_pcap_file_free(ssh_pcap_file pcap){
Packit 6c0a39
	(void) pcap;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
ssh_pcap_file ssh_pcap_file_new(void){
Packit 6c0a39
	return NULL;
Packit 6c0a39
}
Packit 6c0a39
int ssh_pcap_file_open(ssh_pcap_file pcap, const char *filename){
Packit 6c0a39
	(void) pcap;
Packit 6c0a39
	(void) filename;
Packit 6c0a39
	return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
int ssh_set_pcap_file(ssh_session session, ssh_pcap_file pcapfile){
Packit 6c0a39
	(void) pcapfile;
Packit 6c0a39
	ssh_set_error(session,SSH_REQUEST_DENIED,"Pcap support not compiled in");
Packit 6c0a39
	return SSH_ERROR;
Packit 6c0a39
}
Packit 6c0a39
Packit 6c0a39
#endif
Packit 6c0a39
Packit 6c0a39
/** @} */