diff options
author | Jeffrey Hutzelman <jhutz@cmu.edu> | 2013-02-23 03:34:06 -0500 |
---|---|---|
committer | Karl Ramm <kcr@1ts.org> | 2013-02-26 23:01:10 -0500 |
commit | 0fb2236580debdd37eeac27a5e0ae81d160400b4 (patch) | |
tree | 5358646305a76a51b2126b587735eb1e95804732 /server | |
parent | 18e990a4f37a750ff71a2c5c9206afcd95df6208 (diff) |
server: add CLIENT_FLUSHSUBS control message
This adds support to the server for a new client control message,
CLIENT_FLUSHSUBS, which flushes all subscriptions and pending retransmits
for clients belonging to a given principal. The target principal must be
the same as the sender, unless the sender is on the opstaff ACL.
This is the server side of #103
Diffstat (limited to 'server')
-rw-r--r-- | server/client.c | 18 | ||||
-rw-r--r-- | server/dispatch.c | 22 | ||||
-rw-r--r-- | server/zserver.h | 1 |
3 files changed, 40 insertions, 1 deletions
diff --git a/server/client.c b/server/client.c index 56c5190..02e9862 100644 --- a/server/client.c +++ b/server/client.c @@ -146,6 +146,24 @@ client_flush_host(struct in_addr *host) uloc_hflush(host); } +/* Unlike client_flush_host, this flushes only subs, not locations */ +void +client_flush_princ(char *target) +{ + int i; + Client *client, *next; + String *principal = make_string(target, 0); + + for (i = 0; i < HASHSIZE; i++) { + for (client = client_bucket[i]; client; client = next) { + next = client->next; + if (client->principal == principal) + client_deregister(client, 0); + } + } + free_string(principal); +} + Code_t client_send_clients(void) { diff --git a/server/dispatch.c b/server/dispatch.c index 9981581..b1909e0 100644 --- a/server/dispatch.c +++ b/server/dispatch.c @@ -966,7 +966,7 @@ control_dispatch(ZNotice_t *notice, struct sockaddr_in *who, Server *server) { - char *opcode = notice->z_opcode; + char *target, *opcode = notice->z_opcode; Client *client; Code_t retval; int wantdefs; @@ -1100,6 +1100,26 @@ control_dispatch(ZNotice_t *notice, } /* don't flush locations here, let him do it explicitly */ client_deregister(client, 0); + } else if (strcmp(opcode, CLIENT_FLUSHSUBS) == 0) { + target = notice->z_sender; + if (notice->z_message_len > 0 && *notice->z_message != 0) { + target = notice->z_message; + if (memchr(target, '\0', notice->z_message_len) == NULL) { + syslog(LOG_WARNING, "malformed flushsubs"); + if (server == me_server) + nack(notice, who); + return ZERR_NONE; + } + if (strcmp(target, notice->z_sender) != 0 && + !opstaff_check(notice->z_sender)) { + syslog(LOG_NOTICE, "unauth flushsubs for %s by %s", + target, notice->z_sender); + if (server == me_server) + clt_ack(notice, who, AUTH_FAILED); + return ZERR_NONE; + } + } + client_flush_princ(target); } else { syslog(LOG_WARNING, "unknown ctl opcode %s", opcode); if (server == me_server) { diff --git a/server/zserver.h b/server/zserver.h index 28b8fdb..f0f4fda 100644 --- a/server/zserver.h +++ b/server/zserver.h @@ -276,6 +276,7 @@ Code_t client_register(ZNotice_t *notice, struct in_addr *host, Client **client_p, int wantdefaults); void client_deregister(Client *client, int flush); void client_flush_host(struct in_addr *host); +void client_flush_princ(char *target); void client_dump_clients(FILE *fp); Client *client_find(struct in_addr *host, unsigned int port); Code_t client_send_clients(void); |