X-Git-Url: http://andersk.mit.edu/gitweb/moira.git/blobdiff_plain/630e8323e2c43beb87f052bb7ff34198223ff2fa..200545fb5b96f63266e1b27195edd02217592671:/server/mr_scall.c diff --git a/server/mr_scall.c b/server/mr_scall.c index a2a00af0..46043341 100644 --- a/server/mr_scall.c +++ b/server/mr_scall.c @@ -1,231 +1,340 @@ -/* - * $Source$ - * $Author$ - * $Header$ +/* $Id$ * - * Copyright (C) 1987 by the Massachusetts Institute of Technology + * Do RPC * - * $Log$ - * Revision 1.7 1987-07-14 00:39:01 wesommer - * Rearranged loggin. + * Copyright (C) 1987-1998 by the Massachusetts Institute of Technology + * For copying and distribution information, please see the file + * . * - * Revision 1.6 87/06/30 20:04:43 wesommer - * Free returned tuples when possible. - * - * Revision 1.5 87/06/26 10:55:53 wesommer - * Added sms_access, now paiys attention to return code from - * sms_process_query, sms_check_access. - * - * Revision 1.4 87/06/21 16:42:00 wesommer - * Performance work, rearrangement of include files. - * - * Revision 1.3 87/06/04 01:35:01 wesommer - * Added a working query request handler. - * - * Revision 1.2 87/06/03 16:07:50 wesommer - * Fixes for lint. - * - * Revision 1.1 87/06/02 20:07:10 wesommer - * Initial revision - * */ -#ifndef lint -static char *rcsid_sms_scall_c = "$Header$"; -#endif lint +#include +#include "mr_server.h" +#include "query.h" + +#include +#include + +#include +#include -#include #include -#include "sms_server.h" -extern char buf1[]; +#include +#include +#include +#include + +RCSID("$Header$"); + extern int nclients; +extern client **clients; extern char *whoami; -extern void clist_delete(), do_auth(), do_shutdown(); -void do_call(); +extern int dbms_errno, mr_errcode; -/* - * Welcome to the (finite state) machine (highest level). - */ -void -do_client(cp) - client *cp; -{ - free_rtn_tuples(cp); - if (OP_STATUS(cp->pending_op) == OP_CANCELLED) { - (void) sprintf(buf1, "Closed connection (now %d client%s)", - nclients-1, - nclients!=2?"s":""); - com_err(whoami, 0, buf1); - clist_delete(cp); - return; - } - switch (cp->action) { - case CL_ACCEPT: - case CL_SEND: - /* Start recieving next request */ - initialize_operation(cp->pending_op, sms_start_recv, - (char *)&cp->args, (int (*)())NULL); - queue_operation(cp->con, CON_INPUT, cp->pending_op); - cp->action = CL_RECEIVE; - break; - case CL_RECEIVE: - /* Data is here. Process it & start it heading back */ - do_call(cp); /* This may block for a while. */ - initialize_operation(cp->pending_op, sms_start_send, - (char *)&cp->reply, (int (*)())NULL); - queue_operation(cp->con, CON_OUTPUT, cp->pending_op); - cp->action = CL_SEND; - break; - } -} +int max_version; + +void do_call(client *cl); +void free_rtn_tuples(client *cp); +int retr_callback(int argc, char **argv, void *p_cl); +int list_users(client *cl); +void do_retr(client *cl); +void do_access(client *cl); +void get_motd(client *cl); +void do_version(client *cl); char *procnames[] = { - "noop", - "auth", - "shutdown", - "query", - "access", + "noop", + "auth", + "shutdown", + "query", + "access", + "dcm", + "motd", + "proxy", + "version", + "auth_krb5", }; +int newqueries; -void -do_call(cl) - client *cl; +void client_read(client *cl) { - int pn; - cl->reply.sms_argc = 0; - cl->reply.sms_status = 0; - if (((pn = cl->args->sms_procno) < 0) || - (pn > SMS_MAX_PROC)) { - com_err(whoami, 0, "procno out of range"); - cl->reply.sms_status = SMS_UNKNOWN_PROC; - return; - } - if (log_flags & LOG_ARGS) - log_args(procnames[pn], cl->args->sms_argc, - cl->args->sms_argv); - else if (log_flags & LOG_REQUESTS) - com_err(whoami, 0, procnames[pn]); - - switch(pn) { - case SMS_NOOP: - cl->reply.sms_status = 0; - return; - - case SMS_AUTH: - do_auth(cl); - return; - - case SMS_QUERY: - do_retr(cl); - return; - - case SMS_ACCESS: - do_access(cl); - return; - - case SMS_SHUTDOWN: - do_shutdown(cl); - return; - } + int status, pn; + + status = mr_cont_receive(cl->con, &cl->req); + if (status == -1) + return; + else if (status != MR_SUCCESS) + { + cl->state = CL_CLOSING; + if (status != MR_NOT_CONNECTED) + com_err(whoami, status, "while reading from socket"); + return; + } + + pn = cl->req.u.mr_procno; + if (pn < 0 || pn > MR_MAX_PROC) + { + com_err(whoami, 0, "procno out of range"); + client_reply(cl, MR_UNKNOWN_PROC); + goto out; + } + log_args(procnames[pn], 2, cl->req.mr_argc, cl->req.mr_argv); + + if (dormant == ASLEEP && pn != MR_NOOP && pn != MR_MOTD) + { + client_reply(cl, MR_DOWN); + com_err(whoami, MR_DOWN, "(query refused)"); + goto out; + } + + /* make sure this gets cleared before every operation */ + dbms_errno = 0; + + switch (pn) + { + case MR_NOOP: + client_reply(cl, MR_SUCCESS); + break; + + case MR_AUTH: + do_auth(cl); + break; + + case MR_QUERY: + do_retr(cl); + break; + + case MR_ACCESS: + do_access(cl); + break; + + case MR_SHUTDOWN: + do_shutdown(cl); + break; + + case MR_DO_UPDATE: + client_reply(cl, MR_PERM); + break; + + case MR_MOTD: + get_motd(cl); + break; + + case MR_PROXY: + do_proxy(cl); + break; + + case MR_SETVERSION: + do_version(cl); + break; + + case MR_KRB5_AUTH: + do_krb5_auth(cl); + break; + + } + +out: + mr_destroy_reply(cl->req); + memset(&cl->req, 0, sizeof(mr_params)); } -free_rtn_tuples(cp) - client *cp; +/* Set the final return status for a query. We always keep one more + free slot in cl->tuples[] than we're using so that this can't fail */ +void client_reply(client *cl, long status) { - register returned_tuples *temp; - for (temp=cp->first; temp && OP_DONE(temp->op); ) { - register returned_tuples *t1=temp; - temp = t1->next; - if (t1 == cp->last) cp->last = NULL; -#ifdef notdef - sms_destroy_reply(t1->retval); -#endif notdef - if (t1->retval) { - register sms_params *p = t1->retval; - if (p->sms_flattened) - free(p->sms_flattened); - if (p->sms_argl) - free(p->sms_argl); - free(p); - } - delete_operation(t1->op); - free(t1); - } - cp->first = temp; -} + cl->tuples[cl->ntuples].u.mr_status = status; + cl->tuples[cl->ntuples].mr_argc = 0; + cl->tuples[cl->ntuples].mr_argl = NULL; + cl->tuples[cl->ntuples].mr_argv = NULL; + cl->ntuples++; +} -retr_callback(argc, argv, p_cp) - int argc; - char **argv; - char *p_cp; +void client_return_tuple(client *cl, int argc, char **argv) { - register client *cp = (client *)p_cp; - /* - * This takes too much advantage of the fact that - * serialization of the data happens during the queue operation. - */ - sms_params *arg_tmp = (sms_params *)db_alloc(sizeof(sms_params)); - returned_tuples *tp = (returned_tuples *) - db_alloc(sizeof(returned_tuples)); - - OPERATION op_tmp = create_operation(); - - if (log_flags & LOG_RESP) - log_args("return: ", argc, argv); - - tp->op = op_tmp; - tp->retval = arg_tmp; - tp->next = NULL; - - arg_tmp->sms_status = SMS_MORE_DATA; - arg_tmp->sms_argc = argc; - arg_tmp->sms_argv = argv; - arg_tmp->sms_flattened = (char *)NULL; - arg_tmp->sms_argl = (int *)NULL; - - if (cp->last) { - cp->last->next = tp; - cp->last = tp; - } else { - cp->last = cp->first = tp; + if (cl->state == CL_CLOSING || dbms_errno) + return; + + if (cl->ntuples == cl->tuplessize - 1) + { + int newsize = (cl->tuplessize + 4) * 2; + mr_params *newtuples; + + newtuples = realloc(cl->tuples, newsize * sizeof(mr_params)); + if (!newtuples) + { + free_rtn_tuples(cl); + dbms_errno = mr_errcode = MR_NO_MEM; + return; } - - reset_operation(op_tmp); - initialize_operation(op_tmp, sms_start_send, (char *)arg_tmp, - (int (*)())NULL); - queue_operation(cp->con, CON_OUTPUT, op_tmp); + cl->tuplessize = newsize; + cl->tuples = newtuples; + } + + cl->tuples[cl->ntuples].u.mr_status = MR_MORE_DATA; + cl->tuples[cl->ntuples].mr_argc = argc; + cl->tuples[cl->ntuples].mr_argl = NULL; + cl->tuples[cl->ntuples].mr_argv = mr_copy_args(argv, argc); + cl->ntuples++; +} + +void client_write(client *cl) +{ + int status; + + status = mr_send(cl->con, &cl->tuples[cl->nexttuple]); + if (status) + { + com_err(whoami, status, "writing to socket"); + cl->state = CL_CLOSING; + } + else + { + cl->nexttuple++; + if (cl->nexttuple == cl->ntuples) + free_rtn_tuples(cl); + } } +void free_rtn_tuples(client *cl) +{ + for (cl->ntuples--; cl->ntuples >= 0; cl->ntuples--) + free_argv(cl->tuples[cl->ntuples].mr_argv, + cl->tuples[cl->ntuples].mr_argc); + free(cl->tuples); -do_retr(cl) - client *cl; + cl->tuples = xmalloc(sizeof(mr_params)); + cl->tuplessize = 1; + cl->ntuples = cl->nexttuple = 0; +} + +void do_retr(client *cl) { - cl->reply.sms_argc = 0; - cl->reply.sms_status = 0; - - cl->reply.sms_status = - sms_process_query(cl, - cl->args->sms_argv[0], - cl->args->sms_argc-1, - cl->args->sms_argv+1, - retr_callback, - (char *)cl); - if (log_flags & LOG_RES) - com_err(whoami, 0, "Query complete."); + char *queryname; + int status; + + if (cl->req.mr_argc < 1) + { + client_reply(cl, MR_ARGS); + com_err(whoami, MR_ARGS, "got nameless query"); + return; + } + queryname = cl->req.mr_argv[0]; + newqueries++; + + if (!strcmp(queryname, "_list_users")) + status = list_users(cl); + else + status = mr_process_query(cl, queryname, cl->req.mr_argc - 1, + cl->req.mr_argv + 1, retr_callback, cl); + + client_reply(cl, status); + + com_err(whoami, 0, "Query complete."); +} + +int retr_callback(int argc, char **argv, void *p_cl) +{ + client *cl = p_cl; + + mr_trim_args(argc, argv); + client_return_tuple(cl, argc, argv); } -do_access(cl) - client *cl; +void do_access(client *cl) { - cl->reply.sms_argc = 0; - - cl->reply.sms_status = - sms_check_access(cl, - cl->args->sms_argv[0], - cl->args->sms_argc-1, - cl->args->sms_argv+1); - - com_err(whoami, 0, "Access check complete."); + int status; + + if (cl->req.mr_argc < 1) + { + client_reply(cl, MR_ARGS); + com_err(whoami, MR_ARGS, "got nameless access"); + return; + } + + status = mr_check_access(cl, cl->req.mr_argv[0], cl->req.mr_argc - 1, + cl->req.mr_argv + 1); + client_reply(cl, status); + + com_err(whoami, 0, "Access check complete."); } + +void do_version(client *cl) +{ + if (cl->req.mr_argc != 1) + { + client_reply(cl, MR_ARGS); + com_err(whoami, MR_ARGS, "incorrect number of arguments"); + return; + } + + cl->version = atoi(cl->req.mr_argv[0]); + if (cl->version == -1) + cl->version = max_version; + + client_reply(cl, cl->version == max_version ? MR_SUCCESS : + cl->version < max_version ? MR_VERSION_LOW : MR_VERSION_HIGH); +} + +void get_motd(client *cl) +{ + int motd; + char *buffer; + struct stat statb; + + if (stat(MOIRA_MOTD_FILE, &statb) == -1) + { + client_reply(cl, MR_SUCCESS); + return; + } + + buffer = malloc(statb.st_size + 1); + if (!buffer) + { + client_reply(cl, MR_NO_MEM); + return; + } + + motd = open(MOIRA_MOTD_FILE, 0, O_RDONLY); + if (motd) + { + read(motd, buffer, statb.st_size); + close(motd); + buffer[statb.st_size] = '\0'; + client_return_tuple(cl, 1, &buffer); + client_reply(cl, MR_SUCCESS); + } + else + client_reply(cl, errno); + + free(buffer); +} + +int list_users(client *cl) +{ + char *argv[5]; + char buf[30]; + char buf1[30]; + int i; + char *cp; + + for (i = 0; i < nclients; i++) + { + client *c = clients[i]; + argv[0] = c->clname; + argv[1] = inet_ntoa(c->haddr.sin_addr); + argv[2] = buf; + sprintf(buf, "port %d", ntohs(c->haddr.sin_port)); + argv[3] = ctime(&c->last_time_used); + cp = strchr(argv[3], '\n'); + if (cp) + *cp = '\0'; + argv[4] = buf1; + sprintf(buf1, "[#%d]", c->id); + client_return_tuple(cl, 5, argv); + } + return MR_SUCCESS; +} +