summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/anet.c46
-rw-r--r--src/anet.h10
-rw-r--r--src/aof.c1
-rw-r--r--src/connection.c10
-rw-r--r--src/connection.h2
-rw-r--r--src/networking.c48
-rw-r--r--src/replication.c7
-rw-r--r--src/sentinel.c6
-rw-r--r--src/server.h4
9 files changed, 70 insertions, 64 deletions
diff --git a/src/anet.c b/src/anet.c
index e9615a128..d46ce5398 100644
--- a/src/anet.c
+++ b/src/anet.c
@@ -592,11 +592,15 @@ int anetUnixAccept(char *err, int s) {
return fd;
}
-int anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {
+int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type) {
struct sockaddr_storage sa;
socklen_t salen = sizeof(sa);
- if (getpeername(fd,(struct sockaddr*)&sa,&salen) == -1) goto error;
+ if (fd_to_str_type == FD_TO_PEER_NAME) {
+ if (getpeername(fd, (struct sockaddr *)&sa, &salen) == -1) goto error;
+ } else {
+ if (getsockname(fd, (struct sockaddr *)&sa, &salen) == -1) goto error;
+ }
if (ip_len == 0) goto error;
if (sa.ss_family == AF_INET) {
@@ -608,7 +612,7 @@ int anetPeerToString(int fd, char *ip, size_t ip_len, int *port) {
if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);
if (port) *port = ntohs(s->sin6_port);
} else if (sa.ss_family == AF_UNIX) {
- if (ip) strncpy(ip,"/unixsocket",ip_len);
+ if (ip) snprintf(ip, ip_len, "/unixsocket");
if (port) *port = 0;
} else {
goto error;
@@ -636,41 +640,11 @@ int anetFormatAddr(char *buf, size_t buf_len, char *ip, int port) {
"[%s]:%d" : "%s:%d", ip, port);
}
-/* Like anetFormatAddr() but extract ip and port from the socket's peer. */
-int anetFormatPeer(int fd, char *buf, size_t buf_len) {
+/* Like anetFormatAddr() but extract ip and port from the socket's peer/sockname. */
+int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type) {
char ip[INET6_ADDRSTRLEN];
int port;
- anetPeerToString(fd,ip,sizeof(ip),&port);
+ anetFdToString(fd,ip,sizeof(ip),&port,fd_to_str_type);
return anetFormatAddr(buf, buf_len, ip, port);
}
-
-int anetSockName(int fd, char *ip, size_t ip_len, int *port) {
- struct sockaddr_storage sa;
- socklen_t salen = sizeof(sa);
-
- if (getsockname(fd,(struct sockaddr*)&sa,&salen) == -1) {
- if (port) *port = 0;
- ip[0] = '?';
- ip[1] = '\0';
- return -1;
- }
- if (sa.ss_family == AF_INET) {
- struct sockaddr_in *s = (struct sockaddr_in *)&sa;
- if (ip) inet_ntop(AF_INET,(void*)&(s->sin_addr),ip,ip_len);
- if (port) *port = ntohs(s->sin_port);
- } else {
- struct sockaddr_in6 *s = (struct sockaddr_in6 *)&sa;
- if (ip) inet_ntop(AF_INET6,(void*)&(s->sin6_addr),ip,ip_len);
- if (port) *port = ntohs(s->sin6_port);
- }
- return 0;
-}
-
-int anetFormatSock(int fd, char *fmt, size_t fmt_len) {
- char ip[INET6_ADDRSTRLEN];
- int port;
-
- anetSockName(fd,ip,sizeof(ip),&port);
- return anetFormatAddr(fmt, fmt_len, ip, port);
-}
diff --git a/src/anet.h b/src/anet.h
index 23f19643c..fbf41cd17 100644
--- a/src/anet.h
+++ b/src/anet.h
@@ -49,6 +49,10 @@
#undef ip_len
#endif
+/* FD to address string conversion types */
+#define FD_TO_PEER_NAME 0
+#define FD_TO_SOCK_NAME 1
+
int anetTcpConnect(char *err, const char *addr, int port);
int anetTcpNonBlockConnect(char *err, const char *addr, int port);
int anetTcpNonBlockBindConnect(char *err, const char *addr, int port, const char *source_addr);
@@ -71,11 +75,9 @@ int anetDisableTcpNoDelay(char *err, int fd);
int anetTcpKeepAlive(char *err, int fd);
int anetSendTimeout(char *err, int fd, long long ms);
int anetRecvTimeout(char *err, int fd, long long ms);
-int anetPeerToString(int fd, char *ip, size_t ip_len, int *port);
+int anetFdToString(int fd, char *ip, size_t ip_len, int *port, int fd_to_str_type);
int anetKeepAlive(char *err, int fd, int interval);
-int anetSockName(int fd, char *ip, size_t ip_len, int *port);
int anetFormatAddr(char *fmt, size_t fmt_len, char *ip, int port);
-int anetFormatPeer(int fd, char *fmt, size_t fmt_len);
-int anetFormatSock(int fd, char *fmt, size_t fmt_len);
+int anetFormatFdAddr(int fd, char *buf, size_t buf_len, int fd_to_str_type);
#endif
diff --git a/src/aof.c b/src/aof.c
index b9072da93..0f67f0575 100644
--- a/src/aof.c
+++ b/src/aof.c
@@ -681,6 +681,7 @@ struct client *createAOFClient(void) {
c->obuf_soft_limit_reached_time = 0;
c->watched_keys = listCreate();
c->peerid = NULL;
+ c->sockname = NULL;
c->resp = 2;
c->user = NULL;
listSetFreeMethod(c->reply,freeClientReplyValue);
diff --git a/src/connection.c b/src/connection.c
index 83fb84d6d..a4610a42e 100644
--- a/src/connection.c
+++ b/src/connection.c
@@ -374,15 +374,15 @@ int connGetSocketError(connection *conn) {
}
int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port) {
- return anetPeerToString(conn ? conn->fd : -1, ip, ip_len, port);
+ return anetFdToString(conn ? conn->fd : -1, ip, ip_len, port, FD_TO_PEER_NAME);
}
-int connFormatPeer(connection *conn, char *buf, size_t buf_len) {
- return anetFormatPeer(conn ? conn->fd : -1, buf, buf_len);
+int connSockName(connection *conn, char *ip, size_t ip_len, int *port) {
+ return anetFdToString(conn->fd, ip, ip_len, port, FD_TO_SOCK_NAME);
}
-int connSockName(connection *conn, char *ip, size_t ip_len, int *port) {
- return anetSockName(conn->fd, ip, ip_len, port);
+int connFormatFdAddr(connection *conn, char *buf, size_t buf_len, int fd_to_str_type) {
+ return anetFormatFdAddr(conn ? conn->fd : -1, buf, buf_len, fd_to_str_type);
}
int connBlock(connection *conn) {
diff --git a/src/connection.h b/src/connection.h
index 03281a3d9..60f1f70cb 100644
--- a/src/connection.h
+++ b/src/connection.h
@@ -225,7 +225,7 @@ int connKeepAlive(connection *conn, int interval);
int connSendTimeout(connection *conn, long long ms);
int connRecvTimeout(connection *conn, long long ms);
int connPeerToString(connection *conn, char *ip, size_t ip_len, int *port);
-int connFormatPeer(connection *conn, char *buf, size_t buf_len);
+int connFormatFdAddr(connection *conn, char *buf, size_t buf_len, int fd_to_str_type);
int connSockName(connection *conn, char *ip, size_t ip_len, int *port);
const char *connGetInfo(connection *conn, char *buf, size_t buf_len);
diff --git a/src/networking.c b/src/networking.c
index fcb612e0b..4f0e378da 100644
--- a/src/networking.c
+++ b/src/networking.c
@@ -168,6 +168,7 @@ client *createClient(connection *conn) {
c->pubsub_channels = dictCreate(&objectKeyPointerValueDictType,NULL);
c->pubsub_patterns = listCreate();
c->peerid = NULL;
+ c->sockname = NULL;
c->client_list_node = NULL;
c->client_tracking_redirection = 0;
c->client_tracking_prefixes = NULL;
@@ -1300,6 +1301,7 @@ void freeClient(client *c) {
c->argv_len_sum = 0;
freeClientMultiState(c);
sdsfree(c->peerid);
+ sdsfree(c->sockname);
zfree(c);
}
@@ -2079,25 +2081,25 @@ void getClientsMaxBuffers(unsigned long *longest_output_list,
*biggest_input_buffer = bib;
}
-/* A Redis "Peer ID" is a colon separated ip:port pair.
+/* A Redis "Address String" is a colon separated ip:port pair.
* For IPv4 it's in the form x.y.z.k:port, example: "127.0.0.1:1234".
* For IPv6 addresses we use [] around the IP part, like in "[::1]:1234".
* For Unix sockets we use path:0, like in "/tmp/redis:0".
*
- * A Peer ID always fits inside a buffer of NET_PEER_ID_LEN bytes, including
- * the null term.
+ * An Address String always fits inside a buffer of NET_ADDR_STR_LEN bytes,
+ * including the null term.
*
- * On failure the function still populates 'peerid' with the "?:0" string
- * in case you want to relax error checking or need to display something
- * anyway (see anetPeerToString implementation for more info). */
-void genClientPeerId(client *client, char *peerid,
- size_t peerid_len) {
+ * On failure the function still populates 'addr' with the "?:0" string in case
+ * you want to relax error checking or need to display something anyway (see
+ * anetFdToString implementation for more info). */
+void genClientAddrString(client *client, char *addr,
+ size_t addr_len, int fd_to_str_type) {
if (client->flags & CLIENT_UNIX_SOCKET) {
/* Unix socket client. */
- snprintf(peerid,peerid_len,"%s:0",server.unixsocket);
+ snprintf(addr,addr_len,"%s:0",server.unixsocket);
} else {
/* TCP client. */
- connFormatPeer(client->conn,peerid,peerid_len);
+ connFormatFdAddr(client->conn,addr,addr_len,fd_to_str_type);
}
}
@@ -2106,15 +2108,29 @@ void genClientPeerId(client *client, char *peerid,
* The Peer ID never changes during the life of the client, however it
* is expensive to compute. */
char *getClientPeerId(client *c) {
- char peerid[NET_PEER_ID_LEN];
+ char peerid[NET_ADDR_STR_LEN];
if (c->peerid == NULL) {
- genClientPeerId(c,peerid,sizeof(peerid));
+ genClientAddrString(c,peerid,sizeof(peerid),FD_TO_PEER_NAME);
c->peerid = sdsnew(peerid);
}
return c->peerid;
}
+/* This function returns the client bound socket name, by creating and caching
+ * it if client->sockname is NULL, otherwise returning the cached value.
+ * The Socket Name never changes during the life of the client, however it
+ * is expensive to compute. */
+char *getClientSockname(client *c) {
+ char sockname[NET_ADDR_STR_LEN];
+
+ if (c->sockname == NULL) {
+ genClientAddrString(c,sockname,sizeof(sockname),FD_TO_SOCK_NAME);
+ c->sockname = sdsnew(sockname);
+ }
+ return c->sockname;
+}
+
/* Concatenate a string representing the state of a client in a human
* readable format, into the sds string 's'. */
sds catClientInfoString(sds s, client *client) {
@@ -2162,9 +2178,10 @@ sds catClientInfoString(sds s, client *client) {
total_mem += zmalloc_size(client->argv);
return sdscatfmt(s,
- "id=%U addr=%s %s name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i multi=%i qbuf=%U qbuf-free=%U argv-mem=%U obl=%U oll=%U omem=%U tot-mem=%U events=%s cmd=%s user=%s",
+ "id=%U addr=%s laddr=%s %s name=%s age=%I idle=%I flags=%s db=%i sub=%i psub=%i multi=%i qbuf=%U qbuf-free=%U argv-mem=%U obl=%U oll=%U omem=%U tot-mem=%U events=%s cmd=%s user=%s",
(unsigned long long) client->id,
getClientPeerId(client),
+ getClientSockname(client),
connGetInfo(client->conn, conninfo, sizeof(conninfo)),
client->name ? (char*)client->name->ptr : "",
(long long)(server.unixtime - client->ctime),
@@ -2251,6 +2268,7 @@ void clientCommand(client *c) {
"KILL <ip:port> -- Kill connection made from <ip:port>.",
"KILL <option> <value> [option value ...] -- Kill connections. Options are:",
" ADDR <ip:port> -- Kill connection made from <ip:port>",
+" LADDR <ip:port> -- Kill connection made to <ip:port>",
" TYPE (normal|master|replica|pubsub) -- Kill connections by type.",
" USER <username> -- Kill connections authenticated with such user.",
" SKIPME (yes|no) -- Skip killing current connection (default: yes).",
@@ -2304,6 +2322,7 @@ NULL
/* CLIENT KILL <ip:port>
* CLIENT KILL <option> [value] ... <option> [value] */
char *addr = NULL;
+ char *laddr = NULL;
user *user = NULL;
int type = -1;
uint64_t id = 0;
@@ -2336,6 +2355,8 @@ NULL
}
} else if (!strcasecmp(c->argv[i]->ptr,"addr") && moreargs) {
addr = c->argv[i+1]->ptr;
+ } else if (!strcasecmp(c->argv[i]->ptr,"laddr") && moreargs) {
+ laddr = c->argv[i+1]->ptr;
} else if (!strcasecmp(c->argv[i]->ptr,"user") && moreargs) {
user = ACLGetUserByName(c->argv[i+1]->ptr,
sdslen(c->argv[i+1]->ptr));
@@ -2369,6 +2390,7 @@ NULL
while ((ln = listNext(&li)) != NULL) {
client *client = listNodeValue(ln);
if (addr && strcmp(getClientPeerId(client),addr) != 0) continue;
+ if (laddr && strcmp(getClientSockname(client),laddr) != 0) continue;
if (type != -1 && getClientType(client) != type) continue;
if (id != 0 && client->id != id) continue;
if (user && client->user != user) continue;
diff --git a/src/replication.c b/src/replication.c
index da70c4082..d1d26a970 100644
--- a/src/replication.c
+++ b/src/replication.c
@@ -57,7 +57,7 @@ int RDBGeneratedByReplication = 0;
* IP address and its listening port which is more clear for the user, for
* example: "Closing connection with replica 10.1.2.3:6380". */
char *replicationGetSlaveName(client *c) {
- static char buf[NET_PEER_ID_LEN];
+ static char buf[NET_ADDR_STR_LEN];
char ip[NET_IP_STR_LEN];
ip[0] = '\0';
@@ -2792,6 +2792,11 @@ void replicationCacheMaster(client *c) {
sdsfree(c->peerid);
c->peerid = NULL;
}
+ /* Invalidate the Sock Name cache. */
+ if (c->sockname) {
+ sdsfree(c->sockname);
+ c->sockname = NULL;
+ }
/* Caching the master happens instead of the actual freeClient() call,
* so make sure to adjust the replication state. This function will
diff --git a/src/sentinel.c b/src/sentinel.c
index 71e28e1d2..87fc20e9f 100644
--- a/src/sentinel.c
+++ b/src/sentinel.c
@@ -1194,7 +1194,7 @@ sentinelRedisInstance *createSentinelRedisInstance(char *name, int flags, char *
sentinelRedisInstance *ri;
sentinelAddr *addr;
dict *table = NULL;
- char slavename[NET_PEER_ID_LEN], *sdsname;
+ char slavename[NET_ADDR_STR_LEN], *sdsname;
serverAssert(flags & (SRI_MASTER|SRI_SLAVE|SRI_SENTINEL));
serverAssert((flags & SRI_MASTER) || master != NULL);
@@ -1320,7 +1320,7 @@ sentinelRedisInstance *sentinelRedisInstanceLookupSlave(
{
sds key;
sentinelRedisInstance *slave;
- char buf[NET_PEER_ID_LEN];
+ char buf[NET_ADDR_STR_LEN];
serverAssert(ri->flags & SRI_MASTER);
anetFormatAddr(buf,sizeof(buf),ip,port);
@@ -2674,7 +2674,7 @@ int sentinelSendHello(sentinelRedisInstance *ri) {
if (sentinel.announce_ip) {
announce_ip = sentinel.announce_ip;
} else {
- if (anetSockName(ri->link->cc->c.fd,ip,sizeof(ip),NULL) == -1)
+ if (anetFdToString(ri->link->cc->c.fd,ip,sizeof(ip),NULL,FD_TO_SOCK_NAME) == -1)
return C_ERR;
announce_ip = ip;
}
diff --git a/src/server.h b/src/server.h
index b68d06497..b1e645b0c 100644
--- a/src/server.h
+++ b/src/server.h
@@ -112,7 +112,7 @@ typedef long long ustime_t; /* microsecond time type. */
#define CONFIG_DEFAULT_UNIX_SOCKET_PERM 0
#define CONFIG_DEFAULT_LOGFILE ""
#define NET_IP_STR_LEN 46 /* INET6_ADDRSTRLEN is 46, but we need to be sure */
-#define NET_PEER_ID_LEN (NET_IP_STR_LEN+32) /* Must be enough for ip:port */
+#define NET_ADDR_STR_LEN (NET_IP_STR_LEN+32) /* Must be enough for ip:port */
#define CONFIG_BINDADDR_MAX 16
#define CONFIG_MIN_RESERVED_FDS 32
@@ -850,6 +850,7 @@ typedef struct client {
dict *pubsub_channels; /* channels a client is interested in (SUBSCRIBE) */
list *pubsub_patterns; /* patterns a client is interested in (SUBSCRIBE) */
sds peerid; /* Cached peer ID. */
+ sds sockname; /* Cached connection target address. */
listNode *client_list_node; /* list node in client list */
RedisModuleUserChangedFunc auth_callback; /* Module callback to execute
* when the authenticated user
@@ -1716,6 +1717,7 @@ void *dupClientReplyValue(void *o);
void getClientsMaxBuffers(unsigned long *longest_output_list,
unsigned long *biggest_input_buffer);
char *getClientPeerId(client *client);
+char *getClientSockName(client *client);
sds catClientInfoString(sds s, client *client);
sds getAllClientsInfoString(int type);
void rewriteClientCommandVector(client *c, int argc, ...);