mirror of
https://gitlab.nic.cz/labs/bird.git
synced 2024-12-22 17:51:53 +00:00
Flock: telnet to machines
This commit is contained in:
parent
d36ad6af6a
commit
56aff8ef39
@ -8,6 +8,7 @@
|
|||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <sys/mount.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
@ -73,6 +74,39 @@ container_poweroff(int fd, int sig)
|
|||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
container_zombie(void)
|
||||||
|
{
|
||||||
|
zombie = 0;
|
||||||
|
log(L_INFO "Zombie elimination routine invoked.");
|
||||||
|
while (1) {
|
||||||
|
int status;
|
||||||
|
pid_t p = waitpid(-1, &status, WNOHANG);
|
||||||
|
|
||||||
|
if (p < 0)
|
||||||
|
{
|
||||||
|
if (errno != ECHILD)
|
||||||
|
log(L_ERR "Zombie elimination failed: %m");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const char *coreinfo = WCOREDUMP(status) ? " (core dumped)" : "";
|
||||||
|
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
log(L_INFO "Process %d ended with status %d%s", p, WEXITSTATUS(status), coreinfo);
|
||||||
|
else if (WIFSIGNALED(status))
|
||||||
|
log(L_INFO "Process %d exited by signal %d (%s)%s", p, WTERMSIG(status), strsignal(WTERMSIG(status)), coreinfo);
|
||||||
|
else
|
||||||
|
log(L_ERR "Process %d exited with a strange status %d", p, status);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define SYSCALL(x, ...) ({ int e = x(__VA_ARGS__); if (e < 0) die("Failed to run %s at %s:%d: %m", #x, __FILE__, __LINE__); e; })
|
||||||
|
|
||||||
static void
|
static void
|
||||||
container_mainloop(int fd)
|
container_mainloop(int fd)
|
||||||
{
|
{
|
||||||
@ -82,6 +116,10 @@ container_mainloop(int fd)
|
|||||||
signal(SIGINT, container_poweroff_sighandler);
|
signal(SIGINT, container_poweroff_sighandler);
|
||||||
signal(SIGCHLD, container_child_sighandler);
|
signal(SIGCHLD, container_child_sighandler);
|
||||||
|
|
||||||
|
/* Remounting proc to reflect the new PID namespace */
|
||||||
|
SYSCALL(mount, "none", "/", NULL, MS_REC | MS_PRIVATE, NULL);
|
||||||
|
SYSCALL(mount, "proc", "/proc", "proc", MS_NOSUID | MS_NODEV | MS_NOEXEC, NULL);
|
||||||
|
|
||||||
/* TODO: mount overlayfs and chroot */
|
/* TODO: mount overlayfs and chroot */
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
@ -95,13 +133,31 @@ container_mainloop(int fd)
|
|||||||
|
|
||||||
int res = ppoll(&pfd, 1, NULL, &newmask);
|
int res = ppoll(&pfd, 1, NULL, &newmask);
|
||||||
|
|
||||||
|
if ((res < 0) && (errno != EINTR))
|
||||||
|
log(L_INFO "ppoll returned -1: %m");
|
||||||
|
|
||||||
if (poweroff)
|
if (poweroff)
|
||||||
container_poweroff(fd, poweroff);
|
container_poweroff(fd, poweroff);
|
||||||
|
|
||||||
|
if (zombie)
|
||||||
|
container_zombie();
|
||||||
|
|
||||||
if (pfd.revents & POLLIN)
|
if (pfd.revents & POLLIN)
|
||||||
{
|
{
|
||||||
byte buf[128];
|
int sfd = -1;
|
||||||
ssize_t sz = read(fd, buf, sizeof buf);
|
byte buf[128], cbuf[CMSG_SPACE(sizeof sfd)];
|
||||||
|
struct iovec v = {
|
||||||
|
.iov_base = buf,
|
||||||
|
.iov_len = sizeof buf,
|
||||||
|
};
|
||||||
|
struct msghdr m = {
|
||||||
|
.msg_iov = &v,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = &cbuf,
|
||||||
|
.msg_controllen = sizeof cbuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
int sz = recvmsg(fd, &m, 0);
|
||||||
if (sz < 0)
|
if (sz < 0)
|
||||||
{
|
{
|
||||||
log(L_ERR "error reading data from control socket: %m");
|
log(L_ERR "error reading data from control socket: %m");
|
||||||
@ -116,11 +172,47 @@ container_mainloop(int fd)
|
|||||||
container_poweroff(fd, 0);
|
container_poweroff(fd, 0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
case 0x21:
|
||||||
}
|
ASSERT_DIE(buf[2] == 0xf6);
|
||||||
|
struct cmsghdr *c = CMSG_FIRSTHDR(&m);
|
||||||
|
memcpy(&sfd, CMSG_DATA(c), sizeof sfd);
|
||||||
|
|
||||||
/* TODO: check for telnet socket */
|
int e = fork();
|
||||||
log(L_INFO "woken up, res %d (%m)!", res);
|
if (e < 0) bug("Cannot fork: %m");
|
||||||
|
if (e == 0) {
|
||||||
|
int fd = accept(sfd, NULL, 0);
|
||||||
|
if (fd < 0)
|
||||||
|
{
|
||||||
|
log(L_ERR "failed to accept telnet connection: %m");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
log(L_INFO "telnet connected");
|
||||||
|
|
||||||
|
close(0);
|
||||||
|
close(1);
|
||||||
|
close(2);
|
||||||
|
|
||||||
|
dup2(fd, 0);
|
||||||
|
dup2(fd, 1);
|
||||||
|
|
||||||
|
/* Unblock signals */
|
||||||
|
sigset_t newmask;
|
||||||
|
sigemptyset(&newmask);
|
||||||
|
sigprocmask(SIG_SETMASK, &newmask, NULL);
|
||||||
|
|
||||||
|
/* Exec the telnet */
|
||||||
|
e = execl("/usr/sbin/telnetd", "telnetd", "-E", "/bin/bash", NULL);
|
||||||
|
log(L_ERR "failed to execl: %m");
|
||||||
|
exit(42);
|
||||||
|
}
|
||||||
|
close(sfd);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log(L_ERR "unknown command on control socket: %d", buf[1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -356,6 +448,14 @@ crt_err(sock *s, int err UNUSED)
|
|||||||
crt->ccc = NULL;
|
crt->ccc = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
container_ctl_fd(const char *name)
|
||||||
|
{
|
||||||
|
uint h = mem_hash(name, strlen(name));
|
||||||
|
struct container_runtime *crt = HASH_FIND(hcf.hash, CRT, name, h);
|
||||||
|
return (crt && crt->s) ? crt->s->fd : -1;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
container_created(callback *cb)
|
container_created(callback *cb)
|
||||||
{
|
{
|
||||||
|
24
flock/ctl.c
24
flock/ctl.c
@ -186,16 +186,21 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* telnet listener open */
|
case 3: /* telnet listener open */
|
||||||
if ((ctx->type != 7) || (ctx->value != 22))
|
if ((ctx->type == 7) && (ctx->value == 22))
|
||||||
CBOR_PARSER_ERROR("Expected null, got %u-%u", ctx->type, ctx->value);
|
{
|
||||||
/* TODO: allow this also for machines */
|
|
||||||
|
|
||||||
log(L_INFO "Requested telnet open");
|
|
||||||
|
|
||||||
hexp_get_telnet(ctx->sock, NULL);
|
hexp_get_telnet(ctx->sock, NULL);
|
||||||
|
|
||||||
ctx->major_state = 1;
|
ctx->major_state = 1;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
else if (ctx->type != 3)
|
||||||
|
CBOR_PARSER_ERROR("Expected null or string, got %u-%u", ctx->type, ctx->value);
|
||||||
|
|
||||||
|
ASSERT_DIE(!ctx->target_buf);
|
||||||
|
ctx->cfg.cf.name = ctx->target_buf = lp_alloc(ctx->lp, ctx->value + 1);
|
||||||
|
ctx->target_len = ctx->value;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 4: /* telnet listener close */
|
case 4: /* telnet listener close */
|
||||||
if ((ctx->type != 7) || (ctx->value != 22))
|
if ((ctx->type != 7) || (ctx->value != 22))
|
||||||
@ -364,6 +369,11 @@ hcs_parse(struct cbor_parser_context *ctx, const byte *buf, s64 size)
|
|||||||
/* Read completely! */
|
/* Read completely! */
|
||||||
switch (ctx->major_state)
|
switch (ctx->major_state)
|
||||||
{
|
{
|
||||||
|
case 3:
|
||||||
|
hexp_get_telnet(ctx->sock, ctx->cfg.cf.name);
|
||||||
|
ctx->major_state = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
/* Actually not this one */
|
/* Actually not this one */
|
||||||
CBOR_PARSER_ERROR("NOT IMPLEMENTED YET");
|
CBOR_PARSER_ERROR("NOT IMPLEMENTED YET");
|
||||||
|
@ -105,6 +105,12 @@ def container_stop(hypervisor: str, name: str):
|
|||||||
for k,v in msg(hypervisor, { 4: { 0: name, }}).items():
|
for k,v in msg(hypervisor, { 4: { 0: name, }}).items():
|
||||||
print(k,v)
|
print(k,v)
|
||||||
|
|
||||||
|
@handler
|
||||||
|
def container_telnet(hypervisor: str, name: str):
|
||||||
|
for k,v in msg(hypervisor, { 1: name}).items():
|
||||||
|
assert(k == -2)
|
||||||
|
os.execlp("telnet", "telnet", "localhost", str(v))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
binname = sys.argv.pop(0)
|
binname = sys.argv.pop(0)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
@ -48,6 +48,7 @@ union flock_machine_config {
|
|||||||
|
|
||||||
void hypervisor_container_request(sock *s, const char *name, const char *basedir, const char *workdir);
|
void hypervisor_container_request(sock *s, const char *name, const char *basedir, const char *workdir);
|
||||||
void hypervisor_container_shutdown(sock *s, const char *name);
|
void hypervisor_container_shutdown(sock *s, const char *name);
|
||||||
|
int container_ctl_fd(const char *name);
|
||||||
|
|
||||||
extern event reboot_event, poweroff_event;
|
extern event reboot_event, poweroff_event;
|
||||||
extern event_list shutdown_event_list;
|
extern event_list shutdown_event_list;
|
||||||
|
@ -127,6 +127,8 @@ static struct hypervisor_exposed {
|
|||||||
pool *p;
|
pool *p;
|
||||||
sock *s;
|
sock *s;
|
||||||
struct birdloop *loop;
|
struct birdloop *loop;
|
||||||
|
const char *port_name;
|
||||||
|
sock *port_sreq;
|
||||||
} he;
|
} he;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -136,7 +138,6 @@ static struct hypervisor_exposed {
|
|||||||
static void hexp_received_telnet(void *);
|
static void hexp_received_telnet(void *);
|
||||||
struct hexp_received_telnet {
|
struct hexp_received_telnet {
|
||||||
event e;
|
event e;
|
||||||
struct hexp_telnet_port *p;
|
|
||||||
int fd;
|
int fd;
|
||||||
u16 port;
|
u16 port;
|
||||||
};
|
};
|
||||||
@ -165,6 +166,7 @@ hypervisor_telnet_connected(sock *sk, uint size UNUSED)
|
|||||||
{
|
{
|
||||||
log(L_INFO "telnet connected");
|
log(L_INFO "telnet connected");
|
||||||
close(fd);
|
close(fd);
|
||||||
|
sk_close(sk);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,20 +216,12 @@ hypervisor_exposed_parent_rx(sock *sk, uint size UNUSED)
|
|||||||
u16 port = ntohs(*((u16 *) &buf[3]));
|
u16 port = ntohs(*((u16 *) &buf[3]));
|
||||||
log(L_INFO "RX %d bytes, fd %d, port %u", e, sfd, port);
|
log(L_INFO "RX %d bytes, fd %d, port %u", e, sfd, port);
|
||||||
|
|
||||||
sock *skl = sk_new(sk->pool);
|
|
||||||
skl->type = SK_MAGIC;
|
|
||||||
skl->rx_hook = hypervisor_telnet_connected;
|
|
||||||
skl->fd = sfd;
|
|
||||||
if (sk_open(skl, sk->loop) < 0)
|
|
||||||
bug("Telnet listener: sk_open failed");
|
|
||||||
|
|
||||||
struct hexp_received_telnet *hrt = mb_allocz(he.p, sizeof *hrt);
|
struct hexp_received_telnet *hrt = mb_allocz(he.p, sizeof *hrt);
|
||||||
*hrt = (struct hexp_received_telnet) {
|
*hrt = (struct hexp_received_telnet) {
|
||||||
.e = {
|
.e = {
|
||||||
.hook = hexp_received_telnet,
|
.hook = hexp_received_telnet,
|
||||||
.data = hrt,
|
.data = hrt,
|
||||||
},
|
},
|
||||||
.p = sk->data,
|
|
||||||
.port = port,
|
.port = port,
|
||||||
.fd = sfd,
|
.fd = sfd,
|
||||||
};
|
};
|
||||||
@ -413,86 +407,20 @@ hypervisor_exposed_fork(void)
|
|||||||
* Hypervisor's mapping between external ports and names
|
* Hypervisor's mapping between external ports and names
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define HEXP_TELNET_KEY(tp) tp->name, tp->hash
|
|
||||||
#define HEXP_TELNET_NEXT(tp) tp->next
|
|
||||||
#define HEXP_TELNET_EQ(a,h,b,i) ((h) == (i)) && (!(a) && !(b) || !strcmp(a,b))
|
|
||||||
#define HEXP_TELNET_FN(a,h) h
|
|
||||||
|
|
||||||
#define TLIST_PREFIX hexp_telnet_requestor
|
|
||||||
#define TLIST_TYPE struct hexp_telnet_requestor
|
|
||||||
#define TLIST_ITEM n
|
|
||||||
struct hexp_telnet_requestor {
|
|
||||||
TLIST_DEFAULT_NODE;
|
|
||||||
sock *s;
|
|
||||||
struct cbor_parser_context *ctx;
|
|
||||||
};
|
|
||||||
|
|
||||||
#define TLIST_WANT_ADD_TAIL
|
|
||||||
#include "lib/tlists.h"
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
hexp_sock_err(sock *s, int err UNUSED)
|
hexp_sock_err(sock *s, int err UNUSED)
|
||||||
{
|
{
|
||||||
struct hexp_telnet_requestor *req = s->data;
|
ASSERT_DIE(s == he.port_sreq);
|
||||||
s->data = req->ctx;
|
he.port_name = NULL;
|
||||||
|
he.port_sreq = NULL;
|
||||||
hexp_telnet_requestor_rem_node(hexp_telnet_requestor_enlisted(req), req);
|
|
||||||
}
|
|
||||||
|
|
||||||
struct hexp_telnet_port {
|
|
||||||
struct hexp_telnet_port *next;
|
|
||||||
const char *name;
|
|
||||||
uint hash;
|
|
||||||
uint port;
|
|
||||||
|
|
||||||
TLIST_LIST(hexp_telnet_requestor) requestors;
|
|
||||||
int fd;
|
|
||||||
};
|
|
||||||
|
|
||||||
static struct hexp_telnet {
|
|
||||||
pool *pool;
|
|
||||||
HASH(struct hexp_telnet_port) port_hash;
|
|
||||||
} hexp_telnet;
|
|
||||||
|
|
||||||
static void
|
|
||||||
hexp_init_telnet(void)
|
|
||||||
{
|
|
||||||
pool *p = rp_new(hcs_pool, hcs_pool->domain, "Hypervisor exposed telnets");
|
|
||||||
hexp_telnet.pool = p;
|
|
||||||
HASH_INIT(hexp_telnet.port_hash, p, 6);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
hexp_have_telnet(sock *s, struct hexp_telnet_port *p)
|
|
||||||
{
|
|
||||||
struct linpool *lp = lp_new(s->pool);
|
|
||||||
struct cbor_writer *cw = cbor_init(s->tbuf, s->tbsize, lp);
|
|
||||||
cbor_open_block_with_length(cw, 1);
|
|
||||||
cbor_add_int(cw, -2);
|
|
||||||
cbor_add_int(cw, p->port);
|
|
||||||
sk_send(s, cw->pt);
|
|
||||||
rfree(lp);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
hexp_get_telnet(sock *s, const char *name)
|
hexp_get_telnet(sock *s, const char *name)
|
||||||
{
|
{
|
||||||
if (!hexp_telnet.pool)
|
ASSERT_DIE(!he.port_name);
|
||||||
hexp_init_telnet();
|
he.port_name = name ?: "";
|
||||||
|
he.port_sreq = s;
|
||||||
uint h = name ? mem_hash(name, strlen(name)) : 0;
|
|
||||||
struct hexp_telnet_port *p = HASH_FIND(hexp_telnet.port_hash, HEXP_TELNET, name, h);
|
|
||||||
if (p && p->port)
|
|
||||||
return hexp_have_telnet(s, p);
|
|
||||||
else if (!p)
|
|
||||||
{
|
|
||||||
he.s->data = p = mb_alloc(hcs_pool, sizeof *p);
|
|
||||||
*p = (struct hexp_telnet_port) {
|
|
||||||
.name = name,
|
|
||||||
.hash = h,
|
|
||||||
.fd = -1,
|
|
||||||
};
|
|
||||||
HASH_INSERT(hexp_telnet.port_hash, HEXP_TELNET, p);
|
|
||||||
|
|
||||||
uint8_t buf[64];
|
uint8_t buf[64];
|
||||||
linpool *lp = lp_new(s->pool);
|
linpool *lp = lp_new(s->pool);
|
||||||
@ -501,53 +429,86 @@ hexp_get_telnet(sock *s, const char *name)
|
|||||||
cbor_add_int(cw, 1);
|
cbor_add_int(cw, 1);
|
||||||
cw->cbor[cw->pt++] = 0xf6;
|
cw->cbor[cw->pt++] = 0xf6;
|
||||||
|
|
||||||
struct iovec v = {
|
int e = write(he.s->fd, buf, cw->pt);
|
||||||
.iov_base = buf,
|
|
||||||
.iov_len = cw->pt,
|
|
||||||
};
|
|
||||||
struct msghdr m = {
|
|
||||||
.msg_iov = &v,
|
|
||||||
.msg_iovlen = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
int e = sendmsg(he.s->fd, &m, 0);
|
|
||||||
if (e != cw->pt)
|
if (e != cw->pt)
|
||||||
bug("sendmsg error handling not implemented, got %d (%m)", e);
|
bug("write error handling not implemented, got %d (%m)", e);
|
||||||
|
|
||||||
rfree(lp);
|
rfree(lp);
|
||||||
}
|
|
||||||
|
|
||||||
s->err_paused = hexp_sock_err;
|
s->err_paused = hexp_sock_err;
|
||||||
sk_pause_rx(s->loop, s);
|
sk_pause_rx(s->loop, s);
|
||||||
|
|
||||||
struct hexp_telnet_requestor *req = mb_allocz(hcs_pool, sizeof *req);
|
|
||||||
req->s = s;
|
|
||||||
req->ctx = s->data;
|
|
||||||
s->data = req;
|
|
||||||
hexp_telnet_requestor_add_tail(&p->requestors, req);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hexp_received_telnet(void *_data)
|
static void hexp_received_telnet(void *_data)
|
||||||
{
|
{
|
||||||
struct hexp_received_telnet *hrt = _data;
|
struct hexp_received_telnet *hrt = _data;
|
||||||
|
|
||||||
ASSERT_DIE(!hrt->p->port);
|
ASSERT_DIE(he.port_name);
|
||||||
hrt->p->port = hrt->port;
|
const char *name = he.port_name;
|
||||||
hrt->p->fd = hrt->fd;
|
he.port_name = NULL;
|
||||||
|
|
||||||
|
sock *s = he.port_sreq;
|
||||||
|
he.port_sreq = NULL;
|
||||||
|
|
||||||
|
if (name[0])
|
||||||
|
{
|
||||||
|
/* Transferring the received listening socket to the container */
|
||||||
|
int fd = container_ctl_fd(name);
|
||||||
|
|
||||||
|
/* TODO: unduplicate this code */
|
||||||
byte outbuf[128];
|
byte outbuf[128];
|
||||||
linpool *lp = lp_new(hcs_pool);
|
linpool *lp = lp_new(hcs_pool);
|
||||||
struct cbor_writer *cw = cbor_init(outbuf, sizeof outbuf, lp);
|
struct cbor_writer *cw = cbor_init(outbuf, sizeof outbuf, lp);
|
||||||
cbor_open_block_with_length(cw, 1);
|
cbor_open_block_with_length(cw, 1);
|
||||||
cbor_add_int(cw, -2);
|
cbor_add_int(cw, -2);
|
||||||
|
write_item(cw, 7, 22);
|
||||||
|
struct iovec v = {
|
||||||
|
.iov_base = outbuf,
|
||||||
|
.iov_len = cw->pt,
|
||||||
|
};
|
||||||
|
byte cbuf[CMSG_SPACE(sizeof hrt->fd)];
|
||||||
|
struct msghdr m = {
|
||||||
|
.msg_iov = &v,
|
||||||
|
.msg_iovlen = 1,
|
||||||
|
.msg_control = &cbuf,
|
||||||
|
.msg_controllen = sizeof cbuf,
|
||||||
|
};
|
||||||
|
struct cmsghdr *c = CMSG_FIRSTHDR(&m);
|
||||||
|
c->cmsg_level = SOL_SOCKET;
|
||||||
|
c->cmsg_type = SCM_RIGHTS;
|
||||||
|
c->cmsg_len = CMSG_LEN(sizeof hrt->fd);
|
||||||
|
memcpy(CMSG_DATA(c), &hrt->fd, sizeof hrt->fd);
|
||||||
|
|
||||||
|
int e = sendmsg(fd, &m, 0);
|
||||||
|
if (e < 0)
|
||||||
|
log(L_ERR "Failed to send socket: %m");
|
||||||
|
|
||||||
|
close(hrt->fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Opening listener here */
|
||||||
|
|
||||||
|
sock *skl = sk_new(hcs_pool);
|
||||||
|
skl->type = SK_MAGIC;
|
||||||
|
skl->rx_hook = hypervisor_telnet_connected;
|
||||||
|
skl->data = skl;
|
||||||
|
skl->fd = hrt->fd;
|
||||||
|
if (sk_open(skl, hcs_loop) < 0)
|
||||||
|
bug("Telnet listener: sk_open failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s)
|
||||||
|
{
|
||||||
|
linpool *lp = lp_new(hcs_pool);
|
||||||
|
struct cbor_writer *cw = cbor_init(s->tbuf, s->tbsize, lp);
|
||||||
|
cbor_open_block_with_length(cw, 1);
|
||||||
|
cbor_add_int(cw, -2);
|
||||||
cbor_add_int(cw, hrt->port);
|
cbor_add_int(cw, hrt->port);
|
||||||
|
|
||||||
WALK_TLIST_DELSAFE(hexp_telnet_requestor, r, &hrt->p->requestors)
|
sk_send(s, cw->pt);
|
||||||
{
|
sk_resume_rx(hcs_loop, s);
|
||||||
sk_resume_rx(r->s->loop, r->s);
|
rfree(lp);
|
||||||
memcpy(r->s->tbuf, outbuf, cw->pt);
|
|
||||||
sk_send(r->s, cw->pt);
|
|
||||||
hexp_telnet_requestor_rem_node(&hrt->p->requestors, r);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
birdloop_enter(he.loop);
|
birdloop_enter(he.loop);
|
||||||
|
Loading…
Reference in New Issue
Block a user