mirror of https://github.com/wolfSSL/wolfssh.git
Adding code
parent
997013f210
commit
eb82d2bf28
|
@ -20,12 +20,234 @@
|
|||
*/
|
||||
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <wolfssh/ssh.h>
|
||||
|
||||
|
||||
typedef unsigned short word16;
|
||||
typedef int SOCKET_T;
|
||||
#ifdef TEST_IPV6
|
||||
typedef struct sockaddr_in6 SOCKADDR_IN_T;
|
||||
#define AF_INET_V AF_INET6
|
||||
static const char* wolfsshIP = "::1";
|
||||
#else
|
||||
typedef struct sockaddr_in SOCKADDR_IN_T;
|
||||
#define AF_INET_V AF_INET
|
||||
static const char* wolfsshIP = "127.0.0.1";
|
||||
#endif
|
||||
|
||||
#if defined(__MACH__) || defined(USE_WINDOWS_API)
|
||||
#ifndef _SOCKLEN_T
|
||||
typedef int socklen_t;
|
||||
#endif
|
||||
#endif
|
||||
/* HPUX doesn't use socklent_t for third parameter to accept, unless
|
||||
_XOPEN_SOURCE_EXTENDED is defined */
|
||||
#if !defined(__hpux__) && !defined(CYASSL_MDK_ARM) && !defined(CYASSL_IAR_ARM)
|
||||
typedef socklen_t* ACCEPT_THIRD_T;
|
||||
#else
|
||||
#if defined _XOPEN_SOURCE_EXTENDED
|
||||
typedef socklen_t* ACCEPT_THIRD_T;
|
||||
#else
|
||||
typedef int* ACCEPT_THIRD_T;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
static WINLINE void err_sys(const char* msg)
|
||||
{
|
||||
printf("server error: %s\n", msg);
|
||||
if (msg)
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
static WINLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
|
||||
word16 port)
|
||||
{
|
||||
int useLookup = 0;
|
||||
(void)useLookup;
|
||||
|
||||
memset(addr, 0, sizeof(SOCKADDR_IN_T));
|
||||
|
||||
#ifndef TEST_IPV6
|
||||
/* peer could be in human readable form */
|
||||
if ( (peer != INADDR_ANY) && isalpha((int)peer[0])) {
|
||||
#ifdef CYASSL_MDK_ARM
|
||||
int err;
|
||||
struct hostent* entry = gethostbyname(peer, &err);
|
||||
#else
|
||||
struct hostent* entry = gethostbyname(peer);
|
||||
#endif
|
||||
|
||||
if (entry) {
|
||||
memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0],
|
||||
entry->h_length);
|
||||
useLookup = 1;
|
||||
}
|
||||
else
|
||||
err_sys("no entry for host");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef TEST_IPV6
|
||||
#if defined(CYASSL_MDK_ARM)
|
||||
addr->sin_family = PF_INET;
|
||||
#else
|
||||
addr->sin_family = AF_INET_V;
|
||||
#endif
|
||||
addr->sin_port = htons(port);
|
||||
if (peer == INADDR_ANY)
|
||||
addr->sin_addr.s_addr = INADDR_ANY;
|
||||
else {
|
||||
if (!useLookup)
|
||||
addr->sin_addr.s_addr = inet_addr(peer);
|
||||
}
|
||||
#else
|
||||
addr->sin6_family = AF_INET_V;
|
||||
addr->sin6_port = htons(port);
|
||||
if (peer == INADDR_ANY)
|
||||
addr->sin6_addr = in6addr_any;
|
||||
else {
|
||||
#ifdef HAVE_GETADDRINFO
|
||||
struct addrinfo hints;
|
||||
struct addrinfo* answer = NULL;
|
||||
int ret;
|
||||
char strPort[80];
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
hints.ai_family = AF_INET_V;
|
||||
hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
|
||||
hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
|
||||
SNPRINTF(strPort, sizeof(strPort), "%d", port);
|
||||
strPort[79] = '\0';
|
||||
|
||||
ret = getaddrinfo(peer, strPort, &hints, &answer);
|
||||
if (ret < 0 || answer == NULL)
|
||||
err_sys("getaddrinfo failed");
|
||||
|
||||
memcpy(addr, answer->ai_addr, answer->ai_addrlen);
|
||||
freeaddrinfo(answer);
|
||||
#else
|
||||
printf("no ipv6 getaddrinfo, loopback only tests/examples\n");
|
||||
addr->sin6_addr = in6addr_loopback;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static WINLINE void tcp_socket(SOCKET_T* sockfd)
|
||||
{
|
||||
*sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
|
||||
|
||||
#ifdef USE_WINDOWS_API
|
||||
if (*sockfd == INVALID_SOCKET)
|
||||
err_sys("socket failed\n");
|
||||
#else
|
||||
if (*sockfd < 0)
|
||||
err_sys("socket failed\n");
|
||||
#endif
|
||||
|
||||
#ifndef USE_WINDOWS_API
|
||||
#ifdef SO_NOSIGPIPE
|
||||
{
|
||||
int on = 1;
|
||||
socklen_t len = sizeof(on);
|
||||
int res = setsockopt(*sockfd, SOL_SOCKET, SO_NOSIGPIPE, &on, len);
|
||||
if (res < 0)
|
||||
err_sys("setsockopt SO_NOSIGPIPE failed\n");
|
||||
}
|
||||
#elif defined(CYASSL_MDK_ARM)
|
||||
/* nothing to define */
|
||||
#else /* no S_NOSIGPIPE */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* S_NOSIGPIPE */
|
||||
|
||||
#if defined(TCP_NODELAY)
|
||||
{
|
||||
int on = 1;
|
||||
socklen_t len = sizeof(on);
|
||||
int res = setsockopt(*sockfd, IPPROTO_TCP, TCP_NODELAY, &on, len);
|
||||
if (res < 0)
|
||||
err_sys("setsockopt TCP_NODELAY failed\n");
|
||||
}
|
||||
#endif
|
||||
#endif /* USE_WINDOWS_API */
|
||||
}
|
||||
|
||||
|
||||
static WINLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
|
||||
{
|
||||
SOCKADDR_IN_T addr;
|
||||
|
||||
/* don't use INADDR_ANY by default, firewall may block, make user switch
|
||||
on */
|
||||
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfsshIP), *port);
|
||||
tcp_socket(sockfd);
|
||||
|
||||
#if !defined(USE_WINDOWS_API) && !defined(CYASSL_MDK_ARM)
|
||||
{
|
||||
int res, on = 1;
|
||||
socklen_t len = sizeof(on);
|
||||
res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
|
||||
if (res < 0)
|
||||
err_sys("setsockopt SO_REUSEADDR failed\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
err_sys("tcp bind failed");
|
||||
if (listen(*sockfd, 5) != 0)
|
||||
err_sys("tcp listen failed");
|
||||
#if !defined(USE_WINDOWS_API)
|
||||
if (*port == 0) {
|
||||
socklen_t len = sizeof(addr);
|
||||
if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
|
||||
#ifndef TEST_IPV6
|
||||
*port = ntohs(addr.sin_port);
|
||||
#else
|
||||
*port = ntohs(addr.sin6_port);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
static WINLINE void tcp_accept(SOCKET_T* sockfd, SOCKET_T* clientfd, word16 port)
|
||||
{
|
||||
SOCKADDR_IN_T client;
|
||||
socklen_t client_len = sizeof(client);
|
||||
|
||||
tcp_listen(sockfd, &port, 1);
|
||||
|
||||
*clientfd = accept(*sockfd, (struct sockaddr*)&client,
|
||||
(ACCEPT_THIRD_T)&client_len);
|
||||
|
||||
if (*clientfd == -1)
|
||||
err_sys("tcp accept failed");
|
||||
}
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
SOCKET_T sockfd = 0;
|
||||
SOCKET_T clientfd = 0;
|
||||
|
||||
#ifdef DEBUG_WOLFSSH
|
||||
wolfSSH_Debugging_ON();
|
||||
#endif
|
||||
|
@ -34,9 +256,13 @@ int main(void)
|
|||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
tcp_accept(&sockfd, &clientfd, 22222);
|
||||
|
||||
if (wolfSSH_Cleanup() != WS_SUCCESS) {
|
||||
fprintf(stderr, "Couldn't clean up wolfSSH.\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
271
src/ssh.c
271
src/ssh.c
|
@ -44,3 +44,274 @@ int wolfSSH_Cleanup(void)
|
|||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static WOLFSSH_CTX* CtxInit(WOLFSSH_CTX* ctx, void* heap)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter CtxInit()");
|
||||
|
||||
if (ctx == NULL)
|
||||
return ctx;
|
||||
|
||||
WMEMSET(ctx, 0, sizeof(WOLFSSH_CTX));
|
||||
|
||||
if (heap)
|
||||
ctx->heap = heap;
|
||||
|
||||
#ifndef WOLFSSH_USER_IO
|
||||
ctx->ioRecvCb = wsEmbedRecv;
|
||||
ctx->ioSendCb = wsEmbedSend;
|
||||
#endif /* WOLFSSH_USER_IO */
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
WOLFSSH_CTX* wolfSSH_CTX_new(void* heap)
|
||||
{
|
||||
WOLFSSH_CTX* ctx;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_new()");
|
||||
|
||||
ctx = (WOLFSSH_CTX*)WMALLOC(sizeof(WOLFSSH_CTX), heap, WOLFSSH_CTX_TYPE);
|
||||
ctx = CtxInit(ctx, heap);
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_CTX_new(), ctx = %p", ctx);
|
||||
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
||||
static void CtxResourceFree(WOLFSSH_CTX* ctx)
|
||||
{
|
||||
/* when context holds resources, free here */
|
||||
(void)ctx;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter CtxResourceFree()");
|
||||
}
|
||||
|
||||
|
||||
void wolfSSH_CTX_free(WOLFSSH_CTX* ctx)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CTX_free()");
|
||||
|
||||
if (ctx) {
|
||||
CtxResourceFree(ctx);
|
||||
WFREE(ctx, ctx->heap, WOLFSSH_CTX_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static WOLFSSH* SshInit(WOLFSSH* ssh, WOLFSSH_CTX* ctx)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter SshInit()");
|
||||
|
||||
if (ssh == NULL)
|
||||
return ssh;
|
||||
|
||||
WMEMSET(ssh, 0, sizeof(WOLFSSH)); /* default init to zeros */
|
||||
|
||||
if (ctx)
|
||||
ssh->ctx = ctx;
|
||||
else {
|
||||
WLOG(WS_LOG_ERROR, "Trying to init a wolfSSH w/o wolfSSH_CTX");
|
||||
wolfSSH_free(ssh);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ssh->rfd = -1; /* set to invalid */
|
||||
ssh->wfd = -1; /* set to invalid */
|
||||
ssh->ioReadCtx = &ssh->rfd; /* prevent invalid access if not correctly */
|
||||
ssh->ioWriteCtx = &ssh->wfd; /* set */
|
||||
|
||||
return ssh;
|
||||
}
|
||||
|
||||
|
||||
WOLFSSH* wolfSSH_new(WOLFSSH_CTX* ctx)
|
||||
{
|
||||
WOLFSSH* ssh;
|
||||
void* heap = NULL;
|
||||
|
||||
if (ctx)
|
||||
heap = ctx->heap;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_new()");
|
||||
|
||||
ssh = (WOLFSSH*)WMALLOC(sizeof(WOLFSSH), heap, WOLFSSH_TYPE);
|
||||
ssh = SshInit(ssh, ctx);
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_new(), ssh = %p", ssh);
|
||||
|
||||
return ssh;
|
||||
}
|
||||
|
||||
|
||||
static void SshResourceFree(WOLFSSH* ssh)
|
||||
{
|
||||
/* when ssh holds resources, free here */
|
||||
(void)ssh;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter sshResourceFree()");
|
||||
}
|
||||
|
||||
|
||||
void wolfSSH_free(WOLFSSH* ssh)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_free()");
|
||||
|
||||
if (ssh) {
|
||||
SshResourceFree(ssh);
|
||||
WFREE(ssh, ssh->ctx ? ssh->ctx->heap : NULL, WOLFSSH_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static WOLFSSH_CHAN* SshChanInit(WOLFSSH_CHAN* chan, WOLFSSH* ssh)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter SshChanInit()");
|
||||
|
||||
if (chan == NULL)
|
||||
return chan;
|
||||
|
||||
WMEMSET(chan, 0, sizeof(WOLFSSH_CHAN)); /* default init to zeros */
|
||||
|
||||
if (ssh) {
|
||||
chan->ssh = ssh;
|
||||
chan->ctx = ssh->ctx;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_ERROR, "Trying to init a wolfSSH_CHAN w/o wolfSSH");
|
||||
wolfSSH_CHAN_free(chan);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
WOLFSSH_CHAN* wolfSSH_CHAN_new(WOLFSSH* ssh)
|
||||
{
|
||||
WOLFSSH_CHAN* chan;
|
||||
void* heap = NULL;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_CHAN_new()");
|
||||
|
||||
if (ssh != NULL && ssh->ctx != NULL)
|
||||
heap = ssh->ctx->heap;
|
||||
|
||||
chan = (WOLFSSH_CHAN*)WMALLOC(sizeof(WOLFSSH_CHAN),
|
||||
heap, WOLFSSH_CHAN_TYPE);
|
||||
|
||||
chan = SshChanInit(chan, ssh);
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving wolfSSH_CHAN_new(), chan = %p", chan);
|
||||
|
||||
return chan;
|
||||
}
|
||||
|
||||
|
||||
static void SshChanResourceFree(WOLFSSH_CHAN* chan)
|
||||
{
|
||||
/* when ssh channel holds resources, free here */
|
||||
(void)chan;
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Enter SshChanResourceFree()");
|
||||
}
|
||||
|
||||
|
||||
void wolfSSH_CHAN_free(WOLFSSH_CHAN* chan)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSCEP_free()");
|
||||
|
||||
if (chan) {
|
||||
SshChanResourceFree(chan);
|
||||
WFREE(chan, chan->ctx ? chan->ctx->heap : NULL, WOLFSCEP_TYPE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int wolfSSH_set_fd(WOLFSSH* ssh, int fd)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_set_fd()");
|
||||
|
||||
if (ssh) {
|
||||
ssh->rfd = fd;
|
||||
ssh->wfd = fd;
|
||||
|
||||
ssh->ioReadCtx = &ssh->rfd;
|
||||
ssh->ioWriteCtx = &ssh->wfd;
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
|
||||
int wolfSSH_get_fd(const WOLFSSH* ssh)
|
||||
{
|
||||
WLOG(WS_LOG_DEBUG, "Enter wolfSSH_get_fd()");
|
||||
|
||||
if (ssh)
|
||||
return ssh->rfd;
|
||||
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
|
||||
enum {
|
||||
doProcessInit
|
||||
};
|
||||
|
||||
|
||||
int ProcessReply(WOLFSSH* ssh)
|
||||
{
|
||||
int ret = WS_FATAL_ERROR;
|
||||
int readSz;
|
||||
|
||||
(void)readSz;
|
||||
for (;;) {
|
||||
switch (ssh->processReply) {
|
||||
case doProcessInit:
|
||||
readSz = ssh->blockSz;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int wolfSSH_accept(WOLFSSH* ssh)
|
||||
{
|
||||
switch (ssh->acceptState) {
|
||||
case ACCEPT_BEGIN:
|
||||
if ( (ssh->error = ProcessReply(ssh)) < 0) {
|
||||
WLOG(WS_LOG_DEBUG, "accept reply error: %d", ssh->error);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
ssh->acceptState = CLIENT_VERSION_DONE;
|
||||
WLOG(WS_LOG_DEBUG, "accept state CLIENT_VERSION_DONE");
|
||||
|
||||
case CLIENT_VERSION_DONE:
|
||||
break;
|
||||
|
||||
case SERVER_VERSION_SENT:
|
||||
break;
|
||||
}
|
||||
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int SendServerVersion(WOLFSSH* ssh)
|
||||
{
|
||||
(void)ssh;
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
int DoClientVersion(WOLFSSH* ssh)
|
||||
{
|
||||
(void)ssh;
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,21 +29,65 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
|
||||
enum {
|
||||
/* Any of the items can be none. */
|
||||
ID_NONE,
|
||||
|
||||
/* Encryption IDs */
|
||||
ID_AES128_CBC,
|
||||
ID_AES128_CTR,
|
||||
ID_AES128_GCM_WOLF,
|
||||
|
||||
/* Integrity IDs */
|
||||
ID_HMAC_SHA1,
|
||||
ID_HMAC_SHA1_96,
|
||||
|
||||
/* Key Exchange IDs */
|
||||
ID_DH_GROUP1_SHA1,
|
||||
ID_DH_GROUP14_SHA1,
|
||||
|
||||
/* Public Key IDs */
|
||||
ID_SSH_RSA,
|
||||
|
||||
ID_UNKNOWN
|
||||
};
|
||||
|
||||
|
||||
WOLFSSH_LOCAL uint8_t NameToId(const char*);
|
||||
WOLFSSH_LOCAL const char* IdToName(uint8_t);
|
||||
|
||||
|
||||
/* our wolfSSH Context */
|
||||
struct WOLFSSH_CTX {
|
||||
void* heap; /* heap hint */
|
||||
WS_CallbackIORecv ioRecvCb; /* I/O Receive Callback */
|
||||
WS_CallbackIOSend ioSendCb; /* I/O Send Callback */
|
||||
uint8_t compression;
|
||||
};
|
||||
|
||||
|
||||
/* our wolfSSH session */
|
||||
struct WOLFSSH {
|
||||
WOLFSSH_CTX* ctx; /* owner context */
|
||||
int error;
|
||||
int rfd;
|
||||
int wfd;
|
||||
void* ioReadCtx; /* I/O Read Context handle */
|
||||
void* ioWriteCtx; /* I/O Write Context handle */
|
||||
int rflags; /* optional read flags */
|
||||
int wflags; /* optional write flags */
|
||||
WOLFSSH_CHAN *channel; /* single data channel */
|
||||
uint8_t blockSz;
|
||||
uint8_t acceptState;
|
||||
uint8_t processReply;
|
||||
};
|
||||
|
||||
|
||||
/* wolfSSH channel */
|
||||
struct WOLFSSH_CHAN {
|
||||
WOLFSSH_CTX* ctx;
|
||||
WOLFSSH* ssh;
|
||||
int id;
|
||||
};
|
||||
|
||||
|
||||
|
@ -55,6 +99,19 @@ WOLFSSH_LOCAL int wsEmbedSend(WOLFSSH* ssh, void*, uint32_t sz, void* ctx);
|
|||
|
||||
#endif /* WOLFSSH_USER_IO */
|
||||
|
||||
|
||||
WOLFSSH_LOCAL int ProcessReply(WOLFSSH*);
|
||||
WOLFSSH_LOCAL int SendServerVersion(WOLFSSH*);
|
||||
WOLFSSH_LOCAL int DoClientVersion(WOLFSSH*);
|
||||
|
||||
|
||||
enum {
|
||||
ACCEPT_BEGIN = 0,
|
||||
CLIENT_VERSION_DONE,
|
||||
SERVER_VERSION_SENT,
|
||||
};
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -42,12 +42,31 @@ WOLFSSH_API int wolfSSH_Cleanup(void);
|
|||
WOLFSSH_API int wolfSSH_Debugging_ON(void);
|
||||
WOLFSSH_API void wolfSSH_Debugging_OFF(void);
|
||||
|
||||
/* context functions */
|
||||
WOLFSSH_API WOLFSSH_CTX* wolfSSH_CTX_new(void*);
|
||||
WOLFSSH_API void wolfSSH_CTX_free(WOLFSSH_CTX*);
|
||||
|
||||
/* ssh session functions */
|
||||
WOLFSSH_API WOLFSSH* wolfSSH_new(WOLFSSH_CTX*);
|
||||
WOLFSSH_API void wolfSSH_free(WOLFSSH*);
|
||||
|
||||
/* ssh channel functions */
|
||||
WOLFSSH_API WOLFSSH_CHAN* wolfSSH_CHAN_new(WOLFSSH*);
|
||||
WOLFSSH_API void wolfSSH_CHAN_free(WOLFSSH_CHAN*);
|
||||
|
||||
WOLFSSH_API int wolfSSH_set_fd(WOLFSSH*, int);
|
||||
WOLFSSH_API int wolfSSH_get_fd(const WOLFSSH*);
|
||||
|
||||
WOLFSSH_API const char* wolfSSH_get_error(int);
|
||||
|
||||
/* I/O callbacks */
|
||||
typedef int (*WS_CallbackIORecv)(WOLFSSH*, void* buf, uint32_t sz, void* ctx);
|
||||
typedef int (*WS_CallbackIOSend)(WOLFSSH*, void* buf, uint32_t sz, void* ctx);
|
||||
|
||||
/* Channel I/O callbacks */
|
||||
typedef int (*WSH_CallbackChanRecv)();
|
||||
typedef int (*WSH_CallbackChanSend)();
|
||||
|
||||
WOLFSSH_API void wolfSSH_SetIORecv(WOLFSSH_CTX*, WS_CallbackIORecv);
|
||||
WOLFSSH_API void wolfSSH_SetIOSend(WOLFSSH_CTX*, WS_CallbackIOSend);
|
||||
|
||||
|
@ -57,6 +76,7 @@ WOLFSSH_API void wolfSSH_SetIOWriteCtx(WOLFSSH* ssh, void *ctx);
|
|||
WOLFSSH_API void* wolfSSH_GetIOReadCtx(WOLFSSH* ssh);
|
||||
WOLFSSH_API void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh);
|
||||
|
||||
WOLFSSH_API int wolfSSH_accept(WOLFSSH* ssh);
|
||||
|
||||
|
||||
/* dynamic memory types */
|
||||
|
|
Loading…
Reference in New Issue