diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h index 227d518c0ce..3c46ef025c9 100644 --- a/ctdb/include/ctdb_private.h +++ b/ctdb/include/ctdb_private.h @@ -289,6 +289,7 @@ struct ctdb_context { void *private_data; /* private to transport */ struct ctdb_db_context *db_list; struct srvid_context *srv; + struct srvid_context *tunnels; struct ctdb_daemon_data daemon; struct ctdb_statistics statistics; struct ctdb_statistics statistics_current; @@ -552,6 +553,9 @@ int daemon_register_message_handler(struct ctdb_context *ctdb, int daemon_deregister_message_handler(struct ctdb_context *ctdb, uint32_t client_id, uint64_t srvid); +void daemon_tunnel_handler(uint64_t tunnel_id, TDB_DATA data, + void *private_data); + int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork); struct ctdb_req_header *_ctdb_transport_allocate(struct ctdb_context *ctdb, @@ -961,6 +965,13 @@ int32_t ctdb_control_set_tunable(struct ctdb_context *ctdb, TDB_DATA indata); int32_t ctdb_control_list_tunables(struct ctdb_context *ctdb, TDB_DATA *outdata); +/* from ctdb_tunnel.c */ + +int32_t ctdb_control_tunnel_register(struct ctdb_context *ctdb, + uint32_t client_id, uint64_t tunnel_id); +int32_t ctdb_control_tunnel_deregister(struct ctdb_context *ctdb, + uint32_t client_id, uint64_t tunnel_id); + /* from ctdb_update_record.c */ int32_t ctdb_control_update_record(struct ctdb_context *ctdb, diff --git a/ctdb/include/ctdb_protocol.h b/ctdb/include/ctdb_protocol.h index 52ecc456947..7b6014fdff9 100644 --- a/ctdb/include/ctdb_protocol.h +++ b/ctdb/include/ctdb_protocol.h @@ -134,6 +134,14 @@ struct ctdb_req_keepalive_old { uint32_t uptime; }; +struct ctdb_req_tunnel_old { + struct ctdb_req_header hdr; + uint64_t tunnel_id; + uint32_t flags; + uint32_t datalen; + uint8_t data[1]; +}; + /* Structure used for a nodemap. The nodemap is the structure containing a list of all nodes diff --git a/ctdb/server/ctdb_control.c b/ctdb/server/ctdb_control.c index 9aeaa235830..b537cd1aefa 100644 --- a/ctdb/server/ctdb_control.c +++ b/ctdb/server/ctdb_control.c @@ -700,6 +700,12 @@ static int32_t ctdb_control_dispatch(struct ctdb_context *ctdb, CHECK_CONTROL_DATA_SIZE((sizeof(pid_t) + sizeof(uint64_t))); return ctdb_control_check_pid_srvid(ctdb, indata); + case CTDB_CONTROL_TUNNEL_REGISTER: + return ctdb_control_tunnel_register(ctdb, client_id, srvid); + + case CTDB_CONTROL_TUNNEL_DEREGISTER: + return ctdb_control_tunnel_deregister(ctdb, client_id, srvid); + default: DEBUG(DEBUG_CRIT,(__location__ " Unknown CTDB control opcode %u\n", opcode)); return -1; diff --git a/ctdb/server/ctdb_daemon.c b/ctdb/server/ctdb_daemon.c index 185982e65bd..dc2fd5d9695 100644 --- a/ctdb/server/ctdb_daemon.c +++ b/ctdb/server/ctdb_daemon.c @@ -209,6 +209,36 @@ int daemon_deregister_message_handler(struct ctdb_context *ctdb, uint32_t client return srvid_deregister(ctdb->srv, srvid, client); } +void daemon_tunnel_handler(uint64_t tunnel_id, TDB_DATA data, + void *private_data) +{ + struct ctdb_client *client = + talloc_get_type_abort(private_data, struct ctdb_client); + struct ctdb_req_tunnel_old *c, *pkt; + size_t len; + + pkt = (struct ctdb_req_tunnel_old *)data.dptr; + + len = offsetof(struct ctdb_req_tunnel_old, data) + pkt->datalen; + c = ctdbd_allocate_pkt(client->ctdb, client->ctdb, CTDB_REQ_TUNNEL, + len, struct ctdb_req_tunnel_old); + if (c == NULL) { + DEBUG(DEBUG_ERR, ("Memory error in daemon_tunnel_handler\n")); + return; + } + + talloc_set_name_const(c, "req_tunnel packet"); + + c->tunnel_id = tunnel_id; + c->flags = pkt->flags; + c->datalen = pkt->datalen; + memcpy(c->data, pkt->data, pkt->datalen); + + daemon_queue_send(client, &c->hdr); + + talloc_free(c); +} + /* destroy a ctdb_client */ @@ -1256,6 +1286,12 @@ int ctdb_start_daemon(struct ctdb_context *ctdb, bool do_fork) exit(1); } + TALLOC_FREE(ctdb->tunnels); + if (srvid_init(ctdb, &ctdb->tunnels) != 0) { + DEBUG(DEBUG_ERR, ("Failed to setup tunnels context\n")); + exit(1); + } + /* initialize statistics collection */ ctdb_statistics_init(ctdb); diff --git a/ctdb/server/ctdb_tunnel.c b/ctdb/server/ctdb_tunnel.c new file mode 100644 index 00000000000..0f2e001005c --- /dev/null +++ b/ctdb/server/ctdb_tunnel.c @@ -0,0 +1,90 @@ +/* + ctdb_tunnel protocol code + + Copyright (C) Amitay Isaacs 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see . +*/ + +#include "replace.h" +#include "system/network.h" + +#include +#include +#include + +#include "lib/util/debug.h" + +#include "common/logging.h" +#include "common/reqid.h" +#include "common/srvid.h" + +#include "ctdb_private.h" + +int32_t ctdb_control_tunnel_register(struct ctdb_context *ctdb, + uint32_t client_id, uint64_t tunnel_id) +{ + struct ctdb_client *client; + int ret; + + client = reqid_find(ctdb->idr, client_id, struct ctdb_client); + if (client == NULL) { + DEBUG(DEBUG_ERR, ("Bad client_id in ctdb_tunnel_register\n")); + return -1; + } + + ret = srvid_exists(ctdb->tunnels, tunnel_id, NULL); + if (ret == 0) { + DEBUG(DEBUG_ERR, + ("Tunnel id 0x%"PRIx64" already registered\n", + tunnel_id)); + return -1; + } + + ret = srvid_register(ctdb->tunnels, client, tunnel_id, + daemon_tunnel_handler, client); + if (ret != 0) { + DEBUG(DEBUG_ERR, + ("Failed to register tunnel id 0x%"PRIx64"\n", + tunnel_id)); + return -1; + } + + DEBUG(DEBUG_INFO, ("Registered tunnel for id 0x%"PRIx64"\n", + tunnel_id)); + return 0; +} + +int32_t ctdb_control_tunnel_deregister(struct ctdb_context *ctdb, + uint32_t client_id, uint64_t tunnel_id) +{ + struct ctdb_client *client; + int ret; + + client = reqid_find(ctdb->idr, client_id, struct ctdb_client); + if (client == NULL) { + DEBUG(DEBUG_ERR, ("Bad client_id in ctdb_tunnel_deregister\n")); + return -1; + } + + ret = srvid_deregister(ctdb->tunnels, tunnel_id, client); + if (ret != 0) { + DEBUG(DEBUG_ERR, + ("Failed to deregister tunnel id 0x%"PRIx64"\n", + tunnel_id)); + return -1; + } + + return 0; +} diff --git a/ctdb/wscript b/ctdb/wscript index 255dbdc3978..1da1b2dade8 100644 --- a/ctdb/wscript +++ b/ctdb/wscript @@ -462,7 +462,8 @@ def build(bld): ctdb_vacuum.c ctdb_banning.c ctdb_statistics.c ctdb_update_record.c - ctdb_lock.c ctdb_fork.c'''), + ctdb_lock.c ctdb_fork.c + ctdb_tunnel.c'''), includes='include', deps='''ctdb-client ctdb-common ctdb-system ctdb-protocol ctdb-tcp ctdb-util replace sys_rw popt