From 0fb2236580debdd37eeac27a5e0ae81d160400b4 Mon Sep 17 00:00:00 2001 From: Jeffrey Hutzelman Date: Sat, 23 Feb 2013 03:34:06 -0500 Subject: 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 --- h/zephyr/zephyr.h | 1 + server/client.c | 18 ++++++++++++++++++ server/dispatch.c | 22 +++++++++++++++++++++- server/zserver.h | 1 + 4 files changed, 41 insertions(+), 1 deletion(-) diff --git a/h/zephyr/zephyr.h b/h/zephyr/zephyr.h index faa8140..78b4139 100644 --- a/h/zephyr/zephyr.h +++ b/h/zephyr/zephyr.h @@ -316,6 +316,7 @@ void Z_debug_stderr(const char *format, va_list args, void *closure); #define CLIENT_GIMMESUBS "GIMME" /* Opcode: Give me subs */ #define CLIENT_GIMMEDEFS "GIMMEDEFS" /* Opcode: Give me default * subscriptions */ +#define CLIENT_FLUSHSUBS "FLUSHSUBS" /* Opcode: Clear subs for princ */ #define ZEPHYR_CTL_HM "HM" /* Inst: From HM */ #define HM_BOOT "BOOT" /* Opcode: Boot msg */ 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); -- cgit v1.2.3