diff --git a/src/connection.h b/src/connection.h index 0762441732..4f3f4736f3 100644 --- a/src/connection.h +++ b/src/connection.h @@ -132,6 +132,7 @@ struct connection { ConnectionCallbackFunc conn_handler; ConnectionCallbackFunc write_handler; ConnectionCallbackFunc read_handler; + int connected_port; }; #define CONFIG_BINDADDR_MAX 16 @@ -316,6 +317,9 @@ static inline int connFormatAddr(connection *conn, char *buf, size_t buf_len, in return -1; } + if (!remote) { + conn->connected_port = port; + } return formatAddr(buf, buf_len, ip, port); } diff --git a/src/module.c b/src/module.c index 2884239200..52c92d5164 100644 --- a/src/module.c +++ b/src/module.c @@ -2309,6 +2309,10 @@ int VM_IsModuleNameBusy(const char *name) { return de != NULL; } +int VM_GetClientConnectedPort(ValkeyModuleCtx *ctx) { + return getClientConnectedPort(ctx->client); +} + /* Return the current UNIX time in milliseconds. */ mstime_t VM_Milliseconds(void) { return mstime(); @@ -13553,6 +13557,7 @@ void moduleRegisterCoreAPI(void) { REGISTER_API(Strdup); REGISTER_API(CreateCommand); REGISTER_API(GetCommand); + REGISTER_API(GetClientConnectedPort); REGISTER_API(CreateSubcommand); REGISTER_API(SetCommandInfo); REGISTER_API(SetCommandACLCategories); diff --git a/src/networking.c b/src/networking.c index 3a3482e1f7..0c01d5f7bd 100644 --- a/src/networking.c +++ b/src/networking.c @@ -3294,6 +3294,16 @@ char *getClientSockname(client *c) { return c->sockname; } +int getClientConnectedPort(client *c) { + char sockname[NET_ADDR_STR_LEN] = {0}; + + if (c->sockname == NULL) { + genClientAddrString(c, sockname, sizeof(sockname), 0); + c->sockname = sdsnew(sockname); + } + return c->conn->connected_port; +} + int isClientConnIpV6(client *c) { /* The cached client peer id is on the form "[IPv6]:port" for IPv6 * addresses, so we just check for '[' here. */ @@ -3354,6 +3364,7 @@ sds catClientInfoString(sds s, client *client, int hide_user_data) { replBufBlock *cur = listNodeValue(client->ref_repl_buf_node); used_blocks_of_repl_buf = last->id - cur->id + 1; } + sds ret = sdscatfmt( s, FMTARGS( diff --git a/src/server.h b/src/server.h index 3c94d689a2..ae601e7c2b 100644 --- a/src/server.h +++ b/src/server.h @@ -2845,6 +2845,7 @@ void freeClientReplyValue(void *o); void *dupClientReplyValue(void *o); char *getClientPeerId(client *client); char *getClientSockName(client *client); +int getClientConnectedPort(client *client); int isClientConnIpV6(client *c); sds catClientInfoString(sds s, client *client, int hide_user_data); sds getAllClientsInfoString(int type, int hide_user_data); diff --git a/src/valkeymodule.h b/src/valkeymodule.h index c2cdb2f0e7..41d65cce3a 100644 --- a/src/valkeymodule.h +++ b/src/valkeymodule.h @@ -951,6 +951,7 @@ VALKEYMODULE_API int (*ValkeyModule_CreateCommand)(ValkeyModuleCtx *ctx, int keystep) VALKEYMODULE_ATTR; VALKEYMODULE_API ValkeyModuleCommand *(*ValkeyModule_GetCommand)(ValkeyModuleCtx *ctx, const char *name)VALKEYMODULE_ATTR; +VALKEYMODULE_API int (*ValkeyModule_GetClientConnectedPort)(ValkeyModuleCtx *ctx) VALKEYMODULE_ATTR; VALKEYMODULE_API int (*ValkeyModule_CreateSubcommand)(ValkeyModuleCommand *parent, const char *name, ValkeyModuleCmdFunc cmdfunc, @@ -1666,6 +1667,7 @@ static int ValkeyModule_Init(ValkeyModuleCtx *ctx, const char *name, int ver, in VALKEYMODULE_GET_API(Strdup); VALKEYMODULE_GET_API(CreateCommand); VALKEYMODULE_GET_API(GetCommand); + VALKEYMODULE_GET_API(GetClientConnectedPort); VALKEYMODULE_GET_API(CreateSubcommand); VALKEYMODULE_GET_API(SetCommandInfo); VALKEYMODULE_GET_API(SetCommandACLCategories); diff --git a/tests/modules/Makefile b/tests/modules/Makefile index 1690b9b627..7ecd06dd9b 100644 --- a/tests/modules/Makefile +++ b/tests/modules/Makefile @@ -52,6 +52,7 @@ TEST_MODULES = \ mallocsize.so \ aclcheck.so \ list.so \ + adminport.so \ subcommands.so \ reply.so \ cmdintrospection.so \ diff --git a/tests/modules/adminport.c b/tests/modules/adminport.c new file mode 100644 index 0000000000..155013928d --- /dev/null +++ b/tests/modules/adminport.c @@ -0,0 +1,33 @@ +#include "valkeymodule.h" + +#include + +int testadminport_runspecificcommand(ValkeyModuleCtx *ctx, + ValkeyModuleString **argv, int argc) { + VALKEYMODULE_NOT_USED(argv); + VALKEYMODULE_NOT_USED(argc); + int port = ValkeyModule_GetClientConnectedPort(ctx); + if (port == 7001) { + ValkeyModule_ReplyWithSimpleString(ctx, "You can execute this command"); + } else { + ValkeyModule_ReplyWithSimpleString( + ctx, "You have no permission to execute this command"); + } + return VALKEYMODULE_OK; +} + +int ValkeyModule_OnLoad(ValkeyModuleCtx *ctx, ValkeyModuleString **argv, + int argc) { + VALKEYMODULE_NOT_USED(argv); + VALKEYMODULE_NOT_USED(argc); + if (ValkeyModule_Init(ctx, "adminport", 1, VALKEYMODULE_APIVER_1) == + VALKEYMODULE_ERR) + return VALKEYMODULE_ERR; + + if (ValkeyModule_CreateCommand(ctx, "testadminport.runspecificcommand", + testadminport_runspecificcommand, "", 0, 0, + 0) == VALKEYMODULE_ERR) + return VALKEYMODULE_ERR; + + return VALKEYMODULE_OK; +}