summaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
authorGravatar Jeffrey Hutzelman <jhutz@cmu.edu>2013-02-23 03:34:06 -0500
committerGravatar Karl Ramm <kcr@1ts.org>2013-02-26 23:01:10 -0500
commit0fb2236580debdd37eeac27a5e0ae81d160400b4 (patch)
tree5358646305a76a51b2126b587735eb1e95804732 /server
parent18e990a4f37a750ff71a2c5c9206afcd95df6208 (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.c18
-rw-r--r--server/dispatch.c22
-rw-r--r--server/zserver.h1
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);