1 /* This file is part of the Project Athena Zephyr Notification System.
2 * It contains functions for the Client Manager subsystem of the Zephyr server.
4 * Created by: John T. Kohl
8 * Copyright (c) 1987,1988,1991 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, see the file
13 #include <zephyr/mit-copyright.h>
15 #include <sys/socket.h>
17 #if !defined (lint) && !defined (SABER)
18 static const char rcsid_client_c[] =
25 * Code_t client_register(notice, who, client, server, wantdefaults)
27 * struct sockaddr_in *who;
28 * Client **client; (RETURN)
32 * Code_t client_deregister(client, host, flush)
37 * Client *client_find(who, unsigned int port)
38 * struct in_addr *host;
41 * void client_dump_clients(fp, clist)
47 * a client: allocate space, find or insert the address in the
48 * server's list of hosts, initialize and insert the client into
49 * the host's list of clients.
51 * This routine assumes that the client has not been registered yet.
52 * The caller should check by calling client_find.
56 static Client *client_bucket[HASHSIZE];
58 #define INET_HASH(host, port) ((htonl((host)->s_addr) + \
59 htons((unsigned short) (port))) % HASHSIZE)
62 client_register(notice, host, client_p, wantdefaults)
71 /* chain the client's host onto this server's host list */
74 zdbug((LOG_DEBUG, "client_register: adding %s at %s/%d",
75 notice->z_sender, inet_ntoa(*host), ntohs(notice->z_port)));
79 return ZSRV_BADSUBPORT;
81 *client_p = client = client_find(host, notice->z_port);
83 *client_p = client = (Client *) malloc(sizeof(Client));
86 memset(&client->addr, 0, sizeof(struct sockaddr_in));
88 client->session_keyblock = NULL;
91 memset(&client->session_key, 0, sizeof(client->session_key));
94 client->last_send = 0;
95 client->last_ack = NOW;
96 client->addr.sin_family = AF_INET;
97 client->addr.sin_addr.s_addr = host->s_addr;
98 client->addr.sin_port = notice->z_port;
100 client->realm = NULL;
101 client->principal = make_string(notice->z_sender, 0);
102 LIST_INSERT(&client_bucket[INET_HASH(&client->addr.sin_addr,
103 notice->z_port)], client);
106 /* Add default subscriptions only if this is not resulting from a brain
107 * dump, AND this request wants defaults. */
108 if (!bdumping && wantdefaults)
109 return subscr_def_subs(client);
115 * Deregister the client, freeing resources.
116 * Remove any packets in the nack queue, release subscriptions, release
117 * locations, and dequeue him from the host.
121 client_deregister(client, flush)
126 nack_release(client);
127 subscr_cancel_client(client);
128 free_string(client->principal);
130 if (client->session_keyblock)
131 krb5_free_keyblock(Z_krb5_ctx, client->session_keyblock);
134 uloc_flush_client(&client->addr);
139 client_flush_host(host)
140 struct in_addr *host;
143 Client *client, *next;
145 for (i = 0; i < HASHSIZE; i++) {
146 for (client = client_bucket[i]; client; client = next) {
148 if (client->addr.sin_addr.s_addr == host->s_addr)
149 client_deregister(client, 1);
156 client_send_clients()
162 for (i = 0; i < HASHSIZE; i++) {
163 /* Allow packets to be processed between rows of the hash table. */
164 if (packets_waiting()) {
166 bdump_concurrent = 1;
168 bdump_concurrent = 0;
171 for (client = client_bucket[i]; client; client = client->next) {
173 retval = subscr_send_subs(client);
174 if (retval != ZERR_NONE)
183 * dump info about clients in this clist onto the fp.
184 * assumed to be called with SIGFPE blocked
185 * (true if called from signal handler)
189 client_dump_clients(fp)
195 for (i = 0; i < HASHSIZE; i++) {
196 for (client = client_bucket[i]; client; client = client->next) {
197 fprintf(fp, "%s/%d (%s):\n", inet_ntoa(client->addr.sin_addr),
198 ntohs(client->addr.sin_port), client->principal->string);
199 subscr_dump_subs(fp, client->subs);
205 * find a client by host and port
209 client_find(host, port)
210 struct in_addr *host;
216 hashval = INET_HASH(host, port);
217 for (client = client_bucket[hashval]; client; client = client->next) {
218 if (client->addr.sin_addr.s_addr == host->s_addr
219 && client->addr.sin_port == port)