]>
Commit | Line | Data |
---|---|---|
7ac48069 | 1 | /* $Id$ |
2 | * | |
3 | * Do RPC | |
a3cf6921 | 4 | * |
7ac48069 | 5 | * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology |
6 | * For copying and distribution information, please see the file | |
7 | * <mit-copyright.h>. | |
a3cf6921 | 8 | * |
a3cf6921 | 9 | */ |
10 | ||
c801de4c | 11 | #include <mit-copyright.h> |
7ac48069 | 12 | #include "mr_server.h" |
13 | #include "query.h" | |
14 | ||
57c08162 | 15 | #include <sys/stat.h> |
7ac48069 | 16 | #include <sys/types.h> |
17 | ||
960b073b | 18 | #include <arpa/inet.h> |
7ac48069 | 19 | #include <netinet/in.h> |
20 | ||
78849033 | 21 | #include <errno.h> |
7ac48069 | 22 | #include <fcntl.h> |
23 | #include <stdlib.h> | |
24 | #include <string.h> | |
25 | #include <unistd.h> | |
26 | ||
27 | RCSID("$Header$"); | |
28 | ||
a3cf6921 | 29 | extern int nclients; |
85330553 | 30 | extern client **clients; |
a3cf6921 | 31 | extern char *whoami; |
32 | ||
03c05291 | 33 | extern int dbms_errno, mr_errcode; |
78543660 | 34 | |
c44ddfa7 | 35 | int max_version; |
36 | ||
7ac48069 | 37 | void do_call(client *cl); |
38 | void free_rtn_tuples(client *cp); | |
85330553 | 39 | int retr_callback(int argc, char **argv, void *p_cl); |
40 | int list_users(client *cl); | |
8691463b | 41 | void do_retr(client *cl); |
42 | void do_access(client *cl); | |
7ac48069 | 43 | void get_motd(client *cl); |
c44ddfa7 | 44 | void do_version(client *cl); |
7ac48069 | 45 | |
a3cf6921 | 46 | char *procnames[] = { |
5eaef520 | 47 | "noop", |
48 | "auth", | |
49 | "shutdown", | |
50 | "query", | |
51 | "access", | |
52 | "dcm", | |
53 | "motd", | |
ed00e35e | 54 | "proxy", |
c44ddfa7 | 55 | "version", |
991417e4 | 56 | "auth_krb5", |
630e8323 | 57 | }; |
58 | ||
85330553 | 59 | int newqueries; |
a3cf6921 | 60 | |
85330553 | 61 | void client_read(client *cl) |
a3cf6921 | 62 | { |
85330553 | 63 | int status, pn; |
64 | ||
8691463b | 65 | status = mr_cont_receive(cl->con, &cl->req); |
66 | if (status == -1) | |
67 | return; | |
68 | else if (status != MR_SUCCESS) | |
5eaef520 | 69 | { |
8691463b | 70 | cl->state = CL_CLOSING; |
85330553 | 71 | if (status != MR_NOT_CONNECTED) |
72 | com_err(whoami, status, "while reading from socket"); | |
5eaef520 | 73 | return; |
74 | } | |
85330553 | 75 | |
8691463b | 76 | pn = cl->req.u.mr_procno; |
85330553 | 77 | if (pn < 0 || pn > MR_MAX_PROC) |
5eaef520 | 78 | { |
85330553 | 79 | com_err(whoami, 0, "procno out of range"); |
80 | client_reply(cl, MR_UNKNOWN_PROC); | |
187dc9ed | 81 | goto out; |
5eaef520 | 82 | } |
8691463b | 83 | log_args(procnames[pn], 2, cl->req.mr_argc, cl->req.mr_argv); |
5eaef520 | 84 | |
85330553 | 85 | if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD) |
5eaef520 | 86 | { |
85330553 | 87 | client_reply(cl, MR_DOWN); |
88 | com_err(whoami, MR_DOWN, "(query refused)"); | |
187dc9ed | 89 | goto out; |
5eaef520 | 90 | } |
91 | ||
92 | /* make sure this gets cleared before every operation */ | |
93 | dbms_errno = 0; | |
94 | ||
95 | switch (pn) | |
96 | { | |
97 | case MR_NOOP: | |
85330553 | 98 | client_reply(cl, MR_SUCCESS); |
e688520a | 99 | break; |
5eaef520 | 100 | |
101 | case MR_AUTH: | |
8691463b | 102 | do_auth(cl); |
e688520a | 103 | break; |
5eaef520 | 104 | |
105 | case MR_QUERY: | |
8691463b | 106 | do_retr(cl); |
e688520a | 107 | break; |
5eaef520 | 108 | |
109 | case MR_ACCESS: | |
8691463b | 110 | do_access(cl); |
e688520a | 111 | break; |
5eaef520 | 112 | |
113 | case MR_SHUTDOWN: | |
114 | do_shutdown(cl); | |
e688520a | 115 | break; |
5eaef520 | 116 | |
117 | case MR_DO_UPDATE: | |
85330553 | 118 | client_reply(cl, MR_PERM); |
e688520a | 119 | break; |
5eaef520 | 120 | |
121 | case MR_MOTD: | |
122 | get_motd(cl); | |
e688520a | 123 | break; |
ed00e35e | 124 | |
125 | case MR_PROXY: | |
126 | do_proxy(cl); | |
127 | break; | |
c44ddfa7 | 128 | |
129 | case MR_SETVERSION: | |
130 | do_version(cl); | |
131 | break; | |
991417e4 | 132 | |
133 | case MR_KRB5_AUTH: | |
134 | do_krb5_auth(cl); | |
135 | break; | |
136 | ||
5eaef520 | 137 | } |
187dc9ed | 138 | |
139 | out: | |
8691463b | 140 | mr_destroy_reply(cl->req); |
141 | memset(&cl->req, 0, sizeof(mr_params)); | |
a3cf6921 | 142 | } |
143 | ||
85330553 | 144 | /* Set the final return status for a query. We always keep one more |
145 | free slot in cl->tuples[] than we're using so that this can't fail */ | |
146 | void client_reply(client *cl, long status) | |
ed31e0d1 | 147 | { |
85330553 | 148 | cl->tuples[cl->ntuples].u.mr_status = status; |
149 | cl->tuples[cl->ntuples].mr_argc = 0; | |
150 | cl->tuples[cl->ntuples].mr_argl = NULL; | |
151 | cl->tuples[cl->ntuples].mr_argv = NULL; | |
152 | cl->ntuples++; | |
5eaef520 | 153 | } |
ed31e0d1 | 154 | |
85330553 | 155 | void client_return_tuple(client *cl, int argc, char **argv) |
78849033 | 156 | { |
8691463b | 157 | if (cl->state == CL_CLOSING || dbms_errno) |
85330553 | 158 | return; |
5eaef520 | 159 | |
85330553 | 160 | if (cl->ntuples == cl->tuplessize - 1) |
5eaef520 | 161 | { |
85330553 | 162 | int newsize = (cl->tuplessize + 4) * 2; |
163 | mr_params *newtuples; | |
164 | ||
165 | newtuples = realloc(cl->tuples, newsize * sizeof(mr_params)); | |
166 | if (!newtuples) | |
167 | { | |
168 | free_rtn_tuples(cl); | |
169 | dbms_errno = mr_errcode = MR_NO_MEM; | |
170 | return; | |
171 | } | |
172 | cl->tuplessize = newsize; | |
173 | cl->tuples = newtuples; | |
5eaef520 | 174 | } |
5eaef520 | 175 | |
85330553 | 176 | cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA; |
177 | cl->tuples[cl->ntuples].mr_argc = argc; | |
178 | cl->tuples[cl->ntuples].mr_argl = NULL; | |
179 | cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc); | |
180 | cl->ntuples++; | |
78849033 | 181 | } |
182 | ||
85330553 | 183 | void client_write(client *cl) |
de24f12d | 184 | { |
85330553 | 185 | int status; |
5eaef520 | 186 | |
85330553 | 187 | status = mr_send(cl->con, &cl->tuples[cl->nexttuple]); |
188 | if (status) | |
5eaef520 | 189 | { |
85330553 | 190 | com_err(whoami, status, "writing to socket"); |
8691463b | 191 | cl->state = CL_CLOSING; |
85330553 | 192 | } |
193 | else | |
194 | { | |
195 | cl->nexttuple++; | |
196 | if (cl->nexttuple == cl->ntuples) | |
197 | free_rtn_tuples(cl); | |
5eaef520 | 198 | } |
de24f12d | 199 | } |
78849033 | 200 | |
85330553 | 201 | void free_rtn_tuples(client *cl) |
a3cf6921 | 202 | { |
85330553 | 203 | for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--) |
204 | free_argv(cl->tuples[cl->ntuples].mr_argv, | |
205 | cl->tuples[cl->ntuples].mr_argc); | |
206 | free(cl->tuples); | |
207 | ||
208 | cl->tuples = xmalloc(sizeof(mr_params)); | |
209 | cl->tuplessize = 1; | |
210 | cl->ntuples = cl->nexttuple = 0; | |
211 | } | |
5eaef520 | 212 | |
8691463b | 213 | void do_retr(client *cl) |
85330553 | 214 | { |
215 | char *queryname; | |
216 | int status; | |
5eaef520 | 217 | |
8691463b | 218 | if (cl->req.mr_argc < 1) |
5eaef520 | 219 | { |
85330553 | 220 | client_reply(cl, MR_ARGS); |
5eaef520 | 221 | com_err(whoami, MR_ARGS, "got nameless query"); |
222 | return; | |
223 | } | |
8691463b | 224 | queryname = cl->req.mr_argv[0]; |
85330553 | 225 | newqueries++; |
5eaef520 | 226 | |
227 | if (!strcmp(queryname, "_list_users")) | |
85330553 | 228 | status = list_users(cl); |
5eaef520 | 229 | else |
8691463b | 230 | status = mr_process_query(cl, queryname, cl->req.mr_argc - 1, |
231 | cl->req.mr_argv + 1, retr_callback, cl); | |
85330553 | 232 | |
233 | client_reply(cl, status); | |
234 | ||
85330553 | 235 | com_err(whoami, 0, "Query complete."); |
236 | } | |
237 | ||
238 | int retr_callback(int argc, char **argv, void *p_cl) | |
239 | { | |
240 | client *cl = p_cl; | |
241 | ||
242 | mr_trim_args(argc, argv); | |
243 | client_return_tuple(cl, argc, argv); | |
a3cf6921 | 244 | } |
78849033 | 245 | |
8691463b | 246 | void do_access(client *cl) |
3630192b | 247 | { |
85330553 | 248 | int status; |
249 | ||
8691463b | 250 | if (cl->req.mr_argc < 1) |
5eaef520 | 251 | { |
85330553 | 252 | client_reply(cl, MR_ARGS); |
5eaef520 | 253 | com_err(whoami, MR_ARGS, "got nameless access"); |
254 | return; | |
255 | } | |
5eaef520 | 256 | |
8691463b | 257 | status = mr_check_access(cl, cl->req.mr_argv[0], cl->req.mr_argc - 1, |
258 | cl->req.mr_argv + 1); | |
85330553 | 259 | client_reply(cl, status); |
5eaef520 | 260 | |
261 | com_err(whoami, 0, "Access check complete."); | |
3630192b | 262 | } |
8165c536 | 263 | |
c44ddfa7 | 264 | void do_version(client *cl) |
265 | { | |
266 | if (cl->req.mr_argc != 1) | |
267 | { | |
268 | client_reply(cl, MR_ARGS); | |
269 | com_err(whoami, MR_ARGS, "incorrect number of arguments"); | |
270 | return; | |
271 | } | |
272 | ||
273 | cl->version = atoi(cl->req.mr_argv[0]); | |
274 | if (cl->version == -1) | |
275 | cl->version = max_version; | |
276 | ||
277 | client_reply(cl, cl->version == max_version ? MR_SUCCESS : | |
278 | cl->version < max_version ? MR_VERSION_LOW : MR_VERSION_HIGH); | |
279 | } | |
280 | ||
85330553 | 281 | void get_motd(client *cl) |
8165c536 | 282 | { |
85330553 | 283 | int motd; |
284 | char *buffer; | |
285 | struct stat statb; | |
5eaef520 | 286 | |
85330553 | 287 | if (stat(MOIRA_MOTD_FILE, &statb) == -1) |
5eaef520 | 288 | { |
85330553 | 289 | client_reply(cl, MR_SUCCESS); |
290 | return; | |
291 | } | |
292 | ||
293 | buffer = malloc(statb.st_size + 1); | |
294 | if (!buffer) | |
295 | { | |
296 | client_reply(cl, MR_NO_MEM); | |
297 | return; | |
298 | } | |
5eaef520 | 299 | |
85330553 | 300 | motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY); |
301 | if (motd) | |
302 | { | |
303 | read(motd, buffer, statb.st_size); | |
304 | close(motd); | |
305 | buffer[statb.st_size] = '\0'; | |
306 | client_return_tuple(cl, 1, &buffer); | |
307 | client_reply(cl, MR_SUCCESS); | |
5eaef520 | 308 | } |
85330553 | 309 | else |
310 | client_reply(cl, errno); | |
8165c536 | 311 | |
85330553 | 312 | free(buffer); |
313 | } | |
57c08162 | 314 | |
85330553 | 315 | int list_users(client *cl) |
57c08162 | 316 | { |
85330553 | 317 | char *argv[5]; |
318 | char buf[30]; | |
319 | char buf1[30]; | |
320 | int i; | |
321 | char *cp; | |
5eaef520 | 322 | |
85330553 | 323 | for (i = 0; i < nclients; i++) |
324 | { | |
325 | client *c = clients[i]; | |
326 | argv[0] = c->clname; | |
327 | argv[1] = inet_ntoa(c->haddr.sin_addr); | |
328 | argv[2] = buf; | |
329 | sprintf(buf, "port %d", ntohs(c->haddr.sin_port)); | |
330 | argv[3] = ctime(&c->last_time_used); | |
331 | cp = strchr(argv[3], '\n'); | |
332 | if (cp) | |
333 | *cp = '\0'; | |
334 | argv[4] = buf1; | |
335 | sprintf(buf1, "[#%d]", c->id); | |
336 | client_return_tuple(cl, 5, argv); | |
337 | } | |
338 | return MR_SUCCESS; | |
57c08162 | 339 | } |
85330553 | 340 |